| 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 'package:analyzer/src/services/lint.dart'; | 10 import 'package:analyzer/src/services/lint.dart'; |
| 11 | 11 |
| 12 import 'ast.dart'; | 12 import 'ast.dart'; |
| 13 import 'element.dart'; | 13 import 'element.dart'; |
| 14 import 'engine.dart'; | 14 import 'engine.dart'; |
| 15 import 'error.dart'; | 15 import 'error.dart'; |
| 16 import 'error_verifier.dart'; | 16 import 'error_verifier.dart'; |
| 17 import 'incremental_logger.dart' show logger, LoggingTimer; | 17 import 'incremental_logger.dart' show logger, LoggingTimer; |
| 18 import 'java_engine.dart'; | 18 import 'java_engine.dart'; |
| 19 import 'parser.dart'; | 19 import 'parser.dart'; |
| 20 import 'resolver.dart'; | 20 import 'resolver.dart'; |
| 21 import 'scanner.dart'; | 21 import 'scanner.dart'; |
| 22 import 'source.dart'; | 22 import 'source.dart'; |
| 23 import 'utilities_dart.dart'; | 23 import 'utilities_dart.dart'; |
| 24 | 24 |
| 25 | |
| 26 /** | 25 /** |
| 27 * If `true`, an attempt to resolve API-changing modifications is made. | 26 * If `true`, an attempt to resolve API-changing modifications is made. |
| 28 */ | 27 */ |
| 29 bool _resolveApiChanges = false; | 28 bool _resolveApiChanges = false; |
| 30 | 29 |
| 31 | |
| 32 /** | 30 /** |
| 33 * This method is used to enable/disable API-changing modifications resolution. | 31 * This method is used to enable/disable API-changing modifications resolution. |
| 34 */ | 32 */ |
| 35 void set test_resolveApiChanges(bool value) { | 33 void set test_resolveApiChanges(bool value) { |
| 36 _resolveApiChanges = value; | 34 _resolveApiChanges = value; |
| 37 } | 35 } |
| 38 | 36 |
| 39 | |
| 40 /** | 37 /** |
| 41 * Instances of the class [DeclarationMatcher] determine whether the element | 38 * Instances of the class [DeclarationMatcher] determine whether the element |
| 42 * model defined by a given AST structure matches an existing element model. | 39 * model defined by a given AST structure matches an existing element model. |
| 43 */ | 40 */ |
| 44 class DeclarationMatcher extends RecursiveAstVisitor { | 41 class DeclarationMatcher extends RecursiveAstVisitor { |
| 45 /** | 42 /** |
| 46 * The libary containing the AST nodes being visited. | 43 * The libary containing the AST nodes being visited. |
| 47 */ | 44 */ |
| 48 LibraryElement _enclosingLibrary; | 45 LibraryElement _enclosingLibrary; |
| 49 | 46 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 @override | 173 @override |
| 177 visitCompilationUnit(CompilationUnit node) { | 174 visitCompilationUnit(CompilationUnit node) { |
| 178 _processElement(_enclosingUnit); | 175 _processElement(_enclosingUnit); |
| 179 super.visitCompilationUnit(node); | 176 super.visitCompilationUnit(node); |
| 180 } | 177 } |
| 181 | 178 |
| 182 @override | 179 @override |
| 183 visitConstructorDeclaration(ConstructorDeclaration node) { | 180 visitConstructorDeclaration(ConstructorDeclaration node) { |
| 184 _hasConstructor = true; | 181 _hasConstructor = true; |
| 185 SimpleIdentifier constructorName = node.name; | 182 SimpleIdentifier constructorName = node.name; |
| 186 ConstructorElementImpl element = constructorName == null ? | 183 ConstructorElementImpl element = constructorName == null |
| 187 _enclosingClass.unnamedConstructor : | 184 ? _enclosingClass.unnamedConstructor |
| 188 _enclosingClass.getNamedConstructor(constructorName.name); | 185 : _enclosingClass.getNamedConstructor(constructorName.name); |
| 189 _processElement(element); | 186 _processElement(element); |
| 190 _assertCompatibleParameters(node.parameters, element.parameters); | 187 _assertCompatibleParameters(node.parameters, element.parameters); |
| 191 // TODO(scheglov) debug null Location | 188 // TODO(scheglov) debug null Location |
| 192 if (element != null) { | 189 if (element != null) { |
| 193 if (element.context == null || element.source == null) { | 190 if (element.context == null || element.source == null) { |
| 194 logger.log( | 191 logger.log( |
| 195 'Bad constructor element $element for $node in ${node.parent}'); | 192 'Bad constructor element $element for $node in ${node.parent}'); |
| 196 } | 193 } |
| 197 } | 194 } |
| 198 // matches, update the existing element | 195 // matches, update the existing element |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 element = _findElement(_enclosingUnit.functions, name); | 260 element = _findElement(_enclosingUnit.functions, name); |
| 264 } else { | 261 } else { |
| 265 element = _findElement(_enclosingUnit.accessors, name); | 262 element = _findElement(_enclosingUnit.accessors, name); |
| 266 } | 263 } |
| 267 // process element | 264 // process element |
| 268 _processElement(element); | 265 _processElement(element); |
| 269 _assertSameAnnotations(node, element); | 266 _assertSameAnnotations(node, element); |
| 270 _assertFalse(element.isSynthetic); | 267 _assertFalse(element.isSynthetic); |
| 271 _assertSameType(node.returnType, element.returnType); | 268 _assertSameType(node.returnType, element.returnType); |
| 272 _assertCompatibleParameters( | 269 _assertCompatibleParameters( |
| 273 node.functionExpression.parameters, | 270 node.functionExpression.parameters, element.parameters); |
| 274 element.parameters); | |
| 275 _assertBodyModifiers(node.functionExpression.body, element); | 271 _assertBodyModifiers(node.functionExpression.body, element); |
| 276 // matches, update the existing element | 272 // matches, update the existing element |
| 277 ExecutableElement newElement = node.element; | 273 ExecutableElement newElement = node.element; |
| 278 node.name.staticElement = element; | 274 node.name.staticElement = element; |
| 279 node.functionExpression.element = element; | 275 node.functionExpression.element = element; |
| 280 _setLocalElements(element, newElement); | 276 _setLocalElements(element, newElement); |
| 281 } | 277 } |
| 282 | 278 |
| 283 @override | 279 @override |
| 284 visitFunctionTypeAlias(FunctionTypeAlias node) { | 280 visitFunctionTypeAlias(FunctionTypeAlias node) { |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 // verify | 397 // verify |
| 402 PropertyInducingElement newElement = node.name.staticElement; | 398 PropertyInducingElement newElement = node.name.staticElement; |
| 403 _processElement(element); | 399 _processElement(element); |
| 404 _assertSameAnnotations(node, element); | 400 _assertSameAnnotations(node, element); |
| 405 _assertEquals(node.isConst, element.isConst); | 401 _assertEquals(node.isConst, element.isConst); |
| 406 _assertEquals(node.isFinal, element.isFinal); | 402 _assertEquals(node.isFinal, element.isFinal); |
| 407 if (_enclosingFieldNode != null) { | 403 if (_enclosingFieldNode != null) { |
| 408 _assertEquals(_enclosingFieldNode.isStatic, element.isStatic); | 404 _assertEquals(_enclosingFieldNode.isStatic, element.isStatic); |
| 409 } | 405 } |
| 410 _assertSameType( | 406 _assertSameType( |
| 411 (node.parent as VariableDeclarationList).type, | 407 (node.parent as VariableDeclarationList).type, element.type); |
| 412 element.type); | |
| 413 // matches, restore the existing element | 408 // matches, restore the existing element |
| 414 node.name.staticElement = element; | 409 node.name.staticElement = element; |
| 415 if (element is VariableElementImpl) { | 410 if (element is VariableElementImpl) { |
| 416 (element as VariableElementImpl).initializer = newElement.initializer; | 411 (element as VariableElementImpl).initializer = newElement.initializer; |
| 417 } | 412 } |
| 418 } | 413 } |
| 419 | 414 |
| 420 @override | 415 @override |
| 421 visitWithClause(WithClause node) { | 416 visitWithClause(WithClause node) { |
| 422 List<TypeName> nodes = node.mixinTypes; | 417 List<TypeName> nodes = node.mixinTypes; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 for (SimpleIdentifier nameNode in combinator.hiddenNames) { | 451 for (SimpleIdentifier nameNode in combinator.hiddenNames) { |
| 457 String name = nameNode.name; | 452 String name = nameNode.name; |
| 458 _assertTrue(hideNames.remove(name)); | 453 _assertTrue(hideNames.remove(name)); |
| 459 } | 454 } |
| 460 } | 455 } |
| 461 } | 456 } |
| 462 _assertTrue(showNames.isEmpty); | 457 _assertTrue(showNames.isEmpty); |
| 463 _assertTrue(hideNames.isEmpty); | 458 _assertTrue(hideNames.isEmpty); |
| 464 } | 459 } |
| 465 | 460 |
| 466 void _assertCompatibleParameter(FormalParameter node, | 461 void _assertCompatibleParameter( |
| 467 ParameterElement element) { | 462 FormalParameter node, ParameterElement element) { |
| 468 _assertEquals(node.kind, element.parameterKind); | 463 _assertEquals(node.kind, element.parameterKind); |
| 469 if (node.kind == ParameterKind.NAMED) { | 464 if (node.kind == ParameterKind.NAMED) { |
| 470 _assertEquals(node.identifier.name, element.name); | 465 _assertEquals(node.identifier.name, element.name); |
| 471 } | 466 } |
| 472 // check parameter type specific properties | 467 // check parameter type specific properties |
| 473 if (node is DefaultFormalParameter) { | 468 if (node is DefaultFormalParameter) { |
| 474 Expression nodeDefault = node.defaultValue; | 469 Expression nodeDefault = node.defaultValue; |
| 475 if (nodeDefault == null) { | 470 if (nodeDefault == null) { |
| 476 _assertNull(element.defaultValueCode); | 471 _assertNull(element.defaultValueCode); |
| 477 } else { | 472 } else { |
| 478 _assertEquals(nodeDefault.toSource(), element.defaultValueCode); | 473 _assertEquals(nodeDefault.toSource(), element.defaultValueCode); |
| 479 } | 474 } |
| 480 } else if (node is FieldFormalParameter) { | 475 } else if (node is FieldFormalParameter) { |
| 481 _assertTrue(element.isInitializingFormal); | 476 _assertTrue(element.isInitializingFormal); |
| 482 } else if (node is FunctionTypedFormalParameter) { | 477 } else if (node is FunctionTypedFormalParameter) { |
| 483 _assertTrue(element.type is FunctionType); | 478 _assertTrue(element.type is FunctionType); |
| 484 FunctionType elementType = element.type; | 479 FunctionType elementType = element.type; |
| 485 _assertCompatibleParameters(node.parameters, element.parameters); | 480 _assertCompatibleParameters(node.parameters, element.parameters); |
| 486 _assertSameType(node.returnType, elementType.returnType); | 481 _assertSameType(node.returnType, elementType.returnType); |
| 487 } else if (node is SimpleFormalParameter) { | 482 } else if (node is SimpleFormalParameter) { |
| 488 _assertSameType(node.type, element.type); | 483 _assertSameType(node.type, element.type); |
| 489 } | 484 } |
| 490 } | 485 } |
| 491 | 486 |
| 492 void _assertCompatibleParameters(FormalParameterList nodes, | 487 void _assertCompatibleParameters( |
| 493 List<ParameterElement> elements) { | 488 FormalParameterList nodes, List<ParameterElement> elements) { |
| 494 if (nodes == null) { | 489 if (nodes == null) { |
| 495 return _assertEquals(elements.length, 0); | 490 return _assertEquals(elements.length, 0); |
| 496 } | 491 } |
| 497 List<FormalParameter> parameters = nodes.parameters; | 492 List<FormalParameter> parameters = nodes.parameters; |
| 498 int length = parameters.length; | 493 int length = parameters.length; |
| 499 _assertEquals(length, elements.length); | 494 _assertEquals(length, elements.length); |
| 500 for (int i = 0; i < length; i++) { | 495 for (int i = 0; i < length; i++) { |
| 501 _assertCompatibleParameter(parameters[i], elements[i]); | 496 _assertCompatibleParameter(parameters[i], elements[i]); |
| 502 } | 497 } |
| 503 } | 498 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 _assertEquals(nodeName, 'void'); | 585 _assertEquals(nodeName, 'void'); |
| 591 } else if (type.isDynamic) { | 586 } else if (type.isDynamic) { |
| 592 _assertEquals(nodeName, 'dynamic'); | 587 _assertEquals(nodeName, 'dynamic'); |
| 593 } else { | 588 } else { |
| 594 // TODO(scheglov) support other types | 589 // TODO(scheglov) support other types |
| 595 logger.log('node: $node type: $type type.type: ${type.runtimeType}'); | 590 logger.log('node: $node type: $type type.type: ${type.runtimeType}'); |
| 596 _assertTrue(false); | 591 _assertTrue(false); |
| 597 } | 592 } |
| 598 } | 593 } |
| 599 | 594 |
| 600 void _assertSameTypeParameter(TypeParameter node, | 595 void _assertSameTypeParameter( |
| 601 TypeParameterElement element) { | 596 TypeParameter node, TypeParameterElement element) { |
| 602 _assertSameType(node.bound, element.bound); | 597 _assertSameType(node.bound, element.bound); |
| 603 } | 598 } |
| 604 | 599 |
| 605 void _assertSameTypeParameters(TypeParameterList nodesList, | 600 void _assertSameTypeParameters( |
| 606 List<TypeParameterElement> elements) { | 601 TypeParameterList nodesList, List<TypeParameterElement> elements) { |
| 607 if (nodesList == null) { | 602 if (nodesList == null) { |
| 608 return _assertEquals(elements.length, 0); | 603 return _assertEquals(elements.length, 0); |
| 609 } | 604 } |
| 610 List<TypeParameter> nodes = nodesList.typeParameters; | 605 List<TypeParameter> nodes = nodesList.typeParameters; |
| 611 int length = nodes.length; | 606 int length = nodes.length; |
| 612 _assertEquals(length, elements.length); | 607 _assertEquals(length, elements.length); |
| 613 for (int i = 0; i < length; i++) { | 608 for (int i = 0; i < length; i++) { |
| 614 _assertSameTypeParameter(nodes[i], elements[i]); | 609 _assertSameTypeParameter(nodes[i], elements[i]); |
| 615 } | 610 } |
| 616 } | 611 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 return element; | 697 return element; |
| 703 } | 698 } |
| 704 } | 699 } |
| 705 return null; | 700 return null; |
| 706 } | 701 } |
| 707 | 702 |
| 708 /** | 703 /** |
| 709 * Return the [UriReferencedElement] from [elements] with the given [uri], or | 704 * Return the [UriReferencedElement] from [elements] with the given [uri], or |
| 710 * `null` if there is no such element. | 705 * `null` if there is no such element. |
| 711 */ | 706 */ |
| 712 static UriReferencedElement | 707 static UriReferencedElement _findUriReferencedElement( |
| 713 _findUriReferencedElement(List<UriReferencedElement> elements, String uri)
{ | 708 List<UriReferencedElement> elements, String uri) { |
| 714 for (UriReferencedElement element in elements) { | 709 for (UriReferencedElement element in elements) { |
| 715 if (element.uri == uri) { | 710 if (element.uri == uri) { |
| 716 return element; | 711 return element; |
| 717 } | 712 } |
| 718 } | 713 } |
| 719 return null; | 714 return null; |
| 720 } | 715 } |
| 721 | 716 |
| 722 /** | 717 /** |
| 723 * Return the value of [literal], or `null` if the string is not a constant | 718 * Return the value of [literal], or `null` if the string is not a constant |
| (...skipping 12 matching lines...) Expand all Loading... |
| 736 static void _removeIdenticalElement(List elements, Object element) { | 731 static void _removeIdenticalElement(List elements, Object element) { |
| 737 int length = elements.length; | 732 int length = elements.length; |
| 738 for (int i = 0; i < length; i++) { | 733 for (int i = 0; i < length; i++) { |
| 739 if (identical(elements[i], element)) { | 734 if (identical(elements[i], element)) { |
| 740 elements.removeAt(i); | 735 elements.removeAt(i); |
| 741 return; | 736 return; |
| 742 } | 737 } |
| 743 } | 738 } |
| 744 } | 739 } |
| 745 | 740 |
| 746 static void _setLocalElements(ExecutableElementImpl to, | 741 static void _setLocalElements( |
| 747 ExecutableElement from) { | 742 ExecutableElementImpl to, ExecutableElement from) { |
| 748 to.functions = from.functions; | 743 to.functions = from.functions; |
| 749 to.labels = from.labels; | 744 to.labels = from.labels; |
| 750 to.localVariables = from.localVariables; | 745 to.localVariables = from.localVariables; |
| 751 to.parameters = from.parameters; | 746 to.parameters = from.parameters; |
| 752 } | 747 } |
| 753 } | 748 } |
| 754 | 749 |
| 755 | |
| 756 /** | 750 /** |
| 757 * Describes how declarations match an existing elements model. | 751 * Describes how declarations match an existing elements model. |
| 758 */ | 752 */ |
| 759 class DeclarationMatchKind { | 753 class DeclarationMatchKind { |
| 760 /** | 754 /** |
| 761 * Complete match, no API changes. | 755 * Complete match, no API changes. |
| 762 */ | 756 */ |
| 763 static const MATCH = const DeclarationMatchKind('MATCH'); | 757 static const MATCH = const DeclarationMatchKind('MATCH'); |
| 764 | 758 |
| 765 /** | 759 /** |
| 766 * Has API changes that we might be able to resolve incrementally. | 760 * Has API changes that we might be able to resolve incrementally. |
| 767 */ | 761 */ |
| 768 static const MISMATCH_OK = const DeclarationMatchKind('MISMATCH_OK'); | 762 static const MISMATCH_OK = const DeclarationMatchKind('MISMATCH_OK'); |
| 769 | 763 |
| 770 /** | 764 /** |
| 771 * Has API changes that we cannot resolve incrementally. | 765 * Has API changes that we cannot resolve incrementally. |
| 772 */ | 766 */ |
| 773 static const MISMATCH = const DeclarationMatchKind('MISMATCH'); | 767 static const MISMATCH = const DeclarationMatchKind('MISMATCH'); |
| 774 | 768 |
| 775 final String name; | 769 final String name; |
| 776 | 770 |
| 777 const DeclarationMatchKind(this.name); | 771 const DeclarationMatchKind(this.name); |
| 778 | 772 |
| 779 @override | 773 @override |
| 780 String toString() => name; | 774 String toString() => name; |
| 781 } | 775 } |
| 782 | 776 |
| 783 | |
| 784 /** | 777 /** |
| 785 * Instances of the class [IncrementalResolver] resolve the smallest portion of | 778 * Instances of the class [IncrementalResolver] resolve the smallest portion of |
| 786 * an AST structure that we currently know how to resolve. | 779 * an AST structure that we currently know how to resolve. |
| 787 */ | 780 */ |
| 788 class IncrementalResolver { | 781 class IncrementalResolver { |
| 789 /** | 782 /** |
| 790 * The element of the compilation unit being resolved. | 783 * The element of the compilation unit being resolved. |
| 791 */ | 784 */ |
| 792 final CompilationUnitElement _definingUnit; | 785 final CompilationUnitElement _definingUnit; |
| 793 | 786 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 | 931 |
| 939 /** | 932 /** |
| 940 * Return `true` if the given node can be resolved independently of any other | 933 * Return `true` if the given node can be resolved independently of any other |
| 941 * nodes. | 934 * nodes. |
| 942 * | 935 * |
| 943 * *Note*: This method needs to be kept in sync with | 936 * *Note*: This method needs to be kept in sync with |
| 944 * [ScopeBuilder.ContextBuilder]. | 937 * [ScopeBuilder.ContextBuilder]. |
| 945 * | 938 * |
| 946 * [node] - the node being tested. | 939 * [node] - the node being tested. |
| 947 */ | 940 */ |
| 948 bool _canBeResolved(AstNode node) => | 941 bool _canBeResolved(AstNode node) => node is ClassDeclaration || |
| 949 node is ClassDeclaration || | 942 node is ClassTypeAlias || |
| 950 node is ClassTypeAlias || | 943 node is CompilationUnit || |
| 951 node is CompilationUnit || | 944 node is ConstructorDeclaration || |
| 952 node is ConstructorDeclaration || | 945 node is FunctionDeclaration || |
| 953 node is FunctionDeclaration || | 946 node is FunctionTypeAlias || |
| 954 node is FunctionTypeAlias || | 947 node is MethodDeclaration || |
| 955 node is MethodDeclaration || | 948 node is TopLevelVariableDeclaration; |
| 956 node is TopLevelVariableDeclaration; | |
| 957 | 949 |
| 958 /** | 950 /** |
| 959 * Starting at [node], find the smallest AST node that can be resolved | 951 * Starting at [node], find the smallest AST node that can be resolved |
| 960 * independently of any other nodes. Return the node that was found. | 952 * independently of any other nodes. Return the node that was found. |
| 961 * | 953 * |
| 962 * [node] - the node at which the search is to begin | 954 * [node] - the node at which the search is to begin |
| 963 * | 955 * |
| 964 * Throws [AnalysisException] if there is no such node. | 956 * Throws [AnalysisException] if there is no such node. |
| 965 */ | 957 */ |
| 966 AstNode _findResolutionRoot(AstNode node) { | 958 AstNode _findResolutionRoot(AstNode node) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 } | 1000 } |
| 1009 | 1001 |
| 1010 _resolveReferences(AstNode node) { | 1002 _resolveReferences(AstNode node) { |
| 1011 LoggingTimer timer = logger.startTimer(); | 1003 LoggingTimer timer = logger.startTimer(); |
| 1012 try { | 1004 try { |
| 1013 _prepareResolutionContext(node); | 1005 _prepareResolutionContext(node); |
| 1014 Scope scope = _resolutionContext.scope; | 1006 Scope scope = _resolutionContext.scope; |
| 1015 // resolve types | 1007 // resolve types |
| 1016 { | 1008 { |
| 1017 TypeResolverVisitor visitor = new TypeResolverVisitor.con3( | 1009 TypeResolverVisitor visitor = new TypeResolverVisitor.con3( |
| 1018 _definingLibrary, | 1010 _definingLibrary, _source, _typeProvider, scope, errorListener); |
| 1019 _source, | |
| 1020 _typeProvider, | |
| 1021 scope, | |
| 1022 errorListener); | |
| 1023 node.accept(visitor); | 1011 node.accept(visitor); |
| 1024 } | 1012 } |
| 1025 // resolve variables | 1013 // resolve variables |
| 1026 { | 1014 { |
| 1027 VariableResolverVisitor visitor = new VariableResolverVisitor.con2( | 1015 VariableResolverVisitor visitor = new VariableResolverVisitor.con2( |
| 1028 _definingLibrary, | 1016 _definingLibrary, _source, _typeProvider, scope, errorListener); |
| 1029 _source, | |
| 1030 _typeProvider, | |
| 1031 scope, | |
| 1032 errorListener); | |
| 1033 node.accept(visitor); | 1017 node.accept(visitor); |
| 1034 } | 1018 } |
| 1035 // resolve references | 1019 // resolve references |
| 1036 { | 1020 { |
| 1037 ResolverVisitor visitor = new ResolverVisitor.con3( | 1021 ResolverVisitor visitor = new ResolverVisitor.con3( |
| 1038 _definingLibrary, | 1022 _definingLibrary, _source, _typeProvider, scope, errorListener); |
| 1039 _source, | |
| 1040 _typeProvider, | |
| 1041 scope, | |
| 1042 errorListener); | |
| 1043 if (_resolutionContext.enclosingClassDeclaration != null) { | 1023 if (_resolutionContext.enclosingClassDeclaration != null) { |
| 1044 visitor.visitClassDeclarationIncrementally( | 1024 visitor.visitClassDeclarationIncrementally( |
| 1045 _resolutionContext.enclosingClassDeclaration); | 1025 _resolutionContext.enclosingClassDeclaration); |
| 1046 } | 1026 } |
| 1047 if (node is Comment) { | 1027 if (node is Comment) { |
| 1048 visitor.resolveOnlyCommentInFunctionBody = true; | 1028 visitor.resolveOnlyCommentInFunctionBody = true; |
| 1049 node = node.parent; | 1029 node = node.parent; |
| 1050 } | 1030 } |
| 1051 visitor.initForIncrementalResolution(); | 1031 visitor.initForIncrementalResolution(); |
| 1052 node.accept(visitor); | 1032 node.accept(visitor); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1072 int errorOffset = error.offset; | 1052 int errorOffset = error.offset; |
| 1073 if (errorOffset > _updateOffset) { | 1053 if (errorOffset > _updateOffset) { |
| 1074 error.offset += _updateDelta; | 1054 error.offset += _updateDelta; |
| 1075 } | 1055 } |
| 1076 } | 1056 } |
| 1077 } | 1057 } |
| 1078 | 1058 |
| 1079 void _updateElementNameOffsets() { | 1059 void _updateElementNameOffsets() { |
| 1080 LoggingTimer timer = logger.startTimer(); | 1060 LoggingTimer timer = logger.startTimer(); |
| 1081 try { | 1061 try { |
| 1082 _definingUnit.accept( | 1062 _definingUnit |
| 1083 new _ElementNameOffsetUpdater(_updateOffset, _updateDelta)); | 1063 .accept(new _ElementNameOffsetUpdater(_updateOffset, _updateDelta)); |
| 1084 } finally { | 1064 } finally { |
| 1085 timer.stop('update element offsets'); | 1065 timer.stop('update element offsets'); |
| 1086 } | 1066 } |
| 1087 } | 1067 } |
| 1088 | 1068 |
| 1089 void _updateEntry() { | 1069 void _updateEntry() { |
| 1090 { | 1070 { |
| 1091 List<AnalysisError> oldErrors = | 1071 List<AnalysisError> oldErrors = |
| 1092 entry.getValueInLibrary(DartEntry.RESOLUTION_ERRORS, _librarySource); | 1072 entry.getValueInLibrary(DartEntry.RESOLUTION_ERRORS, _librarySource); |
| 1093 List<AnalysisError> errors = _updateErrors(oldErrors, _resolveErrors); | 1073 List<AnalysisError> errors = _updateErrors(oldErrors, _resolveErrors); |
| 1094 entry.setValueInLibrary( | 1074 entry.setValueInLibrary( |
| 1095 DartEntry.RESOLUTION_ERRORS, | 1075 DartEntry.RESOLUTION_ERRORS, _librarySource, errors); |
| 1096 _librarySource, | |
| 1097 errors); | |
| 1098 } | 1076 } |
| 1099 { | 1077 { |
| 1100 List<AnalysisError> oldErrors = | 1078 List<AnalysisError> oldErrors = entry.getValueInLibrary( |
| 1101 entry.getValueInLibrary(DartEntry.VERIFICATION_ERRORS, _librarySource)
; | 1079 DartEntry.VERIFICATION_ERRORS, _librarySource); |
| 1102 List<AnalysisError> errors = _updateErrors(oldErrors, _verifyErrors); | 1080 List<AnalysisError> errors = _updateErrors(oldErrors, _verifyErrors); |
| 1103 entry.setValueInLibrary( | 1081 entry.setValueInLibrary( |
| 1104 DartEntry.VERIFICATION_ERRORS, | 1082 DartEntry.VERIFICATION_ERRORS, _librarySource, errors); |
| 1105 _librarySource, | |
| 1106 errors); | |
| 1107 } | 1083 } |
| 1108 entry.setValueInLibrary(DartEntry.LINTS, _librarySource, _lints); | 1084 entry.setValueInLibrary(DartEntry.LINTS, _librarySource, _lints); |
| 1109 } | 1085 } |
| 1110 | 1086 |
| 1111 List<AnalysisError> _updateErrors(List<AnalysisError> oldErrors, | 1087 List<AnalysisError> _updateErrors( |
| 1112 List<AnalysisError> newErrors) { | 1088 List<AnalysisError> oldErrors, List<AnalysisError> newErrors) { |
| 1113 List<AnalysisError> errors = new List<AnalysisError>(); | 1089 List<AnalysisError> errors = new List<AnalysisError>(); |
| 1114 // add updated old errors | 1090 // add updated old errors |
| 1115 for (AnalysisError error in oldErrors) { | 1091 for (AnalysisError error in oldErrors) { |
| 1116 int errorOffset = error.offset; | 1092 int errorOffset = error.offset; |
| 1117 if (errorOffset < _updateOffset) { | 1093 if (errorOffset < _updateOffset) { |
| 1118 errors.add(error); | 1094 errors.add(error); |
| 1119 } else if (errorOffset > _updateEndOld) { | 1095 } else if (errorOffset > _updateEndOld) { |
| 1120 error.offset += _updateDelta; | 1096 error.offset += _updateDelta; |
| 1121 errors.add(error); | 1097 errors.add(error); |
| 1122 } | 1098 } |
| 1123 } | 1099 } |
| 1124 // add new errors | 1100 // add new errors |
| 1125 for (AnalysisError error in newErrors) { | 1101 for (AnalysisError error in newErrors) { |
| 1126 int errorOffset = error.offset; | 1102 int errorOffset = error.offset; |
| 1127 if (errorOffset > _updateOffset && errorOffset < _updateEndNew) { | 1103 if (errorOffset > _updateOffset && errorOffset < _updateEndNew) { |
| 1128 errors.add(error); | 1104 errors.add(error); |
| 1129 } | 1105 } |
| 1130 } | 1106 } |
| 1131 // done | 1107 // done |
| 1132 return errors; | 1108 return errors; |
| 1133 } | 1109 } |
| 1134 | 1110 |
| 1135 void _verify(AstNode node) { | 1111 void _verify(AstNode node) { |
| 1136 LoggingTimer timer = logger.startTimer(); | 1112 LoggingTimer timer = logger.startTimer(); |
| 1137 try { | 1113 try { |
| 1138 RecordingErrorListener errorListener = new RecordingErrorListener(); | 1114 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 1139 ErrorReporter errorReporter = new ErrorReporter(errorListener, _source); | 1115 ErrorReporter errorReporter = new ErrorReporter(errorListener, _source); |
| 1140 ErrorVerifier errorVerifier = new ErrorVerifier( | 1116 ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, |
| 1141 errorReporter, | 1117 _definingLibrary, _typeProvider, |
| 1142 _definingLibrary, | |
| 1143 _typeProvider, | |
| 1144 new InheritanceManager(_definingLibrary)); | 1118 new InheritanceManager(_definingLibrary)); |
| 1145 if (_resolutionContext.enclosingClassDeclaration != null) { | 1119 if (_resolutionContext.enclosingClassDeclaration != null) { |
| 1146 errorVerifier.visitClassDeclarationIncrementally( | 1120 errorVerifier.visitClassDeclarationIncrementally( |
| 1147 _resolutionContext.enclosingClassDeclaration); | 1121 _resolutionContext.enclosingClassDeclaration); |
| 1148 } | 1122 } |
| 1149 node.accept(errorVerifier); | 1123 node.accept(errorVerifier); |
| 1150 _verifyErrors = errorListener.getErrorsForSource(_source); | 1124 _verifyErrors = errorListener.getErrorsForSource(_source); |
| 1151 } finally { | 1125 } finally { |
| 1152 timer.stop('verify'); | 1126 timer.stop('verify'); |
| 1153 } | 1127 } |
| 1154 } | 1128 } |
| 1155 } | 1129 } |
| 1156 | 1130 |
| 1157 | |
| 1158 class PoorMansIncrementalResolver { | 1131 class PoorMansIncrementalResolver { |
| 1159 final TypeProvider _typeProvider; | 1132 final TypeProvider _typeProvider; |
| 1160 final Source _unitSource; | 1133 final Source _unitSource; |
| 1161 final DartEntry _entry; | 1134 final DartEntry _entry; |
| 1162 final CompilationUnit _oldUnit; | 1135 final CompilationUnit _oldUnit; |
| 1163 CompilationUnitElement _unitElement; | 1136 CompilationUnitElement _unitElement; |
| 1164 | 1137 |
| 1165 int _updateOffset; | 1138 int _updateOffset; |
| 1166 int _updateDelta; | 1139 int _updateDelta; |
| 1167 int _updateEndOld; | 1140 int _updateEndOld; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 bool success = _resolveComment(_oldUnit, newUnit, firstPair); | 1194 bool success = _resolveComment(_oldUnit, newUnit, firstPair); |
| 1222 logger.log('Documentation comment resolved: $success'); | 1195 logger.log('Documentation comment resolved: $success'); |
| 1223 return success; | 1196 return success; |
| 1224 } | 1197 } |
| 1225 // A pure whitespace change. | 1198 // A pure whitespace change. |
| 1226 if (firstPair.kind == _TokenDifferenceKind.OFFSET) { | 1199 if (firstPair.kind == _TokenDifferenceKind.OFFSET) { |
| 1227 logger.log('Whitespace change.'); | 1200 logger.log('Whitespace change.'); |
| 1228 _shiftTokens(firstPair.oldToken); | 1201 _shiftTokens(firstPair.oldToken); |
| 1229 { | 1202 { |
| 1230 IncrementalResolver incrementalResolver = new IncrementalResolver( | 1203 IncrementalResolver incrementalResolver = new IncrementalResolver( |
| 1231 _unitElement, | 1204 _unitElement, _updateOffset, _updateEndOld, _updateEndNew); |
| 1232 _updateOffset, | |
| 1233 _updateEndOld, | |
| 1234 _updateEndNew); | |
| 1235 incrementalResolver._updateElementNameOffsets(); | 1205 incrementalResolver._updateElementNameOffsets(); |
| 1236 incrementalResolver._shiftEntryErrors(); | 1206 incrementalResolver._shiftEntryErrors(); |
| 1237 } | 1207 } |
| 1238 _updateEntry(); | 1208 _updateEntry(); |
| 1239 logger.log('Success.'); | 1209 logger.log('Success.'); |
| 1240 return true; | 1210 return true; |
| 1241 } | 1211 } |
| 1242 // fall-through, end-of-line comment | 1212 // fall-through, end-of-line comment |
| 1243 } | 1213 } |
| 1244 // Find nodes covering the "old" and "new" token ranges. | 1214 // Find nodes covering the "old" and "new" token ranges. |
| 1245 AstNode oldNode = | 1215 AstNode oldNode = |
| 1246 _findNodeCovering(_oldUnit, beginOffsetOld, endOffsetOld); | 1216 _findNodeCovering(_oldUnit, beginOffsetOld, endOffsetOld); |
| 1247 AstNode newNode = | 1217 AstNode newNode = |
| 1248 _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew); | 1218 _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew); |
| 1249 logger.log(() => 'oldNode: $oldNode'); | 1219 logger.log(() => 'oldNode: $oldNode'); |
| 1250 logger.log(() => 'newNode: $newNode'); | 1220 logger.log(() => 'newNode: $newNode'); |
| 1251 // Try to find the smallest common node, a FunctionBody currently. | 1221 // Try to find the smallest common node, a FunctionBody currently. |
| 1252 { | 1222 { |
| 1253 List<AstNode> oldParents = _getParents(oldNode); | 1223 List<AstNode> oldParents = _getParents(oldNode); |
| 1254 List<AstNode> newParents = _getParents(newNode); | 1224 List<AstNode> newParents = _getParents(newNode); |
| 1255 int length = math.min(oldParents.length, newParents.length); | 1225 int length = math.min(oldParents.length, newParents.length); |
| 1256 bool found = false; | 1226 bool found = false; |
| 1257 for (int i = 0; i < length; i++) { | 1227 for (int i = 0; i < length; i++) { |
| 1258 AstNode oldParent = oldParents[i]; | 1228 AstNode oldParent = oldParents[i]; |
| 1259 AstNode newParent = newParents[i]; | 1229 AstNode newParent = newParents[i]; |
| 1260 if (oldParent is FunctionDeclaration && | 1230 if (oldParent is FunctionDeclaration && |
| 1261 newParent is FunctionDeclaration || | 1231 newParent is FunctionDeclaration || |
| 1262 oldParent is MethodDeclaration && newParent is MethodDeclaration
|| | 1232 oldParent is MethodDeclaration && |
| 1263 oldParent is ConstructorDeclaration && newParent is ConstructorD
eclaration) { | 1233 newParent is MethodDeclaration || |
| 1234 oldParent is ConstructorDeclaration && |
| 1235 newParent is ConstructorDeclaration) { |
| 1264 oldNode = oldParent; | 1236 oldNode = oldParent; |
| 1265 newNode = newParent; | 1237 newNode = newParent; |
| 1266 found = true; | 1238 found = true; |
| 1267 } | 1239 } |
| 1268 if (oldParent is FunctionBody && newParent is FunctionBody) { | 1240 if (oldParent is FunctionBody && newParent is FunctionBody) { |
| 1269 oldNode = oldParent; | 1241 oldNode = oldParent; |
| 1270 newNode = newParent; | 1242 newNode = newParent; |
| 1271 found = true; | 1243 found = true; |
| 1272 break; | 1244 break; |
| 1273 } | 1245 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1293 if (oldBeginToken.previous.type == TokenType.EOF) { | 1265 if (oldBeginToken.previous.type == TokenType.EOF) { |
| 1294 _oldUnit.beginToken = newBeginToken; | 1266 _oldUnit.beginToken = newBeginToken; |
| 1295 } else { | 1267 } else { |
| 1296 oldBeginToken.previous.setNext(newBeginToken); | 1268 oldBeginToken.previous.setNext(newBeginToken); |
| 1297 } | 1269 } |
| 1298 newNode.endToken.setNext(oldNode.endToken.next); | 1270 newNode.endToken.setNext(oldNode.endToken.next); |
| 1299 _shiftTokens(oldNode.endToken.next); | 1271 _shiftTokens(oldNode.endToken.next); |
| 1300 } | 1272 } |
| 1301 // perform incremental resolution | 1273 // perform incremental resolution |
| 1302 IncrementalResolver incrementalResolver = new IncrementalResolver( | 1274 IncrementalResolver incrementalResolver = new IncrementalResolver( |
| 1303 _unitElement, | 1275 _unitElement, _updateOffset, _updateEndOld, _updateEndNew); |
| 1304 _updateOffset, | |
| 1305 _updateEndOld, | |
| 1306 _updateEndNew); | |
| 1307 bool success = incrementalResolver.resolve(newNode); | 1276 bool success = incrementalResolver.resolve(newNode); |
| 1308 // check if success | 1277 // check if success |
| 1309 if (!success) { | 1278 if (!success) { |
| 1310 logger.log('Failure: element model changed.'); | 1279 logger.log('Failure: element model changed.'); |
| 1311 return false; | 1280 return false; |
| 1312 } | 1281 } |
| 1313 // update DartEntry | 1282 // update DartEntry |
| 1314 _updateEntry(); | 1283 _updateEntry(); |
| 1315 logger.log('Success.'); | 1284 logger.log('Success.'); |
| 1316 return true; | 1285 return true; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1336 return unit; | 1305 return unit; |
| 1337 } finally { | 1306 } finally { |
| 1338 timer.stop('parse'); | 1307 timer.stop('parse'); |
| 1339 } | 1308 } |
| 1340 } | 1309 } |
| 1341 | 1310 |
| 1342 /** | 1311 /** |
| 1343 * Attempts to resolve a documentation comment change. | 1312 * Attempts to resolve a documentation comment change. |
| 1344 * Returns `true` if success. | 1313 * Returns `true` if success. |
| 1345 */ | 1314 */ |
| 1346 bool _resolveComment(CompilationUnit oldUnit, CompilationUnit newUnit, | 1315 bool _resolveComment( |
| 1347 _TokenPair firstPair) { | 1316 CompilationUnit oldUnit, CompilationUnit newUnit, _TokenPair firstPair) { |
| 1348 Token oldToken = firstPair.oldToken; | 1317 Token oldToken = firstPair.oldToken; |
| 1349 Token newToken = firstPair.newToken; | 1318 Token newToken = firstPair.newToken; |
| 1350 CommentToken oldComments = oldToken.precedingComments; | 1319 CommentToken oldComments = oldToken.precedingComments; |
| 1351 CommentToken newComments = newToken.precedingComments; | 1320 CommentToken newComments = newToken.precedingComments; |
| 1352 if (oldComments == null || newComments == null) { | 1321 if (oldComments == null || newComments == null) { |
| 1353 return false; | 1322 return false; |
| 1354 } | 1323 } |
| 1355 // find nodes | 1324 // find nodes |
| 1356 int offset = oldComments.offset; | 1325 int offset = oldComments.offset; |
| 1357 logger.log('offset: $offset'); | 1326 logger.log('offset: $offset'); |
| 1358 Comment oldComment = _findNodeCovering(oldUnit, offset, offset); | 1327 Comment oldComment = _findNodeCovering(oldUnit, offset, offset); |
| 1359 Comment newComment = _findNodeCovering(newUnit, offset, offset); | 1328 Comment newComment = _findNodeCovering(newUnit, offset, offset); |
| 1360 logger.log('oldComment.beginToken: ${oldComment.beginToken}'); | 1329 logger.log('oldComment.beginToken: ${oldComment.beginToken}'); |
| 1361 logger.log('newComment.beginToken: ${newComment.beginToken}'); | 1330 logger.log('newComment.beginToken: ${newComment.beginToken}'); |
| 1362 _updateOffset = oldToken.offset - 1; | 1331 _updateOffset = oldToken.offset - 1; |
| 1363 // update token references | 1332 // update token references |
| 1364 _shiftTokens(firstPair.oldToken); | 1333 _shiftTokens(firstPair.oldToken); |
| 1365 _setPrecedingComments(oldToken, newComment.tokens.first); | 1334 _setPrecedingComments(oldToken, newComment.tokens.first); |
| 1366 // replace node | 1335 // replace node |
| 1367 NodeReplacer.replace(oldComment, newComment); | 1336 NodeReplacer.replace(oldComment, newComment); |
| 1368 // update elements | 1337 // update elements |
| 1369 IncrementalResolver incrementalResolver = new IncrementalResolver( | 1338 IncrementalResolver incrementalResolver = new IncrementalResolver( |
| 1370 _unitElement, | 1339 _unitElement, _updateOffset, _updateEndOld, _updateEndNew); |
| 1371 _updateOffset, | |
| 1372 _updateEndOld, | |
| 1373 _updateEndNew); | |
| 1374 incrementalResolver._updateElementNameOffsets(); | 1340 incrementalResolver._updateElementNameOffsets(); |
| 1375 incrementalResolver._shiftEntryErrors(); | 1341 incrementalResolver._shiftEntryErrors(); |
| 1376 _updateEntry(); | 1342 _updateEntry(); |
| 1377 // resolve references in the comment | 1343 // resolve references in the comment |
| 1378 incrementalResolver._resolveReferences(newComment); | 1344 incrementalResolver._resolveReferences(newComment); |
| 1379 // OK | 1345 // OK |
| 1380 return true; | 1346 return true; |
| 1381 } | 1347 } |
| 1382 | 1348 |
| 1383 Token _scan(String code) { | 1349 Token _scan(String code) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1418 * Checks if [token] has a balanced number of open and closed curly brackets. | 1384 * Checks if [token] has a balanced number of open and closed curly brackets. |
| 1419 */ | 1385 */ |
| 1420 static bool _areCurlyBracketsBalanced(Token token) { | 1386 static bool _areCurlyBracketsBalanced(Token token) { |
| 1421 int numOpen = _getTokenCount(token, TokenType.OPEN_CURLY_BRACKET); | 1387 int numOpen = _getTokenCount(token, TokenType.OPEN_CURLY_BRACKET); |
| 1422 int numOpen2 = | 1388 int numOpen2 = |
| 1423 _getTokenCount(token, TokenType.STRING_INTERPOLATION_EXPRESSION); | 1389 _getTokenCount(token, TokenType.STRING_INTERPOLATION_EXPRESSION); |
| 1424 int numClosed = _getTokenCount(token, TokenType.CLOSE_CURLY_BRACKET); | 1390 int numClosed = _getTokenCount(token, TokenType.CLOSE_CURLY_BRACKET); |
| 1425 return numOpen + numOpen2 == numClosed; | 1391 return numOpen + numOpen2 == numClosed; |
| 1426 } | 1392 } |
| 1427 | 1393 |
| 1428 static _TokenDifferenceKind _compareToken(Token oldToken, Token newToken, | 1394 static _TokenDifferenceKind _compareToken( |
| 1429 int delta, bool forComment) { | 1395 Token oldToken, Token newToken, int delta, bool forComment) { |
| 1430 while (true) { | 1396 while (true) { |
| 1431 if (oldToken == null && newToken == null) { | 1397 if (oldToken == null && newToken == null) { |
| 1432 return null; | 1398 return null; |
| 1433 } | 1399 } |
| 1434 if (oldToken == null || newToken == null) { | 1400 if (oldToken == null || newToken == null) { |
| 1435 return _TokenDifferenceKind.CONTENT; | 1401 return _TokenDifferenceKind.CONTENT; |
| 1436 } | 1402 } |
| 1437 if (oldToken.type != newToken.type) { | 1403 if (oldToken.type != newToken.type) { |
| 1438 return _TokenDifferenceKind.CONTENT; | 1404 return _TokenDifferenceKind.CONTENT; |
| 1439 } | 1405 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1532 | 1498 |
| 1533 static List<AstNode> _getParents(AstNode node) { | 1499 static List<AstNode> _getParents(AstNode node) { |
| 1534 List<AstNode> parents = <AstNode>[]; | 1500 List<AstNode> parents = <AstNode>[]; |
| 1535 while (node != null) { | 1501 while (node != null) { |
| 1536 parents.insert(0, node); | 1502 parents.insert(0, node); |
| 1537 node = node.parent; | 1503 node = node.parent; |
| 1538 } | 1504 } |
| 1539 return parents; | 1505 return parents; |
| 1540 } | 1506 } |
| 1541 | 1507 |
| 1542 | |
| 1543 /** | 1508 /** |
| 1544 * Returns number of tokens with the given [type]. | 1509 * Returns number of tokens with the given [type]. |
| 1545 */ | 1510 */ |
| 1546 static int _getTokenCount(Token token, TokenType type) { | 1511 static int _getTokenCount(Token token, TokenType type) { |
| 1547 int count = 0; | 1512 int count = 0; |
| 1548 while (token.type != TokenType.EOF) { | 1513 while (token.type != TokenType.EOF) { |
| 1549 if (token.type == type) { | 1514 if (token.type == type) { |
| 1550 count++; | 1515 count++; |
| 1551 } | 1516 } |
| 1552 token = token.next; | 1517 token = token.next; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1566 parent.precedingComments = comment; | 1531 parent.precedingComments = comment; |
| 1567 } else if (parent is TokenWithComment) { | 1532 } else if (parent is TokenWithComment) { |
| 1568 parent.precedingComments = comment; | 1533 parent.precedingComments = comment; |
| 1569 } else { | 1534 } else { |
| 1570 Type parentType = parent != null ? parent.runtimeType : null; | 1535 Type parentType = parent != null ? parent.runtimeType : null; |
| 1571 throw new AnalysisException('Uknown parent token type: $parentType'); | 1536 throw new AnalysisException('Uknown parent token type: $parentType'); |
| 1572 } | 1537 } |
| 1573 } | 1538 } |
| 1574 } | 1539 } |
| 1575 | 1540 |
| 1576 | |
| 1577 /** | 1541 /** |
| 1578 * The context to resolve an [AstNode] in. | 1542 * The context to resolve an [AstNode] in. |
| 1579 */ | 1543 */ |
| 1580 class ResolutionContext { | 1544 class ResolutionContext { |
| 1581 CompilationUnitElement enclosingUnit; | 1545 CompilationUnitElement enclosingUnit; |
| 1582 ClassDeclaration enclosingClassDeclaration; | 1546 ClassDeclaration enclosingClassDeclaration; |
| 1583 ClassElement enclosingClass; | 1547 ClassElement enclosingClass; |
| 1584 Scope scope; | 1548 Scope scope; |
| 1585 } | 1549 } |
| 1586 | 1550 |
| 1587 | |
| 1588 /** | 1551 /** |
| 1589 * Instances of the class [ResolutionContextBuilder] build the context for a | 1552 * Instances of the class [ResolutionContextBuilder] build the context for a |
| 1590 * given node in an AST structure. At the moment, this class only handles | 1553 * given node in an AST structure. At the moment, this class only handles |
| 1591 * top-level and class-level declarations. | 1554 * top-level and class-level declarations. |
| 1592 */ | 1555 */ |
| 1593 class ResolutionContextBuilder { | 1556 class ResolutionContextBuilder { |
| 1594 /** | 1557 /** |
| 1595 * The listener to which analysis errors will be reported. | 1558 * The listener to which analysis errors will be reported. |
| 1596 */ | 1559 */ |
| 1597 final AnalysisErrorListener _errorListener; | 1560 final AnalysisErrorListener _errorListener; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1653 } | 1616 } |
| 1654 Scope scope = _scopeForAstNode(parent); | 1617 Scope scope = _scopeForAstNode(parent); |
| 1655 if (node is ClassDeclaration) { | 1618 if (node is ClassDeclaration) { |
| 1656 _enclosingClassDeclaration = node; | 1619 _enclosingClassDeclaration = node; |
| 1657 _enclosingClass = node.element; | 1620 _enclosingClass = node.element; |
| 1658 if (_enclosingClass == null) { | 1621 if (_enclosingClass == null) { |
| 1659 throw new AnalysisException( | 1622 throw new AnalysisException( |
| 1660 "Cannot build a scope for an unresolved class"); | 1623 "Cannot build a scope for an unresolved class"); |
| 1661 } | 1624 } |
| 1662 scope = new ClassScope( | 1625 scope = new ClassScope( |
| 1663 new TypeParameterScope(scope, _enclosingClass), | 1626 new TypeParameterScope(scope, _enclosingClass), _enclosingClass); |
| 1664 _enclosingClass); | |
| 1665 } else if (node is ClassTypeAlias) { | 1627 } else if (node is ClassTypeAlias) { |
| 1666 ClassElement element = node.element; | 1628 ClassElement element = node.element; |
| 1667 if (element == null) { | 1629 if (element == null) { |
| 1668 throw new AnalysisException( | 1630 throw new AnalysisException( |
| 1669 "Cannot build a scope for an unresolved class type alias"); | 1631 "Cannot build a scope for an unresolved class type alias"); |
| 1670 } | 1632 } |
| 1671 scope = new ClassScope(new TypeParameterScope(scope, element), element); | 1633 scope = new ClassScope(new TypeParameterScope(scope, element), element); |
| 1672 } else if (node is ConstructorDeclaration) { | 1634 } else if (node is ConstructorDeclaration) { |
| 1673 ConstructorElement element = node.element; | 1635 ConstructorElement element = node.element; |
| 1674 if (element == null) { | 1636 if (element == null) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1718 | 1680 |
| 1719 /** | 1681 /** |
| 1720 * Return the context in which the given AST structure should be resolved. | 1682 * Return the context in which the given AST structure should be resolved. |
| 1721 * | 1683 * |
| 1722 * [node] - the root of the AST structure to be resolved. | 1684 * [node] - the root of the AST structure to be resolved. |
| 1723 * [errorListener] - the listener to which analysis errors will be reported. | 1685 * [errorListener] - the listener to which analysis errors will be reported. |
| 1724 * | 1686 * |
| 1725 * Throws [AnalysisException] if the AST structure has not been resolved or | 1687 * Throws [AnalysisException] if the AST structure has not been resolved or |
| 1726 * is not part of a [CompilationUnit] | 1688 * is not part of a [CompilationUnit] |
| 1727 */ | 1689 */ |
| 1728 static ResolutionContext contextFor(AstNode node, | 1690 static ResolutionContext contextFor( |
| 1729 AnalysisErrorListener errorListener) { | 1691 AstNode node, AnalysisErrorListener errorListener) { |
| 1730 if (node == null) { | 1692 if (node == null) { |
| 1731 throw new AnalysisException("Cannot create context: node is null"); | 1693 throw new AnalysisException("Cannot create context: node is null"); |
| 1732 } | 1694 } |
| 1733 // build scope | 1695 // build scope |
| 1734 ResolutionContextBuilder builder = | 1696 ResolutionContextBuilder builder = |
| 1735 new ResolutionContextBuilder(errorListener); | 1697 new ResolutionContextBuilder(errorListener); |
| 1736 Scope scope = builder._scopeFor(node); | 1698 Scope scope = builder._scopeFor(node); |
| 1737 // prepare context | 1699 // prepare context |
| 1738 ResolutionContext context = new ResolutionContext(); | 1700 ResolutionContext context = new ResolutionContext(); |
| 1739 context.scope = scope; | 1701 context.scope = scope; |
| 1740 context.enclosingUnit = builder._enclosingUnit; | 1702 context.enclosingUnit = builder._enclosingUnit; |
| 1741 context.enclosingClassDeclaration = builder._enclosingClassDeclaration; | 1703 context.enclosingClassDeclaration = builder._enclosingClassDeclaration; |
| 1742 context.enclosingClass = builder._enclosingClass; | 1704 context.enclosingClass = builder._enclosingClass; |
| 1743 return context; | 1705 return context; |
| 1744 } | 1706 } |
| 1745 } | 1707 } |
| 1746 | 1708 |
| 1747 | |
| 1748 /** | 1709 /** |
| 1749 * Instances of the class [_DeclarationMismatchException] represent an exception | 1710 * Instances of the class [_DeclarationMismatchException] represent an exception |
| 1750 * that is thrown when the element model defined by a given AST structure does | 1711 * that is thrown when the element model defined by a given AST structure does |
| 1751 * not match an existing element model. | 1712 * not match an existing element model. |
| 1752 */ | 1713 */ |
| 1753 class _DeclarationMismatchException { | 1714 class _DeclarationMismatchException {} |
| 1754 } | |
| 1755 | |
| 1756 | 1715 |
| 1757 class _ElementNameOffsetUpdater extends GeneralizingElementVisitor { | 1716 class _ElementNameOffsetUpdater extends GeneralizingElementVisitor { |
| 1758 final int updateOffset; | 1717 final int updateOffset; |
| 1759 final int updateDelta; | 1718 final int updateDelta; |
| 1760 | 1719 |
| 1761 _ElementNameOffsetUpdater(this.updateOffset, this.updateDelta); | 1720 _ElementNameOffsetUpdater(this.updateOffset, this.updateDelta); |
| 1762 | 1721 |
| 1763 @override | 1722 @override |
| 1764 visitElement(Element element) { | 1723 visitElement(Element element) { |
| 1765 int nameOffset = element.nameOffset; | 1724 int nameOffset = element.nameOffset; |
| 1766 if (nameOffset > updateOffset) { | 1725 if (nameOffset > updateOffset) { |
| 1767 (element as ElementImpl).nameOffset = nameOffset + updateDelta; | 1726 (element as ElementImpl).nameOffset = nameOffset + updateDelta; |
| 1768 } | 1727 } |
| 1769 super.visitElement(element); | 1728 super.visitElement(element); |
| 1770 } | 1729 } |
| 1771 } | 1730 } |
| 1772 | 1731 |
| 1773 | |
| 1774 class _ElementsGatherer extends GeneralizingElementVisitor { | 1732 class _ElementsGatherer extends GeneralizingElementVisitor { |
| 1775 final DeclarationMatcher matcher; | 1733 final DeclarationMatcher matcher; |
| 1776 | 1734 |
| 1777 _ElementsGatherer(this.matcher); | 1735 _ElementsGatherer(this.matcher); |
| 1778 | 1736 |
| 1779 void addElements(List<Element> elements) { | 1737 void addElements(List<Element> elements) { |
| 1780 for (Element element in elements) { | 1738 for (Element element in elements) { |
| 1781 if (!element.isSynthetic) { | 1739 if (!element.isSynthetic) { |
| 1782 _addElement(element); | 1740 _addElement(element); |
| 1783 } | 1741 } |
| 1784 } | 1742 } |
| 1785 } | 1743 } |
| 1786 | 1744 |
| 1787 @override | 1745 @override |
| 1788 visitElement(Element element) { | 1746 visitElement(Element element) { |
| 1789 _addElement(element); | 1747 _addElement(element); |
| 1790 super.visitElement(element); | 1748 super.visitElement(element); |
| 1791 } | 1749 } |
| 1792 | 1750 |
| 1793 @override | 1751 @override |
| 1794 visitExecutableElement(ExecutableElement element) { | 1752 visitExecutableElement(ExecutableElement element) { |
| 1795 _addElement(element); | 1753 _addElement(element); |
| 1796 } | 1754 } |
| 1797 | 1755 |
| 1798 @override | 1756 @override |
| 1799 visitParameterElement(ParameterElement element) { | 1757 visitParameterElement(ParameterElement element) {} |
| 1800 } | |
| 1801 | 1758 |
| 1802 @override | 1759 @override |
| 1803 visitPropertyAccessorElement(PropertyAccessorElement element) { | 1760 visitPropertyAccessorElement(PropertyAccessorElement element) { |
| 1804 if (!element.isSynthetic) { | 1761 if (!element.isSynthetic) { |
| 1805 _addElement(element); | 1762 _addElement(element); |
| 1806 } | 1763 } |
| 1807 // Don't visit children (such as synthetic setter parameters). | 1764 // Don't visit children (such as synthetic setter parameters). |
| 1808 } | 1765 } |
| 1809 | 1766 |
| 1810 @override | 1767 @override |
| 1811 visitPropertyInducingElement(PropertyInducingElement element) { | 1768 visitPropertyInducingElement(PropertyInducingElement element) { |
| 1812 if (!element.isSynthetic) { | 1769 if (!element.isSynthetic) { |
| 1813 _addElement(element); | 1770 _addElement(element); |
| 1814 } | 1771 } |
| 1815 // Don't visit children (such as property accessors). | 1772 // Don't visit children (such as property accessors). |
| 1816 } | 1773 } |
| 1817 | 1774 |
| 1818 @override | 1775 @override |
| 1819 visitTypeParameterElement(TypeParameterElement element) { | 1776 visitTypeParameterElement(TypeParameterElement element) {} |
| 1820 } | |
| 1821 | 1777 |
| 1822 void _addElement(Element element) { | 1778 void _addElement(Element element) { |
| 1823 if (element != null) { | 1779 if (element != null) { |
| 1824 matcher._allElements.add(element); | 1780 matcher._allElements.add(element); |
| 1825 matcher._removedElements.add(element); | 1781 matcher._removedElements.add(element); |
| 1826 } | 1782 } |
| 1827 } | 1783 } |
| 1828 } | 1784 } |
| 1829 | 1785 |
| 1830 | |
| 1831 /** | 1786 /** |
| 1832 * Describes how two [Token]s are different. | 1787 * Describes how two [Token]s are different. |
| 1833 */ | 1788 */ |
| 1834 class _TokenDifferenceKind { | 1789 class _TokenDifferenceKind { |
| 1835 static const COMMENT = const _TokenDifferenceKind('COMMENT'); | 1790 static const COMMENT = const _TokenDifferenceKind('COMMENT'); |
| 1836 static const COMMENT_DOC = const _TokenDifferenceKind('COMMENT_DOC'); | 1791 static const COMMENT_DOC = const _TokenDifferenceKind('COMMENT_DOC'); |
| 1837 static const CONTENT = const _TokenDifferenceKind('CONTENT'); | 1792 static const CONTENT = const _TokenDifferenceKind('CONTENT'); |
| 1838 static const OFFSET = const _TokenDifferenceKind('OFFSET'); | 1793 static const OFFSET = const _TokenDifferenceKind('OFFSET'); |
| 1839 | 1794 |
| 1840 final String name; | 1795 final String name; |
| 1841 | 1796 |
| 1842 const _TokenDifferenceKind(this.name); | 1797 const _TokenDifferenceKind(this.name); |
| 1843 | 1798 |
| 1844 @override | 1799 @override |
| 1845 String toString() => name; | 1800 String toString() => name; |
| 1846 } | 1801 } |
| 1847 | 1802 |
| 1848 | |
| 1849 class _TokenPair { | 1803 class _TokenPair { |
| 1850 final _TokenDifferenceKind kind; | 1804 final _TokenDifferenceKind kind; |
| 1851 final Token oldToken; | 1805 final Token oldToken; |
| 1852 final Token newToken; | 1806 final Token newToken; |
| 1853 _TokenPair(this.kind, this.oldToken, this.newToken); | 1807 _TokenPair(this.kind, this.oldToken, this.newToken); |
| 1854 } | 1808 } |
| OLD | NEW |