| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library analyzer.src.task.dart_work_manager; | 5 library analyzer.src.task.dart_work_manager; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/error/error.dart'; |
| 9 import 'package:analyzer/src/context/cache.dart'; | 10 import 'package:analyzer/src/context/cache.dart'; |
| 10 import 'package:analyzer/src/generated/engine.dart' | 11 import 'package:analyzer/src/generated/engine.dart' |
| 11 show | 12 show AnalysisEngine, AnalysisErrorInfo, CacheState, InternalAnalysisContext; |
| 12 AnalysisEngine, | |
| 13 AnalysisErrorInfo, | |
| 14 AnalysisErrorInfoImpl, | |
| 15 AnalysisOptions, | |
| 16 CacheState, | |
| 17 InternalAnalysisContext; | |
| 18 import 'package:analyzer/src/generated/error.dart'; | |
| 19 import 'package:analyzer/src/generated/source.dart'; | 13 import 'package:analyzer/src/generated/source.dart'; |
| 20 import 'package:analyzer/src/generated/utilities_collection.dart'; | 14 import 'package:analyzer/src/generated/utilities_collection.dart'; |
| 21 import 'package:analyzer/src/task/dart.dart'; | 15 import 'package:analyzer/src/task/dart.dart'; |
| 22 import 'package:analyzer/src/task/html.dart'; | 16 import 'package:analyzer/src/task/html.dart'; |
| 23 import 'package:analyzer/task/dart.dart'; | 17 import 'package:analyzer/task/dart.dart'; |
| 24 import 'package:analyzer/task/model.dart'; | 18 import 'package:analyzer/task/model.dart'; |
| 25 | 19 |
| 26 /** | 20 /** |
| 27 * The manager for Dart specific analysis. | 21 * The manager for Dart specific analysis. |
| 28 */ | 22 */ |
| 29 class DartWorkManager implements WorkManager { | 23 class DartWorkManager implements WorkManager { |
| 30 /** | 24 /** |
| 31 * The list of errors that are reported for raw Dart [Source]s. | 25 * The list of errors that are reported for raw Dart [Source]s. |
| 32 */ | 26 */ |
| 33 static final List<ResultDescriptor> _SOURCE_ERRORS = <ResultDescriptor>[ | 27 static final List<ResultDescriptor<List<AnalysisError>>> _SOURCE_ERRORS = |
| 28 <ResultDescriptor<List<AnalysisError>>>[ |
| 34 BUILD_DIRECTIVES_ERRORS, | 29 BUILD_DIRECTIVES_ERRORS, |
| 35 BUILD_LIBRARY_ERRORS, | 30 BUILD_LIBRARY_ERRORS, |
| 36 PARSE_ERRORS, | 31 PARSE_ERRORS, |
| 37 SCAN_ERRORS | 32 SCAN_ERRORS |
| 38 ]; | 33 ]; |
| 39 | 34 |
| 40 /** | 35 /** |
| 41 * The list of errors that are reported for raw Dart [LibrarySpecificUnit]s. | 36 * The list of errors that are reported for raw Dart [LibrarySpecificUnit]s. |
| 42 */ | 37 */ |
| 43 static final List<ResultDescriptor> _UNIT_ERRORS = <ResultDescriptor>[ | 38 static final List<ResultDescriptor<List<AnalysisError>>> _UNIT_ERRORS = |
| 39 <ResultDescriptor<List<AnalysisError>>>[ |
| 44 HINTS, | 40 HINTS, |
| 45 LINTS, | 41 LINTS, |
| 46 LIBRARY_UNIT_ERRORS, | 42 LIBRARY_UNIT_ERRORS, |
| 47 RESOLVE_TYPE_NAMES_ERRORS, | 43 RESOLVE_TYPE_NAMES_ERRORS, |
| 44 RESOLVE_TYPE_BOUNDS_ERRORS, |
| 48 RESOLVE_UNIT_ERRORS, | 45 RESOLVE_UNIT_ERRORS, |
| 49 STRONG_MODE_ERRORS, | 46 STRONG_MODE_ERRORS, |
| 50 VARIABLE_REFERENCE_ERRORS, | 47 VARIABLE_REFERENCE_ERRORS, |
| 51 VERIFY_ERRORS | 48 VERIFY_ERRORS |
| 52 ]; | 49 ]; |
| 53 | 50 |
| 54 final InternalAnalysisContext context; | 51 final InternalAnalysisContext context; |
| 55 | 52 |
| 56 /** | 53 /** |
| 57 * The [TargetedResult]s that should be computed with priority. | 54 * The [TargetedResult]s that should be computed with priority. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 78 /** | 75 /** |
| 79 * A table mapping part sources to the library sources that include them. | 76 * A table mapping part sources to the library sources that include them. |
| 80 */ | 77 */ |
| 81 final HashMap<Source, List<Source>> partLibrariesMap = | 78 final HashMap<Source, List<Source>> partLibrariesMap = |
| 82 new HashMap<Source, List<Source>>(); | 79 new HashMap<Source, List<Source>>(); |
| 83 | 80 |
| 84 /** | 81 /** |
| 85 * Initialize a newly created manager. | 82 * Initialize a newly created manager. |
| 86 */ | 83 */ |
| 87 DartWorkManager(this.context) { | 84 DartWorkManager(this.context) { |
| 88 analysisCache.onResultInvalidated.listen((InvalidatedResult event) { | 85 context.onResultInvalidated.listen((InvalidatedResult event) { |
| 89 if (event.descriptor == LIBRARY_ERRORS_READY) { | 86 if (event.descriptor == LIBRARY_ERRORS_READY) { |
| 90 CacheEntry entry = event.entry; | 87 CacheEntry entry = event.entry; |
| 91 if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY) { | 88 if (entry.explicitlyAdded && |
| 89 entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY) { |
| 92 librarySourceQueue.add(entry.target); | 90 librarySourceQueue.add(entry.target); |
| 93 } | 91 } |
| 94 } | 92 } |
| 95 }); | 93 }); |
| 96 } | 94 } |
| 97 | 95 |
| 98 /** | 96 /** |
| 99 * Returns the correctly typed result of `context.analysisCache`. | 97 * Returns the correctly typed result of `context.analysisCache`. |
| 100 */ | 98 */ |
| 101 AnalysisCache get analysisCache => context.analysisCache; | 99 AnalysisCache get analysisCache => context.analysisCache; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 112 * to be computed with priority. | 110 * to be computed with priority. |
| 113 */ | 111 */ |
| 114 void addPriorityResult(AnalysisTarget target, ResultDescriptor result) { | 112 void addPriorityResult(AnalysisTarget target, ResultDescriptor result) { |
| 115 priorityResultQueue.add(new TargetedResult(target, result)); | 113 priorityResultQueue.add(new TargetedResult(target, result)); |
| 116 } | 114 } |
| 117 | 115 |
| 118 @override | 116 @override |
| 119 void applyChange(List<Source> addedSources, List<Source> changedSources, | 117 void applyChange(List<Source> addedSources, List<Source> changedSources, |
| 120 List<Source> removedSources) { | 118 List<Source> removedSources) { |
| 121 addedSources = addedSources.where(_isDartSource).toList(); | 119 addedSources = addedSources.where(_isDartSource).toList(); |
| 122 changedSources = changedSources.where(_isDartSource).toList(); | 120 changedSources = changedSources |
| 121 .where(_isDartSource) |
| 122 .where((source) => _needsComputing(source, SOURCE_KIND)) |
| 123 .toList(); |
| 123 removedSources = removedSources.where(_isDartSource).toList(); | 124 removedSources = removedSources.where(_isDartSource).toList(); |
| 124 // unknown queue | 125 // unknown queue |
| 125 unknownSourceQueue.addAll(addedSources); | 126 unknownSourceQueue.addAll(addedSources); |
| 126 unknownSourceQueue.addAll(changedSources); | 127 unknownSourceQueue.addAll(changedSources); |
| 127 unknownSourceQueue.removeAll(removedSources); | 128 unknownSourceQueue.removeAll(removedSources); |
| 128 // library queue | 129 // library queue |
| 129 librarySourceQueue.removeAll(changedSources); | 130 librarySourceQueue.removeAll(changedSources); |
| 130 librarySourceQueue.removeAll(removedSources); | 131 librarySourceQueue.removeAll(removedSources); |
| 131 // parts in libraries | 132 // parts in libraries |
| 132 for (Source changedSource in changedSources) { | 133 for (Source changedSource in changedSources) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 List<AnalysisError> getErrors(Source source) { | 171 List<AnalysisError> getErrors(Source source) { |
| 171 if (!_isDartSource(source) && source is! DartScript) { | 172 if (!_isDartSource(source) && source is! DartScript) { |
| 172 return AnalysisError.NO_ERRORS; | 173 return AnalysisError.NO_ERRORS; |
| 173 } | 174 } |
| 174 // If analysis is finished, use all the errors. | 175 // If analysis is finished, use all the errors. |
| 175 if (analysisCache.getState(source, DART_ERRORS) == CacheState.VALID) { | 176 if (analysisCache.getState(source, DART_ERRORS) == CacheState.VALID) { |
| 176 return analysisCache.getValue(source, DART_ERRORS); | 177 return analysisCache.getValue(source, DART_ERRORS); |
| 177 } | 178 } |
| 178 // If analysis is in progress, combine all known partial results. | 179 // If analysis is in progress, combine all known partial results. |
| 179 List<AnalysisError> errors = <AnalysisError>[]; | 180 List<AnalysisError> errors = <AnalysisError>[]; |
| 180 for (ResultDescriptor descriptor in _SOURCE_ERRORS) { | 181 for (ResultDescriptor<List<AnalysisError>> descriptor in _SOURCE_ERRORS) { |
| 181 errors.addAll(analysisCache.getValue(source, descriptor)); | 182 errors.addAll(analysisCache.getValue(source, descriptor)); |
| 182 } | 183 } |
| 183 for (Source library in context.getLibrariesContaining(source)) { | 184 for (Source library in context.getLibrariesContaining(source)) { |
| 184 LibrarySpecificUnit unit = new LibrarySpecificUnit(library, source); | 185 LibrarySpecificUnit unit = new LibrarySpecificUnit(library, source); |
| 185 for (ResultDescriptor descriptor in _UNIT_ERRORS) { | 186 for (ResultDescriptor<List<AnalysisError>> descriptor in _UNIT_ERRORS) { |
| 186 errors.addAll(analysisCache.getValue(unit, descriptor)); | 187 errors.addAll(analysisCache.getValue(unit, descriptor)); |
| 187 } | 188 } |
| 188 } | 189 } |
| 189 return errors; | 190 return errors; |
| 190 } | 191 } |
| 191 | 192 |
| 192 /** | 193 /** |
| 193 * Returns libraries containing the given [part]. | 194 * Returns libraries containing the given [part]. |
| 194 * Maybe empty, but not null. | 195 * Maybe empty, but not null. |
| 195 */ | 196 */ |
| 196 List<Source> getLibrariesContainingPart(Source part) { | 197 List<Source> getLibrariesContainingPart(Source part) { |
| 197 if (part.isInSystemLibrary) { | 198 if (part.isInSystemLibrary) { |
| 198 DartWorkManager sdkDartWorkManager = _getSdkDartWorkManager(); | 199 DartWorkManager sdkDartWorkManager = _getSdkDartWorkManager(); |
| 199 if (sdkDartWorkManager != this) { | 200 if (sdkDartWorkManager != this) { |
| 200 return sdkDartWorkManager.getLibrariesContainingPart(part); | 201 return sdkDartWorkManager.getLibrariesContainingPart(part); |
| 201 } | 202 } |
| 202 } | 203 } |
| 203 List<Source> libraries = partLibrariesMap[part]; | 204 List<Source> libraries = partLibrariesMap[part]; |
| 204 return libraries != null ? libraries : Source.EMPTY_LIST; | 205 libraries ??= _getLibrariesContainingPartFromResultProvider(part); |
| 206 return libraries?.toList() ?? Source.EMPTY_LIST; |
| 205 } | 207 } |
| 206 | 208 |
| 207 @override | 209 @override |
| 208 TargetedResult getNextResult() { | 210 TargetedResult getNextResult() { |
| 209 // Try to find a priority result to compute. | 211 // Try to find a priority result to compute. |
| 210 while (priorityResultQueue.isNotEmpty) { | 212 while (priorityResultQueue.isNotEmpty) { |
| 211 TargetedResult result = priorityResultQueue.first; | 213 TargetedResult result = priorityResultQueue.first; |
| 212 if (!_needsComputing(result.target, result.result)) { | 214 if (!_needsComputing(result.target, result.result)) { |
| 213 priorityResultQueue.remove(result); | 215 priorityResultQueue.remove(result); |
| 214 continue; | 216 continue; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 if (needErrors) { | 298 if (needErrors) { |
| 297 librarySourceQueue.add(target); | 299 librarySourceQueue.add(target); |
| 298 } | 300 } |
| 299 } | 301 } |
| 300 } | 302 } |
| 301 } | 303 } |
| 302 } | 304 } |
| 303 // Update parts in libraries. | 305 // Update parts in libraries. |
| 304 if (isDartLibrarySource) { | 306 if (isDartLibrarySource) { |
| 305 Source library = target; | 307 Source library = target; |
| 306 List<Source> includedParts = outputs[INCLUDED_PARTS]; | 308 List<Source> includedParts = outputs[INCLUDED_PARTS] as List<Source>; |
| 307 if (includedParts != null) { | 309 if (includedParts != null) { |
| 308 libraryPartsMap[library] = includedParts; | 310 libraryPartsMap[library] = includedParts; |
| 309 for (Source part in includedParts) { | 311 for (Source part in includedParts) { |
| 310 List<Source> libraries = | 312 List<Source> libraries = |
| 311 partLibrariesMap.putIfAbsent(part, () => <Source>[]); | 313 partLibrariesMap.putIfAbsent(part, () => <Source>[]); |
| 312 if (!libraries.contains(library)) { | 314 if (!libraries.contains(library)) { |
| 313 libraries.add(library); | 315 libraries.add(library); |
| 314 _invalidateContainingLibraries(part); | 316 _invalidateContainingLibraries(part); |
| 315 } | 317 } |
| 316 } | 318 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 342 shouldSetErrors = true; | 344 shouldSetErrors = true; |
| 343 } | 345 } |
| 344 }); | 346 }); |
| 345 if (shouldSetErrors) { | 347 if (shouldSetErrors) { |
| 346 AnalysisErrorInfo info = context.getErrors(source); | 348 AnalysisErrorInfo info = context.getErrors(source); |
| 347 context.getNotice(source).setErrors(info.errors, info.lineInfo); | 349 context.getNotice(source).setErrors(info.errors, info.lineInfo); |
| 348 } | 350 } |
| 349 } | 351 } |
| 350 } | 352 } |
| 351 | 353 |
| 354 /** |
| 355 * The given unit was incrementally resolved. Some of its error results might |
| 356 * have been invalidated, so we schedule it for computing errors. |
| 357 */ |
| 352 void unitIncrementallyResolved(Source librarySource, Source unitSource) { | 358 void unitIncrementallyResolved(Source librarySource, Source unitSource) { |
| 353 librarySourceQueue.add(librarySource); | 359 librarySourceQueue.add(librarySource); |
| 354 } | 360 } |
| 355 | 361 |
| 356 /** | 362 /** |
| 363 * Ask the [context]'s result provider for [CONTAINING_LIBRARIES]. |
| 364 * Return the list of containing libraries, or `null` if unknown. |
| 365 */ |
| 366 List<Source> _getLibrariesContainingPartFromResultProvider(Source part) { |
| 367 CacheEntry cacheEntry = context.getCacheEntry(part); |
| 368 bool knows = context.aboutToComputeResult(cacheEntry, CONTAINING_LIBRARIES); |
| 369 if (knows) { |
| 370 return cacheEntry.getValue(CONTAINING_LIBRARIES); |
| 371 } |
| 372 return null; |
| 373 } |
| 374 |
| 375 /** |
| 357 * Return the SDK [DartWorkManager] or this one. | 376 * Return the SDK [DartWorkManager] or this one. |
| 358 */ | 377 */ |
| 359 DartWorkManager _getSdkDartWorkManager() { | 378 DartWorkManager _getSdkDartWorkManager() { |
| 360 SourceFactory sourceFactory = context.sourceFactory; | 379 SourceFactory sourceFactory = context.sourceFactory; |
| 361 InternalAnalysisContext sdkContext = sourceFactory.dartSdk.context; | 380 InternalAnalysisContext sdkContext = sourceFactory.dartSdk.context; |
| 362 if (sdkContext != context) { | 381 if (sdkContext != context) { |
| 363 for (WorkManager workManager in sdkContext.workManagers) { | 382 for (WorkManager workManager in sdkContext.workManagers) { |
| 364 if (workManager is DartWorkManager) { | 383 if (workManager is DartWorkManager) { |
| 365 return workManager; | 384 return workManager; |
| 366 } | 385 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 385 // Optionally gather Dart sources to invalidate URIs resolution. | 404 // Optionally gather Dart sources to invalidate URIs resolution. |
| 386 if (invalidateUris && _isDartSource(target)) { | 405 if (invalidateUris && _isDartSource(target)) { |
| 387 dartSources.add(target); | 406 dartSources.add(target); |
| 388 } | 407 } |
| 389 // LibrarySpecificUnit(s) are roots of Dart resolution. | 408 // LibrarySpecificUnit(s) are roots of Dart resolution. |
| 390 // When one is invalidated, invalidation is propagated to all resolution. | 409 // When one is invalidated, invalidation is propagated to all resolution. |
| 391 if (target is LibrarySpecificUnit) { | 410 if (target is LibrarySpecificUnit) { |
| 392 unitTargets.add(target); | 411 unitTargets.add(target); |
| 393 Source library = target.library; | 412 Source library = target.library; |
| 394 if (context.exists(library)) { | 413 if (context.exists(library)) { |
| 395 librarySourceQueue.add(library); | 414 CacheEntry entry = iterator.value; |
| 415 if (entry.explicitlyAdded) { |
| 416 librarySourceQueue.add(library); |
| 417 } |
| 396 } | 418 } |
| 397 } | 419 } |
| 398 } | 420 } |
| 399 // Invalidate targets and values. | 421 // Invalidate targets and values. |
| 400 unitTargets.forEach(partition.remove); | 422 unitTargets.forEach(partition.remove); |
| 401 for (Source dartSource in dartSources) { | 423 for (Source dartSource in dartSources) { |
| 402 CacheEntry entry = partition.get(dartSource); | 424 CacheEntry entry = partition.get(dartSource); |
| 403 if (dartSource != null) { | 425 if (entry != null) { |
| 404 // TODO(scheglov) we invalidate too much. | 426 // TODO(scheglov) we invalidate too much. |
| 405 // Would be nice to invalidate just URLs resolution. | 427 // Would be nice to invalidate just URLs resolution. |
| 406 entry.setState(PARSED_UNIT, CacheState.INVALID); | 428 entry.setState(PARSED_UNIT, CacheState.INVALID); |
| 407 entry.setState(IMPORTED_LIBRARIES, CacheState.INVALID); | 429 entry.setState(IMPORTED_LIBRARIES, CacheState.INVALID); |
| 408 entry.setState(EXPLICITLY_IMPORTED_LIBRARIES, CacheState.INVALID); | 430 entry.setState(EXPLICITLY_IMPORTED_LIBRARIES, CacheState.INVALID); |
| 409 entry.setState(EXPORTED_LIBRARIES, CacheState.INVALID); | 431 entry.setState(EXPORTED_LIBRARIES, CacheState.INVALID); |
| 410 entry.setState(INCLUDED_PARTS, CacheState.INVALID); | 432 entry.setState(INCLUDED_PARTS, CacheState.INVALID); |
| 433 entry.setState(LIBRARY_SPECIFIC_UNITS, CacheState.INVALID); |
| 434 entry.setState(UNITS, CacheState.INVALID); |
| 411 } | 435 } |
| 412 } | 436 } |
| 413 } | 437 } |
| 414 | 438 |
| 415 /** | 439 /** |
| 416 * Invalidate [CONTAINING_LIBRARIES] for the given [source]. | 440 * Invalidate [CONTAINING_LIBRARIES] for the given [source]. |
| 417 * [CONTAINING_LIBRARIES] does not have dependencies, so we manage it here. | 441 * [CONTAINING_LIBRARIES] does not have dependencies, so we manage it here. |
| 418 * The [source] may be a part, or a library whose contents is updated so | 442 * The [source] may be a part, or a library whose contents is updated so |
| 419 * will be a part. | 443 * will be a part. |
| 420 */ | 444 */ |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 bool needErrors = _shouldErrorsBeComputed(librarySource); | 485 bool needErrors = _shouldErrorsBeComputed(librarySource); |
| 462 if (needErrors) { | 486 if (needErrors) { |
| 463 addPriorityResult(librarySource, LIBRARY_ERRORS_READY); | 487 addPriorityResult(librarySource, LIBRARY_ERRORS_READY); |
| 464 } else { | 488 } else { |
| 465 var target = new LibrarySpecificUnit(librarySource, librarySource); | 489 var target = new LibrarySpecificUnit(librarySource, librarySource); |
| 466 addPriorityResult(target, RESOLVED_UNIT); | 490 addPriorityResult(target, RESOLVED_UNIT); |
| 467 } | 491 } |
| 468 } | 492 } |
| 469 | 493 |
| 470 bool _shouldErrorsBeComputed(Source source) => | 494 bool _shouldErrorsBeComputed(Source source) => |
| 471 context.shouldErrorsBeAnalyzed(source, null); | 495 context.shouldErrorsBeAnalyzed(source); |
| 472 | 496 |
| 473 static bool _isDartSource(AnalysisTarget target) { | 497 static bool _isDartSource(AnalysisTarget target) { |
| 474 return target is Source && AnalysisEngine.isDartFileName(target.fullName); | 498 return target is Source && AnalysisEngine.isDartFileName(target.fullName); |
| 475 } | 499 } |
| 476 } | 500 } |
| OLD | NEW |