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

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

Issue 814533005: Incrementally resolve users of a changed method. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years 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 21f6e7b1c32fd86102eb3955ef4cb7cac28f08d8..d922fb56cac86dd87b719fcc7eb1de033dd82d74 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -115,12 +115,13 @@ class DeclarationMatcher extends RecursiveAstVisitor {
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
- logger.log('_removedElements: $_removedElements');
- logger.log('_addedElements: $_addedElements');
return DeclarationMatchKind.MISMATCH;
}
@@ -188,7 +189,8 @@ class DeclarationMatcher extends RecursiveAstVisitor {
// TODO(scheglov) debug null Location
if (element != null) {
if (element.context == null || element.source == null) {
- logger.log('Bad constructor element $element for $node in ${node.parent}');
+ logger.log(
+ 'Bad constructor element $element for $node in ${node.parent}');
}
}
// matches, update the existing element
@@ -345,12 +347,7 @@ class DeclarationMatcher extends RecursiveAstVisitor {
_setLocalElements(element, newElement);
} on _DeclarationMismatchException catch (e) {
_addedElements.add(newElement);
- // remove old element
- if (element is MethodElement) {
- _enclosingClass.methods.remove(element);
- } else if (element is PropertyAccessorElement) {
- _enclosingClass.accessors.remove(element);
- }
+ _removeElement(element);
// add new element
if (newElement is MethodElement) {
List<MethodElement> methods = _enclosingClass.methods;
@@ -633,6 +630,23 @@ class DeclarationMatcher extends RecursiveAstVisitor {
_removedElements.remove(element);
}
+ void _removeElement(Element element) {
+ if (element != null) {
+ Element enclosingElement = element.enclosingElement;
+ if (element is MethodElement) {
+ ClassElement classElement = enclosingElement;
+ classElement.methods.removeWhere((e) => identical(e, element));
Brian Wilkerson 2014/12/19 15:03:29 Do we really need to iterate over all of the eleme
scheglov 2014/12/19 17:43:04 No, we don't. But we cannot use just List.remove()
+ } else if (element is PropertyAccessorElement) {
+ if (enclosingElement is ClassElement) {
+ enclosingElement.accessors.removeWhere((e) => identical(e, element));
+ }
+ if (enclosingElement is CompilationUnitElement) {
+ enclosingElement.accessors.removeWhere((e) => identical(e, element));
+ }
+ }
+ }
+ }
+
/**
* Return the [Element] in [elements] with the given [name].
*/
@@ -714,14 +728,19 @@ class DeclarationMatchKind {
*/
class IncrementalResolver {
/**
- * The object used to access the types from the core library.
+ * The element of the compilation unit being resolved.
*/
- final TypeProvider _typeProvider;
+ final CompilationUnitElement _definingUnit;
/**
- * The element of the compilation unit being resolved.
+ * The context the compilation unit being resolved in.
*/
- final CompilationUnitElement _definingUnit;
+ AnalysisContextImpl _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.
@@ -729,6 +748,11 @@ class IncrementalResolver {
LibraryElement _definingLibrary;
/**
+ * The [DartEntry] corresponding to the source being resolved.
+ */
+ DartEntry entry;
+
+ /**
* The source representing the compilation unit being visited.
*/
Source _source;
@@ -739,14 +763,16 @@ class IncrementalResolver {
final int _updateOffset;
/**
- * The number of characters in the original contents that were replaced.
+ * The end of the changed contents in the old unit.
*/
- final int _updateOldLength;
+ final int _updateEndOld;
/**
- * The number of characters in the replacement text.
+ * The end of the changed contents in the new unit.
*/
- final int _updateNewLength;
+ final int _updateEndNew;
+
+ int _updateDelta;
RecordingErrorListener errorListener = new RecordingErrorListener();
ResolutionContext _resolutionContext;
@@ -764,10 +790,14 @@ class IncrementalResolver {
* Initialize a newly created incremental resolver to resolve a node in the
* given source in the given library.
*/
- IncrementalResolver(this._typeProvider, this._definingUnit,
- this._updateOffset, this._updateOldLength, this._updateNewLength) {
+ IncrementalResolver(this._definingUnit, this._updateOffset,
+ this._updateEndOld, this._updateEndNew) {
+ _updateDelta = _updateEndNew - _updateEndOld;
_definingLibrary = _definingUnit.library;
_source = _definingUnit.source;
+ _context = _definingUnit.context;
+ _typeProvider = _context.typeProvider;
+ entry = _context.getReadableSourceEntryOrNull(_source);
}
/**
@@ -780,15 +810,10 @@ class IncrementalResolver {
bool resolve(AstNode node) {
logger.enter('resolve: $_definingUnit');
try {
- logger.log(() => 'node: $node');
AstNode rootNode = _findResolutionRoot(node);
- logger.log(() => 'rootNode: $rootNode');
_prepareResolutionContext(rootNode);
// update elements
- _updateElementNameOffsets(
- _definingUnit,
- _updateOffset,
- _updateNewLength - _updateOldLength);
+ _updateElementNameOffsets();
_buildElements(rootNode);
if (!_canBeIncrementallyResolved(rootNode)) {
return false;
@@ -798,6 +823,8 @@ class IncrementalResolver {
// verify
_verify(rootNode);
_generateHints(rootNode);
+ // update entry errors
+ _updateEntry();
// resolve queue in response of API changes
_resolveQueue();
// OK
@@ -874,7 +901,9 @@ class IncrementalResolver {
node is MethodDeclaration;
void _fillResolutionQueue(DeclarationMatcher matcher) {
- for (Element removedElement in matcher._removedElements) {
+ HashSet<Element> removedElements = matcher._removedElements;
+ logger.log('${removedElements.length} elements removed');
+ for (Element removedElement in removedElements) {
AnalysisContextImpl context = removedElement.context;
IntSet users = removedElement.users;
while (!users.isEmpty) {
@@ -948,15 +977,24 @@ class IncrementalResolver {
* TODO(scheglov) revisit later. Each task duration should be kept short.
*/
void _resolveQueue() {
+ logger.log('${_resolutionQueue.length} elements in the resolution queue');
for (Element element in _resolutionQueue) {
// TODO(scheglov) in general, we should not call Element.node, it
// might perform complete unit resolution.
- AstNode node = element.node;
- CompilationUnitElement unit =
- element.getAncestor((e) => e is CompilationUnitElement);
- IncrementalResolver resolver =
- new IncrementalResolver(_typeProvider, unit, 0, 0, 0);
- resolver._resolveReferences(node);
+ logger.enter('resolve $element');
+ try {
+ AstNode node = element.node;
+ CompilationUnitElement unit =
+ element.getAncestor((e) => e is CompilationUnitElement);
+ IncrementalResolver resolver =
+ new IncrementalResolver(unit, node.offset, node.end, node.end);
+ resolver._resolveReferences(node);
+ resolver._verify(node);
+ resolver._generateHints(node);
+ resolver._updateEntry();
+ } finally {
+ logger.exit();
+ }
}
}
@@ -1011,6 +1049,91 @@ class IncrementalResolver {
}
}
+ void _shiftEntryErrors() {
+ Source librarySource = _definingLibrary.source;
+ {
+ List<AnalysisError> errors =
+ entry.getValueInLibrary(DartEntry.RESOLUTION_ERRORS, librarySource);
Brian Wilkerson 2014/12/19 15:03:29 FWIW the error access could also be moved into _sh
scheglov 2014/12/19 17:43:04 Done.
+ _shiftErrors(errors);
+ }
+ {
+ List<AnalysisError> errors =
+ entry.getValueInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource);
+ _shiftErrors(errors);
+ }
+ {
+ List<AnalysisError> errors =
+ entry.getValueInLibrary(DartEntry.HINTS, librarySource);
+ _shiftErrors(errors);
+ }
+ }
+
+ void _shiftErrors(List<AnalysisError> errors) {
+ for (AnalysisError error in errors) {
+ int errorOffset = error.offset;
+ if (errorOffset > _updateOffset) {
+ error.offset += _updateDelta;
+ }
+ }
+ }
+
+ void _updateElementNameOffsets() {
+ LoggingTimer timer = logger.startTimer();
+ try {
+ _definingUnit.accept(
+ new _ElementNameOffsetUpdater(_updateOffset, _updateDelta));
+ } finally {
+ timer.stop('update element offsets');
+ }
+ }
+
+ void _updateEntry() {
+ Source librarySource = _definingLibrary.source;
+ {
+ List<AnalysisError> oldErrors =
+ entry.getValueInLibrary(DartEntry.RESOLUTION_ERRORS, librarySource);
+ List<AnalysisError> errors = _updateErrors(oldErrors, _resolveErrors);
+ entry.setValueInLibrary(
+ DartEntry.RESOLUTION_ERRORS,
+ librarySource,
+ errors);
+ }
+ {
+ List<AnalysisError> oldErrors =
+ entry.getValueInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource);
+ List<AnalysisError> errors = _updateErrors(oldErrors, _verifyErrors);
+ entry.setValueInLibrary(
+ DartEntry.VERIFICATION_ERRORS,
+ librarySource,
+ errors);
+ }
+ entry.setValueInLibrary(DartEntry.HINTS, librarySource, _hints);
+ }
+
+ 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 _verify(AstNode node) {
LoggingTimer timer = logger.startTimer();
try {
@@ -1031,23 +1154,14 @@ class IncrementalResolver {
timer.stop('verify');
}
}
-
- static void _updateElementNameOffsets(Element root, int offset, int delta) {
- LoggingTimer timer = logger.startTimer();
- try {
- root.accept(new _ElementNameOffsetUpdater(offset, delta));
- } finally {
- timer.stop('update element offsets');
- }
- }
}
class PoorMansIncrementalResolver {
final TypeProvider _typeProvider;
final Source _unitSource;
- final Source _librarySource;
final DartEntry _entry;
+ CompilationUnitElement _unitElement;
int _updateOffset;
int _updateDelta;
@@ -1056,12 +1170,9 @@ class PoorMansIncrementalResolver {
List<AnalysisError> _newScanErrors = <AnalysisError>[];
List<AnalysisError> _newParseErrors = <AnalysisError>[];
- List<AnalysisError> _newResolveErrors = <AnalysisError>[];
- List<AnalysisError> _newVerifyErrors = <AnalysisError>[];
- List<AnalysisError> _newHints = <AnalysisError>[];
- PoorMansIncrementalResolver(this._typeProvider, this._unitSource,
- this._librarySource, this._entry, bool resolveApiChanges) {
+ PoorMansIncrementalResolver(this._typeProvider, this._unitSource, this._entry,
+ bool resolveApiChanges) {
_resolveApiChanges = resolveApiChanges;
}
@@ -1074,6 +1185,7 @@ class PoorMansIncrementalResolver {
logger.enter('diff/resolve $_unitSource');
logger.log(oldUnit != null ? 'has oldUnit' : 'oldUnit is null');
try {
+ _unitElement = oldUnit.element;
CompilationUnit newUnit = _parseUnit(newCode);
_TokenPair firstPair =
_findFirstDifferentToken(oldUnit.beginToken, newUnit.beginToken);
@@ -1093,6 +1205,7 @@ class PoorMansIncrementalResolver {
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) {
@@ -1104,10 +1217,15 @@ class PoorMansIncrementalResolver {
if (firstPair.kind == _TokenDifferenceKind.OFFSET) {
logger.log('Whitespace change.');
_shiftTokens(firstPair.oldToken);
- IncrementalResolver._updateElementNameOffsets(
- oldUnit.element,
- _updateOffset,
- _updateDelta);
+ {
+ IncrementalResolver incrementalResolver = new IncrementalResolver(
+ _unitElement,
+ _updateOffset,
+ _updateEndOld,
+ _updateEndNew);
+ incrementalResolver._updateElementNameOffsets();
+ incrementalResolver._shiftEntryErrors();
+ }
_updateEntry();
logger.log('Success.');
return true;
@@ -1172,10 +1290,8 @@ class PoorMansIncrementalResolver {
_shiftTokens(oldNode.endToken.next);
}
// perform incremental resolution
- CompilationUnitElement oldUnitElement = oldUnit.element;
IncrementalResolver incrementalResolver = new IncrementalResolver(
- _typeProvider,
- oldUnitElement,
+ _unitElement,
_updateOffset,
oldNode.length,
newNode.length);
@@ -1186,9 +1302,6 @@ class PoorMansIncrementalResolver {
return false;
}
// update DartEntry
- _newResolveErrors = incrementalResolver._resolveErrors;
- _newVerifyErrors = incrementalResolver._verifyErrors;
- _newHints = incrementalResolver._hints;
_updateEntry();
logger.log('Success.');
return true;
@@ -1234,15 +1347,14 @@ class PoorMansIncrementalResolver {
// replace node
NodeReplacer.replace(oldComment, newComment);
// update elements
- IncrementalResolver._updateElementNameOffsets(
- oldUnit.element,
+ IncrementalResolver incrementalResolver = new IncrementalResolver(
+ _unitElement,
_updateOffset,
- _updateDelta);
+ _updateEndOld,
+ _updateEndNew);
+ incrementalResolver._updateElementNameOffsets();
_updateEntry();
// resolve references in the comment
- CompilationUnitElement oldUnitElement = oldUnit.element;
- IncrementalResolver incrementalResolver =
- new IncrementalResolver(_typeProvider, oldUnitElement, _updateOffset, 0, 0);
incrementalResolver._resolveReferences(newComment);
}
@@ -1278,49 +1390,6 @@ class PoorMansIncrementalResolver {
void _updateEntry() {
_entry.setValue(DartEntry.SCAN_ERRORS, _newScanErrors);
_entry.setValue(DartEntry.PARSE_ERRORS, _newParseErrors);
- {
- List<AnalysisError> oldErrors =
- _entry.getValueInLibrary(DartEntry.RESOLUTION_ERRORS, _librarySource);
- List<AnalysisError> errors = _updateErrors(oldErrors, _newResolveErrors);
- _entry.setValueInLibrary(
- DartEntry.RESOLUTION_ERRORS,
- _librarySource,
- errors);
- }
- {
- List<AnalysisError> oldErrors =
- _entry.getValueInLibrary(DartEntry.VERIFICATION_ERRORS, _librarySource);
- List<AnalysisError> errors = _updateErrors(oldErrors, _newVerifyErrors);
- _entry.setValueInLibrary(
- DartEntry.VERIFICATION_ERRORS,
- _librarySource,
- errors);
- }
- _entry.setValueInLibrary(DartEntry.HINTS, _librarySource, _newHints);
- }
-
- 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;
}
static _TokenDifferenceKind _compareToken(Token oldToken, Token newToken,

Powered by Google App Engine
This is Rietveld 408576698