Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1007)

Unified Diff: packages/analyzer/lib/src/generated/incremental_resolver.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: packages/analyzer/lib/src/generated/incremental_resolver.dart
diff --git a/packages/analyzer/lib/src/generated/incremental_resolver.dart b/packages/analyzer/lib/src/generated/incremental_resolver.dart
index 4a8dada0a00c218f2a40cf1a9a33d5bf9f846e39..f17e793604d77975d0cfd98d274ceed7c6beec6b 100644
--- a/packages/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/packages/analyzer/lib/src/generated/incremental_resolver.dart
@@ -2,846 +2,39 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library engine.incremental_resolver;
+library analyzer.src.generated.incremental_resolver;
import 'dart:collection';
import 'dart:math' as math;
-import 'package:analyzer/src/context/cache.dart'
- show CacheEntry, Delta, DeltaResult;
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/builder.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error_verifier.dart';
+import 'package:analyzer/src/generated/incremental_logger.dart'
+ show logger, LoggingTimer;
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/general.dart' show CONTENT, LINE_INFO;
-import 'package:analyzer/task/model.dart'
- show AnalysisTarget, ResultDescriptor, TargetedResult, TaskDescriptor;
-
-import 'ast.dart';
-import 'element.dart';
-import 'engine.dart'
- show
- AnalysisContext,
- AnalysisOptions,
- CacheState,
- DartEntry,
- DataDescriptor,
- InternalAnalysisContext,
- RecordingErrorListener,
- SourceEntry;
-import 'error.dart';
-import 'error_verifier.dart';
-import 'incremental_logger.dart' show logger, LoggingTimer;
-import 'java_engine.dart';
-import 'parser.dart';
-import 'resolver.dart';
-import 'scanner.dart';
-import 'source.dart';
-import 'utilities_dart.dart';
-
-/**
- * If `true`, an attempt to resolve API-changing modifications is made.
- */
-bool _resolveApiChanges = false;
-
-/**
- * This method is used to enable/disable API-changing modifications resolution.
- */
-void set test_resolveApiChanges(bool value) {
- _resolveApiChanges = value;
-}
-
-/**
- * Instances of the class [DeclarationMatcher] determine whether the element
- * model defined by a given AST structure matches an existing element model.
- */
-class DeclarationMatcher extends RecursiveAstVisitor {
- /**
- * The libary containing the AST nodes being visited.
- */
- LibraryElement _enclosingLibrary;
-
- /**
- * The compilation unit containing the AST nodes being visited.
- */
- CompilationUnitElement _enclosingUnit;
-
- /**
- * The function type alias containing the AST nodes being visited, or `null` if we are not
- * in the scope of a function type alias.
- */
- FunctionTypeAliasElement _enclosingAlias;
-
- /**
- * The class containing the AST nodes being visited, or `null` if we are not
- * in the scope of a class.
- */
- ClassElementImpl _enclosingClass;
-
- /**
- * The parameter containing the AST nodes being visited, or `null` if we are not in the
- * scope of a parameter.
- */
- ParameterElement _enclosingParameter;
-
- FieldDeclaration _enclosingFieldNode = null;
- bool _inTopLevelVariableDeclaration = false;
-
- /**
- * Is `true` if the current class declaration has a constructor.
- */
- bool _hasConstructor = false;
-
- /**
- * A set containing all of the elements in the element model that were defined by the old AST node
- * corresponding to the AST node being visited.
- */
- HashSet<Element> _allElements = new HashSet<Element>();
-
- /**
- * A set containing all of the elements were defined in the old element model,
- * but are not defined in the new element model.
- */
- HashSet<Element> _removedElements = new HashSet<Element>();
-
- /**
- * A set containing all of the elements are defined in the new element model,
- * but were not defined in the old element model.
- */
- HashSet<Element> _addedElements = new HashSet<Element>();
-
- /**
- * Determines how elements model corresponding to the given [node] differs
- * from the [element].
- */
- DeclarationMatchKind matches(AstNode node, Element element) {
- logger.enter('match $element @ ${element.nameOffset}');
- try {
- _captureEnclosingElements(element);
- _gatherElements(element);
- node.accept(this);
- } on _DeclarationMismatchException {
- return DeclarationMatchKind.MISMATCH;
- } finally {
- logger.exit();
- }
- // no API changes
- if (_removedElements.isEmpty && _addedElements.isEmpty) {
- return DeclarationMatchKind.MATCH;
- }
- // simple API change
- logger.log('_removedElements: $_removedElements');
- logger.log('_addedElements: $_addedElements');
- _removedElements.forEach(_removeElement);
- if (_removedElements.length <= 1 && _addedElements.length == 1) {
- return DeclarationMatchKind.MISMATCH_OK;
- }
- // something more complex
- return DeclarationMatchKind.MISMATCH;
- }
-
- @override
- visitBlockFunctionBody(BlockFunctionBody node) {
- // ignore bodies
- }
-
- @override
- visitClassDeclaration(ClassDeclaration node) {
- String name = node.name.name;
- ClassElement element = _findElement(_enclosingUnit.types, name);
- _enclosingClass = element;
- _processElement(element);
- _assertSameAnnotations(node, element);
- _assertSameTypeParameters(node.typeParameters, element.typeParameters);
- // check for missing clauses
- if (node.extendsClause == null) {
- _assertTrue(element.supertype.name == 'Object');
- }
- if (node.implementsClause == null) {
- _assertTrue(element.interfaces.isEmpty);
- }
- if (node.withClause == null) {
- _assertTrue(element.mixins.isEmpty);
- }
- // process clauses and members
- _hasConstructor = false;
- super.visitClassDeclaration(node);
- // process default constructor
- if (!_hasConstructor) {
- ConstructorElement constructor = element.unnamedConstructor;
- _processElement(constructor);
- if (!constructor.isSynthetic) {
- _assertEquals(constructor.parameters.length, 0);
- }
- }
- }
-
- @override
- visitClassTypeAlias(ClassTypeAlias node) {
- String name = node.name.name;
- ClassElement element = _findElement(_enclosingUnit.types, name);
- _enclosingClass = element;
- _processElement(element);
- _assertSameTypeParameters(node.typeParameters, element.typeParameters);
- super.visitClassTypeAlias(node);
- }
-
- @override
- visitCompilationUnit(CompilationUnit node) {
- _processElement(_enclosingUnit);
- super.visitCompilationUnit(node);
- }
-
- @override
- visitConstructorDeclaration(ConstructorDeclaration node) {
- _hasConstructor = true;
- SimpleIdentifier constructorName = node.name;
- ConstructorElementImpl element = constructorName == null
- ? _enclosingClass.unnamedConstructor
- : _enclosingClass.getNamedConstructor(constructorName.name);
- _processElement(element);
- _assertEquals(node.constKeyword != null, element.isConst);
- _assertEquals(node.factoryKeyword != null, element.isFactory);
- _assertCompatibleParameters(node.parameters, element.parameters);
- // matches, update the existing element
- ExecutableElement newElement = node.element;
- node.element = element;
- _setLocalElements(element, newElement);
- }
-
- @override
- visitEnumConstantDeclaration(EnumConstantDeclaration node) {
- String name = node.name.name;
- FieldElement element = _findElement(_enclosingClass.fields, name);
- _processElement(element);
- }
-
- @override
- visitEnumDeclaration(EnumDeclaration node) {
- String name = node.name.name;
- ClassElement element = _findElement(_enclosingUnit.enums, name);
- _enclosingClass = element;
- _processElement(element);
- _assertTrue(element.isEnum);
- super.visitEnumDeclaration(node);
- }
-
- @override
- visitExportDirective(ExportDirective node) {
- String uri = _getStringValue(node.uri);
- if (uri != null) {
- ExportElement element =
- _findUriReferencedElement(_enclosingLibrary.exports, uri);
- _processElement(element);
- _assertCombinators(node.combinators, element.combinators);
- }
- }
-
- @override
- visitExpressionFunctionBody(ExpressionFunctionBody node) {
- // ignore bodies
- }
-
- @override
- visitExtendsClause(ExtendsClause node) {
- _assertSameType(node.superclass, _enclosingClass.supertype);
- }
-
- @override
- visitFieldDeclaration(FieldDeclaration node) {
- _enclosingFieldNode = node;
- try {
- super.visitFieldDeclaration(node);
- } finally {
- _enclosingFieldNode = null;
- }
- }
-
- @override
- visitFunctionDeclaration(FunctionDeclaration node) {
- // prepare element name
- String name = node.name.name;
- if (node.isSetter) {
- name += '=';
- }
- // prepare element
- Token property = node.propertyKeyword;
- ExecutableElementImpl element;
- if (property == null) {
- element = _findElement(_enclosingUnit.functions, name);
- } else {
- element = _findElement(_enclosingUnit.accessors, name);
- }
- // process element
- _processElement(element);
- _assertSameAnnotations(node, element);
- _assertFalse(element.isSynthetic);
- _assertSameType(node.returnType, element.returnType);
- _assertCompatibleParameters(
- node.functionExpression.parameters, element.parameters);
- _assertBody(node.functionExpression.body, element);
- // matches, update the existing element
- ExecutableElement newElement = node.element;
- node.name.staticElement = element;
- node.functionExpression.element = element;
- _setLocalElements(element, newElement);
- }
-
- @override
- visitFunctionTypeAlias(FunctionTypeAlias node) {
- String name = node.name.name;
- FunctionTypeAliasElement element =
- _findElement(_enclosingUnit.functionTypeAliases, name);
- _processElement(element);
- _assertSameTypeParameters(node.typeParameters, element.typeParameters);
- _assertSameType(node.returnType, element.returnType);
- _assertCompatibleParameters(node.parameters, element.parameters);
- }
-
- @override
- visitImplementsClause(ImplementsClause node) {
- List<TypeName> nodes = node.interfaces;
- List<InterfaceType> types = _enclosingClass.interfaces;
- _assertSameTypes(nodes, types);
- }
-
- @override
- visitImportDirective(ImportDirective node) {
- String uri = _getStringValue(node.uri);
- if (uri != null) {
- ImportElement element =
- _findUriReferencedElement(_enclosingLibrary.imports, uri);
- _processElement(element);
- // match the prefix
- SimpleIdentifier prefixNode = node.prefix;
- PrefixElement prefixElement = element.prefix;
- if (prefixNode == null) {
- _assertNull(prefixElement);
- } else {
- _assertNotNull(prefixElement);
- _assertEquals(prefixNode.name, prefixElement.name);
- }
- // match combinators
- _assertCombinators(node.combinators, element.combinators);
- }
- }
-
- @override
- visitMethodDeclaration(MethodDeclaration node) {
- // prepare element name
- String name = node.name.name;
- if (name == TokenType.MINUS.lexeme &&
- node.parameters.parameters.length == 0) {
- name = "unary-";
- }
- if (node.isSetter) {
- name += '=';
- }
- // prepare element
- Token property = node.propertyKeyword;
- ExecutableElementImpl element;
- if (property == null) {
- element = _findElement(_enclosingClass.methods, name);
- } else {
- element = _findElement(_enclosingClass.accessors, name);
- }
- // process element
- ExecutableElement newElement = node.element;
- try {
- _assertNotNull(element);
- _assertSameAnnotations(node, element);
- _assertEquals(node.isStatic, element.isStatic);
- _assertSameType(node.returnType, element.returnType);
- _assertCompatibleParameters(node.parameters, element.parameters);
- _assertBody(node.body, element);
- _removedElements.remove(element);
- // matches, update the existing element
- node.name.staticElement = element;
- _setLocalElements(element, newElement);
- } on _DeclarationMismatchException {
- _removeElement(element);
- // add new element
- if (newElement != null) {
- _addedElements.add(newElement);
- if (newElement is MethodElement) {
- List<MethodElement> methods = _enclosingClass.methods;
- methods.add(newElement);
- _enclosingClass.methods = methods;
- } else {
- List<PropertyAccessorElement> accessors = _enclosingClass.accessors;
- accessors.add(newElement);
- _enclosingClass.accessors = accessors;
- }
- }
- }
- }
-
- @override
- visitPartDirective(PartDirective node) {
- String uri = _getStringValue(node.uri);
- if (uri != null) {
- CompilationUnitElement element =
- _findUriReferencedElement(_enclosingLibrary.parts, uri);
- _processElement(element);
- }
- super.visitPartDirective(node);
- }
-
- @override
- visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- _inTopLevelVariableDeclaration = true;
- try {
- super.visitTopLevelVariableDeclaration(node);
- } finally {
- _inTopLevelVariableDeclaration = false;
- }
- }
-
- @override
- visitVariableDeclaration(VariableDeclaration node) {
- // prepare variable
- String name = node.name.name;
- PropertyInducingElement element;
- if (_inTopLevelVariableDeclaration) {
- element = _findElement(_enclosingUnit.topLevelVariables, name);
- } else {
- element = _findElement(_enclosingClass.fields, name);
- }
- // verify
- PropertyInducingElement newElement = node.name.staticElement;
- _processElement(element);
- _assertSameAnnotations(node, element);
- _assertEquals(node.isConst, element.isConst);
- _assertEquals(node.isFinal, element.isFinal);
- if (_enclosingFieldNode != null) {
- _assertEquals(_enclosingFieldNode.isStatic, element.isStatic);
- }
- _assertSameType(
- (node.parent as VariableDeclarationList).type, element.type);
- // matches, restore the existing element
- node.name.staticElement = element;
- if (element is VariableElementImpl) {
- (element as VariableElementImpl).initializer = newElement.initializer;
- }
- }
-
- @override
- visitWithClause(WithClause node) {
- List<TypeName> nodes = node.mixinTypes;
- List<InterfaceType> types = _enclosingClass.mixins;
- _assertSameTypes(nodes, types);
- }
-
- /**
- * Assert that the given [body] is compatible with the given [element].
- * It should not be empty if the [element] is not an abstract class member.
- * If it is present, it should have the same async / generator modifiers.
- */
- void _assertBody(FunctionBody body, ExecutableElementImpl element) {
- if (body is EmptyFunctionBody) {
- _assertTrue(element.isAbstract);
- } else {
- _assertFalse(element.isAbstract);
- _assertEquals(body.isSynchronous, element.isSynchronous);
- _assertEquals(body.isGenerator, element.isGenerator);
- }
- }
-
- void _assertCombinators(List<Combinator> nodeCombinators,
- List<NamespaceCombinator> elementCombinators) {
- // prepare shown/hidden names in the element
- Set<String> showNames = new Set<String>();
- Set<String> hideNames = new Set<String>();
- for (NamespaceCombinator combinator in elementCombinators) {
- if (combinator is ShowElementCombinator) {
- showNames.addAll(combinator.shownNames);
- } else if (combinator is HideElementCombinator) {
- hideNames.addAll(combinator.hiddenNames);
- }
- }
- // match combinators with the node
- for (Combinator combinator in nodeCombinators) {
- if (combinator is ShowCombinator) {
- for (SimpleIdentifier nameNode in combinator.shownNames) {
- String name = nameNode.name;
- _assertTrue(showNames.remove(name));
- }
- } else if (combinator is HideCombinator) {
- for (SimpleIdentifier nameNode in combinator.hiddenNames) {
- String name = nameNode.name;
- _assertTrue(hideNames.remove(name));
- }
- }
- }
- _assertTrue(showNames.isEmpty);
- _assertTrue(hideNames.isEmpty);
- }
-
- void _assertCompatibleParameter(
- FormalParameter node, ParameterElement element) {
- _assertEquals(node.kind, element.parameterKind);
- if (node.kind == ParameterKind.NAMED) {
- _assertEquals(node.identifier.name, element.name);
- }
- // check parameter type specific properties
- if (node is DefaultFormalParameter) {
- Expression nodeDefault = node.defaultValue;
- if (nodeDefault == null) {
- _assertNull(element.defaultValueCode);
- } else {
- _assertEquals(nodeDefault.toSource(), element.defaultValueCode);
- }
- _assertCompatibleParameter(node.parameter, element);
- } else if (node is FieldFormalParameter) {
- _assertTrue(element.isInitializingFormal);
- DartType parameterType = element.type;
- if (node.type == null && node.parameters == null) {
- FieldFormalParameterElement parameterElement = element;
- if (!parameterElement.hasImplicitType) {
- _assertTrue(parameterType == null || parameterType.isDynamic);
- }
- if (parameterElement.field != null) {
- _assertEquals(node.identifier.name, element.name);
- }
- } else {
- if (node.parameters != null) {
- _assertTrue(parameterType is FunctionType);
- FunctionType parameterFunctionType = parameterType;
- _assertSameType(node.type, parameterFunctionType.returnType);
- } else {
- _assertSameType(node.type, parameterType);
- }
- }
- _assertCompatibleParameters(node.parameters, element.parameters);
- } else if (node is FunctionTypedFormalParameter) {
- _assertFalse(element.isInitializingFormal);
- _assertTrue(element.type is FunctionType);
- FunctionType elementType = element.type;
- _assertCompatibleParameters(node.parameters, element.parameters);
- _assertSameType(node.returnType, elementType.returnType);
- } else if (node is SimpleFormalParameter) {
- _assertFalse(element.isInitializingFormal);
- _assertSameType(node.type, element.type);
- }
- }
-
- void _assertCompatibleParameters(
- FormalParameterList nodes, List<ParameterElement> elements) {
- if (nodes == null) {
- return _assertEquals(elements.length, 0);
- }
- List<FormalParameter> parameters = nodes.parameters;
- int length = parameters.length;
- _assertEquals(length, elements.length);
- for (int i = 0; i < length; i++) {
- _assertCompatibleParameter(parameters[i], elements[i]);
- }
- }
-
- /**
- * Asserts that there is an import with the same prefix as the given
- * [prefixNode], which exposes the given [element].
- */
- void _assertElementVisibleWithPrefix(
- SimpleIdentifier prefixNode, Element element) {
- if (prefixNode == null) {
- return;
- }
- String prefixName = prefixNode.name;
- for (ImportElement import in _enclosingLibrary.imports) {
- if (import.prefix != null && import.prefix.name == prefixName) {
- Namespace namespace =
- new NamespaceBuilder().createImportNamespaceForDirective(import);
- Iterable<Element> visibleElements = namespace.definedNames.values;
- if (visibleElements.contains(element)) {
- return;
- }
- }
- }
- _assertTrue(false);
- }
-
- void _assertEquals(Object a, Object b) {
- if (a != b) {
- throw new _DeclarationMismatchException();
- }
- }
-
- void _assertFalse(bool condition) {
- if (condition) {
- throw new _DeclarationMismatchException();
- }
- }
-
- void _assertNotNull(Object object) {
- if (object == null) {
- throw new _DeclarationMismatchException();
- }
- }
-
- void _assertNull(Object object) {
- if (object != null) {
- throw new _DeclarationMismatchException();
- }
- }
-
- void _assertSameAnnotation(Annotation node, ElementAnnotation annotation) {
- Element element = annotation.element;
- if (element is ConstructorElement) {
- _assertTrue(node.name is SimpleIdentifier);
- _assertNull(node.constructorName);
- TypeName nodeType = new TypeName(node.name, null);
- _assertSameType(nodeType, element.returnType);
- // TODO(scheglov) validate arguments
- }
- if (element is PropertyAccessorElement) {
- _assertTrue(node.name is SimpleIdentifier);
- String nodeName = node.name.name;
- String elementName = element.displayName;
- _assertEquals(nodeName, elementName);
- }
- }
-
- void _assertSameAnnotations(AnnotatedNode node, Element element) {
- List<Annotation> nodeAnnotaitons = node.metadata;
- List<ElementAnnotation> elementAnnotations = element.metadata;
- int length = nodeAnnotaitons.length;
- _assertEquals(elementAnnotations.length, length);
- for (int i = 0; i < length; i++) {
- _assertSameAnnotation(nodeAnnotaitons[i], elementAnnotations[i]);
- }
- }
-
- void _assertSameType(TypeName node, DartType type) {
- // no type == dynamic
- if (node == null) {
- return _assertTrue(type == null || type.isDynamic);
- }
- if (type == null) {
- return _assertTrue(false);
- }
- // prepare name
- SimpleIdentifier prefixIdentifier = null;
- Identifier nameIdentifier = node.name;
- if (nameIdentifier is PrefixedIdentifier) {
- PrefixedIdentifier prefixedIdentifier = nameIdentifier;
- prefixIdentifier = prefixedIdentifier.prefix;
- nameIdentifier = prefixedIdentifier.identifier;
- }
- String nodeName = nameIdentifier.name;
- // check specific type kinds
- if (type is ParameterizedType) {
- _assertEquals(nodeName, type.name);
- _assertElementVisibleWithPrefix(prefixIdentifier, type.element);
- // check arguments
- TypeArgumentList nodeArgumentList = node.typeArguments;
- List<DartType> typeArguments = type.typeArguments;
- if (nodeArgumentList == null) {
- // Node doesn't have type arguments, so all type arguments of the
- // element must be "dynamic".
- for (DartType typeArgument in typeArguments) {
- _assertTrue(typeArgument.isDynamic);
- }
- } else {
- List<TypeName> nodeArguments = nodeArgumentList.arguments;
- _assertSameTypes(nodeArguments, typeArguments);
- }
- } else if (type is TypeParameterType) {
- _assertEquals(nodeName, type.name);
- // TODO(scheglov) it should be possible to rename type parameters
- } else if (type.isVoid) {
- _assertEquals(nodeName, 'void');
- } else if (type.isDynamic) {
- _assertEquals(nodeName, 'dynamic');
- } else {
- // TODO(scheglov) support other types
- logger.log('node: $node type: $type type.type: ${type.runtimeType}');
- _assertTrue(false);
- }
- }
-
- void _assertSameTypeParameter(
- TypeParameter node, TypeParameterElement element) {
- _assertSameType(node.bound, element.bound);
- }
-
- void _assertSameTypeParameters(
- TypeParameterList nodesList, List<TypeParameterElement> elements) {
- if (nodesList == null) {
- return _assertEquals(elements.length, 0);
- }
- List<TypeParameter> nodes = nodesList.typeParameters;
- int length = nodes.length;
- _assertEquals(length, elements.length);
- for (int i = 0; i < length; i++) {
- _assertSameTypeParameter(nodes[i], elements[i]);
- }
- }
-
- void _assertSameTypes(List<TypeName> nodes, List<DartType> types) {
- int length = nodes.length;
- _assertEquals(length, types.length);
- for (int i = 0; i < length; i++) {
- _assertSameType(nodes[i], types[i]);
- }
- }
-
- void _assertTrue(bool condition) {
- if (!condition) {
- throw new _DeclarationMismatchException();
- }
- }
-
- /**
- * Given that the comparison is to begin with the given [element], capture
- * the enclosing elements that might be used while performing the comparison.
- */
- void _captureEnclosingElements(Element element) {
- Element parent =
- element is CompilationUnitElement ? element : element.enclosingElement;
- while (parent != null) {
- if (parent is CompilationUnitElement) {
- _enclosingUnit = parent;
- _enclosingLibrary = element.library;
- } else if (parent is ClassElement) {
- if (_enclosingClass == null) {
- _enclosingClass = parent;
- }
- } else if (parent is FunctionTypeAliasElement) {
- if (_enclosingAlias == null) {
- _enclosingAlias = parent;
- }
- } else if (parent is ParameterElement) {
- if (_enclosingParameter == null) {
- _enclosingParameter = parent;
- }
- }
- parent = parent.enclosingElement;
- }
- }
-
- void _gatherElements(Element element) {
- _ElementsGatherer gatherer = new _ElementsGatherer(this);
- element.accept(gatherer);
- // TODO(scheglov) what if a change in a directive?
- if (identical(element, _enclosingLibrary.definingCompilationUnit)) {
- gatherer.addElements(_enclosingLibrary.imports);
- gatherer.addElements(_enclosingLibrary.exports);
- gatherer.addElements(_enclosingLibrary.parts);
- }
- }
-
- void _processElement(Element element) {
- _assertNotNull(element);
- if (!_allElements.contains(element)) {
- throw new _DeclarationMismatchException();
- }
- _removedElements.remove(element);
- }
-
- void _removeElement(Element element) {
- if (element != null) {
- Element enclosingElement = element.enclosingElement;
- if (element is MethodElement) {
- ClassElement classElement = enclosingElement;
- _removeIdenticalElement(classElement.methods, element);
- } else if (element is PropertyAccessorElement) {
- if (enclosingElement is ClassElement) {
- _removeIdenticalElement(enclosingElement.accessors, element);
- }
- if (enclosingElement is CompilationUnitElement) {
- _removeIdenticalElement(enclosingElement.accessors, element);
- }
- }
- }
- }
-
- /**
- * Return the [Element] in [elements] with the given [name].
- */
- static Element _findElement(List<Element> elements, String name) {
- for (Element element in elements) {
- if (element.name == name) {
- return element;
- }
- }
- return null;
- }
-
- /**
- * Return the [UriReferencedElement] from [elements] with the given [uri], or
- * `null` if there is no such element.
- */
- static UriReferencedElement _findUriReferencedElement(
- List<UriReferencedElement> elements, String uri) {
- for (UriReferencedElement element in elements) {
- if (element.uri == uri) {
- return element;
- }
- }
- return null;
- }
-
- /**
- * Return the value of [literal], or `null` if the string is not a constant
- * string without any string interpolation.
- */
- static String _getStringValue(StringLiteral literal) {
- if (literal is StringInterpolation) {
- return null;
- }
- return literal.stringValue;
- }
-
- /**
- * Removes the first element identical to the given [element] from [elements].
- */
- static void _removeIdenticalElement(List elements, Object element) {
- int length = elements.length;
- for (int i = 0; i < length; i++) {
- if (identical(elements[i], element)) {
- elements.removeAt(i);
- return;
- }
- }
- }
-
- static void _setLocalElements(
- ExecutableElementImpl to, ExecutableElement from) {
- if (from != null) {
- to.functions = from.functions;
- to.labels = from.labels;
- to.localVariables = from.localVariables;
- to.parameters = from.parameters;
- }
- }
-}
-
-/**
- * Describes how declarations match an existing elements model.
- */
-class DeclarationMatchKind {
- /**
- * Complete match, no API changes.
- */
- static const MATCH = const DeclarationMatchKind('MATCH');
-
- /**
- * Has API changes that we might be able to resolve incrementally.
- */
- static const MISMATCH_OK = const DeclarationMatchKind('MISMATCH_OK');
-
- /**
- * Has API changes that we cannot resolve incrementally.
- */
- static const MISMATCH = const DeclarationMatchKind('MISMATCH');
-
- final String name;
-
- const DeclarationMatchKind(this.name);
-
- @override
- String toString() => name;
-}
+import 'package:analyzer/task/model.dart';
/**
* The [Delta] implementation used by incremental resolver.
@@ -874,7 +67,7 @@ class IncrementalBodyDelta extends Delta {
@override
DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
- ResultDescriptor descriptor) {
+ ResultDescriptor descriptor, Object value) {
// A body change delta should never leak outside its source.
// It can cause invalidation of results (e.g. hints) in other sources,
// but only when a result in the updated source is INVALIDATE_NO_DELTA.
@@ -885,6 +78,7 @@ class IncrementalBodyDelta extends Delta {
bool isByTask(TaskDescriptor taskDescriptor) {
return taskDescriptor.results.contains(descriptor);
}
+
if (descriptor == CONTENT) {
return DeltaResult.KEEP_CONTINUE;
}
@@ -901,23 +95,35 @@ class IncrementalBodyDelta extends Delta {
isByTask(BuildLibraryElementTask.DESCRIPTOR) ||
isByTask(BuildPublicNamespaceTask.DESCRIPTOR) ||
isByTask(BuildSourceExportClosureTask.DESCRIPTOR) ||
- isByTask(BuildSourceImportExportClosureTask.DESCRIPTOR) ||
isByTask(ComputeConstantDependenciesTask.DESCRIPTOR) ||
isByTask(ComputeConstantValueTask.DESCRIPTOR) ||
+ isByTask(ComputeInferableStaticVariableDependenciesTask.DESCRIPTOR) ||
isByTask(ComputeLibraryCycleTask.DESCRIPTOR) ||
isByTask(DartErrorsTask.DESCRIPTOR) ||
+ isByTask(ReadyLibraryElement2Task.DESCRIPTOR) ||
+ isByTask(ReadyLibraryElement5Task.DESCRIPTOR) ||
+ isByTask(ReadyLibraryElement7Task.DESCRIPTOR) ||
+ isByTask(ReadyResolvedUnitTask.DESCRIPTOR) ||
isByTask(EvaluateUnitConstantsTask.DESCRIPTOR) ||
isByTask(GenerateHintsTask.DESCRIPTOR) ||
isByTask(InferInstanceMembersInUnitTask.DESCRIPTOR) ||
isByTask(InferStaticVariableTypesInUnitTask.DESCRIPTOR) ||
+ isByTask(InferStaticVariableTypeTask.DESCRIPTOR) ||
isByTask(LibraryErrorsReadyTask.DESCRIPTOR) ||
isByTask(LibraryUnitErrorsTask.DESCRIPTOR) ||
isByTask(ParseDartTask.DESCRIPTOR) ||
isByTask(PartiallyResolveUnitReferencesTask.DESCRIPTOR) ||
isByTask(ScanDartTask.DESCRIPTOR) ||
+ isByTask(ResolveConstantExpressionTask.DESCRIPTOR) ||
+ isByTask(ResolveDirectiveElementsTask.DESCRIPTOR) ||
+ isByTask(ResolvedUnit7InLibraryClosureTask.DESCRIPTOR) ||
+ isByTask(ResolvedUnit7InLibraryTask.DESCRIPTOR) ||
isByTask(ResolveInstanceFieldsInUnitTask.DESCRIPTOR) ||
isByTask(ResolveLibraryReferencesTask.DESCRIPTOR) ||
+ isByTask(ResolveLibraryTask.DESCRIPTOR) ||
isByTask(ResolveLibraryTypeNamesTask.DESCRIPTOR) ||
+ isByTask(ResolveTopLevelLibraryTypeBoundsTask.DESCRIPTOR) ||
+ isByTask(ResolveTopLevelUnitTypeBoundsTask.DESCRIPTOR) ||
isByTask(ResolveUnitTask.DESCRIPTOR) ||
isByTask(ResolveUnitTypeNamesTask.DESCRIPTOR) ||
isByTask(ResolveVariableReferencesTask.DESCRIPTOR) ||
@@ -943,47 +149,44 @@ class IncrementalResolver {
/**
* The context the compilation unit being resolved in.
*/
- AnalysisContext _context;
+ final AnalysisContext _context;
/**
* The object used to access the types from the core library.
*/
- TypeProvider _typeProvider;
+ final TypeProvider _typeProvider;
/**
* The type system primitives.
*/
- TypeSystem _typeSystem;
+ final TypeSystem _typeSystem;
/**
* The element for the library containing the compilation unit being resolved.
*/
- LibraryElementImpl _definingLibrary;
+ final LibraryElementImpl _definingLibrary;
- /**
- * The [DartEntry] corresponding to the source being resolved.
- */
- DartEntry oldEntry;
+ final AnalysisCache _cache;
/**
* The [CacheEntry] corresponding to the source being resolved.
*/
- CacheEntry newSourceEntry;
+ final CacheEntry newSourceEntry;
/**
* The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved.
*/
- CacheEntry newUnitEntry;
+ final CacheEntry newUnitEntry;
/**
* The source representing the compilation unit being visited.
*/
- Source _source;
+ final Source _source;
/**
* The source representing the library of the compilation unit being visited.
*/
- Source _librarySource;
+ final Source _librarySource;
/**
* The offset of the changed contents.
@@ -1003,14 +206,14 @@ class IncrementalResolver {
/**
* The delta between [_updateEndNew] and [_updateEndOld].
*/
- int _updateDelta;
+ final int _updateDelta;
/**
* The set of [AnalysisError]s that have been already shifted.
*/
- Set<AnalysisError> _alreadyShiftedErrors = new HashSet.identity();
+ final Set<AnalysisError> _alreadyShiftedErrors = new HashSet.identity();
- RecordingErrorListener errorListener = new RecordingErrorListener();
+ final RecordingErrorListener errorListener = new RecordingErrorListener();
ResolutionContext _resolutionContext;
List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS;
@@ -1021,118 +224,71 @@ class IncrementalResolver {
* given source in the given library.
*/
IncrementalResolver(
- this.oldEntry,
+ this._cache,
this.newSourceEntry,
this.newUnitEntry,
- this._definingUnit,
+ CompilationUnitElementImpl definingUnit,
this._updateOffset,
- this._updateEndOld,
- this._updateEndNew) {
- _updateDelta = _updateEndNew - _updateEndOld;
- _definingLibrary = _definingUnit.library;
- _librarySource = _definingLibrary.source;
- _source = _definingUnit.source;
- _context = _definingUnit.context;
- _typeProvider = _context.typeProvider;
- _typeSystem = _context.typeSystem;
- }
+ int updateEndOld,
+ int updateEndNew)
+ : _definingUnit = definingUnit,
+ _context = definingUnit.context,
+ _typeProvider = definingUnit.context.typeProvider,
+ _typeSystem = definingUnit.context.typeSystem,
+ _definingLibrary = definingUnit.library,
+ _source = definingUnit.source,
+ _librarySource = definingUnit.library.source,
+ _updateEndOld = updateEndOld,
+ _updateEndNew = updateEndNew,
+ _updateDelta = updateEndNew - updateEndOld;
/**
- * Resolve [node], reporting any errors or warnings to the given listener.
+ * Resolve [body], reporting any errors or warnings to the given listener.
*
- * [node] - the root of the AST structure to be resolved.
- *
- * Returns `true` if resolution was successful.
+ * [body] - the root of the AST structure to be resolved.
*/
- bool resolve(AstNode node) {
+ void resolve(BlockFunctionBody body) {
logger.enter('resolve: $_definingUnit');
try {
- AstNode rootNode = _findResolutionRoot(node);
- _prepareResolutionContext(rootNode);
+ Declaration executable = _findResolutionRoot(body);
+ _prepareResolutionContext(executable);
// update elements
_updateCache();
_updateElementNameOffsets();
- _buildElements(rootNode);
- if (!_canBeIncrementallyResolved(rootNode)) {
- return false;
- }
+ _buildElements(executable, body);
// resolve
- _resolveReferences(rootNode);
- _computeConstants(rootNode);
+ _resolveReferences(executable);
+ _computeConstants(executable);
_resolveErrors = errorListener.getErrorsForSource(_source);
// verify
- _verify(rootNode);
+ _verify(executable);
_context.invalidateLibraryHints(_librarySource);
// update entry errors
_updateEntry();
- // OK
- return true;
} finally {
logger.exit();
}
}
- void _buildElements(AstNode node) {
+ void _buildElements(Declaration executable, AstNode node) {
LoggingTimer timer = logger.startTimer();
try {
ElementHolder holder = new ElementHolder();
- ElementBuilder builder = new ElementBuilder(holder);
- if (_resolutionContext.enclosingClassDeclaration != null) {
- builder.visitClassDeclarationIncrementally(
- _resolutionContext.enclosingClassDeclaration);
- }
+ ElementBuilder builder = new ElementBuilder(holder, _definingUnit);
+ builder.initForFunctionBodyIncrementalResolution();
node.accept(builder);
+ // Move local elements into the ExecutableElementImpl.
+ ExecutableElementImpl executableElement =
+ executable.element as ExecutableElementImpl;
+ executableElement.localVariables = holder.localVariables;
+ executableElement.functions = holder.functions;
+ executableElement.labels = holder.labels;
+ holder.validate();
} finally {
timer.stop('build elements');
}
}
- /**
- * Return `true` if [node] does not have element model changes, or these
- * changes can be incrementally propagated.
- */
- bool _canBeIncrementallyResolved(AstNode node) {
- // If we are replacing the whole declaration, this means that its signature
- // is changed. It might be an API change, or not.
- //
- // If, for example, a required parameter is changed, it is not an API
- // change, but we want to find the existing corresponding Element in the
- // enclosing one, set it for the node and update as needed.
- //
- // If, for example, the name of a method is changed, it is an API change,
- // we need to know the old Element and the new Element. Again, we need to
- // check the whole enclosing Element.
- if (node is Declaration) {
- node = node.parent;
- }
- Element element = _getElement(node);
- DeclarationMatcher matcher = new DeclarationMatcher();
- DeclarationMatchKind matchKind = matcher.matches(node, element);
- if (matchKind == DeclarationMatchKind.MATCH) {
- return true;
- }
- // mismatch that cannot be incrementally fixed
- return false;
- }
-
- /**
- * Return `true` if the given node can be resolved independently of any other
- * nodes.
- *
- * *Note*: This method needs to be kept in sync with
- * [ScopeBuilder.ContextBuilder].
- *
- * [node] - the node being tested.
- */
- bool _canBeResolved(AstNode node) => node is ClassDeclaration ||
- node is ClassTypeAlias ||
- node is CompilationUnit ||
- node is ConstructorDeclaration ||
- node is FunctionDeclaration ||
- node is FunctionTypeAlias ||
- node is MethodDeclaration ||
- node is TopLevelVariableDeclaration;
-
/**
* Compute a value for all of the constants in the given [node].
*/
@@ -1140,9 +296,9 @@ class IncrementalResolver {
// compute values
{
CompilationUnit unit = node.getAncestor((n) => n is CompilationUnit);
- ConstantValueComputer computer = new ConstantValueComputer(_context,
+ ConstantValueComputer computer = new ConstantValueComputer(
_typeProvider, _context.declaredVariables, null, _typeSystem);
- computer.add(unit, _source, _librarySource);
+ computer.add(unit);
computer.computeValues();
}
// validate
@@ -1162,9 +318,11 @@ class IncrementalResolver {
*
* Throws [AnalysisException] if there is no such node.
*/
- AstNode _findResolutionRoot(AstNode node) {
+ Declaration _findResolutionRoot(AstNode node) {
while (node != null) {
- if (_canBeResolved(node)) {
+ if (node is ConstructorDeclaration ||
+ node is FunctionDeclaration ||
+ node is MethodDeclaration) {
return node;
}
node = node.parent;
@@ -1172,23 +330,9 @@ class IncrementalResolver {
throw new AnalysisException("Cannot resolve node: no resolvable node");
}
- /**
- * Return the element defined by [node], or `null` if the node does not
- * define an element.
- */
- Element _getElement(AstNode node) {
- if (node is Declaration) {
- return node.element;
- } else if (node is CompilationUnit) {
- return node.element;
- }
- return null;
- }
-
void _prepareResolutionContext(AstNode node) {
if (_resolutionContext == null) {
- _resolutionContext =
- ResolutionContextBuilder.contextFor(node, errorListener);
+ _resolutionContext = ResolutionContextBuilder.contextFor(node);
}
}
@@ -1233,31 +377,18 @@ class IncrementalResolver {
}
void _shiftEntryErrors() {
- if (oldEntry != null) {
- _shiftEntryErrors_OLD();
- } else {
- _shiftEntryErrors_NEW();
- }
- }
-
- void _shiftEntryErrors_NEW() {
_shiftErrors_NEW(HINTS);
_shiftErrors_NEW(LINTS);
_shiftErrors_NEW(LIBRARY_UNIT_ERRORS);
_shiftErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS);
+ _shiftErrors_NEW(RESOLVE_TYPE_BOUNDS_ERRORS);
_shiftErrors_NEW(RESOLVE_UNIT_ERRORS);
+ _shiftErrors_NEW(STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT);
_shiftErrors_NEW(STRONG_MODE_ERRORS);
_shiftErrors_NEW(VARIABLE_REFERENCE_ERRORS);
_shiftErrors_NEW(VERIFY_ERRORS);
}
- void _shiftEntryErrors_OLD() {
- _shiftErrors_OLD(DartEntry.RESOLUTION_ERRORS);
- _shiftErrors_OLD(DartEntry.VERIFICATION_ERRORS);
- _shiftErrors_OLD(DartEntry.HINTS);
- _shiftErrors_OLD(DartEntry.LINTS);
- }
-
void _shiftErrors(List<AnalysisError> errors) {
for (AnalysisError error in errors) {
if (_alreadyShiftedErrors.add(error)) {
@@ -1274,12 +405,6 @@ class IncrementalResolver {
_shiftErrors(errors);
}
- void _shiftErrors_OLD(DataDescriptor<List<AnalysisError>> descriptor) {
- List<AnalysisError> errors =
- oldEntry.getValueInLibrary(descriptor, _librarySource);
- _shiftErrors(errors);
- }
-
void _updateCache() {
if (newSourceEntry != null) {
LoggingTimer timer = logger.startTimer();
@@ -1296,8 +421,8 @@ class IncrementalResolver {
void _updateElementNameOffsets() {
LoggingTimer timer = logger.startTimer();
try {
- _definingUnit
- .accept(new _ElementNameOffsetUpdater(_updateOffset, _updateDelta));
+ _definingUnit.accept(
+ new _ElementOffsetUpdater(_updateOffset, _updateDelta, _cache));
_definingUnit.afterIncrementalResolution();
} finally {
timer.stop('update element offsets');
@@ -1305,15 +430,8 @@ class IncrementalResolver {
}
void _updateEntry() {
- if (oldEntry != null) {
- _updateEntry_OLD();
- } else {
- _updateEntry_NEW();
- }
- }
-
- void _updateEntry_NEW() {
_updateErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS, []);
+ _updateErrors_NEW(RESOLVE_TYPE_BOUNDS_ERRORS, []);
_updateErrors_NEW(RESOLVE_UNIT_ERRORS, _resolveErrors);
_updateErrors_NEW(VARIABLE_REFERENCE_ERRORS, []);
_updateErrors_NEW(VERIFY_ERRORS, _verifyErrors);
@@ -1325,11 +443,6 @@ class IncrementalResolver {
newUnitEntry.setState(LINTS, CacheState.INVALID);
}
- void _updateEntry_OLD() {
- _updateErrors_OLD(DartEntry.RESOLUTION_ERRORS, _resolveErrors);
- _updateErrors_OLD(DartEntry.VERIFICATION_ERRORS, _verifyErrors);
- }
-
List<AnalysisError> _updateErrors(
List<AnalysisError> oldErrors, List<AnalysisError> newErrors) {
List<AnalysisError> errors = new List<AnalysisError>();
@@ -1361,14 +474,6 @@ class IncrementalResolver {
newUnitEntry.setValueIncremental(descriptor, errors, true);
}
- void _updateErrors_OLD(DataDescriptor<List<AnalysisError>> descriptor,
- List<AnalysisError> newErrors) {
- List<AnalysisError> oldErrors =
- oldEntry.getValueInLibrary(descriptor, _librarySource);
- List<AnalysisError> errors = _updateErrors(oldErrors, newErrors);
- oldEntry.setValueInLibrary(descriptor, _librarySource, errors);
- }
-
void _verify(AstNode node) {
LoggingTimer timer = logger.startTimer();
try {
@@ -1379,7 +484,8 @@ class IncrementalResolver {
_definingLibrary,
_typeProvider,
new InheritanceManager(_definingLibrary),
- _context.analysisOptions.enableSuperMixins);
+ _context.analysisOptions.enableSuperMixins,
+ _context.analysisOptions.enableAssertMessage);
if (_resolutionContext.enclosingClassDeclaration != null) {
errorVerifier.visitClassDeclarationIncrementally(
_resolutionContext.enclosingClassDeclaration);
@@ -1395,21 +501,17 @@ class IncrementalResolver {
class PoorMansIncrementalResolver {
final TypeProvider _typeProvider;
final Source _unitSource;
-
- /**
- * The [DartEntry] corresponding to the source being resolved.
- */
- DartEntry _oldEntry;
+ final AnalysisCache _cache;
/**
* The [CacheEntry] corresponding to the source being resolved.
*/
- CacheEntry _newSourceEntry;
+ final CacheEntry _sourceEntry;
/**
* The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved.
*/
- CacheEntry _newUnitEntry;
+ final CacheEntry _unitEntry;
final CompilationUnit _oldUnit;
CompilationUnitElement _unitElement;
@@ -1426,13 +528,11 @@ class PoorMansIncrementalResolver {
PoorMansIncrementalResolver(
this._typeProvider,
this._unitSource,
- this._oldEntry,
- this._newSourceEntry,
- this._newUnitEntry,
+ this._cache,
+ this._sourceEntry,
+ this._unitEntry,
this._oldUnit,
- bool resolveApiChanges) {
- _resolveApiChanges = resolveApiChanges;
- }
+ bool resolveApiChanges);
/**
* Attempts to update [_oldUnit] to the state corresponding to [newCode].
@@ -1468,41 +568,52 @@ class PoorMansIncrementalResolver {
int endOffsetOld = math.max(firstOffsetOld, lastOffsetOld);
int beginOffsetNew = math.min(firstOffsetNew, lastOffsetNew);
int endOffsetNew = math.max(firstOffsetNew, lastOffsetNew);
- // check for a whitespace only change
- if (identical(lastPair.oldToken, firstPair.oldToken) &&
- identical(lastPair.newToken, firstPair.newToken)) {
+ // A pure whitespace change.
+ if (identical(firstPair.oldToken, lastPair.oldToken) &&
+ identical(firstPair.newToken, lastPair.newToken) &&
+ firstPair.kind == _TokenDifferenceKind.OFFSET) {
_updateOffset = beginOffsetOld - 1;
_updateEndOld = endOffsetOld;
_updateEndNew = endOffsetNew;
_updateDelta = newUnit.length - _oldUnit.length;
- // A Dart documentation comment change.
- if (firstPair.kind == _TokenDifferenceKind.COMMENT_DOC) {
- bool success = _resolveCommentDoc(newUnit, firstPair);
+ logger.log('Whitespace change.');
+ _shiftTokens(firstPair.oldToken, true);
+ IncrementalResolver incrementalResolver = new IncrementalResolver(
+ _cache,
+ _sourceEntry,
+ _unitEntry,
+ _unitElement,
+ _updateOffset,
+ _updateEndOld,
+ _updateEndNew);
+ incrementalResolver._updateCache();
+ incrementalResolver._updateElementNameOffsets();
+ incrementalResolver._shiftEntryErrors();
+ _updateEntry();
+ logger.log('Success.');
+ return true;
+ }
+ // A Dart documentation comment change.
+ {
+ Token firstOldToken = firstPair.oldToken;
+ Token firstNewToken = firstPair.newToken;
+ Token lastOldToken = lastPair.oldToken;
+ Token lastNewToken = lastPair.newToken;
+ if (firstOldToken is DocumentationCommentToken &&
+ firstNewToken is DocumentationCommentToken &&
+ lastOldToken is DocumentationCommentToken &&
+ lastNewToken is DocumentationCommentToken &&
+ identical(firstOldToken.parent, lastOldToken.parent) &&
+ identical(firstNewToken.parent, lastNewToken.parent)) {
+ _updateOffset = beginOffsetOld;
+ _updateEndOld = firstOldToken.parent.offset;
+ _updateEndNew = firstNewToken.parent.offset;
+ _updateDelta = newUnit.length - _oldUnit.length;
+ bool success =
+ _resolveCommentDoc(newUnit, firstOldToken, firstNewToken);
logger.log('Documentation comment resolved: $success');
return success;
}
- // A pure whitespace change.
- if (firstPair.kind == _TokenDifferenceKind.OFFSET) {
- logger.log('Whitespace change.');
- _shiftTokens(firstPair.oldToken);
- {
- IncrementalResolver incrementalResolver = new IncrementalResolver(
- _oldEntry,
- _newSourceEntry,
- _newUnitEntry,
- _unitElement,
- _updateOffset,
- _updateEndOld,
- _updateEndNew);
- incrementalResolver._updateCache();
- incrementalResolver._updateElementNameOffsets();
- incrementalResolver._shiftEntryErrors();
- }
- _updateEntry();
- logger.log('Success.');
- return true;
- }
- // fall-through, end-of-line comment
}
// Find nodes covering the "old" and "new" token ranges.
AstNode oldNode =
@@ -1515,51 +626,67 @@ class PoorMansIncrementalResolver {
{
List<AstNode> oldParents = _getParents(oldNode);
List<AstNode> newParents = _getParents(newNode);
+ // fail if an initializer change
+ if (oldParents.any((n) => n is ConstructorInitializer) ||
+ newParents.any((n) => n is ConstructorInitializer)) {
+ logger.log('Failure: a change in a constructor initializer');
+ return false;
+ }
+ // find matching methods / bodies
int length = math.min(oldParents.length, newParents.length);
bool found = false;
for (int i = 0; i < length; i++) {
AstNode oldParent = oldParents[i];
AstNode newParent = newParents[i];
- if (oldParent is ConstructorInitializer ||
- newParent is ConstructorInitializer) {
- logger.log('Failure: changes in constant constructor initializers'
- ' may cause external changes in constant objects.');
- return false;
- }
- if (oldParent is FunctionDeclaration &&
+ if (oldParent is CompilationUnit && newParent is CompilationUnit) {
+ int oldLength = oldParent.declarations.length;
+ int newLength = newParent.declarations.length;
+ if (oldLength != newLength) {
+ logger.log(
+ 'Failure: unit declarations mismatch $oldLength vs. $newLength');
+ return false;
+ }
+ } else if (oldParent is ClassDeclaration &&
+ newParent is ClassDeclaration) {
+ int oldLength = oldParent.members.length;
+ int newLength = newParent.members.length;
+ if (oldLength != newLength) {
+ logger.log(
+ 'Failure: class declarations mismatch $oldLength vs. $newLength');
+ return false;
+ }
+ } else if (oldParent is FunctionDeclaration &&
newParent is FunctionDeclaration ||
- oldParent is MethodDeclaration &&
- newParent is MethodDeclaration ||
oldParent is ConstructorDeclaration &&
- newParent is ConstructorDeclaration) {
- Element oldElement = (oldParent as Declaration).element;
- if (new DeclarationMatcher().matches(newParent, oldElement) ==
- DeclarationMatchKind.MATCH) {
+ newParent is ConstructorDeclaration ||
+ oldParent is MethodDeclaration &&
+ newParent is MethodDeclaration) {
+ if (oldParents.length == i || newParents.length == i) {
+ return false;
+ }
+ } else if (oldParent is FunctionBody && newParent is FunctionBody) {
+ if (oldParent is BlockFunctionBody &&
+ newParent is BlockFunctionBody) {
oldNode = oldParent;
newNode = newParent;
found = true;
+ break;
}
- }
- if (oldParent is BlockFunctionBody &&
- newParent is BlockFunctionBody) {
- oldNode = oldParent;
- newNode = newParent;
- found = true;
- break;
+ logger.log('Failure: not a block function body.');
+ return false;
+ } else if (oldParent is FunctionExpression &&
+ newParent is FunctionExpression) {
+ // skip
+ } else {
+ logger.log('Failure: old and new parent mismatch'
+ ' ${oldParent.runtimeType} vs. ${newParent.runtimeType}');
+ return false;
}
}
if (!found) {
logger.log('Failure: no enclosing function body or executable.');
return false;
}
- // fail if a comment change outside the bodies
- if (firstPair.kind == _TokenDifferenceKind.COMMENT) {
- if (beginOffsetOld <= oldNode.offset ||
- beginOffsetNew <= newNode.offset) {
- logger.log('Failure: comment outside a function body.');
- return false;
- }
- }
}
logger.log(() => 'oldNode: $oldNode');
logger.log(() => 'newNode: $newNode');
@@ -1584,28 +711,26 @@ class PoorMansIncrementalResolver {
}
// perform incremental resolution
IncrementalResolver incrementalResolver = new IncrementalResolver(
- _oldEntry,
- _newSourceEntry,
- _newUnitEntry,
+ _cache,
+ _sourceEntry,
+ _unitEntry,
_unitElement,
_updateOffset,
_updateEndOld,
_updateEndNew);
- bool success = incrementalResolver.resolve(newNode);
- // check if success
- if (!success) {
- logger.log('Failure: element model changed.');
- return false;
- }
+ incrementalResolver.resolve(newNode);
// update DartEntry
_updateEntry();
logger.log('Success.');
return true;
}
} catch (e, st) {
- logger.log(e);
- logger.log(st);
+ logger.logException(e, st);
logger.log('Failure: exception.');
+ // The incremental resolver log is usually turned off,
+ // so also log the exception to the instrumentation log.
+ AnalysisEngine.instance.logger.logError(
+ 'Failure in incremental resolver', new CaughtException(e, st));
} finally {
logger.exit();
}
@@ -1619,6 +744,7 @@ class PoorMansIncrementalResolver {
RecordingErrorListener errorListener = new RecordingErrorListener();
Parser parser = new Parser(_unitSource, errorListener);
AnalysisOptions options = _unitElement.context.analysisOptions;
+ parser.parseGenericMethodComments = options.strongMode;
parser.parseGenericMethods = options.enableGenericMethods;
CompilationUnit unit = parser.parseCompilationUnit(token);
_newParseErrors = errorListener.errors;
@@ -1632,32 +758,33 @@ class PoorMansIncrementalResolver {
* Attempts to resolve a documentation comment change.
* Returns `true` if success.
*/
- bool _resolveCommentDoc(CompilationUnit newUnit, _TokenPair firstPair) {
- Token oldToken = firstPair.oldToken;
- Token newToken = firstPair.newToken;
- CommentToken oldComments = oldToken.precedingComments;
- CommentToken newComments = newToken.precedingComments;
- if (oldComments == null || newComments == null) {
+ bool _resolveCommentDoc(
+ CompilationUnit newUnit, CommentToken oldToken, CommentToken newToken) {
+ if (oldToken == null || newToken == null) {
return false;
}
// find nodes
- int offset = oldComments.offset;
+ int offset = oldToken.offset;
logger.log('offset: $offset');
- Comment oldComment = _findNodeCovering(_oldUnit, offset, offset);
- Comment newComment = _findNodeCovering(newUnit, offset, offset);
+ AstNode oldNode = _findNodeCovering(_oldUnit, offset, offset);
+ AstNode newNode = _findNodeCovering(newUnit, offset, offset);
+ if (oldNode is! Comment || newNode is! Comment) {
+ return false;
+ }
+ Comment oldComment = oldNode;
+ Comment newComment = newNode;
logger.log('oldComment.beginToken: ${oldComment.beginToken}');
logger.log('newComment.beginToken: ${newComment.beginToken}');
- _updateOffset = oldToken.offset - 1;
// update token references
- _shiftTokens(firstPair.oldToken);
- _setPrecedingComments(oldToken, newComment.tokens.first);
+ _shiftTokens(oldToken.parent);
+ _setPrecedingComments(oldToken.parent, newComment.tokens.first);
// replace node
NodeReplacer.replace(oldComment, newComment);
// update elements
IncrementalResolver incrementalResolver = new IncrementalResolver(
- _oldEntry,
- _newSourceEntry,
- _newUnitEntry,
+ _cache,
+ _sourceEntry,
+ _unitEntry,
_unitElement,
_updateOffset,
_updateEndOld,
@@ -1668,6 +795,29 @@ class PoorMansIncrementalResolver {
_updateEntry();
// resolve references in the comment
incrementalResolver._resolveReferences(newComment);
+ // update 'documentationComment' of the parent element(s)
+ {
+ AstNode parent = newComment.parent;
+ if (parent is AnnotatedNode) {
+ setElementDocumentationForVariables(VariableDeclarationList list) {
+ for (VariableDeclaration variable in list.variables) {
+ Element variableElement = variable.element;
+ if (variableElement is ElementImpl) {
+ setElementDocumentationComment(variableElement, parent);
+ }
+ }
+ }
+
+ Element parentElement = ElementLocator.locate(newComment.parent);
+ if (parentElement is ElementImpl) {
+ setElementDocumentationComment(parentElement, parent);
+ } else if (parent is FieldDeclaration) {
+ setElementDocumentationForVariables(parent.fields);
+ } else if (parent is TopLevelVariableDeclaration) {
+ setElementDocumentationForVariables(parent.variables);
+ }
+ }
+ }
// OK
return true;
}
@@ -1676,6 +826,8 @@ class PoorMansIncrementalResolver {
RecordingErrorListener errorListener = new RecordingErrorListener();
CharSequenceReader reader = new CharSequenceReader(code);
Scanner scanner = new Scanner(_unitSource, reader, errorListener);
+ AnalysisOptions options = _unitElement.context.analysisOptions;
+ scanner.scanGenericMethodComments = options.strongMode;
Token token = scanner.tokenize();
_newLineInfo = new LineInfo(scanner.lineStarts);
_newScanErrors = errorListener.errors;
@@ -1695,13 +847,16 @@ class PoorMansIncrementalResolver {
} else if (token is TokenWithComment) {
token.precedingComments = comment;
} else {
- Type parentType = token != null ? token.runtimeType : null;
+ Type parentType = token?.runtimeType;
throw new AnalysisException('Uknown parent token type: $parentType');
}
}
- void _shiftTokens(Token token) {
+ void _shiftTokens(Token token, [bool goUpComment = false]) {
while (token != null) {
+ if (goUpComment && token is CommentToken) {
+ token = (token as CommentToken).parent;
+ }
if (token.offset > _updateOffset) {
token.offset += _updateDelta;
}
@@ -1721,26 +876,16 @@ class PoorMansIncrementalResolver {
}
void _updateEntry() {
- if (_oldEntry != null) {
- _updateEntry_OLD();
- } else {
- _updateEntry_NEW();
- }
- }
-
- void _updateEntry_NEW() {
// scan results
- _newSourceEntry.setValueIncremental(SCAN_ERRORS, _newScanErrors, true);
- _newSourceEntry.setValueIncremental(LINE_INFO, _newLineInfo, false);
+ _sourceEntry.setValueIncremental(SCAN_ERRORS, _newScanErrors, true);
+ _sourceEntry.setValueIncremental(LINE_INFO, _newLineInfo, false);
// parse results
- _newSourceEntry.setValueIncremental(PARSE_ERRORS, _newParseErrors, true);
- _newSourceEntry.setValueIncremental(PARSED_UNIT, _oldUnit, false);
- }
-
- void _updateEntry_OLD() {
- _oldEntry.setValue(SourceEntry.LINE_INFO, _newLineInfo);
- _oldEntry.setValue(DartEntry.SCAN_ERRORS, _newScanErrors);
- _oldEntry.setValue(DartEntry.PARSE_ERRORS, _newParseErrors);
+ _sourceEntry.setValueIncremental(PARSE_ERRORS, _newParseErrors, true);
+ _sourceEntry.setValueIncremental(PARSED_UNIT, _oldUnit, false);
+ // referenced names
+ ReferencedNames referencedNames = new ReferencedNames(_unitSource);
+ new ReferencedNamesBuilder(referencedNames).build(_oldUnit);
+ _sourceEntry.setValueIncremental(REFERENCED_NAMES, referencedNames, false);
}
/**
@@ -1755,38 +900,27 @@ class PoorMansIncrementalResolver {
}
static _TokenDifferenceKind _compareToken(
- Token oldToken, Token newToken, int delta, bool forComment) {
- while (true) {
- if (oldToken == null && newToken == null) {
- return null;
- }
- if (oldToken == null || newToken == null) {
- return _TokenDifferenceKind.CONTENT;
- }
- if (oldToken.type != newToken.type) {
- return _TokenDifferenceKind.CONTENT;
- }
- if (oldToken.lexeme != newToken.lexeme) {
- return _TokenDifferenceKind.CONTENT;
- }
- if (newToken.offset - oldToken.offset != delta) {
- return _TokenDifferenceKind.OFFSET;
- }
- // continue if comment tokens are being checked
- if (!forComment) {
- break;
- }
- oldToken = oldToken.next;
- newToken = newToken.next;
+ Token oldToken, Token newToken, int delta) {
+ if (oldToken == null && newToken == null) {
+ return null;
+ }
+ if (oldToken == null || newToken == null) {
+ return _TokenDifferenceKind.CONTENT;
+ }
+ if (oldToken.type != newToken.type) {
+ return _TokenDifferenceKind.CONTENT;
+ }
+ if (oldToken.lexeme != newToken.lexeme) {
+ return _TokenDifferenceKind.CONTENT;
+ }
+ if (newToken.offset - oldToken.offset != delta) {
+ return _TokenDifferenceKind.OFFSET;
}
return null;
}
static _TokenPair _findFirstDifferentToken(Token oldToken, Token newToken) {
- while (true) {
- if (oldToken.type == TokenType.EOF && newToken.type == TokenType.EOF) {
- return null;
- }
+ while (oldToken.type != TokenType.EOF || newToken.type != TokenType.EOF) {
if (oldToken.type == TokenType.EOF || newToken.type == TokenType.EOF) {
return new _TokenPair(_TokenDifferenceKind.CONTENT, oldToken, newToken);
}
@@ -1794,18 +928,22 @@ class PoorMansIncrementalResolver {
{
Token oldComment = oldToken.precedingComments;
Token newComment = newToken.precedingComments;
- if (_compareToken(oldComment, newComment, 0, true) != null) {
- _TokenDifferenceKind diffKind = _TokenDifferenceKind.COMMENT;
- if (oldComment is DocumentationCommentToken ||
- newComment is DocumentationCommentToken) {
- diffKind = _TokenDifferenceKind.COMMENT_DOC;
+ while (true) {
+ _TokenDifferenceKind diffKind =
+ _compareToken(oldComment, newComment, 0);
+ if (diffKind != null) {
+ return new _TokenPair(
+ diffKind, oldComment ?? oldToken, newComment ?? newToken);
+ }
+ if (oldComment == null && newComment == null) {
+ break;
}
- return new _TokenPair(diffKind, oldToken, newToken);
+ oldComment = oldComment.next;
+ newComment = newComment.next;
}
}
// compare tokens
- _TokenDifferenceKind diffKind =
- _compareToken(oldToken, newToken, 0, false);
+ _TokenDifferenceKind diffKind = _compareToken(oldToken, newToken, 0);
if (diffKind != null) {
return new _TokenPair(diffKind, oldToken, newToken);
}
@@ -1819,24 +957,40 @@ class PoorMansIncrementalResolver {
static _TokenPair _findLastDifferentToken(Token oldToken, Token newToken) {
int delta = newToken.offset - oldToken.offset;
+ Token prevOldToken;
+ Token prevNewToken;
while (oldToken.previous != oldToken && newToken.previous != newToken) {
// compare tokens
- _TokenDifferenceKind diffKind =
- _compareToken(oldToken, newToken, delta, false);
+ _TokenDifferenceKind diffKind = _compareToken(oldToken, newToken, delta);
if (diffKind != null) {
- return new _TokenPair(diffKind, oldToken.next, newToken.next);
+ return new _TokenPair(diffKind, prevOldToken, prevNewToken);
}
+ prevOldToken = oldToken;
+ prevNewToken = newToken;
// compare comments
{
Token oldComment = oldToken.precedingComments;
Token newComment = newToken.precedingComments;
- if (_compareToken(oldComment, newComment, delta, true) != null) {
- _TokenDifferenceKind diffKind = _TokenDifferenceKind.COMMENT;
- if (oldComment is DocumentationCommentToken ||
- newComment is DocumentationCommentToken) {
- diffKind = _TokenDifferenceKind.COMMENT_DOC;
+ while (oldComment?.next != null) {
+ oldComment = oldComment.next;
+ }
+ while (newComment?.next != null) {
+ newComment = newComment.next;
+ }
+ while (true) {
+ _TokenDifferenceKind diffKind =
+ _compareToken(oldComment, newComment, delta);
+ if (diffKind != null) {
+ return new _TokenPair(
+ diffKind, oldComment ?? oldToken, newComment ?? newToken);
+ }
+ if (oldComment == null && newComment == null) {
+ break;
}
- return new _TokenPair(diffKind, oldToken, newToken);
+ prevOldToken = oldComment;
+ prevNewToken = newComment;
+ oldComment = oldComment.previous;
+ newComment = newComment.previous;
}
}
// next tokens
@@ -1854,7 +1008,7 @@ class PoorMansIncrementalResolver {
static Token _getBeginTokenNotComment(AstNode node) {
Token oldBeginToken = node.beginToken;
if (oldBeginToken is CommentToken) {
- oldBeginToken = (oldBeginToken as CommentToken).parent;
+ return oldBeginToken.parent;
}
return oldBeginToken;
}
@@ -1899,11 +1053,6 @@ class ResolutionContext {
* top-level and class-level declarations.
*/
class ResolutionContextBuilder {
- /**
- * The listener to which analysis errors will be reported.
- */
- final AnalysisErrorListener _errorListener;
-
/**
* The class containing the enclosing [CompilationUnitElement].
*/
@@ -1921,12 +1070,6 @@ class ResolutionContextBuilder {
*/
ClassElement _enclosingClass;
- /**
- * Initialize a newly created scope builder to generate a scope that will
- * report errors to the given listener.
- */
- ResolutionContextBuilder(this._errorListener);
-
Scope _scopeFor(AstNode node) {
if (node is CompilationUnit) {
return _scopeForAstNode(node);
@@ -2020,26 +1163,23 @@ class ResolutionContextBuilder {
throw new AnalysisException(
"Cannot create scope: compilation unit is not part of a library");
}
- return new LibraryScope(libraryElement, _errorListener);
+ return new LibraryScope(libraryElement);
}
/**
* Return the context in which the given AST structure should be resolved.
*
* [node] - the root of the AST structure to be resolved.
- * [errorListener] - the listener to which analysis errors will be reported.
*
* Throws [AnalysisException] if the AST structure has not been resolved or
* is not part of a [CompilationUnit]
*/
- static ResolutionContext contextFor(
- AstNode node, AnalysisErrorListener errorListener) {
+ static ResolutionContext contextFor(AstNode node) {
if (node == null) {
throw new AnalysisException("Cannot create context: node is null");
}
// build scope
- ResolutionContextBuilder builder =
- new ResolutionContextBuilder(errorListener);
+ ResolutionContextBuilder builder = new ResolutionContextBuilder();
Scope scope = builder._scopeFor(node);
// prepare context
ResolutionContext context = new ResolutionContext();
@@ -2052,78 +1192,101 @@ class ResolutionContextBuilder {
}
/**
- * Instances of the class [_DeclarationMismatchException] represent an exception
- * that is thrown when the element model defined by a given AST structure does
- * not match an existing element model.
+ * Adjusts the location of each Element that moved.
+ *
+ * Since `==` and `hashCode` of a local variable or function Element are based
+ * on the element name offsets, we also need to remove these elements from the
+ * cache to avoid a memory leak. TODO(scheglov) fix and remove this
*/
-class _DeclarationMismatchException {}
-
-class _ElementNameOffsetUpdater extends GeneralizingElementVisitor {
+class _ElementOffsetUpdater extends GeneralizingElementVisitor {
final int updateOffset;
final int updateDelta;
+ final AnalysisCache cache;
- _ElementNameOffsetUpdater(this.updateOffset, this.updateDelta);
+ _ElementOffsetUpdater(this.updateOffset, this.updateDelta, this.cache);
@override
visitElement(Element element) {
+ // name offset
int nameOffset = element.nameOffset;
if (nameOffset > updateOffset) {
(element as ElementImpl).nameOffset = nameOffset + updateDelta;
+ if (element is ConstVariableElement) {
+ Expression initializer = element.constantInitializer;
+ if (initializer != null) {
+ _shiftTokens(initializer.beginToken);
+ }
+ _shiftErrors(element.evaluationResult?.errors);
+ }
}
- super.visitElement(element);
- }
-}
-
-class _ElementsGatherer extends GeneralizingElementVisitor {
- final DeclarationMatcher matcher;
-
- _ElementsGatherer(this.matcher);
-
- void addElements(List<Element> elements) {
- for (Element element in elements) {
- if (!element.isSynthetic) {
- _addElement(element);
+ // code range
+ if (element is ElementImpl) {
+ int oldOffset = element.codeOffset;
+ int oldLength = element.codeLength;
+ if (oldOffset != null) {
+ int newOffset = oldOffset;
+ int newLength = oldLength;
+ newOffset += oldOffset > updateOffset ? updateDelta : 0;
+ if (oldOffset <= updateOffset && updateOffset < oldOffset + oldLength) {
+ newLength += updateDelta;
+ }
+ if (newOffset != oldOffset || newLength != oldLength) {
+ element.setCodeRange(newOffset, newLength);
+ }
}
}
- }
-
- @override
- visitElement(Element element) {
- _addElement(element);
- super.visitElement(element);
- }
-
- @override
- visitExecutableElement(ExecutableElement element) {
- _addElement(element);
- }
-
- @override
- visitParameterElement(ParameterElement element) {}
-
- @override
- visitPropertyAccessorElement(PropertyAccessorElement element) {
- if (!element.isSynthetic) {
- _addElement(element);
+ // visible range
+ if (element is LocalElement) {
+ SourceRange visibleRange = element.visibleRange;
+ if (visibleRange != null) {
+ int oldOffset = visibleRange.offset;
+ int oldLength = visibleRange.length;
+ int newOffset = oldOffset;
+ int newLength = oldLength;
+ newOffset += oldOffset > updateOffset ? updateDelta : 0;
+ newLength += visibleRange.contains(updateOffset) ? updateDelta : 0;
+ if (newOffset != oldOffset || newLength != oldLength) {
+ if (element is FunctionElementImpl) {
+ element.setVisibleRange(newOffset, newLength);
+ } else if (element is LocalVariableElementImpl) {
+ element.setVisibleRange(newOffset, newLength);
+ } else if (element is ParameterElementImpl) {
+ element.setVisibleRange(newOffset, newLength);
+ }
+ }
+ }
}
- // Don't visit children (such as synthetic setter parameters).
+ super.visitElement(element);
}
- @override
- visitPropertyInducingElement(PropertyInducingElement element) {
- if (!element.isSynthetic) {
- _addElement(element);
+ void _shiftErrors(List<AnalysisError> errors) {
+ if (errors != null) {
+ for (AnalysisError error in errors) {
+ int errorOffset = error.offset;
+ if (errorOffset > updateOffset) {
+ error.offset += updateDelta;
+ }
+ }
}
- // Don't visit children (such as property accessors).
}
- @override
- visitTypeParameterElement(TypeParameterElement element) {}
-
- void _addElement(Element element) {
- if (element != null) {
- matcher._allElements.add(element);
- matcher._removedElements.add(element);
+ void _shiftTokens(Token token) {
+ while (token != null) {
+ if (token.offset > updateOffset) {
+ token.offset += updateDelta;
+ }
+ // comments
+ _shiftTokens(token.precedingComments);
+ if (token is DocumentationCommentToken) {
+ for (Token reference in token.references) {
+ _shiftTokens(reference);
+ }
+ }
+ // next
+ if (token.type == TokenType.EOF) {
+ break;
+ }
+ token = token.next;
}
}
}
@@ -2132,8 +1295,6 @@ class _ElementsGatherer extends GeneralizingElementVisitor {
* Describes how two [Token]s are different.
*/
class _TokenDifferenceKind {
- static const COMMENT = const _TokenDifferenceKind('COMMENT');
- static const COMMENT_DOC = const _TokenDifferenceKind('COMMENT_DOC');
static const CONTENT = const _TokenDifferenceKind('CONTENT');
static const OFFSET = const _TokenDifferenceKind('OFFSET');

Powered by Google App Engine
This is Rietveld 408576698