| 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/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 if (!_typeSystem.isAssignableTo(bestRightType, leftType)) { | 603 if (!_typeSystem.isAssignableTo(bestRightType, leftType)) { |
| 604 _errorReporter.reportTypeErrorForNode( | 604 _errorReporter.reportTypeErrorForNode( |
| 605 HintCode.INVALID_ASSIGNMENT, rhs, [bestRightType, leftType]); | 605 HintCode.INVALID_ASSIGNMENT, rhs, [bestRightType, leftType]); |
| 606 return true; | 606 return true; |
| 607 } | 607 } |
| 608 } | 608 } |
| 609 return false; | 609 return false; |
| 610 } | 610 } |
| 611 | 611 |
| 612 /** | 612 /** |
| 613 * Produces a hint if the given identifier is a protected field or getter | |
| 614 * accessed outside a subclass. | |
| 615 */ | |
| 616 void _checkForInvalidProtectedPropertyAccess(SimpleIdentifier identifier) { | |
| 617 if (identifier.inDeclarationContext()) { | |
| 618 return; | |
| 619 } | |
| 620 Element element = identifier.bestElement; | |
| 621 if (element is PropertyAccessorElement && | |
| 622 (element.isProtected || element.variable.isProtected)) { | |
| 623 ClassElement definingClass = element.enclosingElement; | |
| 624 if (definingClass == null) { | |
| 625 return; | |
| 626 } | |
| 627 ClassDeclaration accessingClass = | |
| 628 identifier.getAncestor((AstNode node) => node is ClassDeclaration); | |
| 629 | |
| 630 if (accessingClass == null) { | |
| 631 _errorReporter.reportErrorForNode( | |
| 632 HintCode.INVALID_USE_OF_PROTECTED_MEMBER, | |
| 633 identifier, | |
| 634 [identifier.name.toString(), definingClass.name]); | |
| 635 } else if (!_hasSuperClassOrMixin( | |
| 636 accessingClass.element, definingClass.type)) { | |
| 637 _errorReporter.reportErrorForNode( | |
| 638 HintCode.INVALID_USE_OF_PROTECTED_MEMBER, | |
| 639 identifier, | |
| 640 [identifier.name.toString(), definingClass.name]); | |
| 641 } | |
| 642 } | |
| 643 } | |
| 644 | |
| 645 /** | |
| 646 * Produces a hint if the given invocation is of a protected method outside | 613 * Produces a hint if the given invocation is of a protected method outside |
| 647 * a subclass instance method. | 614 * a subclass instance method. |
| 648 */ | 615 */ |
| 649 void _checkForInvalidProtectedMethodCalls(MethodInvocation node) { | 616 void _checkForInvalidProtectedMethodCalls(MethodInvocation node) { |
| 650 Element element = node.methodName.bestElement; | 617 Element element = node.methodName.bestElement; |
| 651 if (element == null || !element.isProtected) { | 618 if (element == null || !element.isProtected) { |
| 652 return; | 619 return; |
| 653 } | 620 } |
| 654 | 621 |
| 655 ClassElement definingClass = element.enclosingElement; | 622 ClassElement definingClass = element.enclosingElement; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 669 if (!_hasSuperClassOrMixin(invokingClass, definingClass.type)) { | 636 if (!_hasSuperClassOrMixin(invokingClass, definingClass.type)) { |
| 670 _errorReporter.reportErrorForNode( | 637 _errorReporter.reportErrorForNode( |
| 671 HintCode.INVALID_USE_OF_PROTECTED_MEMBER, | 638 HintCode.INVALID_USE_OF_PROTECTED_MEMBER, |
| 672 node, | 639 node, |
| 673 [node.methodName.toString(), definingClass.name]); | 640 [node.methodName.toString(), definingClass.name]); |
| 674 } | 641 } |
| 675 } | 642 } |
| 676 } | 643 } |
| 677 | 644 |
| 678 /** | 645 /** |
| 646 * Produces a hint if the given identifier is a protected field or getter |
| 647 * accessed outside a subclass. |
| 648 */ |
| 649 void _checkForInvalidProtectedPropertyAccess(SimpleIdentifier identifier) { |
| 650 if (identifier.inDeclarationContext()) { |
| 651 return; |
| 652 } |
| 653 Element element = identifier.bestElement; |
| 654 if (element is PropertyAccessorElement && |
| 655 (element.isProtected || element.variable.isProtected)) { |
| 656 ClassElement definingClass = element.enclosingElement; |
| 657 if (definingClass == null) { |
| 658 return; |
| 659 } |
| 660 ClassDeclaration accessingClass = |
| 661 identifier.getAncestor((AstNode node) => node is ClassDeclaration); |
| 662 |
| 663 if (accessingClass == null) { |
| 664 _errorReporter.reportErrorForNode( |
| 665 HintCode.INVALID_USE_OF_PROTECTED_MEMBER, |
| 666 identifier, |
| 667 [identifier.name.toString(), definingClass.name]); |
| 668 } else if (!_hasSuperClassOrMixin( |
| 669 accessingClass.element, definingClass.type)) { |
| 670 _errorReporter.reportErrorForNode( |
| 671 HintCode.INVALID_USE_OF_PROTECTED_MEMBER, |
| 672 identifier, |
| 673 [identifier.name.toString(), definingClass.name]); |
| 674 } |
| 675 } |
| 676 } |
| 677 |
| 678 /** |
| 679 * Check that the imported library does not define a loadLibrary function. The
import has already | 679 * Check that the imported library does not define a loadLibrary function. The
import has already |
| 680 * been determined to be deferred when this is called. | 680 * been determined to be deferred when this is called. |
| 681 * | 681 * |
| 682 * @param node the import directive to evaluate | 682 * @param node the import directive to evaluate |
| 683 * @param importElement the [ImportElement] retrieved from the node | 683 * @param importElement the [ImportElement] retrieved from the node |
| 684 * @return `true` if and only if an error code is generated on the passed node | 684 * @return `true` if and only if an error code is generated on the passed node |
| 685 * See [CompileTimeErrorCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION]. | 685 * See [CompileTimeErrorCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION]. |
| 686 */ | 686 */ |
| 687 bool _checkForLoadLibraryFunction( | 687 bool _checkForLoadLibraryFunction( |
| 688 ImportDirective node, ImportElement importElement) { | 688 ImportDirective node, ImportElement importElement) { |
| (...skipping 1428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2117 } | 2117 } |
| 2118 } | 2118 } |
| 2119 } | 2119 } |
| 2120 | 2120 |
| 2121 /** | 2121 /** |
| 2122 * A visitor that resolves declarations in an AST structure to already built | 2122 * A visitor that resolves declarations in an AST structure to already built |
| 2123 * elements. | 2123 * elements. |
| 2124 */ | 2124 */ |
| 2125 class DeclarationResolver extends RecursiveAstVisitor<Object> { | 2125 class DeclarationResolver extends RecursiveAstVisitor<Object> { |
| 2126 /** | 2126 /** |
| 2127 * The analysis context containing the sources to be analyzed. |
| 2128 */ |
| 2129 AnalysisContext _context; |
| 2130 |
| 2131 /** |
| 2127 * The elements that are reachable from the compilation unit element. When a | 2132 * The elements that are reachable from the compilation unit element. When a |
| 2128 * compilation unit has been resolved, this set should be empty. | 2133 * compilation unit has been resolved, this set should be empty. |
| 2129 */ | 2134 */ |
| 2130 Set<Element> _expectedElements; | 2135 Set<Element> _expectedElements; |
| 2131 | 2136 |
| 2132 /** | 2137 /** |
| 2133 * The compilation unit containing the AST nodes being visited. | 2138 * The compilation unit containing the AST nodes being visited. |
| 2134 */ | 2139 */ |
| 2135 CompilationUnitElement _enclosingUnit; | 2140 CompilationUnitElement _enclosingUnit; |
| 2136 | 2141 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2157 * not in the scope of a parameter. | 2162 * not in the scope of a parameter. |
| 2158 */ | 2163 */ |
| 2159 ParameterElement _enclosingParameter; | 2164 ParameterElement _enclosingParameter; |
| 2160 | 2165 |
| 2161 /** | 2166 /** |
| 2162 * Resolve the declarations within the given compilation [unit] to the | 2167 * Resolve the declarations within the given compilation [unit] to the |
| 2163 * elements rooted at the given [element]. Throw an [ElementMismatchException] | 2168 * elements rooted at the given [element]. Throw an [ElementMismatchException] |
| 2164 * if the element model and compilation unit do not match each other. | 2169 * if the element model and compilation unit do not match each other. |
| 2165 */ | 2170 */ |
| 2166 void resolve(CompilationUnit unit, CompilationUnitElement element) { | 2171 void resolve(CompilationUnit unit, CompilationUnitElement element) { |
| 2172 _context = element.context; |
| 2167 ElementGatherer gatherer = new ElementGatherer(); | 2173 ElementGatherer gatherer = new ElementGatherer(); |
| 2168 element.accept(gatherer); | 2174 element.accept(gatherer); |
| 2169 _expectedElements = gatherer.elements; | 2175 _expectedElements = gatherer.elements; |
| 2170 _enclosingUnit = element; | 2176 _enclosingUnit = element; |
| 2171 _expectedElements.remove(element); | 2177 _expectedElements.remove(element); |
| 2172 unit.element = element; | 2178 unit.element = element; |
| 2173 unit.accept(this); | 2179 unit.accept(this); |
| 2174 _validateResolution(); | 2180 _validateResolution(); |
| 2175 } | 2181 } |
| 2176 | 2182 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2294 _resolveMetadata(node.metadata, enclosingEnum); | 2300 _resolveMetadata(node.metadata, enclosingEnum); |
| 2295 return null; | 2301 return null; |
| 2296 } | 2302 } |
| 2297 | 2303 |
| 2298 @override | 2304 @override |
| 2299 Object visitExportDirective(ExportDirective node) { | 2305 Object visitExportDirective(ExportDirective node) { |
| 2300 String uri = _getStringValue(node.uri); | 2306 String uri = _getStringValue(node.uri); |
| 2301 ExportElement exportElement; | 2307 ExportElement exportElement; |
| 2302 if (uri != null) { | 2308 if (uri != null) { |
| 2303 LibraryElement library = _enclosingUnit.library; | 2309 LibraryElement library = _enclosingUnit.library; |
| 2304 exportElement = _findExport( | 2310 Source source = _enclosingUnit.context.sourceFactory |
| 2305 node, | 2311 .resolveUri(_enclosingUnit.source, uri); |
| 2306 library.exports, | 2312 exportElement = _findExport(node, library.exports, source); |
| 2307 _enclosingUnit.context.sourceFactory | |
| 2308 .resolveUri(_enclosingUnit.source, uri)); | |
| 2309 node.element = exportElement; | 2313 node.element = exportElement; |
| 2310 } | 2314 } |
| 2311 super.visitExportDirective(node); | 2315 super.visitExportDirective(node); |
| 2312 _resolveMetadata(node.metadata, exportElement); | 2316 _resolveMetadata(node.metadata, exportElement); |
| 2313 return null; | 2317 return null; |
| 2314 } | 2318 } |
| 2315 | 2319 |
| 2316 @override | 2320 @override |
| 2317 Object visitFieldDeclaration(FieldDeclaration node) { | 2321 Object visitFieldDeclaration(FieldDeclaration node) { |
| 2318 super.visitFieldDeclaration(node); | 2322 super.visitFieldDeclaration(node); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2435 return super.visitFunctionTypedFormalParameter(node); | 2439 return super.visitFunctionTypedFormalParameter(node); |
| 2436 } | 2440 } |
| 2437 } | 2441 } |
| 2438 | 2442 |
| 2439 @override | 2443 @override |
| 2440 Object visitImportDirective(ImportDirective node) { | 2444 Object visitImportDirective(ImportDirective node) { |
| 2441 String uri = _getStringValue(node.uri); | 2445 String uri = _getStringValue(node.uri); |
| 2442 ImportElement importElement; | 2446 ImportElement importElement; |
| 2443 if (uri != null) { | 2447 if (uri != null) { |
| 2444 LibraryElement library = _enclosingUnit.library; | 2448 LibraryElement library = _enclosingUnit.library; |
| 2445 importElement = _findImport( | 2449 Source source = _enclosingUnit.context.sourceFactory |
| 2446 node, | 2450 .resolveUri(_enclosingUnit.source, uri); |
| 2447 library.imports, | 2451 importElement = _findImport(node, library.imports, source); |
| 2448 _enclosingUnit.context.sourceFactory | |
| 2449 .resolveUri(_enclosingUnit.source, uri)); | |
| 2450 node.element = importElement; | 2452 node.element = importElement; |
| 2451 } | 2453 } |
| 2452 super.visitImportDirective(node); | 2454 super.visitImportDirective(node); |
| 2453 _resolveMetadata(node.metadata, importElement); | 2455 _resolveMetadata(node.metadata, importElement); |
| 2454 return null; | 2456 return null; |
| 2455 } | 2457 } |
| 2456 | 2458 |
| 2457 @override | 2459 @override |
| 2458 Object visitLabeledStatement(LabeledStatement node) { | 2460 Object visitLabeledStatement(LabeledStatement node) { |
| 2459 for (Label label in node.labels) { | 2461 for (Label label in node.labels) { |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2650 Element _findAtOffset(List<Element> elements, AstNode node, int offset) => | 2652 Element _findAtOffset(List<Element> elements, AstNode node, int offset) => |
| 2651 _findWithNameAndOffset(elements, node, '', offset); | 2653 _findWithNameAndOffset(elements, node, '', offset); |
| 2652 | 2654 |
| 2653 /** | 2655 /** |
| 2654 * Return the export element from the given list of [exports] whose library | 2656 * Return the export element from the given list of [exports] whose library |
| 2655 * has the given [source]. Throw an [ElementMismatchException] if an element | 2657 * has the given [source]. Throw an [ElementMismatchException] if an element |
| 2656 * corresponding to the identifier cannot be found. | 2658 * corresponding to the identifier cannot be found. |
| 2657 */ | 2659 */ |
| 2658 ExportElement _findExport( | 2660 ExportElement _findExport( |
| 2659 ExportDirective node, List<ExportElement> exports, Source source) { | 2661 ExportDirective node, List<ExportElement> exports, Source source) { |
| 2662 if (source == null || !_context.exists(source)) { |
| 2663 return null; |
| 2664 } |
| 2660 for (ExportElement export in exports) { | 2665 for (ExportElement export in exports) { |
| 2661 if (export.exportedLibrary.source == source) { | 2666 if (export.exportedLibrary.source == source) { |
| 2662 return export; | 2667 return export; |
| 2663 } | 2668 } |
| 2664 } | 2669 } |
| 2665 _mismatch("Could not find export element for '$source'", node); | 2670 _mismatch("Could not find export element for '$source'", node); |
| 2666 return null; // Never reached | 2671 return null; // Never reached |
| 2667 } | 2672 } |
| 2668 | 2673 |
| 2669 /** | 2674 /** |
| 2670 * Return the element in the given list of [elements] that was created for the | 2675 * Return the element in the given list of [elements] that was created for the |
| 2671 * declaration with the given [identifier]. As a side-effect, associate the | 2676 * declaration with the given [identifier]. As a side-effect, associate the |
| 2672 * returned element with the identifier. Throw an [ElementMismatchException] | 2677 * returned element with the identifier. Throw an [ElementMismatchException] |
| 2673 * if an element corresponding to the identifier cannot be found unless | 2678 * if an element corresponding to the identifier cannot be found unless |
| 2674 * [required] is `false`, in which case return `null`. | 2679 * [required] is `false`, in which case return `null`. |
| 2675 */ | 2680 */ |
| 2676 Element _findIdentifier(List<Element> elements, SimpleIdentifier identifier, | 2681 Element _findIdentifier(List<Element> elements, SimpleIdentifier identifier, |
| 2677 {bool required: true}) { | 2682 {bool required: true}) { |
| 2678 Element element = _findWithNameAndOffset( | 2683 Element element = _findWithNameAndOffset( |
| 2679 elements, identifier, identifier.name, identifier.offset, | 2684 elements, identifier, identifier.name, identifier.offset, |
| 2680 required: required); | 2685 required: required); |
| 2681 _expectedElements.remove(element); | 2686 _expectedElements.remove(element); |
| 2682 identifier.staticElement = element; | 2687 identifier.staticElement = element; |
| 2683 return element; | 2688 return element; |
| 2684 } | 2689 } |
| 2685 | 2690 |
| 2686 /** | 2691 /** |
| 2687 * Return the import element from the given list of [imports] whose library | 2692 * Return the import element from the given list of [imports] whose library |
| 2688 * has the given [source] and that has the given [prefix]. Throw an | 2693 * has the given [source]. Throw an [ElementMismatchException] if an element |
| 2689 * [ElementMismatchException] if an element corresponding to the identifier | 2694 * corresponding to the [source] cannot be found. |
| 2690 * cannot be found. | |
| 2691 */ | 2695 */ |
| 2692 ImportElement _findImport( | 2696 ImportElement _findImport( |
| 2693 ImportDirective node, List<ImportElement> imports, Source source) { | 2697 ImportDirective node, List<ImportElement> imports, Source source) { |
| 2698 if (source == null || !_context.exists(source)) { |
| 2699 return null; |
| 2700 } |
| 2694 SimpleIdentifier prefix = node.prefix; | 2701 SimpleIdentifier prefix = node.prefix; |
| 2695 bool foundSource = false; | 2702 bool foundSource = false; |
| 2696 for (ImportElement element in imports) { | 2703 for (ImportElement element in imports) { |
| 2697 if (element.importedLibrary.source == source) { | 2704 if (element.importedLibrary.source == source) { |
| 2698 foundSource = true; | 2705 foundSource = true; |
| 2699 PrefixElement prefixElement = element.prefix; | 2706 PrefixElement prefixElement = element.prefix; |
| 2700 if (prefix == null) { | 2707 if (prefix == null) { |
| 2701 if (prefixElement == null) { | 2708 if (prefixElement == null) { |
| 2702 return element; | 2709 return element; |
| 2703 } | 2710 } |
| (...skipping 10276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12980 nonFields.add(node); | 12987 nonFields.add(node); |
| 12981 return null; | 12988 return null; |
| 12982 } | 12989 } |
| 12983 | 12990 |
| 12984 @override | 12991 @override |
| 12985 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 12992 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 12986 | 12993 |
| 12987 @override | 12994 @override |
| 12988 Object visitWithClause(WithClause node) => null; | 12995 Object visitWithClause(WithClause node) => null; |
| 12989 } | 12996 } |
| OLD | NEW |