| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library engine.resolver; | 5 library engine.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import "dart:math" as math; | 8 import "dart:math" as math; |
| 9 | 9 |
| 10 import 'java_core.dart'; | 10 import 'java_core.dart'; |
| (...skipping 15524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15535 * identifier is not defined). | 15535 * identifier is not defined). |
| 15536 * | 15536 * |
| 15537 * @return the tag that has the given identifier | 15537 * @return the tag that has the given identifier |
| 15538 */ | 15538 */ |
| 15539 String getTagWithId(String identifier) { | 15539 String getTagWithId(String identifier) { |
| 15540 return idToTagMap[identifier]; | 15540 return idToTagMap[identifier]; |
| 15541 } | 15541 } |
| 15542 } | 15542 } |
| 15543 | 15543 |
| 15544 | 15544 |
| 15545 class _UsedElements { |
| 15546 /** |
| 15547 * Resolved, locally defined elements that are used or potentially can be |
| 15548 * used. |
| 15549 */ |
| 15550 final HashSet<Element> elements = new HashSet<Element>(); |
| 15551 |
| 15552 /** |
| 15553 * Names of resolved or unresolved class members that are referenced in the |
| 15554 * library. |
| 15555 */ |
| 15556 final HashSet<String> members = new HashSet<String>(); |
| 15557 } |
| 15558 |
| 15559 |
| 15545 class _GatherUsedElementsVisitor extends RecursiveAstVisitor { | 15560 class _GatherUsedElementsVisitor extends RecursiveAstVisitor { |
| 15546 final Set<Element> usedElements = new HashSet<Element>(); | 15561 final _UsedElements usedElements = new _UsedElements(); |
| 15547 | 15562 |
| 15548 final LibraryElement _enclosingLibrary; | 15563 final LibraryElement _enclosingLibrary; |
| 15549 ClassElement _enclosingClass; | 15564 ClassElement _enclosingClass; |
| 15565 ExecutableElement _enclosingExec; |
| 15550 | 15566 |
| 15551 _GatherUsedElementsVisitor(this._enclosingLibrary); | 15567 _GatherUsedElementsVisitor(this._enclosingLibrary); |
| 15552 | 15568 |
| 15553 @override | 15569 @override |
| 15554 visitCatchClause(CatchClause node) { | 15570 visitCatchClause(CatchClause node) { |
| 15555 SimpleIdentifier exceptionParameter = node.exceptionParameter; | 15571 SimpleIdentifier exceptionParameter = node.exceptionParameter; |
| 15556 _useStaticElement(exceptionParameter); | 15572 _useStaticElement(exceptionParameter); |
| 15557 super.visitCatchClause(node); | 15573 super.visitCatchClause(node); |
| 15558 } | 15574 } |
| 15559 | 15575 |
| 15560 @override | 15576 @override |
| 15561 visitClassDeclaration(ClassDeclaration node) { | 15577 visitClassDeclaration(ClassDeclaration node) { |
| 15562 ClassElement enclosingClassOld = _enclosingClass; | 15578 ClassElement enclosingClassOld = _enclosingClass; |
| 15563 try { | 15579 try { |
| 15564 _enclosingClass = node.element; | 15580 _enclosingClass = node.element; |
| 15565 super.visitClassDeclaration(node); | 15581 super.visitClassDeclaration(node); |
| 15566 } finally { | 15582 } finally { |
| 15567 _enclosingClass = enclosingClassOld; | 15583 _enclosingClass = enclosingClassOld; |
| 15568 } | 15584 } |
| 15569 } | 15585 } |
| 15570 | 15586 |
| 15571 @override | 15587 @override |
| 15588 visitMethodDeclaration(MethodDeclaration node) { |
| 15589 ExecutableElement enclosingExecOld = _enclosingExec; |
| 15590 try { |
| 15591 _enclosingExec = node.element; |
| 15592 super.visitMethodDeclaration(node); |
| 15593 } finally { |
| 15594 _enclosingExec = enclosingExecOld; |
| 15595 } |
| 15596 } |
| 15597 |
| 15598 @override |
| 15572 visitSimpleIdentifier(SimpleIdentifier node) { | 15599 visitSimpleIdentifier(SimpleIdentifier node) { |
| 15573 if (node.inDeclarationContext()) { | 15600 if (node.inDeclarationContext()) { |
| 15574 return; | 15601 return; |
| 15575 } | 15602 } |
| 15576 Element staticElement = node.staticElement; | 15603 Element element = node.staticElement; |
| 15577 if (staticElement is LocalVariableElement) { | 15604 if (element is LocalVariableElement) { |
| 15578 AstNode parent = node.parent; | 15605 AstNode parent = node.parent; |
| 15579 if (node.inGetterContext()) { | 15606 if (node.inGetterContext()) { |
| 15580 if (parent.parent is ExpressionStatement && | 15607 if (parent.parent is ExpressionStatement && |
| 15581 (parent is PrefixExpression || | 15608 (parent is PrefixExpression || |
| 15582 parent is PostfixExpression || | 15609 parent is PostfixExpression || |
| 15583 parent is AssignmentExpression && parent.leftHandSide == node)) { | 15610 parent is AssignmentExpression && parent.leftHandSide == node)) { |
| 15584 // v++; | 15611 // v++; |
| 15585 // ++v; | 15612 // ++v; |
| 15586 // v += 2; | 15613 // v += 2; |
| 15587 } else { | 15614 } else { |
| 15588 _useElement(staticElement); | 15615 _useElement(element); |
| 15589 } | 15616 } |
| 15590 } | 15617 } |
| 15591 if (parent is MethodInvocation && parent.methodName == node) { | 15618 if (parent is MethodInvocation && parent.methodName == node) { |
| 15592 _useElement(staticElement); | 15619 _useElement(element); |
| 15593 } | 15620 } |
| 15594 } else { | 15621 } else { |
| 15595 _useIdentifierElement(node); | 15622 _useIdentifierElement(node); |
| 15623 if (element == null || |
| 15624 element is! LocalElement && !identical(element, _enclosingExec)) { |
| 15625 usedElements.members.add(node.name); |
| 15626 } |
| 15596 } | 15627 } |
| 15597 } | 15628 } |
| 15598 | 15629 |
| 15599 @override | 15630 @override |
| 15600 visitTypeName(TypeName node) { | 15631 visitTypeName(TypeName node) { |
| 15601 _useIdentifierElement(node.name); | 15632 _useIdentifierElement(node.name); |
| 15602 } | 15633 } |
| 15603 | 15634 |
| 15604 /** | 15635 /** |
| 15605 * Marks an [Element] of [node] as used in the library. | 15636 * Marks an [Element] of [node] as used in the library. |
| 15606 */ | 15637 */ |
| 15607 void _useIdentifierElement(Identifier node) { | 15638 void _useIdentifierElement(Identifier node) { |
| 15608 Element element = node.staticElement; | 15639 Element element = node.staticElement; |
| 15609 if (element == null) { | 15640 if (element == null) { |
| 15610 return; | 15641 return; |
| 15611 } | 15642 } |
| 15612 // check if a local element | 15643 // check if a local element |
| 15613 if (!identical(element.library, _enclosingLibrary)) { | 15644 if (!identical(element.library, _enclosingLibrary)) { |
| 15614 return; | 15645 return; |
| 15615 } | 15646 } |
| 15616 // ignore references to an element from itself | 15647 // ignore references to an element from itself |
| 15617 if (identical(element, _enclosingClass)) { | 15648 if (identical(element, _enclosingClass)) { |
| 15618 return; | 15649 return; |
| 15619 } | 15650 } |
| 15651 if (identical(element, _enclosingExec)) { |
| 15652 return; |
| 15653 } |
| 15620 // ignore places where the element is not actually used | 15654 // ignore places where the element is not actually used |
| 15621 if (node.parent is TypeName) { | 15655 if (node.parent is TypeName) { |
| 15622 AstNode parent2 = node.parent.parent; | 15656 AstNode parent2 = node.parent.parent; |
| 15623 if (parent2 is IsExpression) { | 15657 if (parent2 is IsExpression) { |
| 15624 return; | 15658 return; |
| 15625 } | 15659 } |
| 15626 if (parent2 is VariableDeclarationList) { | 15660 if (parent2 is VariableDeclarationList) { |
| 15627 return; | 15661 return; |
| 15628 } | 15662 } |
| 15629 } | 15663 } |
| 15630 // OK | 15664 // OK |
| 15631 _useElement(element); | 15665 _useElement(element); |
| 15632 } | 15666 } |
| 15633 | 15667 |
| 15634 _useElement(Element element) { | 15668 _useElement(Element element) { |
| 15635 if (element != null) { | 15669 if (element != null) { |
| 15636 usedElements.add(element); | 15670 usedElements.elements.add(element); |
| 15637 } | 15671 } |
| 15638 } | 15672 } |
| 15639 | 15673 |
| 15640 void _useStaticElement(SimpleIdentifier identifier) { | 15674 void _useStaticElement(SimpleIdentifier identifier) { |
| 15641 if (identifier != null) { | 15675 if (identifier != null) { |
| 15642 _useElement(identifier.staticElement); | 15676 _useElement(identifier.staticElement); |
| 15643 } | 15677 } |
| 15644 } | 15678 } |
| 15645 } | 15679 } |
| 15646 | 15680 |
| 15647 | 15681 |
| 15648 /** | 15682 /** |
| 15649 * Instances of the class [_UnusedElementsVerifier] traverse an element | 15683 * Instances of the class [_UnusedElementsVerifier] traverse an element |
| 15650 * structure looking for cases of [HintCode.UNUSED_ELEMENT] and | 15684 * structure looking for cases of [HintCode.UNUSED_ELEMENT] and |
| 15651 * [HintCode.UNUSED_LOCAL_VARIABLE]. | 15685 * [HintCode.UNUSED_LOCAL_VARIABLE]. |
| 15652 */ | 15686 */ |
| 15653 class _UnusedElementsVerifier extends RecursiveElementVisitor { | 15687 class _UnusedElementsVerifier extends RecursiveElementVisitor { |
| 15654 /** | 15688 /** |
| 15655 * The error listener to which errors will be reported. | 15689 * The error listener to which errors will be reported. |
| 15656 */ | 15690 */ |
| 15657 final AnalysisErrorListener _errorListener; | 15691 final AnalysisErrorListener _errorListener; |
| 15658 | 15692 |
| 15659 /** | 15693 /** |
| 15660 * The elements know to be used. | 15694 * The elements know to be used. |
| 15661 */ | 15695 */ |
| 15662 final Set<Element> _usedElements; | 15696 final _UsedElements _usedElements; |
| 15663 | 15697 |
| 15664 /** | 15698 /** |
| 15665 * Create a new instance of the [_UnusedElementsVerifier]. | 15699 * Create a new instance of the [_UnusedElementsVerifier]. |
| 15666 */ | 15700 */ |
| 15667 _UnusedElementsVerifier(this._errorListener, this._usedElements); | 15701 _UnusedElementsVerifier(this._errorListener, this._usedElements); |
| 15668 | 15702 |
| 15669 @override | 15703 @override |
| 15670 visitClassElement(ClassElement element) { | 15704 visitClassElement(ClassElement element) { |
| 15671 if (!_isUsed(element)) { | 15705 if (!_isUsedElement(element)) { |
| 15672 _reportErrorForElement( | 15706 _reportErrorForElement( |
| 15673 HintCode.UNUSED_ELEMENT, | 15707 HintCode.UNUSED_ELEMENT, |
| 15674 element, | 15708 element, |
| 15675 [element.kind.displayName, element.displayName]); | 15709 [element.kind.displayName, element.displayName]); |
| 15676 } | 15710 } |
| 15677 element.visitChildren(this); | 15711 super.visitClassElement(element); |
| 15678 } | 15712 } |
| 15679 | 15713 |
| 15680 @override | 15714 @override |
| 15681 visitLocalVariableElement(LocalVariableElement element) { | 15715 visitLocalVariableElement(LocalVariableElement element) { |
| 15682 if (!_isUsed(element)) { | 15716 if (!_isUsedElement(element)) { |
| 15683 _reportErrorForElement( | 15717 _reportErrorForElement( |
| 15684 HintCode.UNUSED_LOCAL_VARIABLE, | 15718 HintCode.UNUSED_LOCAL_VARIABLE, |
| 15685 element, | 15719 element, |
| 15686 [element.displayName]); | 15720 [element.displayName]); |
| 15687 } | 15721 } |
| 15688 } | 15722 } |
| 15689 | 15723 |
| 15690 bool _isUsed(Element element) { | 15724 @override |
| 15725 visitMethodElement(MethodElement element) { |
| 15726 if (!_isUsedMember(element)) { |
| 15727 _reportErrorForElement( |
| 15728 HintCode.UNUSED_ELEMENT, |
| 15729 element, |
| 15730 [element.kind.displayName, element.displayName]); |
| 15731 } |
| 15732 super.visitMethodElement(element); |
| 15733 } |
| 15734 |
| 15735 bool _isUsedElement(Element element) { |
| 15691 if (element is! LocalVariableElement) { | 15736 if (element is! LocalVariableElement) { |
| 15692 if (element.isPublic) { | 15737 if (element.isPublic) { |
| 15693 return true; | 15738 return true; |
| 15694 } | 15739 } |
| 15695 } | 15740 } |
| 15696 return _usedElements.contains(element); | 15741 return _usedElements.elements.contains(element); |
| 15742 } |
| 15743 |
| 15744 bool _isUsedMember(Element element) { |
| 15745 if (element.isPublic) { |
| 15746 return true; |
| 15747 } |
| 15748 if (_usedElements.members.contains(element.displayName)) { |
| 15749 return true; |
| 15750 } |
| 15751 return _usedElements.elements.contains(element); |
| 15697 } | 15752 } |
| 15698 | 15753 |
| 15699 void _reportErrorForElement(ErrorCode errorCode, Element element, List<Object>
arguments) { | 15754 void _reportErrorForElement(ErrorCode errorCode, Element element, List<Object>
arguments) { |
| 15700 if (element != null) { | 15755 if (element != null) { |
| 15701 _errorListener.onError( | 15756 _errorListener.onError( |
| 15702 new AnalysisError.con2( | 15757 new AnalysisError.con2( |
| 15703 element.source, | 15758 element.source, |
| 15704 element.nameOffset, | 15759 element.nameOffset, |
| 15705 element.displayName.length, | 15760 element.displayName.length, |
| 15706 errorCode, | 15761 errorCode, |
| 15707 arguments)); | 15762 arguments)); |
| 15708 } | 15763 } |
| 15709 } | 15764 } |
| 15710 } | 15765 } |
| OLD | NEW |