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 |