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

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

Issue 2096763004: Remove DeclarationMarcher - incrementally resolve only BlockFunctionBody. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 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: pkg/analyzer/lib/src/generated/incremental_resolver.dart
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 37d3801802d4117ec8622ce8aa97b24cf5432cdf..cca604ad642f46dd8e2a5591b244b38223038cb7 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -9,9 +9,7 @@ import 'dart:math' as math;
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/dart/ast/token.dart';
@@ -50,812 +48,6 @@ void set test_resolveApiChanges(bool 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 library 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 enum containing the AST nodes being visited, or `null` if we are not
- * in the scope of an enum.
- */
- EnumElementImpl _enclosingEnum;
-
- /**
- * 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 {
- logger.log("mismatched");
- return DeclarationMatchKind.MISMATCH;
- } finally {
- logger.exit();
- }
- // no API changes
- if (_removedElements.isEmpty && _addedElements.isEmpty) {
- logger.log("no API changes");
- 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);
- }
- }
- // matches, set the element
- node.name.staticElement = element;
- }
-
- @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(_enclosingEnum.fields, name);
- _processElement(element);
- }
-
- @override
- visitEnumDeclaration(EnumDeclaration node) {
- String name = node.name.name;
- ClassElement element = _findElement(_enclosingUnit.enums, name);
- _enclosingEnum = 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.toList();
- methods.add(newElement);
- _enclosingClass.methods = methods;
- } else {
- List<PropertyAccessorElement> accessors =
- _enclosingClass.accessors.toList();
- 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;
- Element variable = element;
- if (variable is VariableElementImpl) {
- variable.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 ||
- element.enclosingElement is ConstructorElement) {
- _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> nodeAnnotations = node.metadata;
- List<ElementAnnotation> elementAnnotations = element.metadata;
- int length = nodeAnnotations.length;
- _assertEquals(elementAnnotations.length, length);
- for (int i = 0; i < length; i++) {
- _assertSameAnnotation(nodeAnnotations[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;
-}
-
-/**
* The [Delta] implementation used by incremental resolver.
* It keeps Dart results that are either don't change or are updated.
*/
@@ -1062,30 +254,27 @@ class IncrementalResolver {
_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.
+ * [body] - the root of the AST structure to be resolved.
*
* Returns `true` if resolution was successful.
*/
- bool resolve(AstNode node) {
+ bool 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();
@@ -1096,69 +285,26 @@ class IncrementalResolver {
}
}
- void _buildElements(AstNode node) {
+ void _buildElements(Declaration executable, AstNode node) {
LoggingTimer timer = logger.startTimer();
try {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = new ElementBuilder(holder, _definingUnit);
- if (_resolutionContext.enclosingClassDeclaration != null) {
- builder.visitClassDeclarationIncrementally(
- _resolutionContext.enclosingClassDeclaration);
- }
+ 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].
*/
void _computeConstants(AstNode node) {
@@ -1187,9 +333,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;
@@ -1197,19 +345,6 @@ 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 =
@@ -1532,13 +667,7 @@ class PoorMansIncrementalResolver {
newParent is ConstructorDeclaration ||
oldParent is MethodDeclaration &&
newParent is MethodDeclaration) {
- Element oldElement = (oldParent as Declaration).element;
- if (new DeclarationMatcher().matches(newParent, oldElement) ==
- DeclarationMatchKind.MATCH) {
- oldNode = oldParent;
- newNode = newParent;
- found = true;
- } else {
+ if (oldParents.length == i || newParents.length == i) {
return false;
}
} else if (oldParent is FunctionBody && newParent is FunctionBody) {
@@ -2072,13 +1201,6 @@ 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.
- */
-class _DeclarationMismatchException {}
-
-/**
* Adjusts the location of each Element that moved.
*
* Since `==` and `hashCode` of a local variable or function Element are based
@@ -2173,60 +1295,6 @@ class _ElementOffsetUpdater extends GeneralizingElementVisitor {
}
}
-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);
- }
- }
- }
-
- @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);
- }
- // Don't visit children (such as synthetic setter parameters).
- }
-
- @override
- visitPropertyInducingElement(PropertyInducingElement element) {
- if (!element.isSynthetic) {
- _addElement(element);
- }
- // 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);
- }
- }
-}
-
/**
* Describes how two [Token]s are different.
*/
« no previous file with comments | « pkg/analyzer/lib/src/dart/element/builder.dart ('k') | pkg/analyzer/test/generated/incremental_resolver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698