Add getParsedLibrary2(), deprecate getParsedLibrary() and other parse related
Change-Id: I585fa1f01b71522dc99ba86c2b9e20da256b2d27
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195880
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index 1cb9178..5fab9db 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -340,7 +340,9 @@
return null;
}
- return getAnalysisDriver(path)?.currentSession.getParsedUnit(path);
+ var session = getAnalysisDriver(path)?.currentSession;
+ var result = session?.getParsedUnit2(path);
+ return result is ParsedUnitResult ? result : null;
}
/// Return the resolved unit for the file with the given [path]. The file is
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
index dd7b2d0..5eec574 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
@@ -12,6 +12,7 @@
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/progress.dart';
import 'package:analysis_server/src/services/correction/sort_members.dart';
+import 'package:analyzer/dart/analysis/results.dart';
class SortMembersCommandHandler extends SimpleEditCommandHandler {
SortMembersCommandHandler(LspAnalysisServer server) : super(server);
@@ -37,18 +38,20 @@
final docIdentifier = server.getVersionedDocumentIdentifier(path);
var driver = server.getAnalysisDriver(path);
- final result = await driver?.parseFile(path);
+ final result0 = await driver?.parseFile2(path);
if (cancellationToken.isCancellationRequested) {
return error(ErrorCodes.RequestCancelled, 'Request was cancelled');
}
- if (result == null) {
+ if (result0 is! ParsedUnitResult) {
return ErrorOr.error(ResponseError(
code: ServerErrorCodes.FileNotAnalyzed,
message: '$commandName is only available for analyzed files',
));
}
+ // TODO(scheglov) inline after migration
+ var result = result0 as ParsedUnitResult;
final code = result.content;
final unit = result.unit;
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
index 5de4b4b..db58a6d 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
@@ -8,6 +8,7 @@
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/services/refactoring/rename.dart';
+import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
@@ -49,7 +50,7 @@
// update declaration
{
var prefix = element.prefix;
- SourceEdit edit;
+ SourceEdit? edit;
if (newName.isEmpty) {
// We should not get `prefix == null` because we check in
// `checkNewName` that the new name is different.
@@ -57,22 +58,28 @@
return;
}
var node = _findNode();
- var uriEnd = node.uri.end;
- var prefixEnd = element.prefixOffset + prefix.nameLength;
- edit = newSourceEdit_range(
- range.startOffsetEndOffset(uriEnd, prefixEnd), '');
+ if (node != null) {
+ var uriEnd = node.uri.end;
+ var prefixEnd = element.prefixOffset + prefix.nameLength;
+ edit = newSourceEdit_range(
+ range.startOffsetEndOffset(uriEnd, prefixEnd), '');
+ }
} else {
if (prefix == null) {
var node = _findNode();
- var uriEnd = node.uri.end;
- edit = newSourceEdit_range(SourceRange(uriEnd, 0), ' as $newName');
+ if (node != null) {
+ var uriEnd = node.uri.end;
+ edit = newSourceEdit_range(SourceRange(uriEnd, 0), ' as $newName');
+ }
} else {
var offset = element.prefixOffset;
var length = prefix.nameLength;
edit = newSourceEdit_range(SourceRange(offset, length), newName);
}
}
- doSourceChange_addElementEdit(change, element, edit);
+ if (edit != null) {
+ doSourceChange_addElementEdit(change, element, edit);
+ }
}
// update references
var matches = await searchEngine.searchReferences(element);
@@ -98,10 +105,14 @@
}
/// Return the [ImportDirective] node that corresponds to the [element].
- ImportDirective _findNode() {
+ ImportDirective? _findNode() {
var library = element.library;
var path = library.source.fullName;
- var unit = session.getParsedUnit(path).unit;
+ var unitResult = session.getParsedUnit2(path);
+ if (unitResult is! ParsedUnitResult) {
+ return null;
+ }
+ var unit = unitResult.unit;
var index = library.imports.indexOf(element);
return unit.directives.whereType<ImportDirective>().elementAt(index);
}
@@ -111,7 +122,11 @@
/// it. Otherwise return `null`.
SimpleIdentifier? _getInterpolationIdentifier(SourceReference reference) {
var source = reference.element.source!;
- var unit = session.getParsedUnit(source.fullName).unit;
+ var unitResult = session.getParsedUnit2(source.fullName);
+ if (unitResult is! ParsedUnitResult) {
+ return null;
+ }
+ var unit = unitResult.unit;
var nodeLocator = NodeLocator(reference.range.offset);
var node = nodeLocator.searchWithin(unit);
if (node is SimpleIdentifier) {
diff --git a/pkg/analysis_server/test/lsp/definition_test.dart b/pkg/analysis_server/test/lsp/definition_test.dart
index f78d059..08b013a 100644
--- a/pkg/analysis_server/test/lsp/definition_test.dart
+++ b/pkg/analysis_server/test/lsp/definition_test.dart
@@ -198,9 +198,6 @@
expect(res, isEmpty);
}
- /// Failing due to incorrect range because _DartNavigationCollector._getCodeLocation
- /// does not handle parts.
- @failingTest
Future<void> test_part() async {
final mainContents = '''
import 'lib.dart';
diff --git a/pkg/analysis_server/test/services/correction/sort_members_test.dart b/pkg/analysis_server/test/services/correction/sort_members_test.dart
index 88cc25d..a766800 100644
--- a/pkg/analysis_server/test/services/correction/sort_members_test.dart
+++ b/pkg/analysis_server/test/services/correction/sort_members_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/correction/sort_members.dart';
+import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -924,7 +925,7 @@
Future<void> _parseTestUnit(String code) async {
addTestSource(code);
- var result = session.getParsedUnit(testFile);
+ var result = session.getParsedUnit2(testFile) as ParsedUnitResult;
testUnit = result.unit;
}
}
diff --git a/pkg/analysis_server/test/verify_sorted_test.dart b/pkg/analysis_server/test/verify_sorted_test.dart
index dff52dd..9cf62ed 100644
--- a/pkg/analysis_server/test/verify_sorted_test.dart
+++ b/pkg/analysis_server/test/verify_sorted_test.dart
@@ -134,8 +134,8 @@
}
var relativePath = pathContext.relative(path, from: testDirPath);
test(relativePath, () {
- var result = session.getParsedUnit(path);
- if (result.state != ResultState.VALID) {
+ var result = session.getParsedUnit2(path);
+ if (result is! ParsedUnitResult) {
fail('Could not parse $path');
}
var code = result.content;
diff --git a/pkg/analysis_server_client/test/verify_sorted_test.dart b/pkg/analysis_server_client/test/verify_sorted_test.dart
index 5a19d51..dfa4c4a 100644
--- a/pkg/analysis_server_client/test/verify_sorted_test.dart
+++ b/pkg/analysis_server_client/test/verify_sorted_test.dart
@@ -55,8 +55,8 @@
}
var relativePath = pathContext.relative(path, from: testDirPath);
test(relativePath, () {
- var result = session.getParsedUnit(path);
- if (result.state != ResultState.VALID) {
+ var result = session.getParsedUnit2(path);
+ if (result is! ParsedUnitResult) {
fail('Could not parse $path');
}
var code = result.content;
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 398e956..13fe6b3 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -11,6 +11,12 @@
Use `AnalysisSession.getLibraryByUri2()` instead.
* Deprecated `AnalysisSession.getErrors()`.
Use `AnalysisSession.getErrors2()` instead.
+* Deprecated `AnalysisSession.getParsedLibrary()`.
+ Use `AnalysisSession.getParsedLibrary2()` instead.
+* Deprecated `AnalysisSession.getParsedLibraryByElement()`.
+ Use `AnalysisSession.getParsedLibraryByElement2()` instead.
+* Deprecated `AnalysisSession.getParsedUnit()`.
+ Use `AnalysisSession.getParsedUnit2()` instead.
## 1.4.0
* Deprecated `TypeProvider.nonSubtypableClasses`.
diff --git a/pkg/analyzer/doc/tutorial/ast.md b/pkg/analyzer/doc/tutorial/ast.md
index 2adab31..3e9e3fa 100644
--- a/pkg/analyzer/doc/tutorial/ast.md
+++ b/pkg/analyzer/doc/tutorial/ast.md
@@ -55,8 +55,10 @@
```dart
void processFile(AnalysisSession session, String path) {
- ParsedUnitResult result = session.getParsedUnit(path);
- CompilationUnit unit = result.unit;
+ var result = session.getParsedUnit2(path);
+ if (result is ParsedUnitResult) {
+ CompilationUnit unit = result.unit;
+ }
}
```
diff --git a/pkg/analyzer/lib/dart/analysis/results.dart b/pkg/analyzer/lib/dart/analysis/results.dart
index 762a44f..a79c4af 100644
--- a/pkg/analyzer/lib/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/dart/analysis/results.dart
@@ -49,6 +49,7 @@
implements
InvalidResult,
SomeLibraryElementResult,
+ SomeParsedLibraryResult,
SomeResolvedLibraryResult {}
/// The declaration of an [Element].
@@ -99,6 +100,8 @@
implements
InvalidResult,
SomeErrorsResult,
+ SomeParsedLibraryResult,
+ SomeParsedUnitResult,
SomeResolvedLibraryResult,
SomeResolvedUnitResult,
SomeUnitElementResult {}
@@ -121,7 +124,10 @@
///
/// Clients may not extend, implement or mix-in this class.
class NotElementOfThisSessionResult
- implements InvalidResult, SomeResolvedLibraryResult {}
+ implements
+ InvalidResult,
+ SomeParsedLibraryResult,
+ SomeResolvedLibraryResult {}
/// The type of [InvalidResult] returned when the given file is not a library,
/// but a part of a library.
@@ -131,6 +137,7 @@
implements
InvalidResult,
SomeLibraryElementResult,
+ SomeParsedLibraryResult,
SomeResolvedLibraryResult {}
/// The type of [InvalidResult] returned when the given file path does not
@@ -145,6 +152,7 @@
implements
InvalidResult,
SomeErrorsResult,
+ SomeParsedLibraryResult,
SomeResolvedLibraryResult,
SomeResolvedUnitResult,
SomeUnitElementResult {}
@@ -152,7 +160,8 @@
/// The result of building parsed AST(s) for the whole library.
///
/// Clients may not extend, implement or mix-in this class.
-abstract class ParsedLibraryResult implements AnalysisResult {
+abstract class ParsedLibraryResult
+ implements SomeParsedLibraryResult, AnalysisResult {
/// The parsed units of the library.
///
/// TODO(migration): should not be null, probably empty list
@@ -168,7 +177,8 @@
/// those discovered during scanning and parsing.
///
/// Clients may not extend, implement or mix-in this class.
-abstract class ParsedUnitResult implements AnalysisResultWithErrors {
+abstract class ParsedUnitResult
+ implements SomeParsedUnitResult, AnalysisResultWithErrors {
/// The content of the file that was scanned and parsed.
String get content;
@@ -278,9 +288,27 @@
///
/// Clients may not extend, implement or mix-in this class.
///
+/// There are existing implementations of this class.
/// [LibraryElementResult] represents a valid result.
abstract class SomeLibraryElementResult {}
+/// The result of building parsed AST(s) for the whole library.
+///
+/// Clients may not extend, implement or mix-in this class.
+///
+/// There are existing implementations of this class.
+/// [ParsedLibraryResult] represents a valid result.
+abstract class SomeParsedLibraryResult {}
+
+/// The result of parsing of a single file. The errors returned include only
+/// those discovered during scanning and parsing.
+///
+/// Clients may not extend, implement or mix-in this class.
+///
+/// There are existing implementations of this class.
+/// [ParsedUnitResult] represents a valid result.
+abstract class SomeParsedUnitResult {}
+
/// The result of building resolved AST(s) for the whole library.
///
/// Clients may not extend, implement or mix-in this class.
@@ -331,11 +359,17 @@
///
/// Clients may not extend, implement or mix-in this class.
class UnspecifiedInvalidResult
- implements InvalidResult, SomeLibraryElementResult {}
+ implements
+ InvalidResult,
+ SomeLibraryElementResult,
+ SomeParsedLibraryResult {}
/// The type of [InvalidResult] returned when the given URI corresponds to
/// a library that is served from an external summary bundle.
///
/// Clients may not extend, implement or mix-in this class.
class UriOfExternalLibraryResult
- implements InvalidResult, SomeResolvedLibraryResult {}
+ implements
+ InvalidResult,
+ SomeParsedLibraryResult,
+ SomeResolvedLibraryResult {}
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 5e4b6fa..8b8db65 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -64,18 +64,33 @@
///
/// Throw [ArgumentError] if the given [path] is not the defining compilation
/// unit for a library (that is, is a part of a library).
+ @Deprecated('Use getParsedLibrary2() instead')
ParsedLibraryResult getParsedLibrary(String path);
/// Return information about the results of parsing units of the library file
+ /// with the given absolute, normalized [path].
+ SomeParsedLibraryResult getParsedLibrary2(String path);
+
+ /// Return information about the results of parsing units of the library file
/// with the given library [element].
///
/// Throw [ArgumentError] if the [element] was not produced by this session.
+ @Deprecated('Use getParsedLibraryByElement2() instead')
ParsedLibraryResult getParsedLibraryByElement(LibraryElement element);
+ /// Return information about the results of parsing units of the library file
+ /// with the given library [element].
+ SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element);
+
/// Return information about the results of parsing the file with the given
/// absolute, normalized [path].
+ @Deprecated('Use getParsedUnit2() instead')
ParsedUnitResult getParsedUnit(String path);
+ /// Return information about the results of parsing the file with the given
+ /// absolute, normalized [path].
+ SomeParsedUnitResult getParsedUnit2(String path);
+
/// Return a future that will complete with information about the results of
/// resolving all of the files in the library with the given absolute,
/// normalized [path].
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 33182f1..fd284cf 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -720,20 +720,40 @@
///
/// The [path] must be absolute and normalized.
ParsedLibraryResult getParsedLibrary(String path) {
- FileState file = _fsState.getFileForPath(path);
+ var result = getParsedLibrary2(path);
- if (file.isExternalLibrary) {
- return ParsedLibraryResultImpl.external(currentSession, file.uri);
+ if (result is NotLibraryButPartResult) {
+ throw ArgumentError('Is a part: $path');
}
+ return result as ParsedLibraryResult;
+ }
+
+ /// Return a [ParsedLibraryResult] for the library with the given [path].
+ ///
+ /// The [path] must be absolute and normalized.
+ SomeParsedLibraryResult getParsedLibrary2(String path) {
+ if (!_isAbsolutePath(path)) {
+ return InvalidPathResult();
+ }
+
+ if (!_fsState.hasUri(path)) {
+ return NotPathOfUriResult();
+ }
+
+ FileState file = _fsState.getFileForPath(path);
+
if (file.isPart) {
- throw ArgumentError('Is a part: $path');
+ return NotLibraryButPartResult();
}
var units = <ParsedUnitResult>[];
for (var unitFile in file.libraryFiles) {
var unitPath = unitFile.path;
- var unitResult = parseFileSync(unitPath);
+ var unitResult = parseFileSync2(unitPath);
+ if (unitResult is! ParsedUnitResult) {
+ return UnspecifiedInvalidResult();
+ }
units.add(unitResult);
}
@@ -744,6 +764,7 @@
///
/// Throw [ArgumentError] if the given [uri] is not the defining compilation
/// unit for a library (that is, is a part of a library).
+ @Deprecated('Use getParsedLibraryByUri2() instead')
ParsedLibraryResult getParsedLibraryByUri(Uri uri) {
var fileOr = _fsState.getFileForUri(uri);
return fileOr.map(
@@ -762,6 +783,25 @@
);
}
+ /// Return a [ParsedLibraryResult] for the library with the given [uri].
+ SomeParsedLibraryResult getParsedLibraryByUri2(Uri uri) {
+ var fileOr = _fsState.getFileForUri(uri);
+ return fileOr.map(
+ (file) {
+ if (file == null) {
+ return CannotResolveUriResult();
+ }
+ if (file.isPart) {
+ return NotLibraryButPartResult();
+ }
+ return getParsedLibrary(file.path);
+ },
+ (externalLibrary) {
+ return UriOfExternalLibraryResult();
+ },
+ );
+ }
+
/// Return a [Future] that completes with a [ResolvedLibraryResult] for the
/// Dart library file with the given [path]. If the file is not a Dart file
/// or cannot be analyzed, the [Future] completes with `null`.
@@ -1096,10 +1136,25 @@
/// The parsing is performed in the method itself, and the result is not
/// produced through the [results] stream (just because it is not a fully
/// resolved unit).
+ @Deprecated('Use parseFile2() instead')
Future<ParsedUnitResult> parseFile(String path) async {
return parseFileSync(path);
}
+ /// Return a [Future] that completes with a [ParsedUnitResult] for the file
+ /// with the given [path].
+ ///
+ /// The [path] must be absolute and normalized.
+ ///
+ /// The [path] can be any file - explicitly or implicitly analyzed, or neither.
+ ///
+ /// The parsing is performed in the method itself, and the result is not
+ /// produced through the [results] stream (just because it is not a fully
+ /// resolved unit).
+ Future<SomeParsedUnitResult> parseFile2(String path) async {
+ return parseFileSync2(path);
+ }
+
/// Return a [ParsedUnitResult] for the file with the given [path].
///
/// The [path] must be absolute and normalized.
@@ -1109,8 +1164,27 @@
/// The parsing is performed in the method itself, and the result is not
/// produced through the [results] stream (just because it is not a fully
/// resolved unit).
+ @Deprecated('Use parseFileSync2() instead')
ParsedUnitResult parseFileSync(String path) {
_throwIfNotAbsolutePath(path);
+
+ return parseFileSync2(path) as ParsedUnitResult;
+ }
+
+ /// Return a [ParsedUnitResult] for the file with the given [path].
+ ///
+ /// The [path] must be absolute and normalized.
+ ///
+ /// The [path] can be any file - explicitly or implicitly analyzed, or neither.
+ ///
+ /// The parsing is performed in the method itself, and the result is not
+ /// produced through the [results] stream (just because it is not a fully
+ /// resolved unit).
+ SomeParsedUnitResult parseFileSync2(String path) {
+ if (!_isAbsolutePath(path)) {
+ return InvalidPathResult();
+ }
+
FileState file = _fileTracker.getFile(path);
RecordingErrorListener listener = RecordingErrorListener();
CompilationUnit unit = file.parse(listener);
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index fe0a088..fbc5371 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -95,6 +95,7 @@
return _driver.getLibraryByUri2(uri);
}
+ @Deprecated('Use getParsedLibrary2() instead')
@override
ParsedLibraryResult getParsedLibrary(String path) {
_checkConsistency();
@@ -102,6 +103,13 @@
}
@override
+ SomeParsedLibraryResult getParsedLibrary2(String path) {
+ _checkConsistency();
+ return _driver.getParsedLibrary2(path);
+ }
+
+ @Deprecated('Use getParsedLibraryByElement2() instead')
+ @override
ParsedLibraryResult getParsedLibraryByElement(LibraryElement element) {
_checkConsistency();
_checkElementOfThisSession(element);
@@ -109,11 +117,29 @@
}
@override
+ SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element) {
+ _checkConsistency();
+
+ if (element.session != this) {
+ return NotElementOfThisSessionResult();
+ }
+
+ return _driver.getParsedLibraryByUri2(element.source.uri);
+ }
+
+ @Deprecated('Use getParsedUnit2() instead')
+ @override
ParsedUnitResult getParsedUnit(String path) {
_checkConsistency();
return _driver.parseFileSync(path);
}
+ @override
+ SomeParsedUnitResult getParsedUnit2(String path) {
+ _checkConsistency();
+ return _driver.parseFileSync2(path);
+ }
+
@Deprecated('Use getResolvedLibrary2() instead')
@override
Future<ResolvedLibraryResult> getResolvedLibrary(String path) {
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 793b2a6..87cdde7 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -1513,6 +1513,57 @@
}, throwsArgumentError);
}
+ test_getParsedLibrary2() async {
+ var content = 'class A {}';
+ addTestFile(content);
+ var result = driver.getParsedLibrary2(testFile);
+ result as ParsedLibraryResult;
+ expect(result.units, hasLength(1));
+ expect(result.units![0].path, testFile);
+ expect(result.units![0].content, content);
+ expect(result.units![0].unit, isNotNull);
+ expect(result.units![0].errors, isEmpty);
+ }
+
+ test_getParsedLibrary2_invalidPath_notAbsolute() async {
+ var result = driver.getParsedLibrary2('not_absolute.dart');
+ expect(result, isA<InvalidPathResult>());
+ }
+
+ test_getParsedLibrary2_notLibraryButPart() async {
+ addTestFile('part of my;');
+ var result = driver.getParsedLibrary2(testFile);
+ expect(result, isA<NotLibraryButPartResult>());
+ }
+
+ test_getParsedLibraryByUri2() async {
+ var content = 'class A {}';
+ addTestFile(content);
+
+ var uri = Uri.parse('package:test/test.dart');
+ var result = driver.getParsedLibraryByUri2(uri);
+ result as ParsedLibraryResult;
+ expect(result.uri, uri);
+ expect(result.units, hasLength(1));
+ expect(result.units![0].uri, uri);
+ expect(result.units![0].path, testFile);
+ expect(result.units![0].content, content);
+ }
+
+ test_getParsedLibraryByUri2_notLibrary() async {
+ addTestFile('part of my;');
+
+ var uri = Uri.parse('package:test/test.dart');
+ var result = driver.getParsedLibraryByUri2(uri);
+ expect(result, isA<NotLibraryButPartResult>());
+ }
+
+ test_getParsedLibraryByUri2_unresolvedUri() async {
+ var uri = Uri.parse('package:unknown/a.dart');
+ var result = driver.getParsedLibraryByUri2(uri);
+ expect(result, isA<CannotResolveUriResult>());
+ }
+
test_getResolvedLibrary2() async {
var content = 'class A {}';
addTestFile(content);
@@ -2480,6 +2531,70 @@
expect(error.errorCode, CompileTimeErrorCode.MISSING_DART_LIBRARY);
}
+ test_parseFile2_changedFile() async {
+ var a = convertPath('/test/lib/a.dart');
+ var b = convertPath('/test/lib/b.dart');
+
+ newFile(a, content: '');
+ newFile(b, content: r'''
+import 'a.dart';
+
+void f(A a) {}
+''');
+
+ // Ensure that [a.dart] library cycle is loaded.
+ // So, `a.dart` is in the library context.
+ await driver.getResultValid(a);
+
+ // Update the file, changing its API signature.
+ // Note that we don't call `changeFile`.
+ newFile(a, content: 'class A {}');
+
+ // Parse the file.
+ // We have not called `changeFile(a)`, so we should not read the file.
+ // Moreover, doing this will create a new library cycle [a.dart].
+ // Library cycles are compared by their identity, so we would try to
+ // reload linked summary for [a.dart], and crash.
+ {
+ var parseResult = await driver.parseFile2(a) as ParsedUnitResult;
+ expect(parseResult.unit.declarations, isEmpty);
+ }
+
+ // We have not read `a.dart`, so `A` is still not declared.
+ {
+ var bResult = await driver.getResultValid(b);
+ expect(bResult.errors, isNotEmpty);
+ }
+
+ // Notify the driver that the file was changed.
+ driver.changeFile(a);
+
+ // So, `class A {}` is declared now.
+ {
+ var parseResult = driver.parseFileSync2(a) as ParsedUnitResult;
+ expect(parseResult.unit.declarations, hasLength(1));
+ }
+ {
+ var bResult = await driver.getResultValid(b);
+ expect(bResult.errors, isEmpty);
+ }
+ }
+
+ test_parseFile2_notAbsolutePath() async {
+ var result = await driver.parseFile2('not_absolute.dart');
+ expect(result, isA<InvalidPathResult>());
+ }
+
+ test_parseFile2_notDart() async {
+ var p = convertPath('/test/bin/a.txt');
+ newFile(p, content: 'class A {}');
+
+ var parseResult = await driver.parseFile2(p) as ParsedUnitResult;
+ expect(parseResult, isNotNull);
+ expect(driver.knownFiles, contains(p));
+ }
+
+ @deprecated
test_parseFile_changedFile() async {
var a = convertPath('/test/lib/a.dart');
var b = convertPath('/test/lib/b.dart');
@@ -2529,12 +2644,14 @@
}
}
+ @deprecated
test_parseFile_notAbsolutePath() async {
expect(() async {
await driver.parseFile('not_absolute.dart');
}, throwsArgumentError);
}
+ @deprecated
test_parseFile_notDart() async {
var p = convertPath('/test/bin/a.txt');
newFile(p, content: 'class A {}');
@@ -2544,6 +2661,138 @@
expect(driver.knownFiles, contains(p));
}
+ test_parseFileSync2_changedFile() async {
+ var a = convertPath('/test/lib/a.dart');
+ var b = convertPath('/test/lib/b.dart');
+
+ newFile(a, content: '');
+ newFile(b, content: r'''
+import 'a.dart';
+
+void f(A a) {}
+''');
+
+ // Ensure that [a.dart] library cycle is loaded.
+ // So, `a.dart` is in the library context.
+ await driver.getResultValid(a);
+
+ // Update the file, changing its API signature.
+ // Note that we don't call `changeFile`.
+ newFile(a, content: 'class A {}');
+
+ // Parse the file.
+ // We have not called `changeFile(a)`, so we should not read the file.
+ // Moreover, doing this will create a new library cycle [a.dart].
+ // Library cycles are compared by their identity, so we would try to
+ // reload linked summary for [a.dart], and crash.
+ {
+ var parseResult = driver.parseFileSync2(a) as ParsedUnitResult;
+ expect(parseResult.unit.declarations, isEmpty);
+ }
+
+ // We have not read `a.dart`, so `A` is still not declared.
+ {
+ var bResult = await driver.getResultValid(b);
+ expect(bResult.errors, isNotEmpty);
+ }
+
+ // Notify the driver that the file was changed.
+ driver.changeFile(a);
+
+ // So, `class A {}` is declared now.
+ {
+ var parseResult = driver.parseFileSync2(a) as ParsedUnitResult;
+ expect(parseResult.unit.declarations, hasLength(1));
+ }
+ {
+ var bResult = await driver.getResultValid(b);
+ expect(bResult.errors, isEmpty);
+ }
+ }
+
+ test_parseFileSync2_doesNotReadImportedFiles() async {
+ var a = convertPath('/test/lib/a.dart');
+ var b = convertPath('/test/lib/b.dart');
+
+ newFile(a, content: '');
+ newFile(b, content: r'''
+import 'a.dart';
+''');
+
+ expect(driver.fsState.knownFilePaths, isEmpty);
+
+ // Don't read `a.dart` when parse.
+ driver.parseFileSync2(b);
+ expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
+
+ // Still don't read `a.dart` when parse the second time.
+ driver.parseFileSync2(b);
+ expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
+ }
+
+ test_parseFileSync2_doesNotReadPartedFiles() async {
+ var a = convertPath('/test/lib/a.dart');
+ var b = convertPath('/test/lib/b.dart');
+
+ newFile(a, content: r'''
+part of my;
+''');
+ newFile(b, content: r'''
+library my;
+part 'a.dart';
+''');
+
+ expect(driver.fsState.knownFilePaths, isEmpty);
+
+ // Don't read `a.dart` when parse.
+ driver.parseFileSync2(b);
+ expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
+
+ // Still don't read `a.dart` when parse the second time.
+ driver.parseFileSync2(b);
+ expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
+ }
+
+ test_parseFileSync2_languageVersion() async {
+ var path = convertPath('/test/lib/test.dart');
+
+ newFile(path, content: r'''
+// @dart = 2.7
+class A {}
+''');
+
+ var parseResult = driver.parseFileSync2(path) as ParsedUnitResult;
+ var languageVersion = parseResult.unit.languageVersionToken!;
+ expect(languageVersion.major, 2);
+ expect(languageVersion.minor, 7);
+ }
+
+ test_parseFileSync2_languageVersion_null() async {
+ var path = convertPath('/test/lib/test.dart');
+
+ newFile(path, content: r'''
+class A {}
+''');
+
+ var parseResult = driver.parseFileSync2(path) as ParsedUnitResult;
+ expect(parseResult.unit.languageVersionToken, isNull);
+ }
+
+ test_parseFileSync2_notAbsolutePath() {
+ var result = driver.parseFileSync2('not_absolute.dart');
+ expect(result, isA<InvalidPathResult>());
+ }
+
+ test_parseFileSync2_notDart() {
+ var p = convertPath('/test/bin/a.txt');
+ newFile(p, content: 'class A {}');
+
+ var parseResult = driver.parseFileSync2(p) as ParsedUnitResult;
+ expect(parseResult, isNotNull);
+ expect(driver.knownFiles, contains(p));
+ }
+
+ @deprecated
test_parseFileSync_changedFile() async {
var a = convertPath('/test/lib/a.dart');
var b = convertPath('/test/lib/b.dart');
@@ -2593,6 +2842,7 @@
}
}
+ @deprecated
test_parseFileSync_doesNotReadImportedFiles() async {
var a = convertPath('/test/lib/a.dart');
var b = convertPath('/test/lib/b.dart');
@@ -2613,6 +2863,7 @@
expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
}
+ @deprecated
test_parseFileSync_doesNotReadPartedFiles() async {
var a = convertPath('/test/lib/a.dart');
var b = convertPath('/test/lib/b.dart');
@@ -2636,6 +2887,7 @@
expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
}
+ @deprecated
test_parseFileSync_languageVersion() async {
var path = convertPath('/test/lib/test.dart');
@@ -2650,6 +2902,7 @@
expect(languageVersion.minor, 7);
}
+ @deprecated
test_parseFileSync_languageVersion_null() async {
var path = convertPath('/test/lib/test.dart');
@@ -2661,12 +2914,14 @@
expect(parseResult.unit.languageVersionToken, isNull);
}
- test_parseFileSync_notAbsolutePath() async {
+ @deprecated
+ test_parseFileSync_notAbsolutePath() {
expect(() {
driver.parseFileSync('not_absolute.dart');
}, throwsArgumentError);
}
+ @deprecated
test_parseFileSync_notDart() {
var p = convertPath('/test/bin/a.txt');
newFile(p, content: 'class A {}');
diff --git a/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart b/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart
index 6984d0e..89fdeda 100644
--- a/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart
@@ -5,7 +5,6 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -438,9 +437,9 @@
return library.getElementDeclaration(element);
}
- ParsedLibraryResultImpl _getParsedLibrary(String path) {
+ ParsedLibraryResult _getParsedLibrary(String path) {
var session = contextFor(path).currentSession;
- return session.getParsedLibrary(path) as ParsedLibraryResultImpl;
+ return session.getParsedLibrary2(path) as ParsedLibraryResult;
}
}
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index e75afcd..5af5179 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -79,6 +79,16 @@
expect(result.uri.toString(), 'package:dart.my/a.dart');
}
+ void test_getParsedLibrary2_notFileOfUri() async {
+ var relPath = 'dart/my/lib/a.dart';
+ newFile('$workspaceRootPath/bazel-bin/$relPath');
+
+ var path = convertPath('$workspaceRootPath/$relPath');
+ var session = contextFor(path).currentSession;
+ var result = session.getParsedLibrary2(path);
+ expect(result, isA<NotPathOfUriResult>());
+ }
+
void test_getResolvedLibrary2_notFileOfUri() async {
var relPath = 'dart/my/lib/a.dart';
newFile('$workspaceRootPath/bazel-bin/$relPath');
@@ -298,6 +308,7 @@
}, throwsArgumentError);
}
+ @deprecated
test_getParsedLibrary() async {
newFile(testPath, content: r'''
class A {}
@@ -319,6 +330,95 @@
}
}
+ test_getParsedLibrary2() async {
+ newFile(testPath, content: r'''
+class A {}
+class B {}
+''');
+
+ var parsedLibrary = session.getParsedLibraryValid(testPath);
+ expect(parsedLibrary.session, session);
+ expect(parsedLibrary.path, testPath);
+ expect(parsedLibrary.uri, Uri.parse('package:test/test.dart'));
+
+ expect(parsedLibrary.units, hasLength(1));
+ {
+ var parsedUnit = parsedLibrary.units![0];
+ expect(parsedUnit.session, session);
+ expect(parsedUnit.path, testPath);
+ expect(parsedUnit.uri, Uri.parse('package:test/test.dart'));
+ expect(parsedUnit.unit.declarations, hasLength(2));
+ }
+ }
+
+ test_getParsedLibrary2_invalidPath_notAbsolute() async {
+ var result = session.getParsedLibrary2('not_absolute.dart');
+ expect(result, isA<InvalidPathResult>());
+ }
+
+ test_getParsedLibrary2_notLibrary() async {
+ newFile(testPath, content: 'part of "a.dart";');
+ expect(session.getParsedLibrary2(testPath), isA<NotLibraryButPartResult>());
+ }
+
+ test_getParsedLibrary2_parts() async {
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+ var c = convertPath('/home/test/lib/c.dart');
+
+ var aContent = r'''
+part 'b.dart';
+part 'c.dart';
+
+class A {}
+''';
+
+ var bContent = r'''
+part of 'a.dart';
+
+class B1 {}
+class B2 {}
+''';
+
+ var cContent = r'''
+part of 'a.dart';
+
+class C1 {}
+class C2 {}
+class C3 {}
+''';
+
+ newFile(a, content: aContent);
+ newFile(b, content: bContent);
+ newFile(c, content: cContent);
+
+ var parsedLibrary = session.getParsedLibraryValid(a);
+ expect(parsedLibrary.path, a);
+ expect(parsedLibrary.uri, Uri.parse('package:test/a.dart'));
+ expect(parsedLibrary.units, hasLength(3));
+
+ {
+ var aUnit = parsedLibrary.units![0];
+ expect(aUnit.path, a);
+ expect(aUnit.uri, Uri.parse('package:test/a.dart'));
+ expect(aUnit.unit.declarations, hasLength(1));
+ }
+
+ {
+ var bUnit = parsedLibrary.units![1];
+ expect(bUnit.path, b);
+ expect(bUnit.uri, Uri.parse('package:test/b.dart'));
+ expect(bUnit.unit.declarations, hasLength(2));
+ }
+
+ {
+ var cUnit = parsedLibrary.units![2];
+ expect(cUnit.path, c);
+ expect(cUnit.uri, Uri.parse('package:test/c.dart'));
+ expect(cUnit.unit.declarations, hasLength(3));
+ }
+ }
+
test_getParsedLibrary_getElementDeclaration_class() async {
newFile(testPath, content: r'''
class A {}
@@ -328,7 +428,7 @@
var libraryResult = await session.getLibraryByUriValid(
'package:test/test.dart',
);
- var parsedLibrary = session.getParsedLibrary(testPath);
+ var parsedLibrary = session.getParsedLibraryValid(testPath);
var element = libraryResult.element.getType('A')!;
var declaration = parsedLibrary.getElementDeclaration(element)!;
@@ -361,7 +461,7 @@
var typeProvider = resolvedUnit.typeProvider;
var intClass = typeProvider.intType.element;
- var parsedLibrary = session.getParsedLibrary(testPath);
+ var parsedLibrary = session.getParsedLibraryValid(testPath);
expect(() {
parsedLibrary.getElementDeclaration(intClass);
@@ -373,7 +473,7 @@
int foo = 0;
''');
- var parsedLibrary = session.getParsedLibrary(testPath);
+ var parsedLibrary = session.getParsedLibraryValid(testPath);
var unitResult = await session.getUnitElement2(testPath);
var unitElement = (unitResult as UnitElementResult).element;
@@ -425,7 +525,7 @@
part 'c.dart';
''');
- var parsedLibrary = session.getParsedLibrary(testPath);
+ var parsedLibrary = session.getParsedLibraryValid(testPath);
expect(parsedLibrary.units, hasLength(3));
expect(
@@ -442,6 +542,7 @@
);
}
+ @deprecated
test_getParsedLibrary_notLibrary() async {
newFile(testPath, content: 'part of "a.dart";');
@@ -450,6 +551,7 @@
}, throwsArgumentError);
}
+ @deprecated
test_getParsedLibrary_parts() async {
var a = convertPath('/home/test/lib/a.dart');
var b = convertPath('/home/test/lib/b.dart');
@@ -508,6 +610,7 @@
}
}
+ @deprecated
test_getParsedLibraryByElement() async {
newFile(testPath, content: '');
@@ -523,6 +626,37 @@
expect(parsedLibrary.units, hasLength(1));
}
+ test_getParsedLibraryByElement2() async {
+ newFile(testPath, content: '');
+
+ var libraryResult = await session.getLibraryByUriValid(
+ 'package:test/test.dart',
+ );
+ var element = libraryResult.element;
+
+ var parsedLibrary = session.getParsedLibraryByElementValid(element);
+ expect(parsedLibrary.session, session);
+ expect(parsedLibrary.path, testPath);
+ expect(parsedLibrary.uri, Uri.parse('package:test/test.dart'));
+ expect(parsedLibrary.units, hasLength(1));
+ }
+
+ test_getParsedLibraryByElement2_differentSession() async {
+ newFile(testPath, content: '');
+
+ var libraryResult = await session.getLibraryByUriValid(
+ 'package:test/test.dart',
+ );
+ var element = libraryResult.element;
+
+ var aaaSession =
+ contextCollection.contextFor(aaaContextPath).currentSession;
+
+ var result = aaaSession.getParsedLibraryByElement2(element);
+ expect(result, isA<NotElementOfThisSessionResult>());
+ }
+
+ @deprecated
test_getParsedLibraryByElement_differentSession() async {
newFile(testPath, content: '');
@@ -539,6 +673,7 @@
}, throwsArgumentError);
}
+ @deprecated
test_getParsedUnit() async {
newFile(testPath, content: r'''
class A {}
@@ -552,6 +687,24 @@
expect(unitResult.unit.declarations, hasLength(2));
}
+ test_getParsedUnit2() async {
+ newFile(testPath, content: r'''
+class A {}
+class B {}
+''');
+
+ var unitResult = session.getParsedUnitValid(testPath);
+ expect(unitResult.session, session);
+ expect(unitResult.path, testPath);
+ expect(unitResult.uri, Uri.parse('package:test/test.dart'));
+ expect(unitResult.unit.declarations, hasLength(2));
+ }
+
+ test_getParsedUnit2_invalidPath_notAbsolute() async {
+ var result = session.getParsedUnit2('not_absolute.dart');
+ expect(result, isA<InvalidPathResult>());
+ }
+
test_getResolvedLibrary() async {
var a = convertPath('/home/test/lib/a.dart');
var b = convertPath('/home/test/lib/b.dart');
@@ -846,6 +999,14 @@
return await getUnitElement2(path) as UnitElementResult;
}
+ ParsedLibraryResult getParsedLibraryValid(String path) {
+ return getParsedLibrary2(path) as ParsedLibraryResult;
+ }
+
+ ParsedUnitResult getParsedUnitValid(String path) {
+ return getParsedUnit2(path) as ParsedUnitResult;
+ }
+
Future<ResolvedLibraryResult> getResolvedLibraryValid(String path) async {
return await getResolvedLibrary2(path) as ResolvedLibraryResult;
}
@@ -859,6 +1020,10 @@
return await getResolvedLibraryByElement2(element) as ResolvedLibraryResult;
}
+ ParsedLibraryResult getParsedLibraryByElementValid(LibraryElement element) {
+ return getParsedLibraryByElement2(element) as ParsedLibraryResult;
+ }
+
Future<ErrorsResult> getErrorsValid(String path) async {
return await getErrors2(path) as ErrorsResult;
}
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index f99f600..c1c68c6 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -251,8 +251,8 @@
/// [path] and return the result.
ParsedUnitResult _parse(AnalysisContextCollection collection, String path) {
AnalysisSession session = collection.contextFor(path).currentSession;
- ParsedUnitResult result = session.getParsedUnit(path);
- if (result.state != ResultState.VALID) {
+ var result = session.getParsedUnit2(path);
+ if (result is! ParsedUnitResult) {
throw StateError('Unable to parse "$path"');
}
return result;
diff --git a/pkg/analyzer/tool/diagnostics/generate.dart b/pkg/analyzer/tool/diagnostics/generate.dart
index 5f8db9e..b95e8dc 100644
--- a/pkg/analyzer/tool/diagnostics/generate.dart
+++ b/pkg/analyzer/tool/diagnostics/generate.dart
@@ -361,8 +361,8 @@
/// [path] and return the result.
ParsedUnitResult _parse(AnalysisContextCollection collection, String path) {
AnalysisSession session = collection.contextFor(path).currentSession;
- ParsedUnitResult result = session.getParsedUnit(path);
- if (result.state != ResultState.VALID) {
+ var result = session.getParsedUnit2(path);
+ if (result is! ParsedUnitResult) {
throw StateError('Unable to parse "$path"');
}
return result;
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index dde44ba..897f2d7 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -2,6 +2,7 @@
// 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.
+import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
@@ -130,13 +131,7 @@
// Read the declaration so we can get the offset after the doc comments.
// TODO(dantup): Skip this for parts (getParsedLibrary will throw), but find
// a better solution.
- var session = codeElement.session;
- final declaration =
- session != null && !session.getFile(location.file).isPart
- ? session
- .getParsedLibrary(location.file)
- .getElementDeclaration(codeElement)
- : null;
+ final declaration = _parsedDeclaration(codeElement);
var node = declaration?.node;
if (node is VariableDeclaration) {
node = node.parent;
@@ -152,6 +147,25 @@
return converter.locationFromElement(element,
offset: codeOffset, length: codeLength);
}
+
+ static ElementDeclarationResult? _parsedDeclaration(Element element) {
+ var session = element.session;
+ if (session == null) {
+ return null;
+ }
+
+ var libraryPath = element.library?.source.fullName;
+ if (libraryPath == null) {
+ return null;
+ }
+
+ var parsedLibrary = session.getParsedLibrary2(libraryPath);
+ if (parsedLibrary is! ParsedLibraryResult) {
+ return null;
+ }
+
+ return parsedLibrary.getElementDeclaration(element);
+ }
}
class _DartNavigationComputerVisitor extends RecursiveAstVisitor<void> {
diff --git a/pkg/analyzer_utilities/lib/verify_tests.dart b/pkg/analyzer_utilities/lib/verify_tests.dart
index d6fad18..201e88d 100644
--- a/pkg/analyzer_utilities/lib/verify_tests.dart
+++ b/pkg/analyzer_utilities/lib/verify_tests.dart
@@ -103,8 +103,8 @@
if (isOkForTestAllToBeMissing(directory)) {
fail('Found "test_all.dart" in $relativePath but did not expect one');
}
- var result = session.getParsedUnit(testAllFile.path);
- if (result.state != ResultState.VALID) {
+ var result = session.getParsedUnit2(testAllFile.path);
+ if (result is! ParsedUnitResult) {
fail('Could not parse ${testAllFile.path}');
}
var importedFiles = <String>[];