Index: analyzer/lib/src/task/incremental_element_builder.dart |
diff --git a/analyzer/lib/src/task/incremental_element_builder.dart b/analyzer/lib/src/task/incremental_element_builder.dart |
deleted file mode 100644 |
index bc562a73e6ce82fc813e4d09a504d3f920ced6ed..0000000000000000000000000000000000000000 |
--- a/analyzer/lib/src/task/incremental_element_builder.dart |
+++ /dev/null |
@@ -1,366 +0,0 @@ |
-// Copyright (c) 2015, 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 analyzer.src.task.incremental_element_builder; |
- |
-import 'dart:collection'; |
- |
-import 'package:analyzer/src/generated/ast.dart'; |
-import 'package:analyzer/src/generated/element.dart'; |
-import 'package:analyzer/src/generated/resolver.dart'; |
-import 'package:analyzer/src/generated/scanner.dart'; |
-import 'package:analyzer/src/generated/source.dart'; |
- |
-/** |
- * The change of a single [CompilationUnitElement]. |
- */ |
-class CompilationUnitElementDelta { |
- /** |
- * One or more directives were added/removed. |
- */ |
- bool hasDirectiveChange = false; |
- |
- /** |
- * The list of added top-level element. |
- */ |
- final List<Element> addedDeclarations = <Element>[]; |
- |
- /** |
- * The list of removed top-level elements. |
- */ |
- final List<Element> removedDeclarations = <Element>[]; |
-} |
- |
-/** |
- * Incrementally updates the existing [unitElement] and builds elements for |
- * the [newUnit]. |
- */ |
-class IncrementalCompilationUnitElementBuilder { |
- final Source unitSource; |
- final Source librarySource; |
- final CompilationUnit oldUnit; |
- final CompilationUnitElementImpl unitElement; |
- final CompilationUnit newUnit; |
- final ElementHolder holder = new ElementHolder(); |
- |
- /** |
- * The change between element models of [oldUnit] and [newUnit]. |
- */ |
- final CompilationUnitElementDelta unitDelta = |
- new CompilationUnitElementDelta(); |
- |
- factory IncrementalCompilationUnitElementBuilder( |
- CompilationUnit oldUnit, CompilationUnit newUnit) { |
- CompilationUnitElementImpl unitElement = oldUnit.element; |
- return new IncrementalCompilationUnitElementBuilder._(unitElement.source, |
- unitElement.librarySource, oldUnit, newUnit, unitElement); |
- } |
- |
- IncrementalCompilationUnitElementBuilder._(this.unitSource, |
- this.librarySource, this.oldUnit, this.newUnit, this.unitElement); |
- |
- /** |
- * Updates [oldUnit] to have the same directives and declarations, in the |
- * same order as in [newUnit]. Existing resolution is kept where possible. |
- * |
- * Updates [unitElement] by adding/removing elements as needed. |
- * |
- * Fills [unitDelta] with added/remove elements. |
- */ |
- void build() { |
- new CompilationUnitBuilder().buildCompilationUnit( |
- unitSource, newUnit, librarySource); |
- _processDirectives(); |
- _processUnitMembers(); |
- newUnit.element = unitElement; |
- _replaceUnitContents(oldUnit, newUnit); |
- } |
- |
- void _addElementToHolder(Element element) { |
- if (element is PropertyAccessorElement) { |
- holder.addAccessor(element); |
- } else if (element is ClassElement) { |
- if (element.isEnum) { |
- holder.addEnum(element); |
- } else { |
- holder.addType(element); |
- } |
- } else if (element is FunctionElement) { |
- holder.addFunction(element); |
- } else if (element is FunctionTypeAliasElement) { |
- holder.addTypeAlias(element); |
- } else if (element is TopLevelVariableElement) { |
- holder.addTopLevelVariable(element); |
- } |
- } |
- |
- void _processDirectives() { |
- Map<String, Directive> oldDirectiveMap = new HashMap<String, Directive>(); |
- for (Directive oldDirective in oldUnit.directives) { |
- String code = TokenUtils.getFullCode(oldDirective); |
- oldDirectiveMap[code] = oldDirective; |
- } |
- // Replace new nodes with the identical old nodes. |
- Set<Directive> removedDirectives = oldUnit.directives.toSet(); |
- for (Directive newDirective in newUnit.directives) { |
- String code = TokenUtils.getFullCode(newDirective); |
- // Prepare an old directive. |
- Directive oldDirective = oldDirectiveMap[code]; |
- if (oldDirective == null) { |
- unitDelta.hasDirectiveChange = true; |
- continue; |
- } |
- // URI's must be resolved to the same sources. |
- if (newDirective is UriBasedDirective && |
- oldDirective is UriBasedDirective) { |
- if (oldDirective.source != newDirective.source) { |
- continue; |
- } |
- } |
- // Do replacement. |
- _replaceNode(newDirective, oldDirective); |
- removedDirectives.remove(oldDirective); |
- } |
- // If there are any directives left, then these directives were removed. |
- if (removedDirectives.isNotEmpty) { |
- unitDelta.hasDirectiveChange = true; |
- } |
- } |
- |
- void _processUnitMembers() { |
- Map<String, CompilationUnitMember> oldNodeMap = |
- new HashMap<String, CompilationUnitMember>(); |
- for (CompilationUnitMember oldNode in oldUnit.declarations) { |
- String code = TokenUtils.getFullCode(oldNode); |
- oldNodeMap[code] = oldNode; |
- } |
- // Prepare all old top-level elements. |
- Set<Element> removedElements = new Set<Element>(); |
- removedElements.addAll(unitElement.accessors); |
- removedElements.addAll(unitElement.enums); |
- removedElements.addAll(unitElement.functions); |
- removedElements.addAll(unitElement.functionTypeAliases); |
- removedElements.addAll(unitElement.types); |
- removedElements.addAll(unitElement.topLevelVariables); |
- // Replace new nodes with the identical old nodes. |
- for (CompilationUnitMember newNode in newUnit.declarations) { |
- String code = TokenUtils.getFullCode(newNode); |
- // Prepare an old node. |
- CompilationUnitMember oldNode = oldNodeMap[code]; |
- if (oldNode == null) { |
- List<Element> elements = _getElements(newNode); |
- elements.forEach(_addElementToHolder); |
- elements.forEach(unitDelta.addedDeclarations.add); |
- continue; |
- } |
- // Do replacement. |
- _replaceNode(newNode, oldNode); |
- List<Element> elements = _getElements(oldNode); |
- elements.forEach(_addElementToHolder); |
- elements.forEach(removedElements.remove); |
- } |
- unitDelta.removedDeclarations.addAll(removedElements); |
- // Update CompilationUnitElement. |
- unitElement.accessors = holder.accessors; |
- unitElement.enums = holder.enums; |
- unitElement.functions = holder.functions; |
- unitElement.typeAliases = holder.typeAliases; |
- unitElement.types = holder.types; |
- unitElement.topLevelVariables = holder.topLevelVariables; |
- holder.validate(); |
- } |
- |
- /** |
- * Replaces [newNode] with [oldNode], updates tokens and elements. |
- * The nodes must have the same tokens, but offsets may be different. |
- */ |
- void _replaceNode(AstNode newNode, AstNode oldNode) { |
- // Replace node. |
- NodeReplacer.replace(newNode, oldNode); |
- // Replace tokens. |
- { |
- Token oldBeginToken = TokenUtils.getBeginTokenNotComment(newNode); |
- Token newBeginToken = TokenUtils.getBeginTokenNotComment(oldNode); |
- oldBeginToken.previous.setNext(newBeginToken); |
- oldNode.endToken.setNext(newNode.endToken.next); |
- } |
- // Change tokens offsets. |
- Map<int, int> offsetMap = new HashMap<int, int>(); |
- TokenUtils.copyTokenOffsets(offsetMap, oldNode.beginToken, |
- newNode.beginToken, oldNode.endToken, newNode.endToken, true); |
- // Change elements offsets. |
- { |
- var visitor = new _UpdateElementOffsetsVisitor(offsetMap); |
- List<Element> elements = _getElements(oldNode); |
- for (Element element in elements) { |
- element.accept(visitor); |
- } |
- } |
- } |
- |
- /** |
- * Returns [Element]s that are declared directly by the given [node]. |
- * This does not include any child elements - parameters, local variables. |
- * |
- * Usually just one [Element] is returned, but [VariableDeclarationList] |
- * nodes may declare more than one. |
- */ |
- static List<Element> _getElements(AstNode node) { |
- List<Element> elements = <Element>[]; |
- if (node is TopLevelVariableDeclaration) { |
- VariableDeclarationList variableList = node.variables; |
- if (variableList != null) { |
- for (VariableDeclaration variable in variableList.variables) { |
- TopLevelVariableElement element = variable.element; |
- elements.add(element); |
- if (element.getter != null) { |
- elements.add(element.getter); |
- } |
- if (element.setter != null) { |
- elements.add(element.setter); |
- } |
- } |
- } |
- } else if (node is PartDirective || node is PartOfDirective) { |
- } else if (node is Directive && node.element != null) { |
- elements.add(node.element); |
- } else if (node is Declaration && node.element != null) { |
- Element element = node.element; |
- elements.add(element); |
- if (element is PropertyAccessorElement) { |
- elements.add(element.variable); |
- } |
- } |
- return elements; |
- } |
- |
- /** |
- * Replaces contents of the [to] unit with the contenxts of the [from] unit. |
- */ |
- static void _replaceUnitContents(CompilationUnit to, CompilationUnit from) { |
- to.directives.clear(); |
- to.declarations.clear(); |
- to.beginToken = from.beginToken; |
- to.scriptTag = from.scriptTag; |
- to.directives.addAll(from.directives); |
- to.declarations.addAll(from.declarations); |
- to.element = to.element; |
- to.lineInfo = from.lineInfo; |
- } |
-} |
- |
-/** |
- * Utilities for [Token] manipulations. |
- */ |
-class TokenUtils { |
- static const String _SEPARATOR = "\uFFFF"; |
- |
- /** |
- * Copy offsets from [newToken]s to [oldToken]s. |
- */ |
- static void copyTokenOffsets(Map<int, int> offsetMap, Token oldToken, |
- Token newToken, Token oldEndToken, Token newEndToken, |
- [bool goUpComment = false]) { |
- if (oldToken is CommentToken && newToken is CommentToken) { |
- if (goUpComment) { |
- copyTokenOffsets(offsetMap, (oldToken as CommentToken).parent, |
- (newToken as CommentToken).parent, oldEndToken, newEndToken); |
- } |
- while (oldToken != null) { |
- offsetMap[oldToken.offset] = newToken.offset; |
- oldToken.offset = newToken.offset; |
- oldToken = oldToken.next; |
- newToken = newToken.next; |
- } |
- assert(oldToken == null); |
- assert(newToken == null); |
- return; |
- } |
- while (true) { |
- if (oldToken.precedingComments != null) { |
- assert(newToken.precedingComments != null); |
- copyTokenOffsets(offsetMap, oldToken.precedingComments, |
- newToken.precedingComments, oldEndToken, newEndToken); |
- } |
- offsetMap[oldToken.offset] = newToken.offset; |
- oldToken.offset = newToken.offset; |
- if (oldToken == oldEndToken) { |
- assert(newToken == newEndToken); |
- break; |
- } |
- oldToken = oldToken.next; |
- newToken = newToken.next; |
- } |
- } |
- |
- static Token getBeginTokenNotComment(AstNode node) { |
- Token oldBeginToken = node.beginToken; |
- if (oldBeginToken is CommentToken) { |
- oldBeginToken = (oldBeginToken as CommentToken).parent; |
- } |
- return oldBeginToken; |
- } |
- |
- /** |
- * Return the token string of all the [node] tokens. |
- */ |
- static String getFullCode(AstNode node) { |
- List<Token> tokens = getTokens(node); |
- return joinTokens(tokens); |
- } |
- |
- /** |
- * Returns all tokends (including comments) of the given [node]. |
- */ |
- static List<Token> getTokens(AstNode node) { |
- List<Token> tokens = <Token>[]; |
- Token token = getBeginTokenNotComment(node); |
- Token endToken = node.endToken; |
- while (true) { |
- // append comment tokens |
- for (Token commentToken = token.precedingComments; |
- commentToken != null; |
- commentToken = commentToken.next) { |
- tokens.add(commentToken); |
- } |
- // append token |
- tokens.add(token); |
- // next token |
- if (token == endToken) { |
- break; |
- } |
- token = token.next; |
- } |
- return tokens; |
- } |
- |
- static String joinTokens(List<Token> tokens) { |
- return tokens.map((token) => token.lexeme).join(_SEPARATOR); |
- } |
-} |
- |
-/** |
- * Updates name offsets of [Element]s according to the [map]. |
- */ |
-class _UpdateElementOffsetsVisitor extends GeneralizingElementVisitor { |
- final Map<int, int> map; |
- |
- _UpdateElementOffsetsVisitor(this.map); |
- |
- void visitElement(Element element) { |
- if (element is CompilationUnitElement) { |
- return; |
- } |
- if (element.isSynthetic) { |
- return; |
- } |
- int oldOffset = element.nameOffset; |
- int newOffset = map[oldOffset]; |
- assert(newOffset != null); |
- (element as ElementImpl).nameOffset = newOffset; |
- if (element is! LibraryElement) { |
- super.visitElement(element); |
- } |
- } |
-} |