Index: packages/analyzer/lib/src/generated/incremental_resolver.dart |
diff --git a/analyzer/lib/src/generated/incremental_resolver.dart b/packages/analyzer/lib/src/generated/incremental_resolver.dart |
similarity index 88% |
rename from analyzer/lib/src/generated/incremental_resolver.dart |
rename to packages/analyzer/lib/src/generated/incremental_resolver.dart |
index 78481ce117eb96306a99b92cb3058f6ec03c3a8a..86a87bd326947747c3525a3e5af2abee2c994729 100644 |
--- a/analyzer/lib/src/generated/incremental_resolver.dart |
+++ b/packages/analyzer/lib/src/generated/incremental_resolver.dart |
@@ -8,27 +8,26 @@ import 'dart:collection'; |
import 'dart:math' as math; |
import 'package:analyzer/src/context/cache.dart' |
- show CacheEntry, TargetedResult; |
+ show CacheEntry, Delta, DeltaResult; |
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 'package:analyzer/src/task/dart.dart'; |
+import 'package:analyzer/task/dart.dart'; |
+import 'package:analyzer/task/general.dart' show CONTENT, LINE_INFO; |
+import 'package:analyzer/task/model.dart' |
+ show AnalysisTarget, ResultDescriptor, TargetedResult, TaskDescriptor; |
import 'ast.dart'; |
import 'element.dart'; |
-import 'engine.dart'; |
+import 'engine.dart' |
+ show |
+ AnalysisContext, |
+ AnalysisOptions, |
+ CacheState, |
+ DartEntry, |
+ DataDescriptor, |
+ InternalAnalysisContext, |
+ RecordingErrorListener, |
+ SourceEntry; |
import 'error.dart'; |
import 'error_verifier.dart'; |
import 'incremental_logger.dart' show logger, LoggingTimer; |
@@ -494,6 +493,24 @@ class DeclarationMatcher extends RecursiveAstVisitor { |
_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); |
@@ -827,6 +844,92 @@ class DeclarationMatchKind { |
} |
/** |
+ * The [Delta] implementation used by incremental resolver. |
+ * It keeps Dart results that are either don't change or are updated. |
+ */ |
+class IncrementalBodyDelta extends Delta { |
+ /** |
+ * 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; |
+ |
+ /** |
+ * The delta between [updateEndNew] and [updateEndOld]. |
+ */ |
+ final int updateDelta; |
+ |
+ IncrementalBodyDelta(Source source, this.updateOffset, this.updateEndOld, |
+ this.updateEndNew, this.updateDelta) |
+ : super(source); |
+ |
+ @override |
+ DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target, |
+ ResultDescriptor descriptor) { |
+ // A body change delta should never leak outside its source. |
+ // It can cause invalidation of results (e.g. hints) in other sources, |
+ // but only when a result in the updated source is INVALIDATE_NO_DELTA. |
+ if (target.source != source) { |
+ return DeltaResult.STOP; |
+ } |
+ // don't invalidate results of standard Dart tasks |
+ bool isByTask(TaskDescriptor taskDescriptor) { |
+ return taskDescriptor.results.contains(descriptor); |
+ } |
+ if (descriptor == CONTENT) { |
+ return DeltaResult.KEEP_CONTINUE; |
+ } |
+ if (target is LibrarySpecificUnit && target.unit != source) { |
+ if (isByTask(GatherUsedLocalElementsTask.DESCRIPTOR) || |
+ isByTask(GatherUsedImportedElementsTask.DESCRIPTOR)) { |
+ return DeltaResult.KEEP_CONTINUE; |
+ } |
+ } |
+ if (isByTask(BuildCompilationUnitElementTask.DESCRIPTOR) || |
+ isByTask(BuildDirectiveElementsTask.DESCRIPTOR) || |
+ isByTask(BuildEnumMemberElementsTask.DESCRIPTOR) || |
+ isByTask(BuildExportNamespaceTask.DESCRIPTOR) || |
+ isByTask(BuildLibraryElementTask.DESCRIPTOR) || |
+ isByTask(BuildPublicNamespaceTask.DESCRIPTOR) || |
+ isByTask(BuildSourceExportClosureTask.DESCRIPTOR) || |
+ isByTask(BuildSourceImportExportClosureTask.DESCRIPTOR) || |
+ isByTask(ComputeConstantDependenciesTask.DESCRIPTOR) || |
+ isByTask(ComputeConstantValueTask.DESCRIPTOR) || |
+ isByTask(ComputeLibraryCycleTask.DESCRIPTOR) || |
+ isByTask(DartErrorsTask.DESCRIPTOR) || |
+ isByTask(EvaluateUnitConstantsTask.DESCRIPTOR) || |
+ isByTask(GenerateHintsTask.DESCRIPTOR) || |
+ isByTask(InferInstanceMembersInUnitTask.DESCRIPTOR) || |
+ isByTask(InferStaticVariableTypesInUnitTask.DESCRIPTOR) || |
+ isByTask(LibraryErrorsReadyTask.DESCRIPTOR) || |
+ isByTask(LibraryUnitErrorsTask.DESCRIPTOR) || |
+ isByTask(ParseDartTask.DESCRIPTOR) || |
+ isByTask(PartiallyResolveUnitReferencesTask.DESCRIPTOR) || |
+ isByTask(ScanDartTask.DESCRIPTOR) || |
+ isByTask(ResolveInstanceFieldsInUnitTask.DESCRIPTOR) || |
+ isByTask(ResolveLibraryReferencesTask.DESCRIPTOR) || |
+ isByTask(ResolveLibraryTypeNamesTask.DESCRIPTOR) || |
+ isByTask(ResolveUnitTask.DESCRIPTOR) || |
+ isByTask(ResolveUnitTypeNamesTask.DESCRIPTOR) || |
+ isByTask(ResolveVariableReferencesTask.DESCRIPTOR) || |
+ isByTask(VerifyUnitTask.DESCRIPTOR)) { |
+ return DeltaResult.KEEP_CONTINUE; |
+ } |
+ // invalidate all the other results |
+ return DeltaResult.INVALIDATE_NO_DELTA; |
+ } |
+} |
+ |
+/** |
* Instances of the class [IncrementalResolver] resolve the smallest portion of |
* an AST structure that we currently know how to resolve. |
*/ |
@@ -847,6 +950,11 @@ class IncrementalResolver { |
TypeProvider _typeProvider; |
/** |
+ * The type system primitives. |
+ */ |
+ TypeSystem _typeSystem; |
+ |
+ /** |
* The element for the library containing the compilation unit being resolved. |
*/ |
LibraryElementImpl _definingLibrary; |
@@ -891,8 +999,16 @@ class IncrementalResolver { |
*/ |
final int _updateEndNew; |
+ /** |
+ * The delta between [_updateEndNew] and [_updateEndOld]. |
+ */ |
int _updateDelta; |
+ /** |
+ * The set of [AnalysisError]s that have been already shifted. |
+ */ |
+ Set<AnalysisError> _alreadyShiftedErrors = new HashSet.identity(); |
+ |
RecordingErrorListener errorListener = new RecordingErrorListener(); |
ResolutionContext _resolutionContext; |
@@ -903,8 +1019,13 @@ class IncrementalResolver { |
* 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, |
+ IncrementalResolver( |
+ this.oldEntry, |
+ this.newSourceEntry, |
+ this.newUnitEntry, |
+ this._definingUnit, |
+ this._updateOffset, |
+ this._updateEndOld, |
this._updateEndNew) { |
_updateDelta = _updateEndNew - _updateEndOld; |
_definingLibrary = _definingUnit.library; |
@@ -912,6 +1033,7 @@ class IncrementalResolver { |
_source = _definingUnit.source; |
_context = _definingUnit.context; |
_typeProvider = _context.typeProvider; |
+ _typeSystem = _context.typeSystem; |
} |
/** |
@@ -927,6 +1049,7 @@ class IncrementalResolver { |
AstNode rootNode = _findResolutionRoot(node); |
_prepareResolutionContext(rootNode); |
// update elements |
+ _updateCache(); |
_updateElementNameOffsets(); |
_buildElements(rootNode); |
if (!_canBeIncrementallyResolved(rootNode)) { |
@@ -941,8 +1064,6 @@ class IncrementalResolver { |
_context.invalidateLibraryHints(_librarySource); |
// update entry errors |
_updateEntry(); |
- // notify unit |
- _definingUnit.afterIncrementalResolution(); |
// OK |
return true; |
} finally { |
@@ -1018,8 +1139,8 @@ class IncrementalResolver { |
// compute values |
{ |
CompilationUnit unit = node.getAncestor((n) => n is CompilationUnit); |
- ConstantValueComputer computer = new ConstantValueComputer( |
- _context, _typeProvider, _context.declaredVariables); |
+ ConstantValueComputer computer = new ConstantValueComputer(_context, |
+ _typeProvider, _context.declaredVariables, null, _typeSystem); |
computer.add(unit, _source, _librarySource); |
computer.computeValues(); |
} |
@@ -1120,8 +1241,10 @@ class IncrementalResolver { |
void _shiftEntryErrors_NEW() { |
_shiftErrors_NEW(HINTS); |
- _shiftErrors_NEW(RESOLVE_REFERENCES_ERRORS); |
+ _shiftErrors_NEW(LINTS); |
+ _shiftErrors_NEW(LIBRARY_UNIT_ERRORS); |
_shiftErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS); |
+ _shiftErrors_NEW(RESOLVE_UNIT_ERRORS); |
_shiftErrors_NEW(VARIABLE_REFERENCE_ERRORS); |
_shiftErrors_NEW(VERIFY_ERRORS); |
} |
@@ -1135,9 +1258,11 @@ class IncrementalResolver { |
void _shiftErrors(List<AnalysisError> errors) { |
for (AnalysisError error in errors) { |
- int errorOffset = error.offset; |
- if (errorOffset > _updateOffset) { |
- error.offset += _updateDelta; |
+ if (_alreadyShiftedErrors.add(error)) { |
+ int errorOffset = error.offset; |
+ if (errorOffset > _updateOffset) { |
+ error.offset += _updateDelta; |
+ } |
} |
} |
} |
@@ -1153,11 +1278,25 @@ class IncrementalResolver { |
_shiftErrors(errors); |
} |
+ void _updateCache() { |
+ if (newSourceEntry != null) { |
+ LoggingTimer timer = logger.startTimer(); |
+ try { |
+ newSourceEntry.setState(CONTENT, CacheState.INVALID, |
+ delta: new IncrementalBodyDelta(_source, _updateOffset, |
+ _updateEndOld, _updateEndNew, _updateDelta)); |
+ } finally { |
+ timer.stop('invalidate cache with delta'); |
+ } |
+ } |
+ } |
+ |
void _updateElementNameOffsets() { |
LoggingTimer timer = logger.startTimer(); |
try { |
_definingUnit |
.accept(new _ElementNameOffsetUpdater(_updateOffset, _updateDelta)); |
+ _definingUnit.afterIncrementalResolution(); |
} finally { |
timer.stop('update element offsets'); |
} |
@@ -1172,14 +1311,15 @@ class IncrementalResolver { |
} |
void _updateEntry_NEW() { |
- _updateErrors_NEW(RESOLVE_REFERENCES_ERRORS, _resolveErrors); |
_updateErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS, []); |
+ _updateErrors_NEW(RESOLVE_UNIT_ERRORS, _resolveErrors); |
_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); |
+ newUnitEntry.setState(LINTS, CacheState.INVALID); |
} |
void _updateEntry_OLD() { |
@@ -1215,7 +1355,7 @@ class IncrementalResolver { |
List<AnalysisError> newErrors) { |
List<AnalysisError> oldErrors = newUnitEntry.getValue(descriptor); |
List<AnalysisError> errors = _updateErrors(oldErrors, newErrors); |
- newUnitEntry.setValueIncremental(descriptor, errors); |
+ newUnitEntry.setValueIncremental(descriptor, errors, true); |
} |
void _updateErrors_OLD(DataDescriptor<List<AnalysisError>> descriptor, |
@@ -1231,9 +1371,12 @@ class IncrementalResolver { |
try { |
RecordingErrorListener errorListener = new RecordingErrorListener(); |
ErrorReporter errorReporter = new ErrorReporter(errorListener, _source); |
- ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, |
- _definingLibrary, _typeProvider, |
- new InheritanceManager(_definingLibrary)); |
+ ErrorVerifier errorVerifier = new ErrorVerifier( |
+ errorReporter, |
+ _definingLibrary, |
+ _typeProvider, |
+ new InheritanceManager(_definingLibrary), |
+ _context.analysisOptions.enableSuperMixins); |
if (_resolutionContext.enclosingClassDeclaration != null) { |
errorVerifier.visitClassDeclarationIncrementally( |
_resolutionContext.enclosingClassDeclaration); |
@@ -1266,7 +1409,6 @@ class PoorMansIncrementalResolver { |
CacheEntry _newUnitEntry; |
final CompilationUnit _oldUnit; |
- final AnalysisOptions _options; |
CompilationUnitElement _unitElement; |
int _updateOffset; |
@@ -1274,12 +1416,18 @@ class PoorMansIncrementalResolver { |
int _updateEndOld; |
int _updateEndNew; |
+ LineInfo _newLineInfo; |
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) { |
+ PoorMansIncrementalResolver( |
+ this._typeProvider, |
+ this._unitSource, |
+ this._oldEntry, |
+ this._newSourceEntry, |
+ this._newUnitEntry, |
+ this._oldUnit, |
+ bool resolveApiChanges) { |
_resolveApiChanges = resolveApiChanges; |
} |
@@ -1336,8 +1484,14 @@ class PoorMansIncrementalResolver { |
_shiftTokens(firstPair.oldToken); |
{ |
IncrementalResolver incrementalResolver = new IncrementalResolver( |
- _oldEntry, _newSourceEntry, _newUnitEntry, _unitElement, |
- _updateOffset, _updateEndOld, _updateEndNew); |
+ _oldEntry, |
+ _newSourceEntry, |
+ _newUnitEntry, |
+ _unitElement, |
+ _updateOffset, |
+ _updateEndOld, |
+ _updateEndNew); |
+ incrementalResolver._updateCache(); |
incrementalResolver._updateElementNameOffsets(); |
incrementalResolver._shiftEntryErrors(); |
} |
@@ -1383,7 +1537,8 @@ class PoorMansIncrementalResolver { |
found = true; |
} |
} |
- if (oldParent is FunctionBody && newParent is FunctionBody) { |
+ if (oldParent is BlockFunctionBody && |
+ newParent is BlockFunctionBody) { |
oldNode = oldParent; |
newNode = newParent; |
found = true; |
@@ -1426,8 +1581,13 @@ class PoorMansIncrementalResolver { |
} |
// perform incremental resolution |
IncrementalResolver incrementalResolver = new IncrementalResolver( |
- _oldEntry, _newSourceEntry, _newUnitEntry, _unitElement, |
- _updateOffset, _updateEndOld, _updateEndNew); |
+ _oldEntry, |
+ _newSourceEntry, |
+ _newUnitEntry, |
+ _unitElement, |
+ _updateOffset, |
+ _updateEndOld, |
+ _updateEndNew); |
bool success = incrementalResolver.resolve(newNode); |
// check if success |
if (!success) { |
@@ -1491,9 +1651,15 @@ class PoorMansIncrementalResolver { |
// replace node |
NodeReplacer.replace(oldComment, newComment); |
// update elements |
- IncrementalResolver incrementalResolver = new IncrementalResolver(_oldEntry, |
- _newSourceEntry, _newUnitEntry, _unitElement, _updateOffset, |
- _updateEndOld, _updateEndNew); |
+ IncrementalResolver incrementalResolver = new IncrementalResolver( |
+ _oldEntry, |
+ _newSourceEntry, |
+ _newUnitEntry, |
+ _unitElement, |
+ _updateOffset, |
+ _updateEndOld, |
+ _updateEndNew); |
+ incrementalResolver._updateCache(); |
incrementalResolver._updateElementNameOffsets(); |
incrementalResolver._shiftEntryErrors(); |
_updateEntry(); |
@@ -1508,6 +1674,7 @@ class PoorMansIncrementalResolver { |
CharSequenceReader reader = new CharSequenceReader(code); |
Scanner scanner = new Scanner(_unitSource, reader, errorListener); |
Token token = scanner.tokenize(); |
+ _newLineInfo = new LineInfo(scanner.lineStarts); |
_newScanErrors = errorListener.errors; |
return token; |
} |
@@ -1559,21 +1726,16 @@ class PoorMansIncrementalResolver { |
} |
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); |
+ _newSourceEntry.setValueIncremental(SCAN_ERRORS, _newScanErrors, true); |
+ _newSourceEntry.setValueIncremental(LINE_INFO, _newLineInfo, false); |
// 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); |
+ _newSourceEntry.setValueIncremental(PARSE_ERRORS, _newParseErrors, true); |
+ _newSourceEntry.setValueIncremental(PARSED_UNIT, _oldUnit, false); |
} |
void _updateEntry_OLD() { |
+ _oldEntry.setValue(SourceEntry.LINE_INFO, _newLineInfo); |
_oldEntry.setValue(DartEntry.SCAN_ERRORS, _newScanErrors); |
_oldEntry.setValue(DartEntry.PARSE_ERRORS, _newParseErrors); |
} |