| 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.incremental_resolver; | 5 library engine.incremental_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 'ast.dart'; | 10 import 'ast.dart'; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 @override | 153 @override |
| 154 visitCompilationUnit(CompilationUnit node) { | 154 visitCompilationUnit(CompilationUnit node) { |
| 155 _processElement(_enclosingUnit); | 155 _processElement(_enclosingUnit); |
| 156 super.visitCompilationUnit(node); | 156 super.visitCompilationUnit(node); |
| 157 } | 157 } |
| 158 | 158 |
| 159 @override | 159 @override |
| 160 visitConstructorDeclaration(ConstructorDeclaration node) { | 160 visitConstructorDeclaration(ConstructorDeclaration node) { |
| 161 _hasConstructor = true; | 161 _hasConstructor = true; |
| 162 SimpleIdentifier constructorName = node.name; | 162 SimpleIdentifier constructorName = node.name; |
| 163 ConstructorElement element = constructorName == null ? | 163 ConstructorElementImpl element = constructorName == null ? |
| 164 _enclosingClass.unnamedConstructor : | 164 _enclosingClass.unnamedConstructor : |
| 165 _enclosingClass.getNamedConstructor(constructorName.name); | 165 _enclosingClass.getNamedConstructor(constructorName.name); |
| 166 _processElement(element); | 166 _processElement(element); |
| 167 _assertCompatibleParameters(node.parameters, element.parameters); |
| 168 // matches, update the existing element |
| 169 ExecutableElement newElement = node.element; |
| 167 node.element = element; | 170 node.element = element; |
| 168 _assertCompatibleParameters(node.parameters, element.parameters); | 171 _setLocalElements(element, newElement); |
| 172 _setParameterElements(node.parameters, element.parameters); |
| 169 } | 173 } |
| 170 | 174 |
| 171 @override | 175 @override |
| 172 visitEnumConstantDeclaration(EnumConstantDeclaration node) { | 176 visitEnumConstantDeclaration(EnumConstantDeclaration node) { |
| 173 String name = node.name.name; | 177 String name = node.name.name; |
| 174 FieldElement element = _findElement(_enclosingClass.fields, name); | 178 FieldElement element = _findElement(_enclosingClass.fields, name); |
| 175 _processElement(element); | 179 _processElement(element); |
| 176 } | 180 } |
| 177 | 181 |
| 178 @override | 182 @override |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 | 222 |
| 219 @override | 223 @override |
| 220 visitFunctionDeclaration(FunctionDeclaration node) { | 224 visitFunctionDeclaration(FunctionDeclaration node) { |
| 221 // prepare element name | 225 // prepare element name |
| 222 String name = node.name.name; | 226 String name = node.name.name; |
| 223 if (node.isSetter) { | 227 if (node.isSetter) { |
| 224 name += '='; | 228 name += '='; |
| 225 } | 229 } |
| 226 // prepare element | 230 // prepare element |
| 227 Token property = node.propertyKeyword; | 231 Token property = node.propertyKeyword; |
| 228 ExecutableElement element; | 232 ExecutableElementImpl element; |
| 229 if (property == null) { | 233 if (property == null) { |
| 230 element = _findElement(_enclosingUnit.functions, name); | 234 element = _findElement(_enclosingUnit.functions, name); |
| 231 } else { | 235 } else { |
| 232 element = _findElement(_enclosingUnit.accessors, name); | 236 element = _findElement(_enclosingUnit.accessors, name); |
| 233 } | 237 } |
| 234 // process element | 238 // process element |
| 235 _processElement(element); | 239 _processElement(element); |
| 236 node.name.staticElement = element; | |
| 237 node.functionExpression.element = element; | |
| 238 _assertFalse(element.isSynthetic); | 240 _assertFalse(element.isSynthetic); |
| 239 _assertSameType(node.returnType, element.returnType); | 241 _assertSameType(node.returnType, element.returnType); |
| 240 _assertCompatibleParameters( | 242 _assertCompatibleParameters( |
| 241 node.functionExpression.parameters, | 243 node.functionExpression.parameters, |
| 242 element.parameters); | 244 element.parameters); |
| 245 // matches, update the existing element |
| 246 ExecutableElement newElement = node.element; |
| 247 node.name.staticElement = element; |
| 248 node.functionExpression.element = element; |
| 249 _setLocalElements(element, newElement); |
| 250 _setParameterElements( |
| 251 node.functionExpression.parameters, |
| 252 element.parameters); |
| 243 } | 253 } |
| 244 | 254 |
| 245 @override | 255 @override |
| 246 visitFunctionTypeAlias(FunctionTypeAlias node) { | 256 visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 247 String name = node.name.name; | 257 String name = node.name.name; |
| 248 FunctionTypeAliasElement element = | 258 FunctionTypeAliasElement element = |
| 249 _findElement(_enclosingUnit.functionTypeAliases, name); | 259 _findElement(_enclosingUnit.functionTypeAliases, name); |
| 250 _processElement(element); | 260 _processElement(element); |
| 251 _assertSameTypeParameters(node.typeParameters, element.typeParameters); | 261 _assertSameTypeParameters(node.typeParameters, element.typeParameters); |
| 252 _assertSameType(node.returnType, element.returnType); | 262 _assertSameType(node.returnType, element.returnType); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 String name = node.name.name; | 297 String name = node.name.name; |
| 288 if (name == TokenType.MINUS.lexeme && | 298 if (name == TokenType.MINUS.lexeme && |
| 289 node.parameters.parameters.length == 0) { | 299 node.parameters.parameters.length == 0) { |
| 290 name = "unary-"; | 300 name = "unary-"; |
| 291 } | 301 } |
| 292 if (node.isSetter) { | 302 if (node.isSetter) { |
| 293 name += '='; | 303 name += '='; |
| 294 } | 304 } |
| 295 // prepare element | 305 // prepare element |
| 296 Token property = node.propertyKeyword; | 306 Token property = node.propertyKeyword; |
| 297 ExecutableElement element; | 307 ExecutableElementImpl element; |
| 298 if (property == null) { | 308 if (property == null) { |
| 299 element = _findElement(_enclosingClass.methods, name); | 309 element = _findElement(_enclosingClass.methods, name); |
| 300 } else { | 310 } else { |
| 301 element = _findElement(_enclosingClass.accessors, name); | 311 element = _findElement(_enclosingClass.accessors, name); |
| 302 } | 312 } |
| 303 // process element | 313 // process element |
| 304 _processElement(element); | 314 _processElement(element); |
| 305 _assertEquals(node.isStatic, element.isStatic); | 315 _assertEquals(node.isStatic, element.isStatic); |
| 306 node.name.staticElement = element; | |
| 307 _assertSameType(node.returnType, element.returnType); | 316 _assertSameType(node.returnType, element.returnType); |
| 308 _assertCompatibleParameters(node.parameters, element.parameters); | 317 _assertCompatibleParameters(node.parameters, element.parameters); |
| 318 // matches, update the existing element |
| 319 ExecutableElement newElement = node.element; |
| 320 node.name.staticElement = element; |
| 321 _setLocalElements(element, newElement); |
| 322 _setParameterElements(node.parameters, element.parameters); |
| 309 } | 323 } |
| 310 | 324 |
| 311 @override | 325 @override |
| 312 visitPartDirective(PartDirective node) { | 326 visitPartDirective(PartDirective node) { |
| 313 String uri = _getStringValue(node.uri); | 327 String uri = _getStringValue(node.uri); |
| 314 if (uri != null) { | 328 if (uri != null) { |
| 315 CompilationUnitElement element = | 329 CompilationUnitElement element = |
| 316 _findUriReferencedElement(_enclosingLibrary.parts, uri); | 330 _findUriReferencedElement(_enclosingLibrary.parts, uri); |
| 317 _processElement(element); | 331 _processElement(element); |
| 318 } | 332 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 343 _assertNotNull(element); | 357 _assertNotNull(element); |
| 344 _processElement(element); | 358 _processElement(element); |
| 345 _assertEquals(node.isConst, element.isConst); | 359 _assertEquals(node.isConst, element.isConst); |
| 346 _assertEquals(node.isFinal, element.isFinal); | 360 _assertEquals(node.isFinal, element.isFinal); |
| 347 if (_enclosingFieldNode != null) { | 361 if (_enclosingFieldNode != null) { |
| 348 _assertEquals(_enclosingFieldNode.isStatic, element.isStatic); | 362 _assertEquals(_enclosingFieldNode.isStatic, element.isStatic); |
| 349 } | 363 } |
| 350 _assertSameType( | 364 _assertSameType( |
| 351 (node.parent as VariableDeclarationList).type, | 365 (node.parent as VariableDeclarationList).type, |
| 352 element.type); | 366 element.type); |
| 367 // matches, restore the existing element |
| 368 node.name.staticElement = element; |
| 353 } | 369 } |
| 354 | 370 |
| 355 @override | 371 @override |
| 356 visitWithClause(WithClause node) { | 372 visitWithClause(WithClause node) { |
| 357 List<TypeName> nodes = node.mixinTypes; | 373 List<TypeName> nodes = node.mixinTypes; |
| 358 List<InterfaceType> types = _enclosingClass.mixins; | 374 List<InterfaceType> types = _enclosingClass.mixins; |
| 359 _assertSameTypes(nodes, types); | 375 _assertSameTypes(nodes, types); |
| 360 } | 376 } |
| 361 | 377 |
| 362 void _assertCombinators(List<Combinator> nodeCombinators, | 378 void _assertCombinators(List<Combinator> nodeCombinators, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 } | 421 } |
| 406 } else if (node is FieldFormalParameter) { | 422 } else if (node is FieldFormalParameter) { |
| 407 _assertTrue(element.isInitializingFormal); | 423 _assertTrue(element.isInitializingFormal); |
| 408 } else if (node is FunctionTypedFormalParameter) { | 424 } else if (node is FunctionTypedFormalParameter) { |
| 409 _assertTrue(element.type is FunctionType); | 425 _assertTrue(element.type is FunctionType); |
| 410 FunctionType elementType = element.type; | 426 FunctionType elementType = element.type; |
| 411 _assertCompatibleParameters(node.parameters, element.parameters); | 427 _assertCompatibleParameters(node.parameters, element.parameters); |
| 412 _assertSameType(node.returnType, elementType.returnType); | 428 _assertSameType(node.returnType, elementType.returnType); |
| 413 } else if (node is SimpleFormalParameter) { | 429 } else if (node is SimpleFormalParameter) { |
| 414 _assertSameType(node.type, element.type); | 430 _assertSameType(node.type, element.type); |
| 415 node.identifier.staticElement = element; | |
| 416 (element as ElementImpl).nameOffset = node.identifier.offset; | |
| 417 (element as ElementImpl).name = node.identifier.name; | |
| 418 } | 431 } |
| 419 } | 432 } |
| 420 | 433 |
| 421 void _assertCompatibleParameters(FormalParameterList nodes, | 434 void _assertCompatibleParameters(FormalParameterList nodes, |
| 422 List<ParameterElement> elements) { | 435 List<ParameterElement> elements) { |
| 423 if (nodes == null) { | 436 if (nodes == null) { |
| 424 return _assertEquals(elements.length, 0); | 437 return _assertEquals(elements.length, 0); |
| 425 } | 438 } |
| 426 List<FormalParameter> parameters = nodes.parameters; | 439 List<FormalParameter> parameters = nodes.parameters; |
| 427 int length = parameters.length; | 440 int length = parameters.length; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 /** | 620 /** |
| 608 * Return the value of [literal], or `null` if the string is not a constant | 621 * Return the value of [literal], or `null` if the string is not a constant |
| 609 * string without any string interpolation. | 622 * string without any string interpolation. |
| 610 */ | 623 */ |
| 611 static String _getStringValue(StringLiteral literal) { | 624 static String _getStringValue(StringLiteral literal) { |
| 612 if (literal is StringInterpolation) { | 625 if (literal is StringInterpolation) { |
| 613 return null; | 626 return null; |
| 614 } | 627 } |
| 615 return literal.stringValue; | 628 return literal.stringValue; |
| 616 } | 629 } |
| 630 |
| 631 static void _setLocalElements(ExecutableElementImpl to, |
| 632 ExecutableElement from) { |
| 633 to.functions = from.functions; |
| 634 to.labels = from.labels; |
| 635 to.localVariables = from.localVariables; |
| 636 } |
| 637 |
| 638 static void _setParameterElements(FormalParameterList nodes, |
| 639 List<ParameterElement> elements) { |
| 640 if (nodes != null) { |
| 641 for (int i = 0; i < elements.length; i++) { |
| 642 ParameterElement element = elements[i]; |
| 643 FormalParameter node = nodes.parameters[i]; |
| 644 ParameterElement newElement = node.element; |
| 645 node.identifier.staticElement = element; |
| 646 (element as ElementImpl).name = newElement.name; |
| 647 (element as ElementImpl).nameOffset = newElement.nameOffset; |
| 648 } |
| 649 } |
| 650 } |
| 617 } | 651 } |
| 618 | 652 |
| 619 | 653 |
| 620 /** | 654 /** |
| 621 * Instances of the class [IncrementalResolver] resolve the smallest portion of | 655 * Instances of the class [IncrementalResolver] resolve the smallest portion of |
| 622 * an AST structure that we currently know how to resolve. | 656 * an AST structure that we currently know how to resolve. |
| 623 */ | 657 */ |
| 624 class IncrementalResolver { | 658 class IncrementalResolver { |
| 625 /** | 659 /** |
| 626 * The object used to access the types from the core library. | 660 * The object used to access the types from the core library. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 650 /** | 684 /** |
| 651 * The number of characters in the original contents that were replaced. | 685 * The number of characters in the original contents that were replaced. |
| 652 */ | 686 */ |
| 653 final int _updateOldLength; | 687 final int _updateOldLength; |
| 654 | 688 |
| 655 /** | 689 /** |
| 656 * The number of characters in the replacement text. | 690 * The number of characters in the replacement text. |
| 657 */ | 691 */ |
| 658 final int _updateNewLength; | 692 final int _updateNewLength; |
| 659 | 693 |
| 694 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 660 ResolutionContext _resolutionContext; | 695 ResolutionContext _resolutionContext; |
| 661 | 696 |
| 662 List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS; | 697 List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS; |
| 663 List<AnalysisError> _verifyErrors = AnalysisError.NO_ERRORS; | 698 List<AnalysisError> _verifyErrors = AnalysisError.NO_ERRORS; |
| 664 List<AnalysisError> _hints = AnalysisError.NO_ERRORS; | 699 List<AnalysisError> _hints = AnalysisError.NO_ERRORS; |
| 665 | 700 |
| 666 /** | 701 /** |
| 667 * Initialize a newly created incremental resolver to resolve a node in the | 702 * Initialize a newly created incremental resolver to resolve a node in the |
| 668 * given source in the given library. | 703 * given source in the given library. |
| 669 */ | 704 */ |
| 670 IncrementalResolver(this._typeProvider, this._definingUnit, | 705 IncrementalResolver(this._typeProvider, this._definingUnit, |
| 671 this._updateOffset, this._updateOldLength, this._updateNewLength) { | 706 this._updateOffset, this._updateOldLength, this._updateNewLength) { |
| 672 _definingLibrary = _definingUnit.library; | 707 _definingLibrary = _definingUnit.library; |
| 673 _source = _definingUnit.source; | 708 _source = _definingUnit.source; |
| 674 } | 709 } |
| 675 | 710 |
| 676 /** | 711 /** |
| 677 * Resolve [node], reporting any errors or warnings to the given listener. | 712 * Resolve [node], reporting any errors or warnings to the given listener. |
| 678 * | 713 * |
| 679 * [node] - the root of the AST structure to be resolved. | 714 * [node] - the root of the AST structure to be resolved. |
| 680 * | 715 * |
| 681 * Returns `true` if resolution was successful. | 716 * Returns `true` if resolution was successful. |
| 682 */ | 717 */ |
| 683 bool resolve(AstNode node) { | 718 bool resolve(AstNode node) { |
| 684 logger.enter('resolve: $_definingUnit'); | 719 logger.enter('resolve: $_definingUnit'); |
| 685 try { | 720 try { |
| 686 logger.log(() => 'node: $node'); | 721 logger.log(() => 'node: $node'); |
| 687 AstNode rootNode = _findResolutionRoot(node); | 722 AstNode rootNode = _findResolutionRoot(node); |
| 688 logger.log(() => 'rootNode: $rootNode'); | 723 logger.log(() => 'rootNode: $rootNode'); |
| 724 _prepareResolutionContext(rootNode); |
| 689 // update elements | 725 // update elements |
| 690 _updateElementNameOffsets( | 726 _updateElementNameOffsets( |
| 691 _definingUnit, | 727 _definingUnit, |
| 692 _updateOffset, | 728 _updateOffset, |
| 693 _updateNewLength - _updateOldLength); | 729 _updateNewLength - _updateOldLength); |
| 730 _buildElements(rootNode); |
| 694 if (_elementModelChanged(rootNode)) { | 731 if (_elementModelChanged(rootNode)) { |
| 695 return false; | 732 return false; |
| 696 } | 733 } |
| 697 _updateElements(rootNode); | |
| 698 // resolve | 734 // resolve |
| 699 _resolveReferences(rootNode); | 735 _resolveReferences(rootNode); |
| 700 // verify | 736 // verify |
| 701 _verify(rootNode); | 737 _verify(rootNode); |
| 702 _generateHints(rootNode); | 738 _generateHints(rootNode); |
| 703 // OK | 739 // OK |
| 704 return true; | 740 return true; |
| 705 } finally { | 741 } finally { |
| 706 logger.exit(); | 742 logger.exit(); |
| 707 } | 743 } |
| 708 } | 744 } |
| 709 | 745 |
| 746 void _buildElements(AstNode node) { |
| 747 LoggingTimer timer = logger.startTimer(); |
| 748 try { |
| 749 ElementHolder holder = new ElementHolder(); |
| 750 ElementBuilder builder = new ElementBuilder(holder); |
| 751 node.accept(builder); |
| 752 } finally { |
| 753 timer.stop('build elements'); |
| 754 } |
| 755 } |
| 756 |
| 710 /** | 757 /** |
| 711 * Return `true` if the given node can be resolved independently of any other | 758 * Return `true` if the given node can be resolved independently of any other |
| 712 * nodes. | 759 * nodes. |
| 713 * | 760 * |
| 714 * *Note*: This method needs to be kept in sync with | 761 * *Note*: This method needs to be kept in sync with |
| 715 * [ScopeBuilder.ContextBuilder]. | 762 * [ScopeBuilder.ContextBuilder]. |
| 716 * | 763 * |
| 717 * [node] - the node being tested. | 764 * [node] - the node being tested. |
| 718 */ | 765 */ |
| 719 bool _canBeResolved(AstNode node) => | 766 bool _canBeResolved(AstNode node) => |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 */ | 843 */ |
| 797 Element _getElement(AstNode node) { | 844 Element _getElement(AstNode node) { |
| 798 if (node is Declaration) { | 845 if (node is Declaration) { |
| 799 return node.element; | 846 return node.element; |
| 800 } else if (node is CompilationUnit) { | 847 } else if (node is CompilationUnit) { |
| 801 return node.element; | 848 return node.element; |
| 802 } | 849 } |
| 803 return null; | 850 return null; |
| 804 } | 851 } |
| 805 | 852 |
| 853 void _prepareResolutionContext(AstNode node) { |
| 854 if (_resolutionContext == null) { |
| 855 _resolutionContext = |
| 856 ResolutionContextBuilder.contextFor(node, errorListener); |
| 857 } |
| 858 } |
| 859 |
| 806 _resolveReferences(AstNode node) { | 860 _resolveReferences(AstNode node) { |
| 807 LoggingTimer timer = logger.startTimer(); | 861 LoggingTimer timer = logger.startTimer(); |
| 808 try { | 862 try { |
| 809 RecordingErrorListener errorListener = new RecordingErrorListener(); | 863 _prepareResolutionContext(node); |
| 810 // prepare context | |
| 811 _resolutionContext = | |
| 812 ResolutionContextBuilder.contextFor(node, errorListener); | |
| 813 Scope scope = _resolutionContext.scope; | 864 Scope scope = _resolutionContext.scope; |
| 814 // resolve types | 865 // resolve types |
| 815 { | 866 { |
| 816 TypeResolverVisitor visitor = new TypeResolverVisitor.con3( | 867 TypeResolverVisitor visitor = new TypeResolverVisitor.con3( |
| 817 _definingLibrary, | 868 _definingLibrary, |
| 818 _source, | 869 _source, |
| 819 _typeProvider, | 870 _typeProvider, |
| 820 scope, | 871 scope, |
| 821 errorListener); | 872 errorListener); |
| 822 node.accept(visitor); | 873 node.accept(visitor); |
| 823 } | 874 } |
| 824 // resolve variables | 875 // resolve variables |
| 825 { | 876 { |
| 826 VariableResolverVisitor visitor = new VariableResolverVisitor.con2( | 877 VariableResolverVisitor visitor = new VariableResolverVisitor.con2( |
| 827 _definingLibrary, | 878 _definingLibrary, |
| 828 _source, | 879 _source, |
| 829 _typeProvider, | 880 _typeProvider, |
| 830 scope, | 881 scope, |
| 831 errorListener); | 882 errorListener); |
| 832 node.accept(visitor); | 883 node.accept(visitor); |
| 833 } | 884 } |
| 834 // resolve references | 885 // resolve references |
| 835 { | 886 { |
| 836 ResolverVisitor visitor = new ResolverVisitor.con3( | 887 ResolverVisitor visitor = new ResolverVisitor.con3( |
| 837 _definingLibrary, | 888 _definingLibrary, |
| 838 _source, | 889 _source, |
| 839 _typeProvider, | 890 _typeProvider, |
| 840 _resolutionContext.scope, | 891 scope, |
| 841 errorListener); | 892 errorListener); |
| 842 if (_resolutionContext.enclosingClassDeclaration != null) { | 893 if (_resolutionContext.enclosingClassDeclaration != null) { |
| 843 visitor.visitClassDeclarationIncrementally( | 894 visitor.visitClassDeclarationIncrementally( |
| 844 _resolutionContext.enclosingClassDeclaration); | 895 _resolutionContext.enclosingClassDeclaration); |
| 845 } | 896 } |
| 846 if (node is Comment) { | 897 if (node is Comment) { |
| 847 visitor.resolveOnlyCommentInFunctionBody = true; | 898 visitor.resolveOnlyCommentInFunctionBody = true; |
| 848 node = node.parent; | 899 node = node.parent; |
| 849 } | 900 } |
| 850 visitor.initForIncrementalResolution(); | 901 visitor.initForIncrementalResolution(); |
| 851 node.accept(visitor); | 902 node.accept(visitor); |
| 852 } | 903 } |
| 853 // remember errors | 904 // remember errors |
| 854 _resolveErrors = errorListener.getErrorsForSource(_source); | 905 _resolveErrors = errorListener.getErrorsForSource(_source); |
| 855 } finally { | 906 } finally { |
| 856 timer.stop('resolve references'); | 907 timer.stop('resolve references'); |
| 857 } | 908 } |
| 858 } | 909 } |
| 859 | 910 |
| 860 void _updateElements(AstNode node) { | |
| 861 LoggingTimer timer = logger.startTimer(); | |
| 862 try { | |
| 863 // build elements in node | |
| 864 ElementHolder holder; | |
| 865 _ElementsRestorer elementsRestorer = new _ElementsRestorer(node); | |
| 866 try { | |
| 867 holder = new ElementHolder(); | |
| 868 ElementBuilder builder = new ElementBuilder(holder); | |
| 869 node.accept(builder); | |
| 870 } finally { | |
| 871 elementsRestorer.restore(); | |
| 872 } | |
| 873 // apply compatible changes to elements | |
| 874 if (node is FunctionDeclaration) { | |
| 875 ExecutableElementImpl oldElement = node.element; | |
| 876 // prepare the new element | |
| 877 ExecutableElement newElement; | |
| 878 { | |
| 879 List<FunctionElement> holderFunctions = holder.functions; | |
| 880 List<PropertyAccessorElement> holderAccessors = holder.accessors; | |
| 881 if (holderFunctions.isNotEmpty) { | |
| 882 newElement = holderFunctions[0]; | |
| 883 } else if (holderAccessors.isNotEmpty) { | |
| 884 newElement = holderAccessors[0]; | |
| 885 } | |
| 886 } | |
| 887 // update the old Element | |
| 888 oldElement.functions = newElement.functions; | |
| 889 oldElement.labels = newElement.labels; | |
| 890 oldElement.localVariables = newElement.localVariables; | |
| 891 } | |
| 892 if (node is MethodDeclaration) { | |
| 893 ExecutableElementImpl oldElement = node.element; | |
| 894 // prepare the new element | |
| 895 ExecutableElement newElement; | |
| 896 { | |
| 897 List<MethodElement> holderMethods = holder.methods; | |
| 898 List<PropertyAccessorElement> holderAccessors = holder.accessors; | |
| 899 if (holderMethods.isNotEmpty) { | |
| 900 newElement = holderMethods[0]; | |
| 901 } else if (holderAccessors.isNotEmpty) { | |
| 902 newElement = holderAccessors[0]; | |
| 903 } | |
| 904 } | |
| 905 // update the old Element | |
| 906 oldElement.functions = newElement.functions; | |
| 907 oldElement.labels = newElement.labels; | |
| 908 oldElement.localVariables = newElement.localVariables; | |
| 909 } | |
| 910 } finally { | |
| 911 timer.stop('update elements'); | |
| 912 } | |
| 913 } | |
| 914 | |
| 915 void _verify(AstNode node) { | 911 void _verify(AstNode node) { |
| 916 LoggingTimer timer = logger.startTimer(); | 912 LoggingTimer timer = logger.startTimer(); |
| 917 try { | 913 try { |
| 918 RecordingErrorListener errorListener = new RecordingErrorListener(); | 914 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 919 ErrorReporter errorReporter = new ErrorReporter(errorListener, _source); | 915 ErrorReporter errorReporter = new ErrorReporter(errorListener, _source); |
| 920 ErrorVerifier errorVerifier = new ErrorVerifier( | 916 ErrorVerifier errorVerifier = new ErrorVerifier( |
| 921 errorReporter, | 917 errorReporter, |
| 922 _definingLibrary, | 918 _definingLibrary, |
| 923 _typeProvider, | 919 _typeProvider, |
| 924 new InheritanceManager(_definingLibrary)); | 920 new InheritanceManager(_definingLibrary)); |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 throw new AnalysisException('Uknown parent token type: $parentType'); | 1342 throw new AnalysisException('Uknown parent token type: $parentType'); |
| 1347 } | 1343 } |
| 1348 } | 1344 } |
| 1349 } | 1345 } |
| 1350 | 1346 |
| 1351 | 1347 |
| 1352 /** | 1348 /** |
| 1353 * The context to resolve an [AstNode] in. | 1349 * The context to resolve an [AstNode] in. |
| 1354 */ | 1350 */ |
| 1355 class ResolutionContext { | 1351 class ResolutionContext { |
| 1352 CompilationUnitElement enclosingUnit; |
| 1356 ClassDeclaration enclosingClassDeclaration; | 1353 ClassDeclaration enclosingClassDeclaration; |
| 1357 ClassElement enclosingClass; | 1354 ClassElement enclosingClass; |
| 1358 Scope scope; | 1355 Scope scope; |
| 1359 } | 1356 } |
| 1360 | 1357 |
| 1361 | 1358 |
| 1362 /** | 1359 /** |
| 1363 * Instances of the class [ResolutionContextBuilder] build the context for a | 1360 * Instances of the class [ResolutionContextBuilder] build the context for a |
| 1364 * given node in an AST structure. At the moment, this class only handles | 1361 * given node in an AST structure. At the moment, this class only handles |
| 1365 * top-level and class-level declarations. | 1362 * top-level and class-level declarations. |
| 1366 */ | 1363 */ |
| 1367 class ResolutionContextBuilder { | 1364 class ResolutionContextBuilder { |
| 1368 /** | 1365 /** |
| 1369 * The listener to which analysis errors will be reported. | 1366 * The listener to which analysis errors will be reported. |
| 1370 */ | 1367 */ |
| 1371 final AnalysisErrorListener _errorListener; | 1368 final AnalysisErrorListener _errorListener; |
| 1372 | 1369 |
| 1373 /** | 1370 /** |
| 1371 * The class containing the enclosing [CompilationUnitElement]. |
| 1372 */ |
| 1373 CompilationUnitElement _enclosingUnit; |
| 1374 |
| 1375 /** |
| 1374 * The class containing the enclosing [ClassDeclaration], or `null` if we are | 1376 * The class containing the enclosing [ClassDeclaration], or `null` if we are |
| 1375 * not in the scope of a class. | 1377 * not in the scope of a class. |
| 1376 */ | 1378 */ |
| 1377 ClassDeclaration _enclosingClassDeclaration; | 1379 ClassDeclaration _enclosingClassDeclaration; |
| 1378 | 1380 |
| 1379 /** | 1381 /** |
| 1380 * The class containing the enclosing [ClassElement], or `null` if we are not | 1382 * The class containing the enclosing [ClassElement], or `null` if we are not |
| 1381 * in the scope of a class. | 1383 * in the scope of a class. |
| 1382 */ | 1384 */ |
| 1383 ClassElement _enclosingClass; | 1385 ClassElement _enclosingClass; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 "Cannot build a scope for an unresolved method"); | 1467 "Cannot build a scope for an unresolved method"); |
| 1466 } | 1468 } |
| 1467 FunctionScope functionScope = new FunctionScope(scope, element); | 1469 FunctionScope functionScope = new FunctionScope(scope, element); |
| 1468 functionScope.defineParameters(); | 1470 functionScope.defineParameters(); |
| 1469 scope = functionScope; | 1471 scope = functionScope; |
| 1470 } | 1472 } |
| 1471 return scope; | 1473 return scope; |
| 1472 } | 1474 } |
| 1473 | 1475 |
| 1474 Scope _scopeForCompilationUnit(CompilationUnit node) { | 1476 Scope _scopeForCompilationUnit(CompilationUnit node) { |
| 1475 CompilationUnitElement unitElement = node.element; | 1477 _enclosingUnit = node.element; |
| 1476 if (unitElement == null) { | 1478 if (_enclosingUnit == null) { |
| 1477 throw new AnalysisException( | 1479 throw new AnalysisException( |
| 1478 "Cannot create scope: compilation unit is not resolved"); | 1480 "Cannot create scope: compilation unit is not resolved"); |
| 1479 } | 1481 } |
| 1480 LibraryElement libraryElement = unitElement.library; | 1482 LibraryElement libraryElement = _enclosingUnit.library; |
| 1481 if (libraryElement == null) { | 1483 if (libraryElement == null) { |
| 1482 throw new AnalysisException( | 1484 throw new AnalysisException( |
| 1483 "Cannot create scope: compilation unit is not part of a library"); | 1485 "Cannot create scope: compilation unit is not part of a library"); |
| 1484 } | 1486 } |
| 1485 return new LibraryScope(libraryElement, _errorListener); | 1487 return new LibraryScope(libraryElement, _errorListener); |
| 1486 } | 1488 } |
| 1487 | 1489 |
| 1488 /** | 1490 /** |
| 1489 * Return the context in which the given AST structure should be resolved. | 1491 * Return the context in which the given AST structure should be resolved. |
| 1490 * | 1492 * |
| 1491 * [node] - the root of the AST structure to be resolved. | 1493 * [node] - the root of the AST structure to be resolved. |
| 1492 * [errorListener] - the listener to which analysis errors will be reported. | 1494 * [errorListener] - the listener to which analysis errors will be reported. |
| 1493 * | 1495 * |
| 1494 * Throws [AnalysisException] if the AST structure has not been resolved or | 1496 * Throws [AnalysisException] if the AST structure has not been resolved or |
| 1495 * is not part of a [CompilationUnit] | 1497 * is not part of a [CompilationUnit] |
| 1496 */ | 1498 */ |
| 1497 static ResolutionContext contextFor(AstNode node, | 1499 static ResolutionContext contextFor(AstNode node, |
| 1498 AnalysisErrorListener errorListener) { | 1500 AnalysisErrorListener errorListener) { |
| 1499 if (node == null) { | 1501 if (node == null) { |
| 1500 throw new AnalysisException("Cannot create context: node is null"); | 1502 throw new AnalysisException("Cannot create context: node is null"); |
| 1501 } | 1503 } |
| 1502 // build scope | 1504 // build scope |
| 1503 ResolutionContextBuilder builder = | 1505 ResolutionContextBuilder builder = |
| 1504 new ResolutionContextBuilder(errorListener); | 1506 new ResolutionContextBuilder(errorListener); |
| 1505 Scope scope = builder._scopeFor(node); | 1507 Scope scope = builder._scopeFor(node); |
| 1506 // prepare context | 1508 // prepare context |
| 1507 ResolutionContext context = new ResolutionContext(); | 1509 ResolutionContext context = new ResolutionContext(); |
| 1508 context.scope = scope; | 1510 context.scope = scope; |
| 1511 context.enclosingUnit = builder._enclosingUnit; |
| 1509 context.enclosingClassDeclaration = builder._enclosingClassDeclaration; | 1512 context.enclosingClassDeclaration = builder._enclosingClassDeclaration; |
| 1510 context.enclosingClass = builder._enclosingClass; | 1513 context.enclosingClass = builder._enclosingClass; |
| 1511 return context; | 1514 return context; |
| 1512 } | 1515 } |
| 1513 } | 1516 } |
| 1514 | 1517 |
| 1515 | 1518 |
| 1516 /** | 1519 /** |
| 1517 * Instances of the class [_DeclarationMismatchException] represent an exception | 1520 * Instances of the class [_DeclarationMismatchException] represent an exception |
| 1518 * that is thrown when the element model defined by a given AST structure does | 1521 * that is thrown when the element model defined by a given AST structure does |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1590 void _addElement(Element element) { | 1593 void _addElement(Element element) { |
| 1591 if (element != null) { | 1594 if (element != null) { |
| 1592 matcher._allElements.add(element); | 1595 matcher._allElements.add(element); |
| 1593 matcher._unmatchedElements.add(element); | 1596 matcher._unmatchedElements.add(element); |
| 1594 } | 1597 } |
| 1595 } | 1598 } |
| 1596 } | 1599 } |
| 1597 | 1600 |
| 1598 | 1601 |
| 1599 /** | 1602 /** |
| 1600 * [ElementBuilder] not just builds elements, it also applies them to nodes. | |
| 1601 * But we want to keep externally visible (and referenced) elements instances. | |
| 1602 * So, we need to remember them and restore. | |
| 1603 */ | |
| 1604 class _ElementsRestorer extends RecursiveAstVisitor { | |
| 1605 final Map<AstNode, Element> _elements = <AstNode, Element>{}; | |
| 1606 | |
| 1607 _ElementsRestorer(AstNode root) { | |
| 1608 root.accept(this); | |
| 1609 } | |
| 1610 | |
| 1611 void restore() { | |
| 1612 _elements.forEach((AstNode node, Element element) { | |
| 1613 if (node is ConstructorDeclaration) { | |
| 1614 node.element = element; | |
| 1615 } else if (node is FunctionExpression) { | |
| 1616 node.element = element; | |
| 1617 } else if (node is SimpleIdentifier) { | |
| 1618 node.staticElement = element; | |
| 1619 } | |
| 1620 }); | |
| 1621 } | |
| 1622 | |
| 1623 @override | |
| 1624 visitBlockFunctionBody(BlockFunctionBody node) { | |
| 1625 } | |
| 1626 | |
| 1627 @override | |
| 1628 visitConstructorDeclaration(ConstructorDeclaration node) { | |
| 1629 _elements[node] = node.element; | |
| 1630 super.visitConstructorDeclaration(node); | |
| 1631 } | |
| 1632 | |
| 1633 @override | |
| 1634 visitExpressionFunctionBody(ExpressionFunctionBody node) { | |
| 1635 } | |
| 1636 | |
| 1637 @override | |
| 1638 visitFunctionExpression(FunctionExpression node) { | |
| 1639 _elements[node] = node.element; | |
| 1640 super.visitFunctionExpression(node); | |
| 1641 } | |
| 1642 | |
| 1643 @override | |
| 1644 visitSimpleIdentifier(SimpleIdentifier node) { | |
| 1645 _elements[node] = node.staticElement; | |
| 1646 } | |
| 1647 } | |
| 1648 | |
| 1649 | |
| 1650 /** | |
| 1651 * Describes how two [Token]s are different. | 1603 * Describes how two [Token]s are different. |
| 1652 */ | 1604 */ |
| 1653 class _TokenDifferenceKind { | 1605 class _TokenDifferenceKind { |
| 1654 static const COMMENT = const _TokenDifferenceKind('COMMENT'); | 1606 static const COMMENT = const _TokenDifferenceKind('COMMENT'); |
| 1655 static const COMMENT_DOC = const _TokenDifferenceKind('COMMENT_DOC'); | 1607 static const COMMENT_DOC = const _TokenDifferenceKind('COMMENT_DOC'); |
| 1656 static const CONTENT = const _TokenDifferenceKind('CONTENT'); | 1608 static const CONTENT = const _TokenDifferenceKind('CONTENT'); |
| 1657 static const OFFSET = const _TokenDifferenceKind('OFFSET'); | 1609 static const OFFSET = const _TokenDifferenceKind('OFFSET'); |
| 1658 | 1610 |
| 1659 final String name; | 1611 final String name; |
| 1660 | 1612 |
| 1661 const _TokenDifferenceKind(this.name); | 1613 const _TokenDifferenceKind(this.name); |
| 1662 | 1614 |
| 1663 @override | 1615 @override |
| 1664 String toString() => name; | 1616 String toString() => name; |
| 1665 } | 1617 } |
| 1666 | 1618 |
| 1667 | 1619 |
| 1668 class _TokenPair { | 1620 class _TokenPair { |
| 1669 final _TokenDifferenceKind kind; | 1621 final _TokenDifferenceKind kind; |
| 1670 final Token oldToken; | 1622 final Token oldToken; |
| 1671 final Token newToken; | 1623 final Token newToken; |
| 1672 _TokenPair(this.kind, this.oldToken, this.newToken); | 1624 _TokenPair(this.kind, this.oldToken, this.newToken); |
| 1673 } | 1625 } |
| OLD | NEW |