Index: packages/analyzer/test/src/context/context_test.dart |
diff --git a/packages/analyzer/test/src/context/context_test.dart b/packages/analyzer/test/src/context/context_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0544bf56789d0e1808811cd27d21d7b1d1996e64 |
--- /dev/null |
+++ b/packages/analyzer/test/src/context/context_test.dart |
@@ -0,0 +1,2524 @@ |
+// 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 test.src.context.context_test; |
+ |
+import 'dart:async'; |
+ |
+import 'package:analyzer/file_system/memory_file_system.dart'; |
+import 'package:analyzer/src/cancelable_future.dart'; |
+import 'package:analyzer/src/context/cache.dart'; |
+import 'package:analyzer/src/context/context.dart'; |
+import 'package:analyzer/src/generated/ast.dart'; |
+import 'package:analyzer/src/generated/element.dart'; |
+import 'package:analyzer/src/generated/engine.dart' |
+ show |
+ AnalysisContext, |
+ AnalysisContextStatistics, |
+ AnalysisDelta, |
+ AnalysisEngine, |
+ AnalysisErrorInfo, |
+ AnalysisLevel, |
+ AnalysisNotScheduledError, |
+ AnalysisOptions, |
+ AnalysisOptionsImpl, |
+ AnalysisResult, |
+ CacheState, |
+ ChangeNotice, |
+ ChangeSet, |
+ IncrementalAnalysisCache, |
+ TimestampedData; |
+import 'package:analyzer/src/generated/error.dart'; |
+import 'package:analyzer/src/generated/java_engine.dart'; |
+import 'package:analyzer/src/generated/resolver.dart'; |
+import 'package:analyzer/src/generated/scanner.dart'; |
+import 'package:analyzer/src/generated/source.dart'; |
+import 'package:analyzer/src/task/dart.dart'; |
+import 'package:analyzer/src/task/html.dart'; |
+import 'package:analyzer/task/dart.dart'; |
+import 'package:analyzer/task/model.dart'; |
+import 'package:html/dom.dart' show Document; |
+import 'package:unittest/unittest.dart'; |
+import 'package:watcher/src/utils.dart'; |
+ |
+import '../../generated/engine_test.dart'; |
+import '../../generated/test_support.dart'; |
+import '../../reflective_tests.dart'; |
+import '../../utils.dart'; |
+import 'abstract_context.dart'; |
+ |
+main() { |
+ initializeTestEnvironment(); |
+ runReflectiveTests(AnalysisContextImplTest); |
+ runReflectiveTests(LimitedInvalidateTest); |
+} |
+ |
+@reflectiveTest |
+class AnalysisContextImplTest extends AbstractContextTest { |
+ Future fail_implicitAnalysisEvents_removed() async { |
+ AnalyzedSourcesListener listener = new AnalyzedSourcesListener(); |
+ context.implicitAnalysisEvents.listen(listener.onData); |
+ // |
+ // Create a file that references an file that is not explicitly being |
+ // analyzed and fully analyze it. Ensure that the listener is told about |
+ // the implicitly analyzed file. |
+ // |
+ Source sourceA = newSource('/a.dart', "library a; import 'b.dart';"); |
+ Source sourceB = newSource('/b.dart', "library b;"); |
+ ChangeSet changeSet = new ChangeSet(); |
+ changeSet.addedSource(sourceA); |
+ context.applyChanges(changeSet); |
+ context.computeErrors(sourceA); |
+ await pumpEventQueue(); |
+ listener.expectAnalyzed(sourceB); |
+ // |
+ // Remove the reference and ensure that the listener is told that we're no |
+ // longer implicitly analyzing the file. |
+ // |
+ context.setContents(sourceA, "library a;"); |
+ context.computeErrors(sourceA); |
+ await pumpEventQueue(); |
+ listener.expectNotAnalyzed(sourceB); |
+ } |
+ |
+ void fail_performAnalysisTask_importedLibraryDelete_html() { |
+ // NOTE: This was failing before converting to the new task model. |
+ Source htmlSource = addSource( |
+ "/page.html", |
+ r''' |
+<html><body><script type="application/dart"> |
+ import 'libB.dart'; |
+ main() {print('hello dart');} |
+</script></body></html>'''); |
+ Source libBSource = addSource("/libB.dart", "library libB;"); |
+ _analyzeAll_assertFinished(); |
+ context.computeErrors(htmlSource); |
+ expect( |
+ context.getResolvedCompilationUnit2(libBSource, libBSource), isNotNull, |
+ reason: "libB resolved 1"); |
+ expect(!_hasAnalysisErrorWithErrorSeverity(context.getErrors(htmlSource)), |
+ isTrue, |
+ reason: "htmlSource doesn't have errors"); |
+ // remove libB.dart content and analyze |
+ context.setContents(libBSource, null); |
+ _analyzeAll_assertFinished(); |
+ context.computeErrors(htmlSource); |
+ AnalysisErrorInfo errors = context.getErrors(htmlSource); |
+ expect(_hasAnalysisErrorWithErrorSeverity(errors), isTrue, |
+ reason: "htmlSource has an error"); |
+ } |
+ |
+ void fail_recordLibraryElements() { |
+ fail("Implement this"); |
+ } |
+ |
+ @override |
+ void tearDown() { |
+ context = null; |
+ sourceFactory = null; |
+ super.tearDown(); |
+ } |
+ |
+ Future test_applyChanges_add() { |
+ SourcesChangedListener listener = new SourcesChangedListener(); |
+ context.onSourcesChanged.listen(listener.onData); |
+ expect(context.sourcesNeedingProcessing, isEmpty); |
+ Source source = newSource('/test.dart'); |
+ ChangeSet changeSet = new ChangeSet(); |
+ changeSet.addedSource(source); |
+ context.applyChanges(changeSet); |
+ expect(context.sourcesNeedingProcessing, contains(source)); |
+ return pumpEventQueue().then((_) { |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertNoMoreEvents(); |
+ }); |
+ } |
+ |
+ Future test_applyChanges_change() { |
+ SourcesChangedListener listener = new SourcesChangedListener(); |
+ context.onSourcesChanged.listen(listener.onData); |
+ expect(context.sourcesNeedingProcessing, isEmpty); |
+ Source source = newSource('/test.dart'); |
+ ChangeSet changeSet1 = new ChangeSet(); |
+ changeSet1.addedSource(source); |
+ context.applyChanges(changeSet1); |
+ expect(context.sourcesNeedingProcessing, contains(source)); |
+ Source source2 = newSource('/test2.dart'); |
+ ChangeSet changeSet2 = new ChangeSet(); |
+ changeSet2.addedSource(source2); |
+ changeSet2.changedSource(source); |
+ context.applyChanges(changeSet2); |
+ return pumpEventQueue().then((_) { |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(wereSourcesAdded: true, changedSources: [source]); |
+ listener.assertNoMoreEvents(); |
+ }); |
+ } |
+ |
+ Future test_applyChanges_change_content() { |
+ SourcesChangedListener listener = new SourcesChangedListener(); |
+ context.onSourcesChanged.listen(listener.onData); |
+ expect(context.sourcesNeedingProcessing, isEmpty); |
+ Source source = newSource('/test.dart'); |
+ ChangeSet changeSet1 = new ChangeSet(); |
+ changeSet1.addedSource(source); |
+ context.applyChanges(changeSet1); |
+ expect(context.sourcesNeedingProcessing, contains(source)); |
+ Source source2 = newSource('/test2.dart'); |
+ ChangeSet changeSet2 = new ChangeSet(); |
+ changeSet2.addedSource(source2); |
+ changeSet2.changedContent(source, 'library test;'); |
+ context.applyChanges(changeSet2); |
+ return pumpEventQueue().then((_) { |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(wereSourcesAdded: true, changedSources: [source]); |
+ listener.assertNoMoreEvents(); |
+ }); |
+ } |
+ |
+ void test_applyChanges_change_flush_element() { |
+ Source librarySource = addSource( |
+ "/lib.dart", |
+ r''' |
+library lib; |
+int a = 0;'''); |
+ expect(context.computeLibraryElement(librarySource), isNotNull); |
+ context.setContents( |
+ librarySource, |
+ r''' |
+library lib; |
+int aa = 0;'''); |
+ expect(context.getLibraryElement(librarySource), isNull); |
+ } |
+ |
+ Future test_applyChanges_change_multiple() { |
+ SourcesChangedListener listener = new SourcesChangedListener(); |
+ context.onSourcesChanged.listen(listener.onData); |
+ String libraryContents1 = r''' |
+library lib; |
+part 'part.dart'; |
+int a = 0;'''; |
+ Source librarySource = addSource("/lib.dart", libraryContents1); |
+ String partContents1 = r''' |
+part of lib; |
+int b = a;'''; |
+ Source partSource = addSource("/part.dart", partContents1); |
+ context.computeLibraryElement(librarySource); |
+ String libraryContents2 = r''' |
+library lib; |
+part 'part.dart'; |
+int aa = 0;'''; |
+ context.setContents(librarySource, libraryContents2); |
+ String partContents2 = r''' |
+part of lib; |
+int b = aa;'''; |
+ context.setContents(partSource, partContents2); |
+ context.computeLibraryElement(librarySource); |
+ CompilationUnit libraryUnit = |
+ context.resolveCompilationUnit2(librarySource, librarySource); |
+ expect(libraryUnit, isNotNull); |
+ CompilationUnit partUnit = |
+ context.resolveCompilationUnit2(partSource, librarySource); |
+ expect(partUnit, isNotNull); |
+ TopLevelVariableDeclaration declaration = |
+ libraryUnit.declarations[0] as TopLevelVariableDeclaration; |
+ Element declarationElement = declaration.variables.variables[0].element; |
+ TopLevelVariableDeclaration use = |
+ partUnit.declarations[0] as TopLevelVariableDeclaration; |
+ Element useElement = (use.variables.variables[0].initializer |
+ as SimpleIdentifier).staticElement; |
+ expect((useElement as PropertyAccessorElement).variable, |
+ same(declarationElement)); |
+ return pumpEventQueue().then((_) { |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(changedSources: [librarySource]); |
+ listener.assertEvent(changedSources: [partSource]); |
+ listener.assertNoMoreEvents(); |
+ }); |
+ } |
+ |
+ Future test_applyChanges_change_range() { |
+ SourcesChangedListener listener = new SourcesChangedListener(); |
+ context.onSourcesChanged.listen(listener.onData); |
+ expect(context.sourcesNeedingProcessing, isEmpty); |
+ Source source = newSource('/test.dart'); |
+ ChangeSet changeSet1 = new ChangeSet(); |
+ changeSet1.addedSource(source); |
+ context.applyChanges(changeSet1); |
+ expect(context.sourcesNeedingProcessing, contains(source)); |
+ Source source2 = newSource('/test2.dart'); |
+ ChangeSet changeSet2 = new ChangeSet(); |
+ changeSet2.addedSource(source2); |
+ changeSet2.changedRange(source, 'library test;', 0, 0, 13); |
+ context.applyChanges(changeSet2); |
+ return pumpEventQueue().then((_) { |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(wereSourcesAdded: true, changedSources: [source]); |
+ listener.assertNoMoreEvents(); |
+ }); |
+ } |
+ |
+ void test_applyChanges_empty() { |
+ context.applyChanges(new ChangeSet()); |
+ expect(context.performAnalysisTask().changeNotices, isNull); |
+ } |
+ |
+ void test_applyChanges_overriddenSource() { |
+ // Note: addSource adds the source to the contentCache. |
+ Source source = addSource("/test.dart", "library test;"); |
+ context.computeErrors(source); |
+ while (!context.sourcesNeedingProcessing.isEmpty) { |
+ context.performAnalysisTask(); |
+ } |
+ // Adding the source as a changedSource should have no effect since |
+ // it is already overridden in the content cache. |
+ ChangeSet changeSet = new ChangeSet(); |
+ changeSet.changedSource(source); |
+ context.applyChanges(changeSet); |
+ expect(context.sourcesNeedingProcessing, hasLength(0)); |
+ } |
+ |
+ Future test_applyChanges_remove() { |
+ SourcesChangedListener listener = new SourcesChangedListener(); |
+ context.onSourcesChanged.listen(listener.onData); |
+ String libAContents = r''' |
+library libA; |
+import 'libB.dart';'''; |
+ Source libA = addSource("/libA.dart", libAContents); |
+ String libBContents = "library libB;"; |
+ Source libB = addSource("/libB.dart", libBContents); |
+ LibraryElement libAElement = context.computeLibraryElement(libA); |
+ expect(libAElement, isNotNull); |
+ List<LibraryElement> importedLibraries = libAElement.importedLibraries; |
+ expect(importedLibraries, hasLength(2)); |
+ context.computeErrors(libA); |
+ context.computeErrors(libB); |
+ expect(context.sourcesNeedingProcessing, hasLength(0)); |
+ context.setContents(libB, null); |
+ _removeSource(libB); |
+ List<Source> sources = context.sourcesNeedingProcessing; |
+ expect(sources, hasLength(1)); |
+ expect(sources[0], same(libA)); |
+ libAElement = context.computeLibraryElement(libA); |
+ importedLibraries = libAElement.importedLibraries; |
+ expect(importedLibraries, hasLength(1)); |
+ return pumpEventQueue().then((_) { |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(wereSourcesRemovedOrDeleted: true); |
+ listener.assertNoMoreEvents(); |
+ }); |
+ } |
+ |
+ /** |
+ * IDEA uses the following scenario: |
+ * 1. Add overlay. |
+ * 2. Change overlay. |
+ * 3. If the contents of the document buffer is the same as the contents |
+ * of the file, remove overlay. |
+ * So, we need to try to use incremental resolution for removing overlays too. |
+ */ |
+ void test_applyChanges_remove_incremental() { |
+ MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); |
+ Source source = resourceProvider |
+ .newFile( |
+ '/test.dart', |
+ r''' |
+main() { |
+ print(1); |
+} |
+''') |
+ .createSource(); |
+ context.analysisOptions = new AnalysisOptionsImpl()..incremental = true; |
+ context.applyChanges(new ChangeSet()..addedSource(source)); |
+ // remember compilation unit |
+ _analyzeAll_assertFinished(); |
+ CompilationUnit unit = context.getResolvedCompilationUnit2(source, source); |
+ // add overlay |
+ context.setContents( |
+ source, |
+ r''' |
+main() { |
+ print(12); |
+} |
+'''); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(source, source), unit); |
+ // remove overlay |
+ context.setContents(source, null); |
+ context.validateCacheConsistency(); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(source, source), unit); |
+ } |
+ |
+ Future test_applyChanges_removeContainer() { |
+ SourcesChangedListener listener = new SourcesChangedListener(); |
+ context.onSourcesChanged.listen(listener.onData); |
+ String libAContents = r''' |
+library libA; |
+import 'libB.dart';'''; |
+ Source libA = addSource("/libA.dart", libAContents); |
+ String libBContents = "library libB;"; |
+ Source libB = addSource("/libB.dart", libBContents); |
+ context.computeLibraryElement(libA); |
+ context.computeErrors(libA); |
+ context.computeErrors(libB); |
+ expect(context.sourcesNeedingProcessing, hasLength(0)); |
+ ChangeSet changeSet = new ChangeSet(); |
+ SourceContainer removedContainer = |
+ new _AnalysisContextImplTest_test_applyChanges_removeContainer(libB); |
+ changeSet.removedContainer(removedContainer); |
+ context.applyChanges(changeSet); |
+ List<Source> sources = context.sourcesNeedingProcessing; |
+ expect(sources, hasLength(1)); |
+ expect(sources[0], same(libA)); |
+ return pumpEventQueue().then((_) { |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(wereSourcesRemovedOrDeleted: true); |
+ listener.assertNoMoreEvents(); |
+ }); |
+ } |
+ |
+ void test_computeDocumentationComment_block() { |
+ String comment = "/** Comment */"; |
+ Source source = addSource( |
+ "/test.dart", |
+ """ |
+$comment |
+class A {}"""); |
+ LibraryElement libraryElement = context.computeLibraryElement(source); |
+ expect(libraryElement, isNotNull); |
+ ClassElement classElement = libraryElement.definingCompilationUnit.types[0]; |
+ expect(libraryElement, isNotNull); |
+ expect(context.computeDocumentationComment(classElement), comment); |
+ } |
+ |
+ void test_computeDocumentationComment_none() { |
+ Source source = addSource("/test.dart", "class A {}"); |
+ LibraryElement libraryElement = context.computeLibraryElement(source); |
+ expect(libraryElement, isNotNull); |
+ ClassElement classElement = libraryElement.definingCompilationUnit.types[0]; |
+ expect(libraryElement, isNotNull); |
+ expect(context.computeDocumentationComment(classElement), isNull); |
+ } |
+ |
+ void test_computeDocumentationComment_null() { |
+ expect(context.computeDocumentationComment(null), isNull); |
+ } |
+ |
+ void test_computeDocumentationComment_singleLine_multiple_EOL_n() { |
+ String comment = "/// line 1\n/// line 2\n/// line 3\n"; |
+ Source source = addSource("/test.dart", "${comment}class A {}"); |
+ LibraryElement libraryElement = context.computeLibraryElement(source); |
+ expect(libraryElement, isNotNull); |
+ ClassElement classElement = libraryElement.definingCompilationUnit.types[0]; |
+ expect(libraryElement, isNotNull); |
+ String actual = context.computeDocumentationComment(classElement); |
+ expect(actual, "/// line 1\n/// line 2\n/// line 3"); |
+ } |
+ |
+ void test_computeDocumentationComment_singleLine_multiple_EOL_rn() { |
+ String comment = "/// line 1\r\n/// line 2\r\n/// line 3\r\n"; |
+ Source source = addSource("/test.dart", "${comment}class A {}"); |
+ LibraryElement libraryElement = context.computeLibraryElement(source); |
+ expect(libraryElement, isNotNull); |
+ ClassElement classElement = libraryElement.definingCompilationUnit.types[0]; |
+ expect(libraryElement, isNotNull); |
+ String actual = context.computeDocumentationComment(classElement); |
+ expect(actual, "/// line 1\n/// line 2\n/// line 3"); |
+ } |
+ |
+ void test_computeErrors_dart_none() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ List<AnalysisError> errors = context.computeErrors(source); |
+ expect(errors, hasLength(0)); |
+ } |
+ |
+ void test_computeErrors_dart_part() { |
+ Source librarySource = |
+ addSource("/lib.dart", "library lib; part 'part.dart';"); |
+ Source partSource = addSource("/part.dart", "part of 'lib';"); |
+ context.parseCompilationUnit(librarySource); |
+ List<AnalysisError> errors = context.computeErrors(partSource); |
+ expect(errors, isNotNull); |
+ expect(errors.length > 0, isTrue); |
+ } |
+ |
+ void test_computeErrors_dart_some() { |
+ Source source = addSource("/lib.dart", "library 'lib';"); |
+ List<AnalysisError> errors = context.computeErrors(source); |
+ expect(errors, isNotNull); |
+ expect(errors.length > 0, isTrue); |
+ } |
+ |
+ void test_computeErrors_html_none() { |
+ Source source = addSource("/test.html", "<!DOCTYPE html><html></html>"); |
+ List<AnalysisError> errors = context.computeErrors(source); |
+ expect(errors, hasLength(0)); |
+ } |
+ |
+ void test_computeExportedLibraries_none() { |
+ Source source = addSource("/test.dart", "library test;"); |
+ expect(context.computeExportedLibraries(source), hasLength(0)); |
+ } |
+ |
+ void test_computeExportedLibraries_some() { |
+ // addSource("/lib1.dart", "library lib1;"); |
+ // addSource("/lib2.dart", "library lib2;"); |
+ Source source = addSource( |
+ "/test.dart", "library test; export 'lib1.dart'; export 'lib2.dart';"); |
+ expect(context.computeExportedLibraries(source), hasLength(2)); |
+ } |
+ |
+ void test_computeImportedLibraries_none() { |
+ Source source = addSource("/test.dart", "library test;"); |
+ expect(context.computeImportedLibraries(source), hasLength(0)); |
+ } |
+ |
+ void test_computeImportedLibraries_some() { |
+ Source source = addSource( |
+ "/test.dart", "library test; import 'lib1.dart'; import 'lib2.dart';"); |
+ expect(context.computeImportedLibraries(source), hasLength(2)); |
+ } |
+ |
+ void test_computeKindOf_html() { |
+ Source source = addSource("/test.html", ""); |
+ expect(context.computeKindOf(source), same(SourceKind.HTML)); |
+ } |
+ |
+ void test_computeKindOf_library() { |
+ Source source = addSource("/test.dart", "library lib;"); |
+ expect(context.computeKindOf(source), same(SourceKind.LIBRARY)); |
+ } |
+ |
+ void test_computeKindOf_libraryAndPart() { |
+ Source source = addSource("/test.dart", "library lib; part of lib;"); |
+ expect(context.computeKindOf(source), same(SourceKind.LIBRARY)); |
+ } |
+ |
+ void test_computeKindOf_part() { |
+ Source source = addSource("/test.dart", "part of lib;"); |
+ expect(context.computeKindOf(source), same(SourceKind.PART)); |
+ } |
+ |
+ void test_computeLibraryElement() { |
+ Source source = addSource("/test.dart", "library lib;"); |
+ LibraryElement element = context.computeLibraryElement(source); |
+ expect(element, isNotNull); |
+ } |
+ |
+ void test_computeLineInfo_dart() { |
+ Source source = addSource( |
+ "/test.dart", |
+ r''' |
+library lib; |
+ |
+main() {}'''); |
+ LineInfo info = context.computeLineInfo(source); |
+ expect(info, isNotNull); |
+ } |
+ |
+ void test_computeLineInfo_html() { |
+ Source source = addSource( |
+ "/test.html", |
+ r''' |
+<html> |
+ <body> |
+ <h1>A</h1> |
+ </body> |
+</html>'''); |
+ LineInfo info = context.computeLineInfo(source); |
+ expect(info, isNotNull); |
+ } |
+ |
+ Future test_computeResolvedCompilationUnitAsync() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ // Complete all pending analysis tasks and flush the AST so that it won't |
+ // be available immediately. |
+ _performPendingAnalysisTasks(); |
+ _flushAst(source); |
+ bool completed = false; |
+ context |
+ .computeResolvedCompilationUnitAsync(source, source) |
+ .then((CompilationUnit unit) { |
+ expect(unit, isNotNull); |
+ completed = true; |
+ }); |
+ return pumpEventQueue().then((_) { |
+ expect(completed, isFalse); |
+ _performPendingAnalysisTasks(); |
+ }).then((_) => pumpEventQueue()).then((_) { |
+ expect(completed, isTrue); |
+ }); |
+ } |
+ |
+ Future test_computeResolvedCompilationUnitAsync_afterDispose() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ // Complete all pending analysis tasks and flush the AST so that it won't |
+ // be available immediately. |
+ _performPendingAnalysisTasks(); |
+ _flushAst(source); |
+ // Dispose of the context. |
+ context.dispose(); |
+ // Any attempt to start an asynchronous computation should return a future |
+ // which completes with error. |
+ CancelableFuture<CompilationUnit> future = |
+ context.computeResolvedCompilationUnitAsync(source, source); |
+ bool completed = false; |
+ future.then((CompilationUnit unit) { |
+ fail('Future should have completed with error'); |
+ }, onError: (error) { |
+ expect(error, new isInstanceOf<AnalysisNotScheduledError>()); |
+ completed = true; |
+ }); |
+ return pumpEventQueue().then((_) { |
+ expect(completed, isTrue); |
+ }); |
+ } |
+ |
+ Future test_computeResolvedCompilationUnitAsync_cancel() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ // Complete all pending analysis tasks and flush the AST so that it won't |
+ // be available immediately. |
+ _performPendingAnalysisTasks(); |
+ _flushAst(source); |
+ CancelableFuture<CompilationUnit> future = |
+ context.computeResolvedCompilationUnitAsync(source, source); |
+ bool completed = false; |
+ future.then((CompilationUnit unit) { |
+ fail('Future should have been canceled'); |
+ }, onError: (error) { |
+ expect(error, new isInstanceOf<FutureCanceledError>()); |
+ completed = true; |
+ }); |
+ expect(completed, isFalse); |
+ expect(context.pendingFutureSources_forTesting, isNotEmpty); |
+ future.cancel(); |
+ expect(context.pendingFutureSources_forTesting, isEmpty); |
+ return pumpEventQueue().then((_) { |
+ expect(completed, isTrue); |
+ expect(context.pendingFutureSources_forTesting, isEmpty); |
+ }); |
+ } |
+ |
+ Future test_computeResolvedCompilationUnitAsync_dispose() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ // Complete all pending analysis tasks and flush the AST so that it won't |
+ // be available immediately. |
+ _performPendingAnalysisTasks(); |
+ _flushAst(source); |
+ bool completed = false; |
+ CancelableFuture<CompilationUnit> future = |
+ context.computeResolvedCompilationUnitAsync(source, source); |
+ future.then((CompilationUnit unit) { |
+ fail('Future should have completed with error'); |
+ }, onError: (error) { |
+ expect(error, new isInstanceOf<AnalysisNotScheduledError>()); |
+ completed = true; |
+ }); |
+ expect(completed, isFalse); |
+ expect(context.pendingFutureSources_forTesting, isNotEmpty); |
+ // Disposing of the context should cause all pending futures to complete |
+ // with AnalysisNotScheduled, so that no clients are left hanging. |
+ context.dispose(); |
+ expect(context.pendingFutureSources_forTesting, isEmpty); |
+ return pumpEventQueue().then((_) { |
+ expect(completed, isTrue); |
+ expect(context.pendingFutureSources_forTesting, isEmpty); |
+ }); |
+ } |
+ |
+ Future test_computeResolvedCompilationUnitAsync_noCacheEntry() { |
+ Source librarySource = addSource("/lib.dart", "library lib;"); |
+ Source partSource = addSource("/part.dart", "part of foo;"); |
+ bool completed = false; |
+ context |
+ .computeResolvedCompilationUnitAsync(partSource, librarySource) |
+ .then((CompilationUnit unit) { |
+ expect(unit, isNotNull); |
+ completed = true; |
+ }); |
+ return pumpEventQueue().then((_) { |
+ expect(completed, isFalse); |
+ _performPendingAnalysisTasks(); |
+ }).then((_) => pumpEventQueue()).then((_) { |
+ expect(completed, isTrue); |
+ }); |
+ } |
+ |
+ void test_dispose() { |
+ expect(context.isDisposed, isFalse); |
+ context.dispose(); |
+ expect(context.isDisposed, isTrue); |
+ } |
+ |
+ void test_ensureResolvedDartUnits_definingUnit_hasResolved() { |
+ Source source = addSource('/test.dart', ''); |
+ LibrarySpecificUnit libTarget = new LibrarySpecificUnit(source, source); |
+ analysisDriver.computeResult(libTarget, RESOLVED_UNIT); |
+ CompilationUnit unit = |
+ context.getCacheEntry(libTarget).getValue(RESOLVED_UNIT); |
+ List<CompilationUnit> units = context.ensureResolvedDartUnits(source); |
+ expect(units, unorderedEquals([unit])); |
+ } |
+ |
+ void test_ensureResolvedDartUnits_definingUnit_notResolved() { |
+ Source source = addSource('/test.dart', ''); |
+ LibrarySpecificUnit libTarget = new LibrarySpecificUnit(source, source); |
+ analysisDriver.computeResult(libTarget, RESOLVED_UNIT); |
+ // flush |
+ context |
+ .getCacheEntry(libTarget) |
+ .setState(RESOLVED_UNIT, CacheState.FLUSHED); |
+ // schedule recomputing |
+ List<CompilationUnit> units = context.ensureResolvedDartUnits(source); |
+ expect(units, isNull); |
+ // should be the next result to compute |
+ TargetedResult nextResult = context.dartWorkManager.getNextResult(); |
+ expect(nextResult.target, libTarget); |
+ expect(nextResult.result, RESOLVED_UNIT); |
+ } |
+ |
+ void test_ensureResolvedDartUnits_partUnit_hasResolved() { |
+ Source libSource1 = addSource( |
+ '/lib1.dart', |
+ r''' |
+library lib; |
+part 'part.dart'; |
+'''); |
+ Source libSource2 = addSource( |
+ '/lib2.dart', |
+ r''' |
+library lib; |
+part 'part.dart'; |
+'''); |
+ Source partSource = addSource( |
+ '/part.dart', |
+ r''' |
+part of lib; |
+'''); |
+ LibrarySpecificUnit partTarget1 = |
+ new LibrarySpecificUnit(libSource1, partSource); |
+ LibrarySpecificUnit partTarget2 = |
+ new LibrarySpecificUnit(libSource2, partSource); |
+ analysisDriver.computeResult(partTarget1, RESOLVED_UNIT); |
+ analysisDriver.computeResult(partTarget2, RESOLVED_UNIT); |
+ CompilationUnit unit1 = |
+ context.getCacheEntry(partTarget1).getValue(RESOLVED_UNIT); |
+ CompilationUnit unit2 = |
+ context.getCacheEntry(partTarget2).getValue(RESOLVED_UNIT); |
+ List<CompilationUnit> units = context.ensureResolvedDartUnits(partSource); |
+ expect(units, unorderedEquals([unit1, unit2])); |
+ } |
+ |
+ void test_ensureResolvedDartUnits_partUnit_notResolved() { |
+ Source libSource1 = addSource( |
+ '/lib1.dart', |
+ r''' |
+library lib; |
+part 'part.dart'; |
+'''); |
+ Source libSource2 = addSource( |
+ '/lib2.dart', |
+ r''' |
+library lib; |
+part 'part.dart'; |
+'''); |
+ Source partSource = addSource( |
+ '/part.dart', |
+ r''' |
+part of lib; |
+'''); |
+ LibrarySpecificUnit partTarget1 = |
+ new LibrarySpecificUnit(libSource1, partSource); |
+ LibrarySpecificUnit partTarget2 = |
+ new LibrarySpecificUnit(libSource2, partSource); |
+ analysisDriver.computeResult(partTarget1, RESOLVED_UNIT); |
+ analysisDriver.computeResult(partTarget2, RESOLVED_UNIT); |
+ // flush |
+ context |
+ .getCacheEntry(partTarget1) |
+ .setState(RESOLVED_UNIT, CacheState.FLUSHED); |
+ context |
+ .getCacheEntry(partTarget2) |
+ .setState(RESOLVED_UNIT, CacheState.FLUSHED); |
+ // schedule recomputing |
+ List<CompilationUnit> units = context.ensureResolvedDartUnits(partSource); |
+ expect(units, isNull); |
+ // should be the next result to compute |
+ TargetedResult nextResult = context.dartWorkManager.getNextResult(); |
+ expect(nextResult.target, anyOf(partTarget1, partTarget2)); |
+ expect(nextResult.result, RESOLVED_UNIT); |
+ } |
+ |
+ void test_exists_false() { |
+ TestSource source = new TestSource(); |
+ source.exists2 = false; |
+ expect(context.exists(source), isFalse); |
+ } |
+ |
+ void test_exists_null() { |
+ expect(context.exists(null), isFalse); |
+ } |
+ |
+ void test_exists_overridden() { |
+ Source source = new TestSource(); |
+ context.setContents(source, ""); |
+ expect(context.exists(source), isTrue); |
+ } |
+ |
+ void test_exists_true() { |
+ expect(context.exists(new AnalysisContextImplTest_Source_exists_true()), |
+ isTrue); |
+ } |
+ |
+ void test_getAnalysisOptions() { |
+ expect(context.analysisOptions, isNotNull); |
+ } |
+ |
+ void test_getContents_fromSource() { |
+ String content = "library lib;"; |
+ TimestampedData<String> contents = |
+ context.getContents(new TestSource('/test.dart', content)); |
+ expect(contents.data.toString(), content); |
+ } |
+ |
+ void test_getContents_overridden() { |
+ String content = "library lib;"; |
+ Source source = new TestSource(); |
+ context.setContents(source, content); |
+ TimestampedData<String> contents = context.getContents(source); |
+ expect(contents.data.toString(), content); |
+ } |
+ |
+ void test_getContents_unoverridden() { |
+ String content = "library lib;"; |
+ Source source = new TestSource('/test.dart', content); |
+ context.setContents(source, "part of lib;"); |
+ context.setContents(source, null); |
+ TimestampedData<String> contents = context.getContents(source); |
+ expect(contents.data.toString(), content); |
+ } |
+ |
+ void test_getDeclaredVariables() { |
+ expect(context.declaredVariables, isNotNull); |
+ } |
+ |
+ void test_getElement() { |
+ LibraryElement core = |
+ context.computeLibraryElement(sourceFactory.forUri("dart:core")); |
+ expect(core, isNotNull); |
+ ClassElement classObject = |
+ _findClass(core.definingCompilationUnit, "Object"); |
+ expect(classObject, isNotNull); |
+ ElementLocation location = classObject.location; |
+ Element element = context.getElement(location); |
+ expect(element, same(classObject)); |
+ } |
+ |
+ void test_getElement_constructor_named() { |
+ Source source = addSource( |
+ "/lib.dart", |
+ r''' |
+class A { |
+ A.named() {} |
+}'''); |
+ _analyzeAll_assertFinished(); |
+ LibraryElement library = context.computeLibraryElement(source); |
+ ClassElement classA = _findClass(library.definingCompilationUnit, "A"); |
+ ConstructorElement constructor = classA.constructors[0]; |
+ ElementLocation location = constructor.location; |
+ Element element = context.getElement(location); |
+ expect(element, same(constructor)); |
+ } |
+ |
+ void test_getElement_constructor_unnamed() { |
+ Source source = addSource( |
+ "/lib.dart", |
+ r''' |
+class A { |
+ A() {} |
+}'''); |
+ _analyzeAll_assertFinished(); |
+ LibraryElement library = context.computeLibraryElement(source); |
+ ClassElement classA = _findClass(library.definingCompilationUnit, "A"); |
+ ConstructorElement constructor = classA.constructors[0]; |
+ ElementLocation location = constructor.location; |
+ Element element = context.getElement(location); |
+ expect(element, same(constructor)); |
+ } |
+ |
+ void test_getElement_enum() { |
+ Source source = addSource('/test.dart', 'enum MyEnum {A, B, C}'); |
+ _analyzeAll_assertFinished(); |
+ LibraryElement library = context.computeLibraryElement(source); |
+ ClassElement myEnum = library.definingCompilationUnit.getEnum('MyEnum'); |
+ ElementLocation location = myEnum.location; |
+ Element element = context.getElement(location); |
+ expect(element, same(myEnum)); |
+ } |
+ |
+ void test_getErrors_dart_none() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ var errorInfo = context.getErrors(source); |
+ expect(errorInfo, isNotNull); |
+ List<AnalysisError> errors = errorInfo.errors; |
+ expect(errors, hasLength(0)); |
+ context.computeErrors(source); |
+ errors = errorInfo.errors; |
+ expect(errors, hasLength(0)); |
+ } |
+ |
+ void test_getErrors_dart_some() { |
+ Source source = addSource("/lib.dart", "library 'lib';"); |
+ var errorInfo = context.getErrors(source); |
+ expect(errorInfo, isNotNull); |
+ List<AnalysisError> errors = errorInfo.errors; |
+ expect(errors, hasLength(0)); |
+ errors = context.computeErrors(source); |
+ expect(errors, hasLength(1)); |
+ } |
+ |
+ void test_getErrors_html_none() { |
+ Source source = addSource("/test.html", "<html></html>"); |
+ AnalysisErrorInfo errorInfo = context.getErrors(source); |
+ expect(errorInfo, isNotNull); |
+ List<AnalysisError> errors = errorInfo.errors; |
+ expect(errors, hasLength(0)); |
+ context.computeErrors(source); |
+ errors = errorInfo.errors; |
+ expect(errors, hasLength(0)); |
+ } |
+ |
+ void test_getErrors_html_some() { |
+ Source source = addSource( |
+ "/test.html", |
+ r''' |
+<html><head> |
+<script type='application/dart' src='test.dart'/> |
+</head></html>'''); |
+ AnalysisErrorInfo errorInfo = context.getErrors(source); |
+ expect(errorInfo, isNotNull); |
+ List<AnalysisError> errors = errorInfo.errors; |
+ expect(errors, hasLength(0)); |
+ errors = context.computeErrors(source); |
+ expect(errors, hasLength(3)); |
+ } |
+ |
+ void test_getHtmlFilesReferencing_html() { |
+ Source htmlSource = addSource( |
+ "/test.html", |
+ r''' |
+<html><head> |
+<script type='application/dart' src='test.dart'/> |
+<script type='application/dart' src='test.js'/> |
+</head></html>'''); |
+ Source librarySource = addSource("/test.dart", "library lib;"); |
+ Source secondHtmlSource = addSource("/test.html", "<html></html>"); |
+ context.computeLibraryElement(librarySource); |
+ List<Source> result = context.getHtmlFilesReferencing(secondHtmlSource); |
+ expect(result, hasLength(0)); |
+ context.parseHtmlDocument(htmlSource); |
+ result = context.getHtmlFilesReferencing(secondHtmlSource); |
+ expect(result, hasLength(0)); |
+ } |
+ |
+ void test_getHtmlFilesReferencing_library() { |
+ Source htmlSource = addSource( |
+ "/test.html", |
+ r''' |
+<!DOCTYPE html> |
+<html><head> |
+<script type='application/dart' src='test.dart'/> |
+<script type='application/dart' src='test.js'/> |
+</head></html>'''); |
+ Source librarySource = addSource("/test.dart", "library lib;"); |
+ context.computeLibraryElement(librarySource); |
+ List<Source> result = context.getHtmlFilesReferencing(librarySource); |
+ expect(result, hasLength(0)); |
+ // Indirectly force the data to be computed. |
+ context.computeErrors(htmlSource); |
+ result = context.getHtmlFilesReferencing(librarySource); |
+ expect(result, hasLength(1)); |
+ expect(result[0], htmlSource); |
+ } |
+ |
+ void test_getHtmlFilesReferencing_part() { |
+ Source htmlSource = addSource( |
+ "/test.html", |
+ r''' |
+<!DOCTYPE html> |
+<html><head> |
+<script type='application/dart' src='test.dart'/> |
+<script type='application/dart' src='test.js'/> |
+</head></html>'''); |
+ Source librarySource = |
+ addSource("/test.dart", "library lib; part 'part.dart';"); |
+ Source partSource = addSource("/part.dart", "part of lib;"); |
+ context.computeLibraryElement(librarySource); |
+ List<Source> result = context.getHtmlFilesReferencing(partSource); |
+ expect(result, hasLength(0)); |
+ // Indirectly force the data to be computed. |
+ context.computeErrors(htmlSource); |
+ result = context.getHtmlFilesReferencing(partSource); |
+ expect(result, hasLength(1)); |
+ expect(result[0], htmlSource); |
+ } |
+ |
+ void test_getHtmlSources() { |
+ List<Source> sources = context.htmlSources; |
+ expect(sources, hasLength(0)); |
+ Source source = addSource("/test.html", ""); |
+ sources = context.htmlSources; |
+ expect(sources, hasLength(1)); |
+ expect(sources[0], source); |
+ } |
+ |
+ void test_getKindOf_html() { |
+ Source source = addSource("/test.html", ""); |
+ expect(context.getKindOf(source), same(SourceKind.HTML)); |
+ } |
+ |
+ void test_getKindOf_library() { |
+ Source source = addSource("/test.dart", "library lib;"); |
+ expect(context.getKindOf(source), same(SourceKind.UNKNOWN)); |
+ context.computeKindOf(source); |
+ expect(context.getKindOf(source), same(SourceKind.LIBRARY)); |
+ } |
+ |
+ void test_getKindOf_part() { |
+ Source source = addSource("/test.dart", "part of lib;"); |
+ expect(context.getKindOf(source), same(SourceKind.UNKNOWN)); |
+ context.computeKindOf(source); |
+ expect(context.getKindOf(source), same(SourceKind.PART)); |
+ } |
+ |
+ void test_getKindOf_unknown() { |
+ Source source = addSource("/test.css", ""); |
+ expect(context.getKindOf(source), same(SourceKind.UNKNOWN)); |
+ } |
+ |
+ void test_getLaunchableClientLibrarySources_doesNotImportHtml() { |
+ Source source = addSource( |
+ "/test.dart", |
+ r''' |
+main() {}'''); |
+ context.computeLibraryElement(source); |
+ List<Source> sources = context.launchableClientLibrarySources; |
+ expect(sources, isEmpty); |
+ } |
+ |
+ void test_getLaunchableClientLibrarySources_importsHtml_explicitly() { |
+ List<Source> sources = context.launchableClientLibrarySources; |
+ expect(sources, isEmpty); |
+ Source source = addSource( |
+ "/test.dart", |
+ r''' |
+import 'dart:html'; |
+main() {}'''); |
+ context.computeLibraryElement(source); |
+ sources = context.launchableClientLibrarySources; |
+ expect(sources, unorderedEquals([source])); |
+ } |
+ |
+ void test_getLaunchableClientLibrarySources_importsHtml_implicitly() { |
+ List<Source> sources = context.launchableClientLibrarySources; |
+ expect(sources, isEmpty); |
+ addSource( |
+ "/a.dart", |
+ r''' |
+import 'dart:html'; |
+'''); |
+ Source source = addSource( |
+ "/test.dart", |
+ r''' |
+import 'a.dart'; |
+main() {}'''); |
+ context.computeLibraryElement(source); |
+ sources = context.launchableClientLibrarySources; |
+ expect(sources, unorderedEquals([source])); |
+ } |
+ |
+ void test_getLaunchableClientLibrarySources_importsHtml_implicitly2() { |
+ List<Source> sources = context.launchableClientLibrarySources; |
+ expect(sources, isEmpty); |
+ addSource( |
+ "/a.dart", |
+ r''' |
+export 'dart:html'; |
+'''); |
+ Source source = addSource( |
+ "/test.dart", |
+ r''' |
+import 'a.dart'; |
+main() {}'''); |
+ context.computeLibraryElement(source); |
+ sources = context.launchableClientLibrarySources; |
+ expect(sources, unorderedEquals([source])); |
+ } |
+ |
+ void test_getLaunchableServerLibrarySources() { |
+ expect(context.launchableServerLibrarySources, isEmpty); |
+ Source source = addSource("/test.dart", "main() {}"); |
+ context.computeLibraryElement(source); |
+ expect(context.launchableServerLibrarySources, unorderedEquals([source])); |
+ } |
+ |
+ void test_getLaunchableServerLibrarySources_importsHtml_explicitly() { |
+ Source source = addSource( |
+ "/test.dart", |
+ r''' |
+import 'dart:html'; |
+main() {} |
+'''); |
+ context.computeLibraryElement(source); |
+ expect(context.launchableServerLibrarySources, isEmpty); |
+ } |
+ |
+ void test_getLaunchableServerLibrarySources_importsHtml_implicitly() { |
+ addSource( |
+ "/imports_html.dart", |
+ r''' |
+import 'dart:html'; |
+'''); |
+ Source source = addSource( |
+ "/test.dart", |
+ r''' |
+import 'imports_html.dart'; |
+main() {}'''); |
+ context.computeLibraryElement(source); |
+ expect(context.launchableServerLibrarySources, isEmpty); |
+ } |
+ |
+ void test_getLaunchableServerLibrarySources_noMain() { |
+ Source source = addSource("/test.dart", ''); |
+ context.computeLibraryElement(source); |
+ expect(context.launchableServerLibrarySources, isEmpty); |
+ } |
+ |
+ void test_getLibrariesContaining() { |
+ Source librarySource = addSource( |
+ "/lib.dart", |
+ r''' |
+library lib; |
+part 'part.dart';'''); |
+ Source partSource = addSource("/part.dart", "part of lib;"); |
+ context.computeLibraryElement(librarySource); |
+ List<Source> result = context.getLibrariesContaining(librarySource); |
+ expect(result, hasLength(1)); |
+ expect(result[0], librarySource); |
+ result = context.getLibrariesContaining(partSource); |
+ expect(result, hasLength(1)); |
+ expect(result[0], librarySource); |
+ } |
+ |
+ void test_getLibrariesDependingOn() { |
+ Source libASource = addSource("/libA.dart", "library libA;"); |
+ addSource("/libB.dart", "library libB;"); |
+ Source lib1Source = addSource( |
+ "/lib1.dart", |
+ r''' |
+library lib1; |
+import 'libA.dart'; |
+export 'libB.dart';'''); |
+ Source lib2Source = addSource( |
+ "/lib2.dart", |
+ r''' |
+library lib2; |
+import 'libB.dart'; |
+export 'libA.dart';'''); |
+ context.computeLibraryElement(lib1Source); |
+ context.computeLibraryElement(lib2Source); |
+ List<Source> result = context.getLibrariesDependingOn(libASource); |
+ expect(result, unorderedEquals([lib1Source, lib2Source])); |
+ } |
+ |
+ void test_getLibrariesReferencedFromHtml() { |
+ Source htmlSource = addSource( |
+ "/test.html", |
+ r''' |
+<!DOCTYPE html> |
+<html><head> |
+<script type='application/dart' src='test.dart'/> |
+<script type='application/dart' src='test.js'/> |
+</head></html>'''); |
+ Source librarySource = addSource("/test.dart", "library lib;"); |
+ context.computeLibraryElement(librarySource); |
+ // Indirectly force the data to be computed. |
+ context.computeErrors(htmlSource); |
+ List<Source> result = context.getLibrariesReferencedFromHtml(htmlSource); |
+ expect(result, hasLength(1)); |
+ expect(result[0], librarySource); |
+ } |
+ |
+ void test_getLibrariesReferencedFromHtml_none() { |
+ Source htmlSource = addSource( |
+ "/test.html", |
+ r''' |
+<html><head> |
+<script type='application/dart' src='test.js'/> |
+</head></html>'''); |
+ addSource("/test.dart", "library lib;"); |
+ context.parseHtmlDocument(htmlSource); |
+ List<Source> result = context.getLibrariesReferencedFromHtml(htmlSource); |
+ expect(result, hasLength(0)); |
+ } |
+ |
+ void test_getLibraryElement() { |
+ Source source = addSource("/test.dart", "library lib;"); |
+ LibraryElement element = context.getLibraryElement(source); |
+ expect(element, isNull); |
+ context.computeLibraryElement(source); |
+ element = context.getLibraryElement(source); |
+ expect(element, isNotNull); |
+ } |
+ |
+ void test_getLibrarySources() { |
+ List<Source> sources = context.librarySources; |
+ int originalLength = sources.length; |
+ Source source = addSource("/test.dart", "library lib;"); |
+ context.computeKindOf(source); |
+ sources = context.librarySources; |
+ expect(sources, hasLength(originalLength + 1)); |
+ for (Source returnedSource in sources) { |
+ if (returnedSource == source) { |
+ return; |
+ } |
+ } |
+ fail("The added source was not in the list of library sources"); |
+ } |
+ |
+ void test_getLineInfo() { |
+ Source source = addSource( |
+ "/test.dart", |
+ r''' |
+library lib; |
+ |
+main() {}'''); |
+ LineInfo info = context.getLineInfo(source); |
+ expect(info, isNull); |
+ context.parseCompilationUnit(source); |
+ info = context.getLineInfo(source); |
+ expect(info, isNotNull); |
+ } |
+ |
+ void test_getModificationStamp_fromSource() { |
+ int stamp = 42; |
+ expect( |
+ context.getModificationStamp( |
+ new AnalysisContextImplTest_Source_getModificationStamp_fromSource( |
+ stamp)), |
+ stamp); |
+ } |
+ |
+ void test_getModificationStamp_overridden() { |
+ int stamp = 42; |
+ Source source = |
+ new AnalysisContextImplTest_Source_getModificationStamp_overridden( |
+ stamp); |
+ context.setContents(source, ""); |
+ expect(stamp != context.getModificationStamp(source), isTrue); |
+ } |
+ |
+ void test_getPublicNamespace_element() { |
+ Source source = addSource("/test.dart", "class A {}"); |
+ LibraryElement library = context.computeLibraryElement(source); |
+ expect(library, isNotNull); |
+ Namespace namespace = context.getPublicNamespace(library); |
+ expect(namespace, isNotNull); |
+ EngineTestCase.assertInstanceOf( |
+ (obj) => obj is ClassElement, ClassElement, namespace.get("A")); |
+ } |
+ |
+ void test_getResolvedCompilationUnit_library() { |
+ Source source = addSource("/lib.dart", "library libb;"); |
+ LibraryElement library = context.computeLibraryElement(source); |
+ context.computeErrors(source); // Force the resolved unit to be built. |
+ expect(context.getResolvedCompilationUnit(source, library), isNotNull); |
+ context.setContents(source, "library lib;"); |
+ expect(context.getResolvedCompilationUnit(source, library), isNull); |
+ } |
+ |
+ void test_getResolvedCompilationUnit_library_null() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ expect(context.getResolvedCompilationUnit(source, null), isNull); |
+ } |
+ |
+ void test_getResolvedCompilationUnit_source_dart() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ expect(context.getResolvedCompilationUnit2(source, source), isNull); |
+ context.resolveCompilationUnit2(source, source); |
+ expect(context.getResolvedCompilationUnit2(source, source), isNotNull); |
+ } |
+ |
+ void test_getSourceFactory() { |
+ expect(context.sourceFactory, same(sourceFactory)); |
+ } |
+ |
+ void test_getSourcesWithFullName() { |
+ String filePath = '/foo/lib/file.dart'; |
+ List<Source> expected = <Source>[]; |
+ ChangeSet changeSet = new ChangeSet(); |
+ |
+ TestSourceWithUri source1 = |
+ new TestSourceWithUri(filePath, Uri.parse('file://$filePath')); |
+ expected.add(source1); |
+ changeSet.addedSource(source1); |
+ |
+ TestSourceWithUri source2 = |
+ new TestSourceWithUri(filePath, Uri.parse('package:foo/file.dart')); |
+ expected.add(source2); |
+ changeSet.addedSource(source2); |
+ |
+ context.applyChanges(changeSet); |
+ expect(context.getSourcesWithFullName(filePath), unorderedEquals(expected)); |
+ } |
+ |
+ void test_getStatistics() { |
+ AnalysisContextStatistics statistics = context.statistics; |
+ expect(statistics, isNotNull); |
+ // The following lines are fragile. |
+ // The values depend on the number of libraries in the SDK. |
+// assertLength(0, statistics.getCacheRows()); |
+// assertLength(0, statistics.getExceptions()); |
+// assertLength(0, statistics.getSources()); |
+ } |
+ |
+ void test_handleContentsChanged() { |
+ ContentCache contentCache = new ContentCache(); |
+ context.contentCache = contentCache; |
+ String oldContents = 'foo() {}'; |
+ String newContents = 'bar() {}'; |
+ // old contents |
+ Source source = addSource("/test.dart", oldContents); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(source, source), isNotNull); |
+ // new contents |
+ contentCache.setContents(source, newContents); |
+ context.handleContentsChanged(source, oldContents, newContents, true); |
+ // there is some work to do |
+ AnalysisResult analysisResult = context.performAnalysisTask(); |
+ expect(analysisResult.changeNotices, isNotNull); |
+ } |
+ |
+ Future test_implicitAnalysisEvents_added() async { |
+ AnalyzedSourcesListener listener = new AnalyzedSourcesListener(); |
+ context.implicitAnalysisEvents.listen(listener.onData); |
+ // |
+ // Create a file that references an file that is not explicitly being |
+ // analyzed and fully analyze it. Ensure that the listener is told about |
+ // the implicitly analyzed file. |
+ // |
+ Source sourceA = newSource('/a.dart', "library a; import 'b.dart';"); |
+ Source sourceB = newSource('/b.dart', "library b;"); |
+ ChangeSet changeSet = new ChangeSet(); |
+ changeSet.addedSource(sourceA); |
+ context.applyChanges(changeSet); |
+ context.computeErrors(sourceA); |
+ await pumpEventQueue(); |
+ listener.expectAnalyzed(sourceB); |
+ } |
+ |
+ void test_isClientLibrary_dart() { |
+ Source source = addSource( |
+ "/test.dart", |
+ r''' |
+import 'dart:html'; |
+ |
+main() {}'''); |
+ expect(context.isClientLibrary(source), isFalse); |
+ expect(context.isServerLibrary(source), isFalse); |
+ context.computeLibraryElement(source); |
+ expect(context.isClientLibrary(source), isTrue); |
+ expect(context.isServerLibrary(source), isFalse); |
+ } |
+ |
+ void test_isClientLibrary_html() { |
+ Source source = addSource("/test.html", "<html></html>"); |
+ expect(context.isClientLibrary(source), isFalse); |
+ } |
+ |
+ void test_isServerLibrary_dart() { |
+ Source source = addSource( |
+ "/test.dart", |
+ r''' |
+library lib; |
+ |
+main() {}'''); |
+ expect(context.isClientLibrary(source), isFalse); |
+ expect(context.isServerLibrary(source), isFalse); |
+ context.computeLibraryElement(source); |
+ expect(context.isClientLibrary(source), isFalse); |
+ expect(context.isServerLibrary(source), isTrue); |
+ } |
+ |
+ void test_isServerLibrary_html() { |
+ Source source = addSource("/test.html", "<html></html>"); |
+ expect(context.isServerLibrary(source), isFalse); |
+ } |
+ |
+ void test_parseCompilationUnit_errors() { |
+ Source source = addSource("/lib.dart", "library {"); |
+ CompilationUnit compilationUnit = context.parseCompilationUnit(source); |
+ expect(compilationUnit, isNotNull); |
+ var errorInfo = context.getErrors(source); |
+ expect(errorInfo, isNotNull); |
+ List<AnalysisError> errors = errorInfo.errors; |
+ expect(errors, isNotNull); |
+ expect(errors.length > 0, isTrue); |
+ } |
+ |
+ void test_parseCompilationUnit_exception() { |
+ Source source = _addSourceWithException("/test.dart"); |
+ try { |
+ context.parseCompilationUnit(source); |
+ fail("Expected AnalysisException"); |
+ } on AnalysisException { |
+ // Expected |
+ } |
+ } |
+ |
+ void test_parseCompilationUnit_html() { |
+ Source source = addSource("/test.html", "<html></html>"); |
+ expect(context.parseCompilationUnit(source), isNull); |
+ } |
+ |
+ void test_parseCompilationUnit_noErrors() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ CompilationUnit compilationUnit = context.parseCompilationUnit(source); |
+ expect(compilationUnit, isNotNull); |
+ AnalysisErrorInfo errorInfo = context.getErrors(source); |
+ expect(errorInfo, isNotNull); |
+ expect(errorInfo.errors, hasLength(0)); |
+ } |
+ |
+ void test_parseCompilationUnit_nonExistentSource() { |
+ Source source = newSource('/test.dart'); |
+ resourceProvider.deleteFile('/test.dart'); |
+ try { |
+ context.parseCompilationUnit(source); |
+ fail("Expected AnalysisException because file does not exist"); |
+ } on AnalysisException { |
+ // Expected result |
+ } |
+ } |
+ |
+ void test_parseHtmlDocument() { |
+ Source source = addSource("/lib.html", "<!DOCTYPE html><html></html>"); |
+ Document document = context.parseHtmlDocument(source); |
+ expect(document, isNotNull); |
+ } |
+ |
+ void test_parseHtmlUnit_resolveDirectives() { |
+ Source libSource = addSource( |
+ "/lib.dart", |
+ r''' |
+library lib; |
+class ClassA {}'''); |
+ Source source = addSource( |
+ "/lib.html", |
+ r''' |
+<!DOCTYPE html> |
+<html> |
+<head> |
+ <script type='application/dart'> |
+ import 'lib.dart'; |
+ ClassA v = null; |
+ </script> |
+</head> |
+<body> |
+</body> |
+</html>'''); |
+ Document document = context.parseHtmlDocument(source); |
+ expect(document, isNotNull); |
+ List<DartScript> scripts = context.computeResult(source, DART_SCRIPTS); |
+ expect(scripts, hasLength(1)); |
+ CompilationUnit unit = context.computeResult(scripts[0], PARSED_UNIT); |
+ ImportDirective importNode = unit.directives[0] as ImportDirective; |
+ expect(importNode.uriContent, isNotNull); |
+ expect(importNode.source, libSource); |
+ } |
+ |
+ void test_performAnalysisTask_addPart() { |
+ Source libSource = addSource( |
+ "/lib.dart", |
+ r''' |
+library lib; |
+part 'part.dart';'''); |
+ // run all tasks without part |
+ _analyzeAll_assertFinished(); |
+ expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(libSource)), |
+ isTrue, |
+ reason: "lib has errors"); |
+ // add part and run all tasks |
+ Source partSource = addSource( |
+ "/part.dart", |
+ r''' |
+part of lib; |
+'''); |
+ _analyzeAll_assertFinished(); |
+ // "libSource" should be here |
+ List<Source> librariesWithPart = context.getLibrariesContaining(partSource); |
+ expect(librariesWithPart, unorderedEquals([libSource])); |
+ expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(libSource)), |
+ isFalse, |
+ reason: "lib doesn't have errors"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, |
+ reason: "part resolved"); |
+ } |
+ |
+ void test_performAnalysisTask_changeLibraryContents() { |
+ Source libSource = |
+ addSource("/test.dart", "library lib; part 'test-part.dart';"); |
+ Source partSource = addSource("/test-part.dart", "part of lib;"); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 1"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, |
+ reason: "part resolved 1"); |
+ // update and analyze #1 |
+ context.setContents(libSource, "library lib;"); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull, |
+ reason: "library changed 2"); |
+ expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull, |
+ reason: "part changed 2"); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 2"); |
+ expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull, |
+ reason: "part resolved 2"); |
+ // update and analyze #2 |
+ context.setContents(libSource, "library lib; part 'test-part.dart';"); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull, |
+ reason: "library changed 3"); |
+ expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull, |
+ reason: "part changed 3"); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 3"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, |
+ reason: "part resolved 3"); |
+ } |
+ |
+ void test_performAnalysisTask_changeLibraryThenPartContents() { |
+ Source libSource = |
+ addSource("/test.dart", "library lib; part 'test-part.dart';"); |
+ Source partSource = addSource("/test-part.dart", "part of lib;"); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 1"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, |
+ reason: "part resolved 1"); |
+ // update and analyze #1 |
+ context.setContents(libSource, "library lib;"); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull, |
+ reason: "library changed 2"); |
+ expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull, |
+ reason: "part changed 2"); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 2"); |
+ expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull, |
+ reason: "part resolved 2"); |
+ // update and analyze #2 |
+ context.setContents(partSource, "part of lib; // 1"); |
+ // Assert that changing the part's content does not effect the library |
+ // now that it is no longer part of that library |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library changed 3"); |
+ expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull, |
+ reason: "part changed 3"); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 3"); |
+ expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull, |
+ reason: "part resolved 3"); |
+ } |
+ |
+ void test_performAnalysisTask_changePartContents_makeItAPart() { |
+ Source libSource = addSource( |
+ "/lib.dart", |
+ r''' |
+library lib; |
+part 'part.dart'; |
+void f(x) {}'''); |
+ Source partSource = addSource("/part.dart", "void g() { f(null); }"); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 1"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, partSource), isNotNull, |
+ reason: "part resolved 1"); |
+ // update and analyze |
+ context.setContents( |
+ partSource, |
+ r''' |
+part of lib; |
+void g() { f(null); }'''); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull, |
+ reason: "library changed 2"); |
+ expect(context.getResolvedCompilationUnit2(partSource, partSource), isNull, |
+ reason: "part changed 2"); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 2"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, |
+ reason: "part resolved 2"); |
+ expect(context.getErrors(libSource).errors, hasLength(0)); |
+ expect(context.getErrors(partSource).errors, hasLength(0)); |
+ } |
+ |
+ /** |
+ * https://code.google.com/p/dart/issues/detail?id=12424 |
+ */ |
+ void test_performAnalysisTask_changePartContents_makeItNotPart() { |
+ Source libSource = addSource( |
+ "/lib.dart", |
+ r''' |
+library lib; |
+part 'part.dart'; |
+void f(x) {}'''); |
+ Source partSource = addSource( |
+ "/part.dart", |
+ r''' |
+part of lib; |
+void g() { f(null); }'''); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getErrors(libSource).errors, hasLength(0)); |
+ expect(context.getErrors(partSource).errors, hasLength(0)); |
+ // Remove 'part' directive, which should make "f(null)" an error. |
+ context.setContents( |
+ partSource, |
+ r''' |
+//part of lib; |
+void g() { f(null); }'''); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getErrors(libSource).errors.length != 0, isTrue); |
+ } |
+ |
+ void test_performAnalysisTask_changePartContents_noSemanticChanges() { |
+ Source libSource = |
+ addSource("/test.dart", "library lib; part 'test-part.dart';"); |
+ Source partSource = addSource("/test-part.dart", "part of lib;"); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 1"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, |
+ reason: "part resolved 1"); |
+ // update and analyze #1 |
+ context.setContents(partSource, "part of lib; // 1"); |
+ if (AnalysisEngine.instance.limitInvalidationInTaskModel) { |
+ expect( |
+ context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library changed 2"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, |
+ reason: "part changed 2"); |
+ } else { |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull, |
+ reason: "library changed 2"); |
+ expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull, |
+ reason: "part changed 2"); |
+ _analyzeAll_assertFinished(); |
+ expect( |
+ context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 2"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, |
+ reason: "part resolved 2"); |
+ } |
+ // update and analyze #2 |
+ context.setContents(partSource, "part of lib; // 12"); |
+ if (AnalysisEngine.instance.limitInvalidationInTaskModel) { |
+ expect( |
+ context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library changed 3"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, |
+ reason: "part changed 3"); |
+ } else { |
+ expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull, |
+ reason: "library changed 3"); |
+ expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull, |
+ reason: "part changed 3"); |
+ _analyzeAll_assertFinished(); |
+ expect( |
+ context.getResolvedCompilationUnit2(libSource, libSource), isNotNull, |
+ reason: "library resolved 3"); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, |
+ reason: "part resolved 3"); |
+ } |
+ } |
+ |
+ void test_performAnalysisTask_getContentException_dart() { |
+ Source source = _addSourceWithException('test.dart'); |
+ // prepare errors |
+ _analyzeAll_assertFinished(); |
+ List<AnalysisError> errors = context.getErrors(source).errors; |
+ // validate errors |
+ expect(errors, hasLength(1)); |
+ AnalysisError error = errors[0]; |
+ expect(error.source, same(source)); |
+ expect(error.errorCode, ScannerErrorCode.UNABLE_GET_CONTENT); |
+ } |
+ |
+ void test_performAnalysisTask_getContentException_html() { |
+ Source source = _addSourceWithException('test.html'); |
+ // prepare errors |
+ _analyzeAll_assertFinished(); |
+ List<AnalysisError> errors = context.getErrors(source).errors; |
+ // validate errors |
+ expect(errors, hasLength(1)); |
+ AnalysisError error = errors[0]; |
+ expect(error.source, same(source)); |
+ expect(error.errorCode, ScannerErrorCode.UNABLE_GET_CONTENT); |
+ } |
+ |
+ void test_performAnalysisTask_importedLibraryAdd() { |
+ Source libASource = |
+ addSource("/libA.dart", "library libA; import 'libB.dart';"); |
+ _analyzeAll_assertFinished(); |
+ expect( |
+ context.getResolvedCompilationUnit2(libASource, libASource), isNotNull, |
+ reason: "libA resolved 1"); |
+ expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(libASource)), |
+ isTrue, |
+ reason: "libA has an error"); |
+ // add libB.dart and analyze |
+ Source libBSource = addSource("/libB.dart", "library libB;"); |
+ _analyzeAll_assertFinished(); |
+ expect( |
+ context.getResolvedCompilationUnit2(libASource, libASource), isNotNull, |
+ reason: "libA resolved 2"); |
+ expect( |
+ context.getResolvedCompilationUnit2(libBSource, libBSource), isNotNull, |
+ reason: "libB resolved 2"); |
+ expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(libASource)), |
+ isFalse, |
+ reason: "libA doesn't have errors"); |
+ } |
+ |
+ void test_performAnalysisTask_importedLibraryAdd_html() { |
+ Source htmlSource = addSource( |
+ "/page.html", |
+ r''' |
+<html><body><script type="application/dart"> |
+ import '/libB.dart'; |
+ main() {print('hello dart');} |
+</script></body></html>'''); |
+ _analyzeAll_assertFinished(); |
+ context.computeErrors(htmlSource); |
+ expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(htmlSource)), |
+ isTrue, |
+ reason: "htmlSource has an error"); |
+ // add libB.dart and analyze |
+ Source libBSource = addSource("/libB.dart", "library libB;"); |
+ _analyzeAll_assertFinished(); |
+ expect( |
+ context.getResolvedCompilationUnit2(libBSource, libBSource), isNotNull, |
+ reason: "libB resolved 2"); |
+ // TODO (danrubel) commented out to fix red bots |
+// context.computeErrors(htmlSource); |
+// AnalysisErrorInfo errors = _context.getErrors(htmlSource); |
+// expect( |
+// !_hasAnalysisErrorWithErrorSeverity(errors), |
+// isTrue, |
+// reason: "htmlSource doesn't have errors"); |
+ } |
+ |
+ void test_performAnalysisTask_importedLibraryDelete() { |
+ Source libASource = |
+ addSource("/libA.dart", "library libA; import 'libB.dart';"); |
+ Source libBSource = addSource("/libB.dart", "library libB;"); |
+ _analyzeAll_assertFinished(); |
+ expect( |
+ context.getResolvedCompilationUnit2(libASource, libASource), isNotNull, |
+ reason: "libA resolved 1"); |
+ expect( |
+ context.getResolvedCompilationUnit2(libBSource, libBSource), isNotNull, |
+ reason: "libB resolved 1"); |
+ expect(!_hasAnalysisErrorWithErrorSeverity(context.getErrors(libASource)), |
+ isTrue, |
+ reason: "libA doesn't have errors"); |
+ // remove libB.dart and analyze |
+ _removeSource(libBSource); |
+ _analyzeAll_assertFinished(); |
+ expect( |
+ context.getResolvedCompilationUnit2(libASource, libASource), isNotNull, |
+ reason: "libA resolved 2"); |
+ expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(libASource)), |
+ isTrue, |
+ reason: "libA has an error"); |
+ } |
+ |
+ void test_performAnalysisTask_IOException() { |
+ TestSource source = _addSourceWithException2("/test.dart", "library test;"); |
+ source.generateExceptionOnRead = false; |
+ _analyzeAll_assertFinished(); |
+ expect(source.readCount, 2); |
+ _changeSource(source, ""); |
+ source.generateExceptionOnRead = true; |
+ _analyzeAll_assertFinished(); |
+ if (AnalysisEngine.instance.limitInvalidationInTaskModel) { |
+ expect(source.readCount, 7); |
+ } else { |
+ expect(source.readCount, 5); |
+ } |
+ } |
+ |
+ void test_performAnalysisTask_missingPart() { |
+ Source source = |
+ addSource("/test.dart", "library lib; part 'no-such-file.dart';"); |
+ _analyzeAll_assertFinished(); |
+ expect(context.getLibraryElement(source), isNotNull, |
+ reason: "performAnalysisTask failed to compute an element model"); |
+ } |
+ |
+ void test_performAnalysisTask_modifiedAfterParse() { |
+ // TODO(scheglov) no threads in Dart |
+// Source source = _addSource("/test.dart", "library lib;"); |
+// int initialTime = _context.getModificationStamp(source); |
+// List<Source> sources = <Source>[]; |
+// sources.add(source); |
+// _context.analysisPriorityOrder = sources; |
+// _context.parseCompilationUnit(source); |
+// while (initialTime == JavaSystem.currentTimeMillis()) { |
+// Thread.sleep(1); |
+// // Force the modification time to be different. |
+// } |
+// _context.setContents(source, "library test;"); |
+// JUnitTestCase.assertTrue(initialTime != _context.getModificationStamp(source)); |
+// _analyzeAll_assertFinished(); |
+// JUnitTestCase.assertNotNullMsg("performAnalysisTask failed to compute an element model", _context.getLibraryElement(source)); |
+ } |
+ |
+ void test_performAnalysisTask_onResultComputed() { |
+ Set<String> libraryElementUris = new Set<String>(); |
+ Set<String> parsedUnitUris = new Set<String>(); |
+ Set<String> resolvedUnitUris = new Set<String>(); |
+ // listen |
+ context.onResultComputed(LIBRARY_ELEMENT).listen((event) { |
+ Source librarySource = event.target; |
+ libraryElementUris.add(librarySource.uri.toString()); |
+ }); |
+ context.onResultComputed(PARSED_UNIT).listen((event) { |
+ Source source = event.target; |
+ parsedUnitUris.add(source.uri.toString()); |
+ }); |
+ context.onResultComputed(RESOLVED_UNIT).listen((event) { |
+ LibrarySpecificUnit target = event.target; |
+ Source librarySource = target.library; |
+ resolvedUnitUris.add(librarySource.uri.toString()); |
+ }); |
+ // analyze |
+ addSource('/test.dart', 'main() {}'); |
+ _analyzeAll_assertFinished(); |
+ // verify |
+ expect(libraryElementUris, contains('dart:core')); |
+ expect(libraryElementUris, contains('file:///test.dart')); |
+ expect(parsedUnitUris, contains('dart:core')); |
+ expect(parsedUnitUris, contains('file:///test.dart')); |
+ expect(resolvedUnitUris, contains('dart:core')); |
+ expect(resolvedUnitUris, contains('file:///test.dart')); |
+ } |
+ |
+ void test_resolveCompilationUnit_import_relative() { |
+ Source sourceA = |
+ addSource("/libA.dart", "library libA; import 'libB.dart'; class A{}"); |
+ addSource("/libB.dart", "library libB; class B{}"); |
+ CompilationUnit compilationUnit = |
+ context.resolveCompilationUnit2(sourceA, sourceA); |
+ expect(compilationUnit, isNotNull); |
+ LibraryElement library = compilationUnit.element.library; |
+ List<LibraryElement> importedLibraries = library.importedLibraries; |
+ assertNamedElements(importedLibraries, ["dart.core", "libB"]); |
+ List<LibraryElement> visibleLibraries = library.visibleLibraries; |
+ assertNamedElements(visibleLibraries, |
+ ["dart.core", "dart.async", "dart.math", "libA", "libB"]); |
+ } |
+ |
+ void test_resolveCompilationUnit_import_relative_cyclic() { |
+ Source sourceA = |
+ addSource("/libA.dart", "library libA; import 'libB.dart'; class A{}"); |
+ addSource("/libB.dart", "library libB; import 'libA.dart'; class B{}"); |
+ CompilationUnit compilationUnit = |
+ context.resolveCompilationUnit2(sourceA, sourceA); |
+ expect(compilationUnit, isNotNull); |
+ LibraryElement library = compilationUnit.element.library; |
+ List<LibraryElement> importedLibraries = library.importedLibraries; |
+ assertNamedElements(importedLibraries, ["dart.core", "libB"]); |
+ List<LibraryElement> visibleLibraries = library.visibleLibraries; |
+ assertNamedElements(visibleLibraries, |
+ ["dart.core", "dart.async", "dart.math", "libA", "libB"]); |
+ } |
+ |
+ void test_resolveCompilationUnit_library() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ LibraryElement library = context.computeLibraryElement(source); |
+ CompilationUnit compilationUnit = |
+ context.resolveCompilationUnit(source, library); |
+ expect(compilationUnit, isNotNull); |
+ expect(compilationUnit.element, isNotNull); |
+ } |
+ |
+// void test_resolveCompilationUnit_sourceChangeDuringResolution() { |
+// _context = new _AnalysisContext_sourceChangeDuringResolution(); |
+// AnalysisContextFactory.initContextWithCore(_context); |
+// _sourceFactory = _context.sourceFactory; |
+// Source source = _addSource("/lib.dart", "library lib;"); |
+// CompilationUnit compilationUnit = |
+// _context.resolveCompilationUnit2(source, source); |
+// expect(compilationUnit, isNotNull); |
+// expect(_context.getLineInfo(source), isNotNull); |
+// } |
+ |
+ void test_resolveCompilationUnit_source() { |
+ Source source = addSource("/lib.dart", "library lib;"); |
+ CompilationUnit compilationUnit = |
+ context.resolveCompilationUnit2(source, source); |
+ expect(compilationUnit, isNotNull); |
+ } |
+ |
+ void test_setAnalysisOptions() { |
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
+ options.cacheSize = 42; |
+ options.dart2jsHint = false; |
+ options.hint = false; |
+ context.analysisOptions = options; |
+ AnalysisOptions result = context.analysisOptions; |
+ expect(result.cacheSize, options.cacheSize); |
+ expect(result.dart2jsHint, options.dart2jsHint); |
+ expect(result.hint, options.hint); |
+ } |
+ |
+ void test_setAnalysisPriorityOrder() { |
+ int priorityCount = 4; |
+ List<Source> sources = <Source>[]; |
+ for (int index = 0; index < priorityCount; index++) { |
+ sources.add(addSource("/lib.dart$index", "")); |
+ } |
+ context.analysisPriorityOrder = sources; |
+ expect(_getPriorityOrder(context).length, priorityCount); |
+ } |
+ |
+ void test_setAnalysisPriorityOrder_empty() { |
+ context.analysisPriorityOrder = <Source>[]; |
+ } |
+ |
+ void test_setAnalysisPriorityOrder_nonEmpty() { |
+ List<Source> sources = <Source>[]; |
+ sources.add(addSource("/lib.dart", "library lib;")); |
+ context.analysisPriorityOrder = sources; |
+ } |
+ |
+ void test_setAnalysisPriorityOrder_resetAnalysisDriver() { |
+ Source source = addSource('/lib.dart', 'library lib;'); |
+ // start analysis |
+ context.performAnalysisTask(); |
+ expect(context.driver.currentWorkOrder, isNotNull); |
+ // set priority sources, AnalysisDriver is reset |
+ context.analysisPriorityOrder = <Source>[source]; |
+ expect(context.driver.currentWorkOrder, isNull); |
+ // analysis continues |
+ context.performAnalysisTask(); |
+ expect(context.driver.currentWorkOrder, isNotNull); |
+ } |
+ |
+ Future test_setChangedContents_libraryWithPart() { |
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
+ options.incremental = true; |
+ context.analysisOptions = options; |
+ SourcesChangedListener listener = new SourcesChangedListener(); |
+ context.onSourcesChanged.listen(listener.onData); |
+ String oldCode = r''' |
+library lib; |
+part 'part.dart'; |
+int a = 0;'''; |
+ Source librarySource = addSource("/lib.dart", oldCode); |
+ String partContents = r''' |
+part of lib; |
+int b = a;'''; |
+ Source partSource = addSource("/part.dart", partContents); |
+ LibraryElement element = context.computeLibraryElement(librarySource); |
+ CompilationUnit unit = |
+ context.resolveCompilationUnit(librarySource, element); |
+ expect(unit, isNotNull); |
+ int offset = oldCode.indexOf("int a") + 4; |
+ String newCode = r''' |
+library lib; |
+part 'part.dart'; |
+int ya = 0;'''; |
+ context.setChangedContents(librarySource, newCode, offset, 0, 1); |
+ expect(context.getContents(librarySource).data, newCode); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, librarySource), isNull); |
+ return pumpEventQueue().then((_) { |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(changedSources: [librarySource]); |
+ listener.assertNoMoreEvents(); |
+ }); |
+ } |
+ |
+ void test_setChangedContents_notResolved() { |
+ AnalysisOptionsImpl options = |
+ new AnalysisOptionsImpl.from(context.analysisOptions); |
+ options.incremental = true; |
+ context.analysisOptions = options; |
+ String oldCode = r''' |
+library lib; |
+int a = 0;'''; |
+ Source librarySource = addSource("/lib.dart", oldCode); |
+ int offset = oldCode.indexOf("int a") + 4; |
+ String newCode = r''' |
+library lib; |
+int ya = 0;'''; |
+ context.setChangedContents(librarySource, newCode, offset, 0, 1); |
+ expect(context.getContents(librarySource).data, newCode); |
+ } |
+ |
+ Future test_setContents_libraryWithPart() { |
+ SourcesChangedListener listener = new SourcesChangedListener(); |
+ context.onSourcesChanged.listen(listener.onData); |
+ String libraryContents1 = r''' |
+library lib; |
+part 'part.dart'; |
+int a = 0;'''; |
+ Source librarySource = addSource("/lib.dart", libraryContents1); |
+ String partContents1 = r''' |
+part of lib; |
+int b = a;'''; |
+ Source partSource = addSource("/part.dart", partContents1); |
+ context.computeLibraryElement(librarySource); |
+ String libraryContents2 = r''' |
+library lib; |
+part 'part.dart'; |
+int aa = 0;'''; |
+ context.setContents(librarySource, libraryContents2); |
+ expect( |
+ context.getResolvedCompilationUnit2(partSource, librarySource), isNull); |
+ return pumpEventQueue().then((_) { |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(wereSourcesAdded: true); |
+ listener.assertEvent(changedSources: [librarySource]); |
+ listener.assertNoMoreEvents(); |
+ }); |
+ } |
+ |
+ void test_setContents_null() { |
+ Source librarySource = addSource( |
+ "/lib.dart", |
+ r''' |
+library lib; |
+int a = 0;'''); |
+ context.setContents(librarySource, '// different'); |
+ context.computeLibraryElement(librarySource); |
+ context.setContents(librarySource, null); |
+ expect(context.getResolvedCompilationUnit2(librarySource, librarySource), |
+ isNull); |
+ } |
+ |
+ void test_setContents_unchanged_consistentModificationTime() { |
+ String contents = "// foo"; |
+ Source source = addSource("/test.dart", contents); |
+ context.setContents(source, contents); |
+ // do all, no tasks |
+ _analyzeAll_assertFinished(); |
+ { |
+ AnalysisResult result = context.performAnalysisTask(); |
+ expect(result.changeNotices, isNull); |
+ } |
+ // set the same contents, still no tasks |
+ context.setContents(source, contents); |
+ { |
+ AnalysisResult result = context.performAnalysisTask(); |
+ expect(result.changeNotices, isNull); |
+ } |
+ } |
+ |
+ void test_setSourceFactory() { |
+ expect(context.sourceFactory, sourceFactory); |
+ SourceFactory factory = new SourceFactory([]); |
+ context.sourceFactory = factory; |
+ expect(context.sourceFactory, factory); |
+ } |
+ |
+ void test_updateAnalysis() { |
+ expect(context.sourcesNeedingProcessing, isEmpty); |
+ Source source = newSource('/test.dart'); |
+ AnalysisDelta delta = new AnalysisDelta(); |
+ delta.setAnalysisLevel(source, AnalysisLevel.ALL); |
+ context.applyAnalysisDelta(delta); |
+ expect(context.sourcesNeedingProcessing, contains(source)); |
+ delta = new AnalysisDelta(); |
+ delta.setAnalysisLevel(source, AnalysisLevel.NONE); |
+ context.applyAnalysisDelta(delta); |
+ expect(context.sourcesNeedingProcessing.contains(source), isFalse); |
+ } |
+ |
+ void test_validateCacheConsistency_deletedSource() { |
+ MemoryResourceProvider resourceProvider = new MemoryResourceProvider(); |
+ var fileA = resourceProvider.newFile('/a.dart', ""); |
+ var fileB = resourceProvider.newFile('/b.dart', "import 'a.dart';"); |
+ Source sourceA = fileA.createSource(); |
+ Source sourceB = fileB.createSource(); |
+ context.applyChanges( |
+ new ChangeSet()..addedSource(sourceA)..addedSource(sourceB)); |
+ // analyze everything |
+ _analyzeAll_assertFinished(); |
+ // delete a.dart |
+ resourceProvider.deleteFile('/a.dart'); |
+ // analysis should eventually stop |
+ _analyzeAll_assertFinished(); |
+ } |
+ |
+ void xtest_performAnalysisTask_stress() { |
+ int maxCacheSize = 4; |
+ AnalysisOptionsImpl options = |
+ new AnalysisOptionsImpl.from(context.analysisOptions); |
+ options.cacheSize = maxCacheSize; |
+ context.analysisOptions = options; |
+ int sourceCount = maxCacheSize + 2; |
+ List<Source> sources = <Source>[]; |
+ ChangeSet changeSet = new ChangeSet(); |
+ for (int i = 0; i < sourceCount; i++) { |
+ Source source = addSource("/lib$i.dart", "library lib$i;"); |
+ sources.add(source); |
+ changeSet.addedSource(source); |
+ } |
+ context.applyChanges(changeSet); |
+ context.analysisPriorityOrder = sources; |
+ for (int i = 0; i < 1000; i++) { |
+ List<ChangeNotice> notice = context.performAnalysisTask().changeNotices; |
+ if (notice == null) { |
+ //System.out.println("test_performAnalysisTask_stress: " + i); |
+ break; |
+ } |
+ } |
+ List<ChangeNotice> notice = context.performAnalysisTask().changeNotices; |
+ if (notice != null) { |
+ fail( |
+ "performAnalysisTask failed to terminate after analyzing all sources"); |
+ } |
+ } |
+ |
+ TestSource _addSourceWithException(String fileName) { |
+ return _addSourceWithException2(fileName, ""); |
+ } |
+ |
+ TestSource _addSourceWithException2(String fileName, String contents) { |
+ TestSource source = new TestSource(fileName, contents); |
+ source.generateExceptionOnRead = true; |
+ ChangeSet changeSet = new ChangeSet(); |
+ changeSet.addedSource(source); |
+ context.applyChanges(changeSet); |
+ return source; |
+ } |
+ |
+ /** |
+ * Perform analysis tasks up to 512 times and assert that it was enough. |
+ */ |
+ void _analyzeAll_assertFinished([int maxIterations = 512]) { |
+ for (int i = 0; i < maxIterations; i++) { |
+ List<ChangeNotice> notice = context.performAnalysisTask().changeNotices; |
+ if (notice == null) { |
+ bool inconsistent = context.validateCacheConsistency(); |
+ if (!inconsistent) { |
+ return; |
+ } |
+ } |
+ } |
+ fail("performAnalysisTask failed to terminate after analyzing all sources"); |
+ } |
+ |
+ void _changeSource(TestSource source, String contents) { |
+ source.setContents(contents); |
+ ChangeSet changeSet = new ChangeSet(); |
+ changeSet.changedSource(source); |
+ context.applyChanges(changeSet); |
+ } |
+ |
+ /** |
+ * Search the given compilation unit for a class with the given name. Return the class with the |
+ * given name, or `null` if the class cannot be found. |
+ * |
+ * @param unit the compilation unit being searched |
+ * @param className the name of the class being searched for |
+ * @return the class with the given name |
+ */ |
+ ClassElement _findClass(CompilationUnitElement unit, String className) { |
+ for (ClassElement classElement in unit.types) { |
+ if (classElement.displayName == className) { |
+ return classElement; |
+ } |
+ } |
+ return null; |
+ } |
+ |
+ void _flushAst(Source source) { |
+ CacheEntry entry = |
+ context.getCacheEntry(new LibrarySpecificUnit(source, source)); |
+ entry.setState(RESOLVED_UNIT, CacheState.FLUSHED); |
+ } |
+ |
+ List<Source> _getPriorityOrder(AnalysisContextImpl context) { |
+ return context.test_priorityOrder; |
+ } |
+ |
+ void _performPendingAnalysisTasks([int maxTasks = 512]) { |
+ for (int i = 0; context.performAnalysisTask().hasMoreWork; i++) { |
+ if (i > maxTasks) { |
+ fail('Analysis did not terminate.'); |
+ } |
+ } |
+ } |
+ |
+ void _removeSource(Source source) { |
+ resourceProvider.deleteFile(source.fullName); |
+ ChangeSet changeSet = new ChangeSet(); |
+ changeSet.removedSource(source); |
+ context.applyChanges(changeSet); |
+ } |
+ |
+ /** |
+ * Returns `true` if there is an [AnalysisError] with [ErrorSeverity.ERROR] in |
+ * the given [AnalysisErrorInfo]. |
+ */ |
+ static bool _hasAnalysisErrorWithErrorSeverity(AnalysisErrorInfo errorInfo) { |
+ List<AnalysisError> errors = errorInfo.errors; |
+ for (AnalysisError analysisError in errors) { |
+ if (analysisError.errorCode.errorSeverity == ErrorSeverity.ERROR) { |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
+} |
+ |
+@reflectiveTest |
+class LimitedInvalidateTest extends AbstractContextTest { |
+ @override |
+ void setUp() { |
+ AnalysisEngine.instance.limitInvalidationInTaskModel = true; |
+ super.setUp(); |
+ AnalysisOptionsImpl options = |
+ new AnalysisOptionsImpl.from(context.analysisOptions); |
+ options.incremental = true; |
+ context.analysisOptions = options; |
+ } |
+ |
+ @override |
+ void tearDown() { |
+ AnalysisEngine.instance.limitInvalidationInTaskModel = false; |
+ super.tearDown(); |
+ } |
+ |
+ void test_noChange_thenChange() { |
+ Source sourceA = addSource( |
+ "/a.dart", |
+ r''' |
+library lib_a; |
+ |
+class A { |
+ A(); |
+} |
+class B { |
+ B(); |
+} |
+'''); |
+ Source sourceB = addSource( |
+ "/b.dart", |
+ r''' |
+library lib_b; |
+import 'a.dart'; |
+main() { |
+ new A(); |
+} |
+'''); |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(sourceA).errors, hasLength(0)); |
+ expect(context.getErrors(sourceB).errors, hasLength(0)); |
+ var unitA = context.getResolvedCompilationUnit2(sourceA, sourceA); |
+ var unitElementA = unitA.element; |
+ var libraryElementA = unitElementA.library; |
+ // Update a.dart, no declaration changes. |
+ context.setContents( |
+ sourceA, |
+ r''' |
+library lib_a; |
+class A { |
+ A(); |
+} |
+class B { |
+ B(); |
+} |
+'''); |
+ _assertInvalid(sourceA, LIBRARY_ERRORS_READY); |
+ _assertValid(sourceB, LIBRARY_ELEMENT); |
+ // The a.dart's unit and element are updated incrementally. |
+ // They are the same instances as initially. |
+ // So, all the references from other units are still valid. |
+ { |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(sourceA, sourceA); |
+ expect(analysisCache.getValue(target, RESOLVED_UNIT1), same(unitA)); |
+ expect(unitA.element, same(unitElementA)); |
+ expect(unitElementA.library, same(libraryElementA)); |
+ } |
+ // Analyze. |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(sourceA).errors, hasLength(0)); |
+ expect(context.getErrors(sourceB).errors, hasLength(0)); |
+ // The a.dart's unit and element are the same. |
+ { |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(sourceA, sourceA); |
+ expect(analysisCache.getValue(target, RESOLVED_UNIT), same(unitA)); |
+ expect(unitA.element, same(unitElementA)); |
+ expect(unitElementA.library, same(libraryElementA)); |
+ } |
+ // Update a.dart, rename A to A2, invalidates b.dart, so |
+ // we know that the previous update did not damage dependencies. |
+ context.setContents( |
+ sourceA, |
+ r''' |
+library lib_a; |
+class A { |
+ A(); |
+ m() {} |
+} |
+class B { |
+ B(); |
+} |
+'''); |
+ _assertInvalid(sourceA, LIBRARY_ERRORS_READY); |
+ _assertInvalid(sourceB, LIBRARY_ELEMENT); |
+ // The a.dart's unit and element are the same. |
+ { |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(sourceA, sourceA); |
+ expect(analysisCache.getValue(target, RESOLVED_UNIT1), same(unitA)); |
+ expect(unitA.element, same(unitElementA)); |
+ expect(unitElementA.library, same(libraryElementA)); |
+ } |
+ // Analyze. |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(sourceA).errors, hasLength(0)); |
+ expect(context.getErrors(sourceB).errors, hasLength(0)); |
+ } |
+ |
+ void test_unusedName() { |
+ Source sourceA = addSource( |
+ "/a.dart", |
+ r''' |
+library lib_a; |
+class A {} |
+class B {} |
+class C {} |
+'''); |
+ Source sourceB = addSource( |
+ "/b.dart", |
+ r''' |
+library lib_b; |
+import 'a.dart'; |
+main() { |
+ new A(); |
+ new C(); |
+} |
+'''); |
+ _performPendingAnalysisTasks(); |
+ // Update A. |
+ context.setContents( |
+ sourceA, |
+ r''' |
+library lib_a; |
+class A {} |
+class B2 {} |
+class C {} |
+'''); |
+ // Only a.dart is invalidated. |
+ // Because b.dart does not use B, so it is valid. |
+ _assertInvalid(sourceA, LIBRARY_ERRORS_READY); |
+ _assertValid(sourceB, LIBRARY_ERRORS_READY); |
+ } |
+ |
+ void test_usedName_directUser() { |
+ Source sourceA = addSource( |
+ "/a.dart", |
+ r''' |
+library lib_a; |
+class A {} |
+class B {} |
+class C {} |
+'''); |
+ Source sourceB = addSource( |
+ "/b.dart", |
+ r''' |
+library lib_b; |
+import 'a.dart'; |
+main() { |
+ new A(); |
+ new C2(); |
+} |
+'''); |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(sourceB).errors, hasLength(1)); |
+ // Update a.dart, invalidates b.dart because it references "C2". |
+ context.setContents( |
+ sourceA, |
+ r''' |
+library lib_a; |
+class A {} |
+class B {} |
+class C2 {} |
+'''); |
+ _assertInvalid(sourceA, LIBRARY_ERRORS_READY); |
+ _assertInvalid(sourceB, LIBRARY_ERRORS_READY); |
+ // Now b.dart is analyzed and the error is fixed. |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(sourceB).errors, hasLength(0)); |
+ // Update a.dart, invalidates b.dart because it references "C". |
+ context.setContents( |
+ sourceA, |
+ r''' |
+library lib_a; |
+class A {} |
+class B {} |
+class C {} |
+'''); |
+ _assertInvalid(sourceA, LIBRARY_ERRORS_READY); |
+ _assertInvalid(sourceB, LIBRARY_ERRORS_READY); |
+ _performPendingAnalysisTasks(); |
+ // Now b.dart is analyzed and it again has the error. |
+ expect(context.getErrors(sourceB).errors, hasLength(1)); |
+ } |
+ |
+ void test_usedName_directUser_withIncremental() { |
+ Source sourceA = addSource( |
+ "/a.dart", |
+ r''' |
+library lib_a; |
+class A { |
+ m() {} |
+} |
+'''); |
+ Source sourceB = addSource( |
+ "/b.dart", |
+ r''' |
+library lib_b; |
+import 'a.dart'; |
+main() { |
+ A a = new A(); |
+ a.m(); |
+} |
+'''); |
+ _performPendingAnalysisTasks(); |
+ // Update A. |
+ context.setContents( |
+ sourceA, |
+ r''' |
+library lib_a; |
+class A { |
+ m2() {} |
+} |
+'''); |
+ _assertInvalid(sourceA, LIBRARY_ERRORS_READY); |
+ _assertInvalid(sourceB, LIBRARY_ERRORS_READY); |
+ } |
+ |
+ void test_usedName_indirectUser() { |
+ Source sourceA = addSource( |
+ "/a.dart", |
+ r''' |
+library lib_a; |
+class A { |
+ m() {} |
+} |
+'''); |
+ Source sourceB = addSource( |
+ "/b.dart", |
+ r''' |
+library lib_b; |
+import 'a.dart'; |
+class B extends A {} |
+'''); |
+ Source sourceC = addSource( |
+ "/c.dart", |
+ r''' |
+library lib_c; |
+import 'b.dart'; |
+class C extends B { |
+ main() { |
+ m(); |
+ } |
+} |
+'''); |
+ // No errors, "A.m" exists. |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(sourceC).errors, hasLength(0)); |
+ // Replace "A.m" with "A.m2", invalidate both b.dart and c.dart files. |
+ context.setContents( |
+ sourceA, |
+ r''' |
+library lib_a; |
+class A { |
+ m2() {} |
+} |
+'''); |
+ _assertInvalid(sourceA, LIBRARY_ERRORS_READY); |
+ _assertInvalid(sourceB, LIBRARY_ERRORS_READY); |
+ _assertInvalid(sourceC, LIBRARY_ERRORS_READY); |
+ // There is an error in c.dart, "A.m" does not exist. |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(sourceB).errors, hasLength(0)); |
+ expect(context.getErrors(sourceC).errors, hasLength(1)); |
+ // Restore "A.m", invalidate both b.dart and c.dart files. |
+ context.setContents( |
+ sourceA, |
+ r''' |
+library lib_a; |
+class A { |
+ m() {} |
+} |
+'''); |
+ _assertInvalid(sourceA, LIBRARY_ERRORS_READY); |
+ _assertInvalid(sourceB, LIBRARY_ERRORS_READY); |
+ _assertInvalid(sourceC, LIBRARY_ERRORS_READY); |
+ // No errors, "A.m" exists. |
+ _performPendingAnalysisTasks(); |
+ expect(context.getErrors(sourceC).errors, hasLength(0)); |
+ } |
+ |
+ void _assertInvalid(AnalysisTarget target, ResultDescriptor descriptor) { |
+ CacheState state = analysisCache.getState(target, descriptor); |
+ expect(state, CacheState.INVALID); |
+ } |
+ |
+ void _assertValid(AnalysisTarget target, ResultDescriptor descriptor) { |
+ CacheState state = analysisCache.getState(target, descriptor); |
+ expect(state, CacheState.VALID); |
+ } |
+ |
+ void _performPendingAnalysisTasks([int maxTasks = 512]) { |
+ for (int i = 0; context.performAnalysisTask().hasMoreWork; i++) { |
+ if (i > maxTasks) { |
+ fail('Analysis did not terminate.'); |
+ } |
+ } |
+ } |
+} |
+ |
+class _AnalysisContextImplTest_test_applyChanges_removeContainer |
+ implements SourceContainer { |
+ Source libB; |
+ _AnalysisContextImplTest_test_applyChanges_removeContainer(this.libB); |
+ @override |
+ bool contains(Source source) => source == libB; |
+} |