| 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 analyzer.src.generated.resolver; | 5 library analyzer.src.generated.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/visitor.dart'; | 10 import 'package:analyzer/dart/ast/visitor.dart'; |
| 11 import 'package:analyzer/dart/element/element.dart'; | 11 import 'package:analyzer/dart/element/element.dart'; |
| 12 import 'package:analyzer/dart/element/type.dart'; | 12 import 'package:analyzer/dart/element/type.dart'; |
| 13 import 'package:analyzer/dart/element/visitor.dart'; | 13 import 'package:analyzer/dart/element/visitor.dart'; |
| 14 import 'package:analyzer/src/dart/ast/utilities.dart'; | 14 import 'package:analyzer/src/dart/ast/utilities.dart'; |
| 15 import 'package:analyzer/src/dart/element/element.dart'; | 15 import 'package:analyzer/src/dart/element/element.dart'; |
| 16 import 'package:analyzer/src/dart/element/member.dart'; | 16 import 'package:analyzer/src/dart/element/member.dart'; |
| 17 import 'package:analyzer/src/dart/element/type.dart'; | 17 import 'package:analyzer/src/dart/element/type.dart'; |
| 18 import 'package:analyzer/src/dart/element/utilities.dart'; |
| 18 import 'package:analyzer/src/generated/constant.dart'; | 19 import 'package:analyzer/src/generated/constant.dart'; |
| 19 import 'package:analyzer/src/generated/element_resolver.dart'; | 20 import 'package:analyzer/src/generated/element_resolver.dart'; |
| 20 import 'package:analyzer/src/generated/engine.dart'; | 21 import 'package:analyzer/src/generated/engine.dart'; |
| 21 import 'package:analyzer/src/generated/error.dart'; | 22 import 'package:analyzer/src/generated/error.dart'; |
| 22 import 'package:analyzer/src/generated/error_verifier.dart'; | 23 import 'package:analyzer/src/generated/error_verifier.dart'; |
| 23 import 'package:analyzer/src/generated/java_core.dart'; | 24 import 'package:analyzer/src/generated/java_core.dart'; |
| 24 import 'package:analyzer/src/generated/java_engine.dart'; | 25 import 'package:analyzer/src/generated/java_engine.dart'; |
| 25 import 'package:analyzer/src/generated/scanner.dart'; | 26 import 'package:analyzer/src/generated/scanner.dart'; |
| 26 import 'package:analyzer/src/generated/source.dart'; | 27 import 'package:analyzer/src/generated/source.dart'; |
| 27 import 'package:analyzer/src/generated/static_type_analyzer.dart'; | 28 import 'package:analyzer/src/generated/static_type_analyzer.dart'; |
| (...skipping 2000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2028 } | 2029 } |
| 2029 } | 2030 } |
| 2030 } | 2031 } |
| 2031 | 2032 |
| 2032 /** | 2033 /** |
| 2033 * A visitor that resolves declarations in an AST structure to already built | 2034 * A visitor that resolves declarations in an AST structure to already built |
| 2034 * elements. | 2035 * elements. |
| 2035 */ | 2036 */ |
| 2036 class DeclarationResolver extends RecursiveAstVisitor<Object> { | 2037 class DeclarationResolver extends RecursiveAstVisitor<Object> { |
| 2037 /** | 2038 /** |
| 2039 * The elements that are reachable from the compilation unit element. When a |
| 2040 * compilation unit has been resolved, this set should be empty. |
| 2041 */ |
| 2042 Set<Element> _expectedElements; |
| 2043 |
| 2044 /** |
| 2038 * The compilation unit containing the AST nodes being visited. | 2045 * The compilation unit containing the AST nodes being visited. |
| 2039 */ | 2046 */ |
| 2040 CompilationUnitElement _enclosingUnit; | 2047 CompilationUnitElement _enclosingUnit; |
| 2041 | 2048 |
| 2042 /** | 2049 /** |
| 2043 * The function type alias containing the AST nodes being visited, or `null` | 2050 * The function type alias containing the AST nodes being visited, or `null` |
| 2044 * if we are not in the scope of a function type alias. | 2051 * if we are not in the scope of a function type alias. |
| 2045 */ | 2052 */ |
| 2046 FunctionTypeAliasElement _enclosingAlias; | 2053 FunctionTypeAliasElement _enclosingAlias; |
| 2047 | 2054 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2062 * not in the scope of a parameter. | 2069 * not in the scope of a parameter. |
| 2063 */ | 2070 */ |
| 2064 ParameterElement _enclosingParameter; | 2071 ParameterElement _enclosingParameter; |
| 2065 | 2072 |
| 2066 /** | 2073 /** |
| 2067 * Resolve the declarations within the given compilation [unit] to the | 2074 * Resolve the declarations within the given compilation [unit] to the |
| 2068 * elements rooted at the given [element]. Throw an [ElementMismatchException] | 2075 * elements rooted at the given [element]. Throw an [ElementMismatchException] |
| 2069 * if the element model and compilation unit do not match each other. | 2076 * if the element model and compilation unit do not match each other. |
| 2070 */ | 2077 */ |
| 2071 void resolve(CompilationUnit unit, CompilationUnitElement element) { | 2078 void resolve(CompilationUnit unit, CompilationUnitElement element) { |
| 2079 ElementGatherer gatherer = new ElementGatherer(); |
| 2080 element.accept(gatherer); |
| 2081 _expectedElements = gatherer.elements; |
| 2072 _enclosingUnit = element; | 2082 _enclosingUnit = element; |
| 2083 _expectedElements.remove(element); |
| 2073 unit.element = element; | 2084 unit.element = element; |
| 2074 unit.accept(this); | 2085 unit.accept(this); |
| 2086 _validateResolution(); |
| 2075 } | 2087 } |
| 2076 | 2088 |
| 2077 @override | 2089 @override |
| 2078 Object visitCatchClause(CatchClause node) { | 2090 Object visitCatchClause(CatchClause node) { |
| 2079 SimpleIdentifier exceptionParameter = node.exceptionParameter; | 2091 SimpleIdentifier exceptionParameter = node.exceptionParameter; |
| 2080 if (exceptionParameter != null) { | 2092 if (exceptionParameter != null) { |
| 2081 List<LocalVariableElement> localVariables = | 2093 List<LocalVariableElement> localVariables = |
| 2082 _enclosingExecutable.localVariables; | 2094 _enclosingExecutable.localVariables; |
| 2083 _findIdentifier(localVariables, exceptionParameter); | 2095 _findIdentifier(localVariables, exceptionParameter); |
| 2084 SimpleIdentifier stackTraceParameter = node.stackTraceParameter; | 2096 SimpleIdentifier stackTraceParameter = node.stackTraceParameter; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2130 } else { | 2142 } else { |
| 2131 _enclosingExecutable = | 2143 _enclosingExecutable = |
| 2132 _enclosingClass.getNamedConstructor(constructorName.name); | 2144 _enclosingClass.getNamedConstructor(constructorName.name); |
| 2133 if (_enclosingExecutable == null) { | 2145 if (_enclosingExecutable == null) { |
| 2134 _mismatch( | 2146 _mismatch( |
| 2135 'Could not find constructor element with name "${constructorName.n
ame}', | 2147 'Could not find constructor element with name "${constructorName.n
ame}', |
| 2136 node); | 2148 node); |
| 2137 } | 2149 } |
| 2138 constructorName.staticElement = _enclosingExecutable; | 2150 constructorName.staticElement = _enclosingExecutable; |
| 2139 } | 2151 } |
| 2152 _expectedElements.remove(_enclosingExecutable); |
| 2140 node.element = _enclosingExecutable as ConstructorElement; | 2153 node.element = _enclosingExecutable as ConstructorElement; |
| 2141 super.visitConstructorDeclaration(node); | 2154 super.visitConstructorDeclaration(node); |
| 2142 _resolveMetadata(node.metadata, _enclosingExecutable); | 2155 _resolveMetadata(node.metadata, _enclosingExecutable); |
| 2143 return null; | 2156 return null; |
| 2144 } finally { | 2157 } finally { |
| 2145 _enclosingExecutable = outerExecutable; | 2158 _enclosingExecutable = outerExecutable; |
| 2146 } | 2159 } |
| 2147 } | 2160 } |
| 2148 | 2161 |
| 2149 @override | 2162 @override |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2262 accessors = _enclosingClass.accessors; | 2275 accessors = _enclosingClass.accessors; |
| 2263 } else { | 2276 } else { |
| 2264 accessors = _enclosingUnit.accessors; | 2277 accessors = _enclosingUnit.accessors; |
| 2265 } | 2278 } |
| 2266 PropertyAccessorElement accessor; | 2279 PropertyAccessorElement accessor; |
| 2267 if ((property as KeywordToken).keyword == Keyword.GET) { | 2280 if ((property as KeywordToken).keyword == Keyword.GET) { |
| 2268 accessor = _findIdentifier(accessors, functionName); | 2281 accessor = _findIdentifier(accessors, functionName); |
| 2269 } else if ((property as KeywordToken).keyword == Keyword.SET) { | 2282 } else if ((property as KeywordToken).keyword == Keyword.SET) { |
| 2270 accessor = _findWithNameAndOffset(accessors, functionName, | 2283 accessor = _findWithNameAndOffset(accessors, functionName, |
| 2271 functionName.name + '=', functionName.offset); | 2284 functionName.name + '=', functionName.offset); |
| 2285 _expectedElements.remove(accessor); |
| 2272 functionName.staticElement = accessor; | 2286 functionName.staticElement = accessor; |
| 2273 } | 2287 } |
| 2274 _enclosingExecutable = accessor; | 2288 _enclosingExecutable = accessor; |
| 2275 } | 2289 } |
| 2276 } | 2290 } |
| 2277 node.functionExpression.element = _enclosingExecutable; | 2291 node.functionExpression.element = _enclosingExecutable; |
| 2278 super.visitFunctionDeclaration(node); | 2292 super.visitFunctionDeclaration(node); |
| 2279 _resolveMetadata(node.metadata, _enclosingExecutable); | 2293 _resolveMetadata(node.metadata, _enclosingExecutable); |
| 2280 return null; | 2294 return null; |
| 2281 } finally { | 2295 } finally { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2372 @override | 2386 @override |
| 2373 Object visitMethodDeclaration(MethodDeclaration node) { | 2387 Object visitMethodDeclaration(MethodDeclaration node) { |
| 2374 ExecutableElement outerExecutable = _enclosingExecutable; | 2388 ExecutableElement outerExecutable = _enclosingExecutable; |
| 2375 try { | 2389 try { |
| 2376 Token property = node.propertyKeyword; | 2390 Token property = node.propertyKeyword; |
| 2377 SimpleIdentifier methodName = node.name; | 2391 SimpleIdentifier methodName = node.name; |
| 2378 String nameOfMethod = methodName.name; | 2392 String nameOfMethod = methodName.name; |
| 2379 if (property == null) { | 2393 if (property == null) { |
| 2380 _enclosingExecutable = _findWithNameAndOffset(_enclosingClass.methods, | 2394 _enclosingExecutable = _findWithNameAndOffset(_enclosingClass.methods, |
| 2381 methodName, nameOfMethod, methodName.offset); | 2395 methodName, nameOfMethod, methodName.offset); |
| 2396 _expectedElements.remove(_enclosingExecutable); |
| 2382 methodName.staticElement = _enclosingExecutable; | 2397 methodName.staticElement = _enclosingExecutable; |
| 2383 } else { | 2398 } else { |
| 2384 PropertyAccessorElement accessor; | 2399 PropertyAccessorElement accessor; |
| 2385 if ((property as KeywordToken).keyword == Keyword.GET) { | 2400 if ((property as KeywordToken).keyword == Keyword.GET) { |
| 2386 accessor = _findIdentifier(_enclosingClass.accessors, methodName); | 2401 accessor = _findIdentifier(_enclosingClass.accessors, methodName); |
| 2387 } else if ((property as KeywordToken).keyword == Keyword.SET) { | 2402 } else if ((property as KeywordToken).keyword == Keyword.SET) { |
| 2388 accessor = _findWithNameAndOffset(_enclosingClass.accessors, | 2403 accessor = _findWithNameAndOffset(_enclosingClass.accessors, |
| 2389 methodName, methodName.name + '=', methodName.offset); | 2404 methodName, methodName.name + '=', methodName.offset); |
| 2405 _expectedElements.remove(accessor); |
| 2390 methodName.staticElement = accessor; | 2406 methodName.staticElement = accessor; |
| 2391 } | 2407 } |
| 2392 _enclosingExecutable = accessor; | 2408 _enclosingExecutable = accessor; |
| 2393 } | 2409 } |
| 2394 super.visitMethodDeclaration(node); | 2410 super.visitMethodDeclaration(node); |
| 2395 _resolveMetadata(node.metadata, _enclosingExecutable); | 2411 _resolveMetadata(node.metadata, _enclosingExecutable); |
| 2396 return null; | 2412 return null; |
| 2397 } finally { | 2413 } finally { |
| 2398 _enclosingExecutable = outerExecutable; | 2414 _enclosingExecutable = outerExecutable; |
| 2399 } | 2415 } |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2557 * declaration with the given [identifier]. As a side-effect, associate the | 2573 * declaration with the given [identifier]. As a side-effect, associate the |
| 2558 * returned element with the identifier. Throw an [ElementMismatchException] | 2574 * returned element with the identifier. Throw an [ElementMismatchException] |
| 2559 * if an element corresponding to the identifier cannot be found unless | 2575 * if an element corresponding to the identifier cannot be found unless |
| 2560 * [required] is `false`, in which case return `null`. | 2576 * [required] is `false`, in which case return `null`. |
| 2561 */ | 2577 */ |
| 2562 Element _findIdentifier(List<Element> elements, SimpleIdentifier identifier, | 2578 Element _findIdentifier(List<Element> elements, SimpleIdentifier identifier, |
| 2563 {bool required: true}) { | 2579 {bool required: true}) { |
| 2564 Element element = _findWithNameAndOffset( | 2580 Element element = _findWithNameAndOffset( |
| 2565 elements, identifier, identifier.name, identifier.offset, | 2581 elements, identifier, identifier.name, identifier.offset, |
| 2566 required: required); | 2582 required: required); |
| 2583 _expectedElements.remove(element); |
| 2567 identifier.staticElement = element; | 2584 identifier.staticElement = element; |
| 2568 return element; | 2585 return element; |
| 2569 } | 2586 } |
| 2570 | 2587 |
| 2571 /** | 2588 /** |
| 2572 * Return the import element from the given list of [imports] whose library | 2589 * Return the import element from the given list of [imports] whose library |
| 2573 * has the given [source] and that has the given [prefix]. Throw an | 2590 * has the given [source] and that has the given [prefix]. Throw an |
| 2574 * [ElementMismatchException] if an element corresponding to the identifier | 2591 * [ElementMismatchException] if an element corresponding to the identifier |
| 2575 * cannot be found. | 2592 * cannot be found. |
| 2576 */ | 2593 */ |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2731 */ | 2748 */ |
| 2732 void _resolveMetadata(NodeList<Annotation> astMetadata, Element element) { | 2749 void _resolveMetadata(NodeList<Annotation> astMetadata, Element element) { |
| 2733 if (element != null) { | 2750 if (element != null) { |
| 2734 List<ElementAnnotation> elementMetadata = element.metadata; | 2751 List<ElementAnnotation> elementMetadata = element.metadata; |
| 2735 assert(astMetadata.length == elementMetadata.length); | 2752 assert(astMetadata.length == elementMetadata.length); |
| 2736 for (int i = 0; i < astMetadata.length; i++) { | 2753 for (int i = 0; i < astMetadata.length; i++) { |
| 2737 astMetadata[i].elementAnnotation = elementMetadata[i]; | 2754 astMetadata[i].elementAnnotation = elementMetadata[i]; |
| 2738 } | 2755 } |
| 2739 } | 2756 } |
| 2740 } | 2757 } |
| 2758 |
| 2759 /** |
| 2760 * Throw an exception if there are non-synthetic elements in the element model |
| 2761 * that were not associated with an AST node. |
| 2762 */ |
| 2763 void _validateResolution() { |
| 2764 if (_expectedElements.isNotEmpty) { |
| 2765 StringBuffer buffer = new StringBuffer(); |
| 2766 buffer.write(_expectedElements.length); |
| 2767 buffer.writeln(' unmatched elements found:'); |
| 2768 for (Element element in _expectedElements) { |
| 2769 buffer.write(' '); |
| 2770 buffer.writeln(element); |
| 2771 } |
| 2772 throw new ElementMismatchException(buffer.toString()); |
| 2773 } |
| 2774 } |
| 2741 } | 2775 } |
| 2742 | 2776 |
| 2743 /** | 2777 /** |
| 2744 * Instances of the class `ElementHolder` hold on to elements created while trav
ersing an AST | 2778 * Instances of the class `ElementHolder` hold on to elements created while trav
ersing an AST |
| 2745 * structure so that they can be accessed when creating their enclosing element. | 2779 * structure so that they can be accessed when creating their enclosing element. |
| 2746 */ | 2780 */ |
| 2747 class ElementHolder { | 2781 class ElementHolder { |
| 2748 List<PropertyAccessorElement> _accessors; | 2782 List<PropertyAccessorElement> _accessors; |
| 2749 | 2783 |
| 2750 List<ConstructorElement> _constructors; | 2784 List<ConstructorElement> _constructors; |
| (...skipping 9895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12646 nonFields.add(node); | 12680 nonFields.add(node); |
| 12647 return null; | 12681 return null; |
| 12648 } | 12682 } |
| 12649 | 12683 |
| 12650 @override | 12684 @override |
| 12651 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 12685 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 12652 | 12686 |
| 12653 @override | 12687 @override |
| 12654 Object visitWithClause(WithClause node) => null; | 12688 Object visitWithClause(WithClause node) => null; |
| 12655 } | 12689 } |
| OLD | NEW |