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

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

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 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: analyzer/lib/src/generated/incremental_resolver.dart
diff --git a/analyzer/lib/src/generated/incremental_resolver.dart b/analyzer/lib/src/generated/incremental_resolver.dart
deleted file mode 100644
index 78481ce117eb96306a99b92cb3058f6ec03c3a8a..0000000000000000000000000000000000000000
--- a/analyzer/lib/src/generated/incremental_resolver.dart
+++ /dev/null
@@ -1,1988 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// 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;
-
-import 'dart:collection';
-import 'dart:math' as math;
-
-import 'package:analyzer/src/context/cache.dart'
- show CacheEntry, TargetedResult;
-import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/task/dart.dart'
- show
- HINTS,
- PARSE_ERRORS,
- RESOLVE_REFERENCES_ERRORS,
- RESOLVE_TYPE_NAMES_ERRORS,
- SCAN_ERRORS,
- USED_IMPORTED_ELEMENTS,
- USED_LOCAL_ELEMENTS,
- VARIABLE_REFERENCE_ERRORS,
- VERIFY_ERRORS;
-import 'package:analyzer/task/dart.dart'
- show DART_ERRORS, LibrarySpecificUnit, PARSED_UNIT, TOKEN_STREAM;
-import 'package:analyzer/task/general.dart' show CONTENT;
-import 'package:analyzer/task/model.dart' show ResultDescriptor;
-
-import 'ast.dart';
-import 'element.dart';
-import 'engine.dart';
-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);
- _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;
-}
-
-/**
- * Instances of the class [IncrementalResolver] resolve the smallest portion of
- * an AST structure that we currently know how to resolve.
- */
-class IncrementalResolver {
- /**
- * The element of the compilation unit being resolved.
- */
- final CompilationUnitElementImpl _definingUnit;
-
- /**
- * The context the compilation unit being resolved in.
- */
- AnalysisContext _context;
-
- /**
- * The object used to access the types from the core library.
- */
- TypeProvider _typeProvider;
-
- /**
- * The element for the library containing the compilation unit being resolved.
- */
- LibraryElementImpl _definingLibrary;
-
- /**
- * The [DartEntry] corresponding to the source being resolved.
- */
- DartEntry oldEntry;
-
- /**
- * The [CacheEntry] corresponding to the source being resolved.
- */
- CacheEntry newSourceEntry;
-
- /**
- * The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved.
- */
- CacheEntry newUnitEntry;
-
- /**
- * The source representing the compilation unit being visited.
- */
- Source _source;
-
- /**
- * The source representing the library of the compilation unit being visited.
- */
- Source _librarySource;
-
- /**
- * The offset of the changed contents.
- */
- final int _updateOffset;
-
- /**
- * The end of the changed contents in the old unit.
- */
- final int _updateEndOld;
-
- /**
- * The end of the changed contents in the new unit.
- */
- final int _updateEndNew;
-
- int _updateDelta;
-
- RecordingErrorListener errorListener = new RecordingErrorListener();
- ResolutionContext _resolutionContext;
-
- List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS;
- List<AnalysisError> _verifyErrors = AnalysisError.NO_ERRORS;
-
- /**
- * Initialize a newly created incremental resolver to resolve a node in the
- * given source in the given library.
- */
- IncrementalResolver(this.oldEntry, this.newSourceEntry, this.newUnitEntry,
- this._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;
- }
-
- /**
- * Resolve [node], 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.
- */
- bool resolve(AstNode node) {
- logger.enter('resolve: $_definingUnit');
- try {
- AstNode rootNode = _findResolutionRoot(node);
- _prepareResolutionContext(rootNode);
- // update elements
- _updateElementNameOffsets();
- _buildElements(rootNode);
- if (!_canBeIncrementallyResolved(rootNode)) {
- return false;
- }
- // resolve
- _resolveReferences(rootNode);
- _computeConstants(rootNode);
- _resolveErrors = errorListener.getErrorsForSource(_source);
- // verify
- _verify(rootNode);
- _context.invalidateLibraryHints(_librarySource);
- // update entry errors
- _updateEntry();
- // notify unit
- _definingUnit.afterIncrementalResolution();
- // OK
- return true;
- } finally {
- logger.exit();
- }
- }
-
- void _buildElements(AstNode node) {
- LoggingTimer timer = logger.startTimer();
- try {
- ElementHolder holder = new ElementHolder();
- ElementBuilder builder = new ElementBuilder(holder);
- if (_resolutionContext.enclosingClassDeclaration != null) {
- builder.visitClassDeclarationIncrementally(
- _resolutionContext.enclosingClassDeclaration);
- }
- node.accept(builder);
- } 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) {
- // compute values
- {
- CompilationUnit unit = node.getAncestor((n) => n is CompilationUnit);
- ConstantValueComputer computer = new ConstantValueComputer(
- _context, _typeProvider, _context.declaredVariables);
- computer.add(unit, _source, _librarySource);
- computer.computeValues();
- }
- // validate
- {
- ErrorReporter errorReporter = new ErrorReporter(errorListener, _source);
- ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter,
- _definingLibrary, _typeProvider, _context.declaredVariables);
- node.accept(constantVerifier);
- }
- }
-
- /**
- * Starting at [node], find the smallest AST node that can be resolved
- * independently of any other nodes. Return the node that was found.
- *
- * [node] - the node at which the search is to begin
- *
- * Throws [AnalysisException] if there is no such node.
- */
- AstNode _findResolutionRoot(AstNode node) {
- while (node != null) {
- if (_canBeResolved(node)) {
- return node;
- }
- node = node.parent;
- }
- 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);
- }
- }
-
- _resolveReferences(AstNode node) {
- LoggingTimer timer = logger.startTimer();
- try {
- _prepareResolutionContext(node);
- Scope scope = _resolutionContext.scope;
- // resolve types
- {
- TypeResolverVisitor visitor = new TypeResolverVisitor(
- _definingLibrary, _source, _typeProvider, errorListener,
- nameScope: scope);
- node.accept(visitor);
- }
- // resolve variables
- {
- VariableResolverVisitor visitor = new VariableResolverVisitor(
- _definingLibrary, _source, _typeProvider, errorListener,
- nameScope: scope);
- node.accept(visitor);
- }
- // resolve references
- {
- ResolverVisitor visitor = new ResolverVisitor(
- _definingLibrary, _source, _typeProvider, errorListener,
- nameScope: scope);
- if (_resolutionContext.enclosingClassDeclaration != null) {
- visitor.visitClassDeclarationIncrementally(
- _resolutionContext.enclosingClassDeclaration);
- }
- if (node is Comment) {
- visitor.resolveOnlyCommentInFunctionBody = true;
- node = node.parent;
- }
- visitor.initForIncrementalResolution();
- node.accept(visitor);
- }
- } finally {
- timer.stop('resolve references');
- }
- }
-
- void _shiftEntryErrors() {
- if (oldEntry != null) {
- _shiftEntryErrors_OLD();
- } else {
- _shiftEntryErrors_NEW();
- }
- }
-
- void _shiftEntryErrors_NEW() {
- _shiftErrors_NEW(HINTS);
- _shiftErrors_NEW(RESOLVE_REFERENCES_ERRORS);
- _shiftErrors_NEW(RESOLVE_TYPE_NAMES_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) {
- int errorOffset = error.offset;
- if (errorOffset > _updateOffset) {
- error.offset += _updateDelta;
- }
- }
- }
-
- void _shiftErrors_NEW(ResultDescriptor<List<AnalysisError>> descriptor) {
- List<AnalysisError> errors = newUnitEntry.getValue(descriptor);
- _shiftErrors(errors);
- }
-
- void _shiftErrors_OLD(DataDescriptor<List<AnalysisError>> descriptor) {
- List<AnalysisError> errors =
- oldEntry.getValueInLibrary(descriptor, _librarySource);
- _shiftErrors(errors);
- }
-
- void _updateElementNameOffsets() {
- LoggingTimer timer = logger.startTimer();
- try {
- _definingUnit
- .accept(new _ElementNameOffsetUpdater(_updateOffset, _updateDelta));
- } finally {
- timer.stop('update element offsets');
- }
- }
-
- void _updateEntry() {
- if (oldEntry != null) {
- _updateEntry_OLD();
- } else {
- _updateEntry_NEW();
- }
- }
-
- void _updateEntry_NEW() {
- _updateErrors_NEW(RESOLVE_REFERENCES_ERRORS, _resolveErrors);
- _updateErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS, []);
- _updateErrors_NEW(VARIABLE_REFERENCE_ERRORS, []);
- _updateErrors_NEW(VERIFY_ERRORS, _verifyErrors);
- // invalidate results we don't update incrementally
- newUnitEntry.setState(USED_IMPORTED_ELEMENTS, CacheState.INVALID);
- newUnitEntry.setState(USED_LOCAL_ELEMENTS, CacheState.INVALID);
- newUnitEntry.setState(HINTS, 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>();
- // add updated old errors
- for (AnalysisError error in oldErrors) {
- int errorOffset = error.offset;
- if (errorOffset < _updateOffset) {
- errors.add(error);
- } else if (errorOffset > _updateEndOld) {
- error.offset += _updateDelta;
- errors.add(error);
- }
- }
- // add new errors
- for (AnalysisError error in newErrors) {
- int errorOffset = error.offset;
- if (errorOffset > _updateOffset && errorOffset < _updateEndNew) {
- errors.add(error);
- }
- }
- // done
- return errors;
- }
-
- void _updateErrors_NEW(ResultDescriptor<List<AnalysisError>> descriptor,
- List<AnalysisError> newErrors) {
- List<AnalysisError> oldErrors = newUnitEntry.getValue(descriptor);
- List<AnalysisError> errors = _updateErrors(oldErrors, newErrors);
- newUnitEntry.setValueIncremental(descriptor, errors);
- }
-
- 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 {
- RecordingErrorListener errorListener = new RecordingErrorListener();
- ErrorReporter errorReporter = new ErrorReporter(errorListener, _source);
- ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter,
- _definingLibrary, _typeProvider,
- new InheritanceManager(_definingLibrary));
- if (_resolutionContext.enclosingClassDeclaration != null) {
- errorVerifier.visitClassDeclarationIncrementally(
- _resolutionContext.enclosingClassDeclaration);
- }
- node.accept(errorVerifier);
- _verifyErrors = errorListener.getErrorsForSource(_source);
- } finally {
- timer.stop('verify');
- }
- }
-}
-
-class PoorMansIncrementalResolver {
- final TypeProvider _typeProvider;
- final Source _unitSource;
-
- /**
- * The [DartEntry] corresponding to the source being resolved.
- */
- DartEntry _oldEntry;
-
- /**
- * The [CacheEntry] corresponding to the source being resolved.
- */
- CacheEntry _newSourceEntry;
-
- /**
- * The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved.
- */
- CacheEntry _newUnitEntry;
-
- final CompilationUnit _oldUnit;
- final AnalysisOptions _options;
- CompilationUnitElement _unitElement;
-
- int _updateOffset;
- int _updateDelta;
- int _updateEndOld;
- int _updateEndNew;
-
- List<AnalysisError> _newScanErrors = <AnalysisError>[];
- List<AnalysisError> _newParseErrors = <AnalysisError>[];
-
- PoorMansIncrementalResolver(this._typeProvider, this._unitSource,
- this._oldEntry, this._newSourceEntry, this._newUnitEntry, this._oldUnit,
- bool resolveApiChanges, this._options) {
- _resolveApiChanges = resolveApiChanges;
- }
-
- /**
- * Attempts to update [_oldUnit] to the state corresponding to [newCode].
- * Returns `true` if success, or `false` otherwise.
- * The [_oldUnit] might be damaged.
- */
- bool resolve(String newCode) {
- logger.enter('diff/resolve $_unitSource');
- try {
- // prepare old unit
- if (!_areCurlyBracketsBalanced(_oldUnit.beginToken)) {
- logger.log('Unbalanced number of curly brackets in the old unit.');
- return false;
- }
- _unitElement = _oldUnit.element;
- // prepare new unit
- CompilationUnit newUnit = _parseUnit(newCode);
- if (!_areCurlyBracketsBalanced(newUnit.beginToken)) {
- logger.log('Unbalanced number of curly brackets in the new unit.');
- return false;
- }
- // find difference
- _TokenPair firstPair =
- _findFirstDifferentToken(_oldUnit.beginToken, newUnit.beginToken);
- _TokenPair lastPair =
- _findLastDifferentToken(_oldUnit.endToken, newUnit.endToken);
- if (firstPair != null && lastPair != null) {
- int firstOffsetOld = firstPair.oldToken.offset;
- int firstOffsetNew = firstPair.newToken.offset;
- int lastOffsetOld = lastPair.oldToken.end;
- int lastOffsetNew = lastPair.newToken.end;
- int beginOffsetOld = math.min(firstOffsetOld, lastOffsetOld);
- 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)) {
- _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('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._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 =
- _findNodeCovering(_oldUnit, beginOffsetOld, endOffsetOld - 1);
- AstNode newNode =
- _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew - 1);
- logger.log(() => 'oldNode: $oldNode');
- logger.log(() => 'newNode: $newNode');
- // Try to find the smallest common node, a FunctionBody currently.
- {
- List<AstNode> oldParents = _getParents(oldNode);
- List<AstNode> newParents = _getParents(newNode);
- 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 &&
- 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) {
- oldNode = oldParent;
- newNode = newParent;
- found = true;
- }
- }
- if (oldParent is FunctionBody && newParent is FunctionBody) {
- oldNode = oldParent;
- newNode = newParent;
- found = true;
- break;
- }
- }
- 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');
- // prepare update range
- _updateOffset = oldNode.offset;
- _updateEndOld = oldNode.end;
- _updateEndNew = newNode.end;
- _updateDelta = _updateEndNew - _updateEndOld;
- // replace node
- NodeReplacer.replace(oldNode, newNode);
- // update token references
- {
- Token oldBeginToken = _getBeginTokenNotComment(oldNode);
- Token newBeginToken = _getBeginTokenNotComment(newNode);
- if (oldBeginToken.previous.type == TokenType.EOF) {
- _oldUnit.beginToken = newBeginToken;
- } else {
- oldBeginToken.previous.setNext(newBeginToken);
- }
- newNode.endToken.setNext(oldNode.endToken.next);
- _shiftTokens(oldNode.endToken.next);
- }
- // perform incremental resolution
- IncrementalResolver incrementalResolver = new IncrementalResolver(
- _oldEntry, _newSourceEntry, _newUnitEntry, _unitElement,
- _updateOffset, _updateEndOld, _updateEndNew);
- bool success = incrementalResolver.resolve(newNode);
- // check if success
- if (!success) {
- logger.log('Failure: element model changed.');
- return false;
- }
- // update DartEntry
- _updateEntry();
- logger.log('Success.');
- return true;
- }
- } catch (e, st) {
- logger.log(e);
- logger.log(st);
- logger.log('Failure: exception.');
- } finally {
- logger.exit();
- }
- return false;
- }
-
- CompilationUnit _parseUnit(String code) {
- LoggingTimer timer = logger.startTimer();
- try {
- Token token = _scan(code);
- RecordingErrorListener errorListener = new RecordingErrorListener();
- Parser parser = new Parser(_unitSource, errorListener);
- AnalysisOptions options = _unitElement.context.analysisOptions;
- parser.parseGenericMethods = options.enableGenericMethods;
- CompilationUnit unit = parser.parseCompilationUnit(token);
- _newParseErrors = errorListener.errors;
- return unit;
- } finally {
- timer.stop('parse');
- }
- }
-
- /**
- * 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) {
- return false;
- }
- // find nodes
- int offset = oldComments.offset;
- logger.log('offset: $offset');
- Comment oldComment = _findNodeCovering(_oldUnit, offset, offset);
- Comment newComment = _findNodeCovering(newUnit, offset, offset);
- 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);
- // replace node
- NodeReplacer.replace(oldComment, newComment);
- // update elements
- IncrementalResolver incrementalResolver = new IncrementalResolver(_oldEntry,
- _newSourceEntry, _newUnitEntry, _unitElement, _updateOffset,
- _updateEndOld, _updateEndNew);
- incrementalResolver._updateElementNameOffsets();
- incrementalResolver._shiftEntryErrors();
- _updateEntry();
- // resolve references in the comment
- incrementalResolver._resolveReferences(newComment);
- // OK
- return true;
- }
-
- Token _scan(String code) {
- RecordingErrorListener errorListener = new RecordingErrorListener();
- CharSequenceReader reader = new CharSequenceReader(code);
- Scanner scanner = new Scanner(_unitSource, reader, errorListener);
- Token token = scanner.tokenize();
- _newScanErrors = errorListener.errors;
- return token;
- }
-
- /**
- * Set the given [comment] as a "precedingComments" for [token].
- */
- void _setPrecedingComments(Token token, CommentToken comment) {
- if (token is BeginTokenWithComment) {
- token.precedingComments = comment;
- } else if (token is KeywordTokenWithComment) {
- token.precedingComments = comment;
- } else if (token is StringTokenWithComment) {
- token.precedingComments = comment;
- } else if (token is TokenWithComment) {
- token.precedingComments = comment;
- } else {
- Type parentType = token != null ? token.runtimeType : null;
- throw new AnalysisException('Uknown parent token type: $parentType');
- }
- }
-
- 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;
- }
- }
-
- void _updateEntry() {
- if (_oldEntry != null) {
- _updateEntry_OLD();
- } else {
- _updateEntry_NEW();
- }
- }
-
- void _updateEntry_NEW() {
- _newSourceEntry.setState(DART_ERRORS, CacheState.INVALID);
- // scan results
- _newSourceEntry.setState(SCAN_ERRORS, CacheState.INVALID);
- List<TargetedResult> scanDeps =
- <TargetedResult>[new TargetedResult(_unitSource, CONTENT)];
- _newSourceEntry.setValue(SCAN_ERRORS, _newScanErrors, scanDeps);
- // parse results
- List<TargetedResult> parseDeps =
- <TargetedResult>[new TargetedResult(_unitSource, TOKEN_STREAM)];
- _newSourceEntry.setState(PARSE_ERRORS, CacheState.INVALID);
- _newSourceEntry.setValue(PARSE_ERRORS, _newParseErrors, parseDeps);
- _newSourceEntry.setValue(PARSED_UNIT, _oldUnit, parseDeps);
- }
-
- void _updateEntry_OLD() {
- _oldEntry.setValue(DartEntry.SCAN_ERRORS, _newScanErrors);
- _oldEntry.setValue(DartEntry.PARSE_ERRORS, _newParseErrors);
- }
-
- /**
- * Checks if [token] has a balanced number of open and closed curly brackets.
- */
- static bool _areCurlyBracketsBalanced(Token token) {
- int numOpen = _getTokenCount(token, TokenType.OPEN_CURLY_BRACKET);
- int numOpen2 =
- _getTokenCount(token, TokenType.STRING_INTERPOLATION_EXPRESSION);
- int numClosed = _getTokenCount(token, TokenType.CLOSE_CURLY_BRACKET);
- return numOpen + numOpen2 == numClosed;
- }
-
- 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;
- }
- return null;
- }
-
- static _TokenPair _findFirstDifferentToken(Token oldToken, Token newToken) {
- while (true) {
- if (oldToken.type == TokenType.EOF && newToken.type == TokenType.EOF) {
- return null;
- }
- if (oldToken.type == TokenType.EOF || newToken.type == TokenType.EOF) {
- return new _TokenPair(_TokenDifferenceKind.CONTENT, oldToken, newToken);
- }
- // compare comments
- {
- 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;
- }
- return new _TokenPair(diffKind, oldToken, newToken);
- }
- }
- // compare tokens
- _TokenDifferenceKind diffKind =
- _compareToken(oldToken, newToken, 0, false);
- if (diffKind != null) {
- return new _TokenPair(diffKind, oldToken, newToken);
- }
- // next tokens
- oldToken = oldToken.next;
- newToken = newToken.next;
- }
- // no difference
- return null;
- }
-
- static _TokenPair _findLastDifferentToken(Token oldToken, Token newToken) {
- int delta = newToken.offset - oldToken.offset;
- while (oldToken.previous != oldToken && newToken.previous != newToken) {
- // compare tokens
- _TokenDifferenceKind diffKind =
- _compareToken(oldToken, newToken, delta, false);
- if (diffKind != null) {
- return new _TokenPair(diffKind, oldToken.next, newToken.next);
- }
- // 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;
- }
- return new _TokenPair(diffKind, oldToken, newToken);
- }
- }
- // next tokens
- oldToken = oldToken.previous;
- newToken = newToken.previous;
- }
- return null;
- }
-
- static AstNode _findNodeCovering(AstNode root, int offset, int end) {
- NodeLocator nodeLocator = new NodeLocator(offset, end);
- return nodeLocator.searchWithin(root);
- }
-
- static Token _getBeginTokenNotComment(AstNode node) {
- Token oldBeginToken = node.beginToken;
- if (oldBeginToken is CommentToken) {
- oldBeginToken = (oldBeginToken as CommentToken).parent;
- }
- return oldBeginToken;
- }
-
- static List<AstNode> _getParents(AstNode node) {
- List<AstNode> parents = <AstNode>[];
- while (node != null) {
- parents.insert(0, node);
- node = node.parent;
- }
- return parents;
- }
-
- /**
- * Returns number of tokens with the given [type].
- */
- static int _getTokenCount(Token token, TokenType type) {
- int count = 0;
- while (token.type != TokenType.EOF) {
- if (token.type == type) {
- count++;
- }
- token = token.next;
- }
- return count;
- }
-}
-
-/**
- * The context to resolve an [AstNode] in.
- */
-class ResolutionContext {
- CompilationUnitElement enclosingUnit;
- ClassDeclaration enclosingClassDeclaration;
- ClassElement enclosingClass;
- Scope scope;
-}
-
-/**
- * Instances of the class [ResolutionContextBuilder] build the context for a
- * given node in an AST structure. At the moment, this class only handles
- * 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].
- */
- CompilationUnitElement _enclosingUnit;
-
- /**
- * The class containing the enclosing [ClassDeclaration], or `null` if we are
- * not in the scope of a class.
- */
- ClassDeclaration _enclosingClassDeclaration;
-
- /**
- * The class containing the enclosing [ClassElement], or `null` if we are not
- * in the scope of a class.
- */
- 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);
- }
- AstNode parent = node.parent;
- if (parent == null) {
- throw new AnalysisException(
- "Cannot create scope: node is not part of a CompilationUnit");
- }
- return _scopeForAstNode(parent);
- }
-
- /**
- * Return the scope in which the given AST structure should be resolved.
- *
- * *Note:* This method needs to be kept in sync with
- * [IncrementalResolver.canBeResolved].
- *
- * [node] - the root of the AST structure to be resolved.
- *
- * Throws [AnalysisException] if the AST structure has not been resolved or
- * is not part of a [CompilationUnit]
- */
- Scope _scopeForAstNode(AstNode node) {
- if (node is CompilationUnit) {
- return _scopeForCompilationUnit(node);
- }
- AstNode parent = node.parent;
- if (parent == null) {
- throw new AnalysisException(
- "Cannot create scope: node is not part of a CompilationUnit");
- }
- Scope scope = _scopeForAstNode(parent);
- if (node is ClassDeclaration) {
- _enclosingClassDeclaration = node;
- _enclosingClass = node.element;
- if (_enclosingClass == null) {
- throw new AnalysisException(
- "Cannot build a scope for an unresolved class");
- }
- scope = new ClassScope(
- new TypeParameterScope(scope, _enclosingClass), _enclosingClass);
- } else if (node is ClassTypeAlias) {
- ClassElement element = node.element;
- if (element == null) {
- throw new AnalysisException(
- "Cannot build a scope for an unresolved class type alias");
- }
- scope = new ClassScope(new TypeParameterScope(scope, element), element);
- } else if (node is ConstructorDeclaration) {
- ConstructorElement element = node.element;
- if (element == null) {
- throw new AnalysisException(
- "Cannot build a scope for an unresolved constructor");
- }
- FunctionScope functionScope = new FunctionScope(scope, element);
- functionScope.defineParameters();
- scope = functionScope;
- } else if (node is FunctionDeclaration) {
- ExecutableElement element = node.element;
- if (element == null) {
- throw new AnalysisException(
- "Cannot build a scope for an unresolved function");
- }
- FunctionScope functionScope = new FunctionScope(scope, element);
- functionScope.defineParameters();
- scope = functionScope;
- } else if (node is FunctionTypeAlias) {
- scope = new FunctionTypeScope(scope, node.element);
- } else if (node is MethodDeclaration) {
- ExecutableElement element = node.element;
- if (element == null) {
- throw new AnalysisException(
- "Cannot build a scope for an unresolved method");
- }
- FunctionScope functionScope = new FunctionScope(scope, element);
- functionScope.defineParameters();
- scope = functionScope;
- }
- return scope;
- }
-
- Scope _scopeForCompilationUnit(CompilationUnit node) {
- _enclosingUnit = node.element;
- if (_enclosingUnit == null) {
- throw new AnalysisException(
- "Cannot create scope: compilation unit is not resolved");
- }
- LibraryElement libraryElement = _enclosingUnit.library;
- if (libraryElement == null) {
- throw new AnalysisException(
- "Cannot create scope: compilation unit is not part of a library");
- }
- return new LibraryScope(libraryElement, _errorListener);
- }
-
- /**
- * 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) {
- if (node == null) {
- throw new AnalysisException("Cannot create context: node is null");
- }
- // build scope
- ResolutionContextBuilder builder =
- new ResolutionContextBuilder(errorListener);
- Scope scope = builder._scopeFor(node);
- // prepare context
- ResolutionContext context = new ResolutionContext();
- context.scope = scope;
- context.enclosingUnit = builder._enclosingUnit;
- context.enclosingClassDeclaration = builder._enclosingClassDeclaration;
- context.enclosingClass = builder._enclosingClass;
- return context;
- }
-}
-
-/**
- * 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 {}
-
-class _ElementNameOffsetUpdater extends GeneralizingElementVisitor {
- final int updateOffset;
- final int updateDelta;
-
- _ElementNameOffsetUpdater(this.updateOffset, this.updateDelta);
-
- @override
- visitElement(Element element) {
- int nameOffset = element.nameOffset;
- if (nameOffset > updateOffset) {
- (element as ElementImpl).nameOffset = nameOffset + updateDelta;
- }
- 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);
- }
- }
- }
-
- @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.
- */
-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');
-
- final String name;
-
- const _TokenDifferenceKind(this.name);
-
- @override
- String toString() => name;
-}
-
-class _TokenPair {
- final _TokenDifferenceKind kind;
- final Token oldToken;
- final Token newToken;
- _TokenPair(this.kind, this.oldToken, this.newToken);
-}
« no previous file with comments | « analyzer/lib/src/generated/incremental_resolution_validator.dart ('k') | analyzer/lib/src/generated/incremental_scanner.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698