Return PartWithoutLibraryResult when a part without its library.
Change-Id: I5eb384d77c263b489b10e112a79115bf028e79af Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/245081 Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
committed by
Commit Bot
parent
93f3065cac
commit
e28972166c
@@ -96,6 +96,12 @@ library my.lib;
|
||||
}
|
||||
|
||||
Future<void> test_libraryName_hasPartOfDirective() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
library lib;
|
||||
|
||||
part 'test.dart';
|
||||
''');
|
||||
|
||||
addTestFile('''
|
||||
part of my.lib;
|
||||
''');
|
||||
|
||||
@@ -742,8 +742,8 @@ void f() {
|
||||
}
|
||||
''');
|
||||
await findElementReferences('fff(p) {}', false);
|
||||
expect(results, hasLength(1));
|
||||
assertHasResult(SearchResultKind.INVOCATION, 'fff(10);');
|
||||
// A part without library, no results.
|
||||
expect(results, isEmpty);
|
||||
}
|
||||
|
||||
Future<void> test_parameter() async {
|
||||
|
||||
@@ -2272,6 +2272,7 @@ void m() {
|
||||
assertSuggestKeywords([]);
|
||||
}
|
||||
|
||||
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
|
||||
Future<void> test_part_of() async {
|
||||
addTestSource('part of foo;^');
|
||||
await computeSuggestions();
|
||||
|
||||
+1
@@ -105,6 +105,7 @@ void f() {
|
||||
''');
|
||||
}
|
||||
|
||||
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
|
||||
Future<void> test_function_hasZero_partOfName_noLibrary() async {
|
||||
await resolveTestCode('''
|
||||
part of my_lib;
|
||||
|
||||
@@ -79,6 +79,7 @@ class A {
|
||||
''', target: a);
|
||||
}
|
||||
|
||||
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
|
||||
Future<void> test_inPart_partOfName_noLibrary() async {
|
||||
await resolveTestCode('''
|
||||
part of my_lib;
|
||||
|
||||
@@ -383,6 +383,7 @@ void f(A a) {
|
||||
});
|
||||
}
|
||||
|
||||
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
|
||||
Future<void> test_inPart_self() async {
|
||||
await resolveTestCode('''
|
||||
part of lib;
|
||||
|
||||
@@ -326,6 +326,7 @@ void f(A a) {
|
||||
});
|
||||
}
|
||||
|
||||
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
|
||||
Future<void> test_qualified_instance_inPart_self() async {
|
||||
await resolveTestCode('''
|
||||
part of lib;
|
||||
|
||||
@@ -320,6 +320,7 @@ void f(A a) {
|
||||
});
|
||||
}
|
||||
|
||||
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
|
||||
Future<void> test_qualified_instance_inPart_self() async {
|
||||
await resolveTestCode('''
|
||||
part of lib;
|
||||
|
||||
@@ -195,6 +195,22 @@ abstract class ParseStringResult {
|
||||
CompilationUnit get unit;
|
||||
}
|
||||
|
||||
/// The type of [InvalidResult] returned when the file is a part, and its
|
||||
/// containing library is not known.
|
||||
///
|
||||
/// Clients may not extend, implement or mix-in this class.
|
||||
///
|
||||
/// TODO(scheglov) Add an error that points at the `part of` location.
|
||||
abstract class PartWithoutLibraryResult
|
||||
implements
|
||||
InvalidResult,
|
||||
SomeErrorsResult,
|
||||
SomeResolvedUnitResult,
|
||||
SomeUnitElementResult {
|
||||
/// The absolute and normalized path of the file.
|
||||
String get path;
|
||||
}
|
||||
|
||||
/// The result of building resolved AST(s) for the whole library.
|
||||
///
|
||||
/// Clients may not extend, implement or mix-in this class.
|
||||
|
||||
@@ -159,7 +159,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
|
||||
/// The mapping from the files for which analysis was requested using
|
||||
/// [getResult] to the [Completer]s to report the result.
|
||||
final _requestedFiles = <String, List<Completer<ResolvedUnitResult>>>{};
|
||||
final _requestedFiles = <String, List<Completer<SomeResolvedUnitResult>>>{};
|
||||
|
||||
/// The mapping from the files for which analysis was requested using
|
||||
/// [getResolvedLibrary] to the [Completer]s to report the result.
|
||||
@@ -182,35 +182,17 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
|
||||
/// The mapping from the files for which errors were requested using
|
||||
/// [getErrors] to the [Completer]s to report the result.
|
||||
final _errorsRequestedFiles = <String, List<Completer<ErrorsResult>>>{};
|
||||
|
||||
/// The requests from [_errorsRequestedFiles] for files which were found to
|
||||
/// be parts without known libraries, so delayed.
|
||||
final _errorsRequestedParts = <String, List<Completer<ErrorsResult>>>{};
|
||||
final _errorsRequestedFiles = <String, List<Completer<SomeErrorsResult>>>{};
|
||||
|
||||
/// The mapping from the files for which the index was requested using
|
||||
/// [getIndex] to the [Completer]s to report the result.
|
||||
final _indexRequestedFiles =
|
||||
<String, List<Completer<AnalysisDriverUnitIndex>>>{};
|
||||
<String, List<Completer<AnalysisDriverUnitIndex?>>>{};
|
||||
|
||||
/// The mapping from the files for which the unit element was requested using
|
||||
/// [getUnitElement] to the [Completer]s to report the result.
|
||||
final _unitElementRequestedFiles =
|
||||
<String, List<Completer<UnitElementResult>>>{};
|
||||
|
||||
/// The mapping from the files for which the unit element was requested using
|
||||
/// [getUnitElement], and which were found to be parts without known
|
||||
/// libraries, to the [Completer]s to report the result.
|
||||
final _unitElementRequestedParts =
|
||||
<String, List<Completer<UnitElementResult>>>{};
|
||||
|
||||
/// The mapping from the files for which analysis was requested using
|
||||
/// [getResult], and which were found to be parts without known libraries,
|
||||
/// to the [Completer]s to report the result.
|
||||
final _requestedParts = <String, List<Completer<ResolvedUnitResult>>>{};
|
||||
|
||||
/// The set of part files that are currently scheduled for analysis.
|
||||
final _partsToAnalyze = <String>{};
|
||||
<String, List<Completer<SomeUnitElementResult>>>{};
|
||||
|
||||
/// The controller for the [results] stream.
|
||||
final _resultController = StreamController<Object>();
|
||||
@@ -249,6 +231,11 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
/// Whether `dart:core` has been transitively discovered.
|
||||
bool _hasDartCoreDiscovered = false;
|
||||
|
||||
/// This flag is reset to `false` when a new file is added, because it
|
||||
/// might be a library, so that some files that were disconnected parts
|
||||
/// could be analyzed now.
|
||||
bool _hasLibrariesDiscovered = false;
|
||||
|
||||
/// If testing data is being retained, a pointer to the object that is
|
||||
/// retaining the testing data. Otherwise `null`.
|
||||
final TestingData? testingData;
|
||||
@@ -311,9 +298,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
return hasPendingFileChanges ||
|
||||
_fileTracker.hasChangedFiles ||
|
||||
_requestedFiles.isNotEmpty ||
|
||||
_requestedParts.isNotEmpty ||
|
||||
_fileTracker.hasPendingFiles ||
|
||||
_partsToAnalyze.isNotEmpty;
|
||||
_fileTracker.hasPendingFiles;
|
||||
}
|
||||
|
||||
bool get hasPendingFileChanges => _pendingFileChanges.isNotEmpty;
|
||||
@@ -455,11 +440,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
if (_fileTracker.hasPendingFiles) {
|
||||
return AnalysisDriverPriority.general;
|
||||
}
|
||||
if (_errorsRequestedParts.isNotEmpty ||
|
||||
_requestedParts.isNotEmpty ||
|
||||
_partsToAnalyze.isNotEmpty ||
|
||||
_unitElementRequestedParts.isNotEmpty ||
|
||||
_pendingFileChangesCompleters.isNotEmpty) {
|
||||
if (_pendingFileChangesCompleters.isNotEmpty) {
|
||||
return AnalysisDriverPriority.general;
|
||||
}
|
||||
return AnalysisDriverPriority.nothing;
|
||||
@@ -627,9 +608,9 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
);
|
||||
}
|
||||
|
||||
var completer = Completer<ErrorsResult>();
|
||||
var completer = Completer<SomeErrorsResult>();
|
||||
_errorsRequestedFiles
|
||||
.putIfAbsent(path, () => <Completer<ErrorsResult>>[])
|
||||
.putIfAbsent(path, () => <Completer<SomeErrorsResult>>[])
|
||||
.add(completer);
|
||||
_scheduler.notify(this);
|
||||
return completer.future;
|
||||
@@ -699,9 +680,9 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
if (!_fsState.hasUri(path)) {
|
||||
return Future.value();
|
||||
}
|
||||
var completer = Completer<AnalysisDriverUnitIndex>();
|
||||
var completer = Completer<AnalysisDriverUnitIndex?>();
|
||||
_indexRequestedFiles
|
||||
.putIfAbsent(path, () => <Completer<AnalysisDriverUnitIndex>>[])
|
||||
.putIfAbsent(path, () => <Completer<AnalysisDriverUnitIndex?>>[])
|
||||
.add(completer);
|
||||
_scheduler.notify(this);
|
||||
return completer.future;
|
||||
@@ -918,9 +899,9 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
}
|
||||
|
||||
// Schedule analysis.
|
||||
var completer = Completer<ResolvedUnitResult>();
|
||||
var completer = Completer<SomeResolvedUnitResult>();
|
||||
_requestedFiles
|
||||
.putIfAbsent(path, () => <Completer<ResolvedUnitResult>>[])
|
||||
.putIfAbsent(path, () => <Completer<SomeResolvedUnitResult>>[])
|
||||
.add(completer);
|
||||
_scheduler.notify(this);
|
||||
return completer.future;
|
||||
@@ -964,9 +945,9 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
);
|
||||
}
|
||||
|
||||
var completer = Completer<UnitElementResult>();
|
||||
var completer = Completer<SomeUnitElementResult>();
|
||||
_unitElementRequestedFiles
|
||||
.putIfAbsent(path, () => <Completer<UnitElementResult>>[])
|
||||
.putIfAbsent(path, () => <Completer<SomeUnitElementResult>>[])
|
||||
.add(completer);
|
||||
_scheduler.notify(this);
|
||||
return completer.future;
|
||||
@@ -1041,10 +1022,8 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
|
||||
@override
|
||||
Future<void> performWork() async {
|
||||
if (!_hasDartCoreDiscovered) {
|
||||
_hasDartCoreDiscovered = true;
|
||||
_discoverDartCore();
|
||||
}
|
||||
_discoverDartCore();
|
||||
_discoverLibraries();
|
||||
|
||||
if (_resolveForCompletionRequests.isNotEmpty) {
|
||||
final request = _resolveForCompletionRequests.removeLast();
|
||||
@@ -1061,27 +1040,26 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
|
||||
// Analyze a requested file.
|
||||
if (_requestedFiles.isNotEmpty) {
|
||||
String path = _requestedFiles.keys.first;
|
||||
final path = _requestedFiles.keys.first;
|
||||
final completers = _requestedFiles.remove(path)!;
|
||||
_fileTracker.fileWasAnalyzed(path);
|
||||
try {
|
||||
var result = await _computeAnalysisResult(path, withUnit: true);
|
||||
// If a part without a library, delay its analysis.
|
||||
if (result == null) {
|
||||
_requestedParts
|
||||
.putIfAbsent(path, () => [])
|
||||
.addAll(_requestedFiles.remove(path)!);
|
||||
return;
|
||||
final result = await _computeAnalysisResult(path, withUnit: true);
|
||||
final SomeResolvedUnitResult unitResult;
|
||||
if (result != null) {
|
||||
unitResult = result.unitResult!;
|
||||
} else {
|
||||
unitResult = PartWithoutLibraryResultImpl(
|
||||
path: path,
|
||||
);
|
||||
}
|
||||
// Notify the completers.
|
||||
for (var completer in _requestedFiles.remove(path)!) {
|
||||
completer.complete(result.unitResult!);
|
||||
for (final completer in completers) {
|
||||
completer.complete(unitResult);
|
||||
}
|
||||
// Remove from to be analyzed and produce it now.
|
||||
_fileTracker.fileWasAnalyzed(path);
|
||||
_resultController.add(result.unitResult!);
|
||||
_resultController.add(unitResult);
|
||||
} catch (exception, stackTrace) {
|
||||
_reportException(path, exception, stackTrace);
|
||||
_fileTracker.fileWasAnalyzed(path);
|
||||
for (var completer in _requestedFiles.remove(path)!) {
|
||||
for (final completer in completers) {
|
||||
completer.completeError(exception, stackTrace);
|
||||
}
|
||||
_clearLibraryContextAfterException();
|
||||
@@ -1112,14 +1090,10 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
var completers = _errorsRequestedFiles.remove(path)!;
|
||||
var result = await _computeErrors(
|
||||
path: path,
|
||||
asIsIfPartWithoutLibrary: false,
|
||||
);
|
||||
if (result != null) {
|
||||
for (var completer in completers) {
|
||||
completer.complete(result);
|
||||
}
|
||||
} else {
|
||||
_errorsRequestedParts.putIfAbsent(path, () => []).addAll(completers);
|
||||
result ??= PartWithoutLibraryResultImpl(path: path);
|
||||
for (var completer in completers) {
|
||||
completer.complete(result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1127,7 +1101,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
// Process an index request.
|
||||
if (_indexRequestedFiles.isNotEmpty) {
|
||||
String path = _indexRequestedFiles.keys.first;
|
||||
AnalysisDriverUnitIndex index = await _computeIndex(path);
|
||||
final index = await _computeIndex(path);
|
||||
for (var completer in _indexRequestedFiles.remove(path)!) {
|
||||
completer.complete(index);
|
||||
}
|
||||
@@ -1137,16 +1111,11 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
// Process a unit element request.
|
||||
if (_unitElementRequestedFiles.isNotEmpty) {
|
||||
String path = _unitElementRequestedFiles.keys.first;
|
||||
UnitElementResult? result = await _computeUnitElement(path);
|
||||
var completers = _unitElementRequestedFiles.remove(path)!;
|
||||
if (result != null) {
|
||||
for (var completer in completers) {
|
||||
completer.complete(result);
|
||||
}
|
||||
} else {
|
||||
_unitElementRequestedParts
|
||||
.putIfAbsent(path, () => [])
|
||||
.addAll(completers);
|
||||
SomeUnitElementResult? result = await _computeUnitElement(path);
|
||||
result ??= PartWithoutLibraryResultImpl(path: path);
|
||||
for (var completer in completers) {
|
||||
completer.complete(result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1186,7 +1155,14 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
try {
|
||||
var result = await _computeAnalysisResult(path, withUnit: true);
|
||||
if (result == null) {
|
||||
_partsToAnalyze.add(path);
|
||||
// We report an invalid result (instead of silently ignoring
|
||||
// this disconnected part) so that the listener of the stream
|
||||
// knows, and for example removes all errors.
|
||||
_resultController.add(
|
||||
PartWithoutLibraryResultImpl(
|
||||
path: path,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
_resultController.add(result.unitResult!);
|
||||
}
|
||||
@@ -1208,7 +1184,11 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
var result = await _computeAnalysisResult(path,
|
||||
withUnit: false, skipIfSameSignature: true);
|
||||
if (result == null) {
|
||||
_partsToAnalyze.add(path);
|
||||
_resultController.add(
|
||||
PartWithoutLibraryResultImpl(
|
||||
path: path,
|
||||
),
|
||||
);
|
||||
} else if (result.isUnchangedErrors) {
|
||||
// We found that the set of errors is the same as we produced the
|
||||
// last time, so we don't need to produce it again now.
|
||||
@@ -1224,79 +1204,6 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Analyze a requested part file.
|
||||
if (_requestedParts.isNotEmpty) {
|
||||
String path = _requestedParts.keys.first;
|
||||
try {
|
||||
var result = await _computeAnalysisResult(path,
|
||||
withUnit: true, asIsIfPartWithoutLibrary: true);
|
||||
result!;
|
||||
// Notify the completers.
|
||||
for (var completer in _requestedParts.remove(path)!) {
|
||||
completer.complete(result.unitResult!);
|
||||
}
|
||||
// Remove from to be analyzed and produce it now.
|
||||
_partsToAnalyze.remove(path);
|
||||
_resultController.add(result.unitResult!);
|
||||
} catch (exception, stackTrace) {
|
||||
_reportException(path, exception, stackTrace);
|
||||
_partsToAnalyze.remove(path);
|
||||
for (var completer in _requestedParts.remove(path)!) {
|
||||
completer.completeError(exception, stackTrace);
|
||||
}
|
||||
_clearLibraryContextAfterException();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Analyze a general part.
|
||||
if (_partsToAnalyze.isNotEmpty) {
|
||||
String path = _partsToAnalyze.first;
|
||||
_partsToAnalyze.remove(path);
|
||||
try {
|
||||
var withUnit = _priorityFiles.contains(path);
|
||||
if (withUnit) {
|
||||
var result = await _computeAnalysisResult(path,
|
||||
withUnit: true, asIsIfPartWithoutLibrary: true);
|
||||
_resultController.add(result!.unitResult!);
|
||||
} else {
|
||||
var result = await _computeAnalysisResult(path,
|
||||
withUnit: false, asIsIfPartWithoutLibrary: true);
|
||||
_resultController.add(result!.errorsResult!);
|
||||
}
|
||||
} catch (exception, stackTrace) {
|
||||
_reportException(path, exception, stackTrace);
|
||||
_clearLibraryContextAfterException();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Process a unit element request for a part.
|
||||
if (_unitElementRequestedParts.isNotEmpty) {
|
||||
String path = _unitElementRequestedParts.keys.first;
|
||||
var result =
|
||||
await _computeUnitElement(path, asIsIfPartWithoutLibrary: true);
|
||||
result!;
|
||||
for (var completer in _unitElementRequestedParts.remove(path)!) {
|
||||
completer.complete(result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute errors in a part.
|
||||
if (_errorsRequestedParts.isNotEmpty) {
|
||||
var path = _errorsRequestedParts.keys.first;
|
||||
var completers = _errorsRequestedParts.remove(path)!;
|
||||
var result = await _computeErrors(
|
||||
path: path,
|
||||
asIsIfPartWithoutLibrary: true,
|
||||
);
|
||||
for (var completer in completers) {
|
||||
completer.complete(result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the file with the given [path] from the list of files to analyze.
|
||||
@@ -1496,24 +1403,16 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
});
|
||||
}
|
||||
|
||||
Future<ErrorsResult?> _computeErrors({
|
||||
Future<SomeErrorsResult?> _computeErrors({
|
||||
required String path,
|
||||
required bool asIsIfPartWithoutLibrary,
|
||||
}) async {
|
||||
var analysisResult = await _computeAnalysisResult(path,
|
||||
withUnit: false, asIsIfPartWithoutLibrary: asIsIfPartWithoutLibrary);
|
||||
|
||||
if (analysisResult == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return analysisResult.errorsResult;
|
||||
var analysisResult = await _computeAnalysisResult(path, withUnit: false);
|
||||
return analysisResult?.errorsResult;
|
||||
}
|
||||
|
||||
Future<AnalysisDriverUnitIndex> _computeIndex(String path) async {
|
||||
var analysisResult = await _computeAnalysisResult(path,
|
||||
withUnit: false, asIsIfPartWithoutLibrary: true);
|
||||
return analysisResult!._index!;
|
||||
Future<AnalysisDriverUnitIndex?> _computeIndex(String path) async {
|
||||
var analysisResult = await _computeAnalysisResult(path, withUnit: false);
|
||||
return analysisResult?._index;
|
||||
}
|
||||
|
||||
/// Return the newly computed resolution result of the library with the
|
||||
@@ -1646,6 +1545,11 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
/// The current workaround for this is to discover `dart:core` before any
|
||||
/// analysis.
|
||||
void _discoverDartCore() {
|
||||
if (_hasDartCoreDiscovered) {
|
||||
return;
|
||||
}
|
||||
_hasDartCoreDiscovered = true;
|
||||
|
||||
_fsState.getFileForUri(Uri.parse('dart:core')).map(
|
||||
(file) {
|
||||
file?.transitiveFiles;
|
||||
@@ -1654,6 +1558,17 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
);
|
||||
}
|
||||
|
||||
void _discoverLibraries() {
|
||||
if (_hasLibrariesDiscovered) {
|
||||
return;
|
||||
}
|
||||
_hasLibrariesDiscovered = true;
|
||||
|
||||
for (final path in _fileTracker.addedFiles) {
|
||||
_fsState.getFileForPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
void _fillSalt() {
|
||||
_fillSaltForUnlinked();
|
||||
_fillSaltForElements();
|
||||
|
||||
@@ -139,6 +139,15 @@ class ParseStringResultImpl implements ParseStringResult {
|
||||
LineInfo get lineInfo => unit.lineInfo;
|
||||
}
|
||||
|
||||
class PartWithoutLibraryResultImpl implements PartWithoutLibraryResult {
|
||||
@override
|
||||
final String path;
|
||||
|
||||
PartWithoutLibraryResultImpl({
|
||||
required this.path,
|
||||
});
|
||||
}
|
||||
|
||||
class ResolvedForCompletionResultImpl {
|
||||
final AnalysisSession analysisSession;
|
||||
final String path;
|
||||
|
||||
@@ -6019,6 +6019,7 @@ CompileTimeErrorCode:
|
||||
implicitly uses the same version as the defining compilation unit:
|
||||
|
||||
```dart
|
||||
%uri="lib/part.dart"
|
||||
part of 'test.dart';
|
||||
```
|
||||
|
||||
@@ -10939,6 +10940,7 @@ CompileTimeErrorCode:
|
||||
by URI:
|
||||
|
||||
```dart
|
||||
%uri="lib/part_file.dart"
|
||||
part of 'test.dart';
|
||||
```
|
||||
POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT:
|
||||
|
||||
@@ -270,15 +270,20 @@ const a = 1;
|
||||
}
|
||||
|
||||
test_annotation_onDirective_partOf() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
final a = newFile('$testPackageLibPath/a.dart', r'''
|
||||
part 'test.dart';
|
||||
''');
|
||||
|
||||
addTestFile(r'''
|
||||
@a
|
||||
part of 'a.dart';
|
||||
|
||||
const a = 1;
|
||||
''');
|
||||
|
||||
// Make sure that the part knows its library.
|
||||
contextFor(a.path).currentSession.getParsedUnit(a.path);
|
||||
|
||||
await resolveTestFile();
|
||||
|
||||
var directive = findNode.partOf('a.dart');
|
||||
|
||||
@@ -2734,21 +2734,15 @@ Future<int> f;
|
||||
}
|
||||
|
||||
test_part_getResult_noLibrary() async {
|
||||
var c = convertPath('/test/lib/c.dart');
|
||||
newFile(c, r'''
|
||||
final c = newFile('/test/lib/c.dart', r'''
|
||||
part of a;
|
||||
class C {}
|
||||
var a = new A();
|
||||
var b = new B();
|
||||
''');
|
||||
|
||||
driver.addFile(c);
|
||||
|
||||
// There is no library which c.dart is a part of, so it has unresolved
|
||||
// A and B references.
|
||||
ResolvedUnitResult result = await driver.getResultValid(c);
|
||||
expect(result.errors, isNotEmpty);
|
||||
expect(result.unit, isNotNull);
|
||||
// There is no library which c.dart is a part of, so invalid result.
|
||||
final result = await driver.getResult(c.path);
|
||||
result as PartWithoutLibraryResult;
|
||||
expect(result.path, c.path);
|
||||
}
|
||||
|
||||
test_part_getUnitElement_afterLibrary() async {
|
||||
@@ -2829,28 +2823,14 @@ var b = new B();
|
||||
}
|
||||
|
||||
test_part_getUnitElement_noLibrary() async {
|
||||
var c = convertPath('/test/lib/c.dart');
|
||||
newFile(c, r'''
|
||||
final c = newFile('/test/lib/c.dart', r'''
|
||||
part of a;
|
||||
var a = new A();
|
||||
var b = new B();
|
||||
''');
|
||||
|
||||
driver.addFile(c);
|
||||
|
||||
// We don't know the library of c.dart, but we should get a result.
|
||||
// The types "A" and "B" are unresolved.
|
||||
{
|
||||
var result = await driver.getUnitElement(c);
|
||||
result as UnitElementResult;
|
||||
var partUnit = result.element;
|
||||
|
||||
expect(partUnit.topLevelVariables[0].name, 'a');
|
||||
assertType(partUnit.topLevelVariables[0].type, 'dynamic');
|
||||
|
||||
expect(partUnit.topLevelVariables[1].name, 'b');
|
||||
assertType(partUnit.topLevelVariables[1].type, 'dynamic');
|
||||
}
|
||||
// We don't know the library of c.dart, so invalid result.
|
||||
var result = await driver.getUnitElement(c.path);
|
||||
result as PartWithoutLibraryResult;
|
||||
expect(result.path, c.path);
|
||||
}
|
||||
|
||||
test_part_results_afterLibrary() async {
|
||||
@@ -2889,15 +2869,16 @@ var b = new B();
|
||||
|
||||
// Update a.dart so that c.dart is not a part.
|
||||
{
|
||||
allResults.clear();
|
||||
|
||||
modifyFile(a, '// does not use c.dart anymore');
|
||||
driver.changeFile(a);
|
||||
await waitForIdleWithoutExceptions();
|
||||
|
||||
// Now c.dart does not have a library context, so A and B cannot be
|
||||
// resolved, so there are errors.
|
||||
var result =
|
||||
allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
|
||||
expect(result.errors, isNotEmpty);
|
||||
// Now c.dart does not know the library, so invalid result.
|
||||
allResults
|
||||
.whereType<PartWithoutLibraryResult>()
|
||||
.lastWhere((r) => r.path == c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2949,11 +2930,29 @@ var b = new B();
|
||||
|
||||
await waitForIdleWithoutExceptions();
|
||||
|
||||
// There is no library which c.dart is a part of, so it has unresolved
|
||||
// A and B references.
|
||||
var result =
|
||||
allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
|
||||
expect(result.errors, isNotEmpty);
|
||||
// We don't know the library for `c.dart`, so report an invalid result.
|
||||
allResults
|
||||
.whereType<PartWithoutLibraryResult>()
|
||||
.lastWhere((result) => result.path == c);
|
||||
}
|
||||
|
||||
test_part_results_noLibrary_priority() async {
|
||||
var c = newFile('/test/lib/c.dart', r'''
|
||||
part of a;
|
||||
class C {}
|
||||
var a = new A();
|
||||
var b = new B();
|
||||
''');
|
||||
|
||||
driver.addFile(c.path);
|
||||
driver.priorityFiles = [c.path];
|
||||
|
||||
await waitForIdleWithoutExceptions();
|
||||
|
||||
// We don't know the library for `c.dart`, so report an invalid result.
|
||||
allResults
|
||||
.whereType<PartWithoutLibraryResult>()
|
||||
.lastWhere((result) => result.path == c.path);
|
||||
}
|
||||
|
||||
test_part_results_priority_beforeLibrary() async {
|
||||
|
||||
@@ -2526,24 +2526,6 @@ class A {}
|
||||
expect(c.id, endsWith('c.dart;C'));
|
||||
}
|
||||
|
||||
test_subtypes_class_partWithoutLibrary() async {
|
||||
await resolveTestCode('''
|
||||
part of lib;
|
||||
|
||||
class A {}
|
||||
class B extends A {}
|
||||
''');
|
||||
var a = findElement.class_('A');
|
||||
|
||||
List<SubtypeResult> subtypes =
|
||||
await driver.search.subtypes(SearchedFiles(), type: a);
|
||||
expect(subtypes, hasLength(1));
|
||||
|
||||
SubtypeResult b = subtypes.singleWhere((r) => r.name == 'B');
|
||||
expect(b.libraryUri, testUriStr);
|
||||
expect(b.id, '$testUriStr;$testUriStr;B');
|
||||
}
|
||||
|
||||
test_subtypes_enum() async {
|
||||
await resolveTestCode('''
|
||||
class A {}
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
// 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/src/dart/error/hint_codes.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
import 'sdk_constraint_verifier_support.dart';
|
||||
|
||||
main() {
|
||||
@@ -49,14 +52,31 @@ Future<int> zero() async => 0;
|
||||
}
|
||||
|
||||
test_equals_implicitImportOfCore_inPart() async {
|
||||
newFile('/lib.dart', '''
|
||||
writeTestPackagePubspecYamlFile(
|
||||
PubspecYamlFileConfig(
|
||||
sdkVersion: '>=2.1.0',
|
||||
),
|
||||
);
|
||||
|
||||
final lib = newFile('$testPackageLibPath/lib.dart', '''
|
||||
library lib;
|
||||
|
||||
part 'a.dart';
|
||||
''');
|
||||
await verifyVersion('2.1.0', '''
|
||||
|
||||
final a = newFile('$testPackageLibPath/a.dart', r'''
|
||||
part of lib;
|
||||
|
||||
Future<int> zero() async => 0;
|
||||
''');
|
||||
|
||||
final analysisSession = contextFor(lib.path).currentSession;
|
||||
final resolvedLibrary = await analysisSession.getResolvedLibrary(lib.path);
|
||||
resolvedLibrary as ResolvedLibraryResult;
|
||||
|
||||
final resolvedPart = resolvedLibrary.units.last;
|
||||
expect(resolvedPart.path, a.path);
|
||||
assertErrorsInList(resolvedPart.errors, []);
|
||||
}
|
||||
|
||||
test_lessThan_explicitImportOfAsync() async {
|
||||
@@ -97,14 +117,31 @@ Future<int> zero() async => 0;
|
||||
}
|
||||
|
||||
test_lessThan_implicitImportOfCore_inPart() async {
|
||||
newFile('/lib.dart', '''
|
||||
writeTestPackagePubspecYamlFile(
|
||||
PubspecYamlFileConfig(
|
||||
sdkVersion: '>=2.0.0',
|
||||
),
|
||||
);
|
||||
|
||||
final lib = newFile('$testPackageLibPath/lib.dart', '''
|
||||
library lib;
|
||||
|
||||
part 'a.dart';
|
||||
''');
|
||||
await verifyVersion('2.0.0', '''
|
||||
|
||||
final a = newFile('$testPackageLibPath/a.dart', r'''
|
||||
part of lib;
|
||||
|
||||
Future<int> zero() async => 0;
|
||||
''', expectedErrors: [
|
||||
''');
|
||||
|
||||
final analysisSession = contextFor(lib.path).currentSession;
|
||||
final resolvedLibrary = await analysisSession.getResolvedLibrary(lib.path);
|
||||
resolvedLibrary as ResolvedLibraryResult;
|
||||
|
||||
final resolvedPart = resolvedLibrary.units.last;
|
||||
expect(resolvedPart.path, a.path);
|
||||
assertErrorsInList(resolvedPart.errors, [
|
||||
error(HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE, 14, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -3068,16 +3068,17 @@ void main() {C.^ print("something");}''');
|
||||
int T1;
|
||||
F1() { }
|
||||
class X {X.c(); X._d(); z() {}}''');
|
||||
addSource('/home/test/lib/a.dart', '''
|
||||
final a = newFile('/home/test/lib/a.dart', '''
|
||||
library libA;
|
||||
import 'b.dart';
|
||||
part "$testFile";
|
||||
part 'test.dart';
|
||||
class A { }
|
||||
var m;''');
|
||||
addTestSource('''
|
||||
part of libA;
|
||||
class B { B.bar(int x); }
|
||||
main() {new ^}''');
|
||||
await resolveFile(a.path);
|
||||
await computeSuggestions();
|
||||
expect(replacementOffset, completionOffset);
|
||||
expect(replacementLength, 0);
|
||||
|
||||
@@ -5730,10 +5730,9 @@ int f2(int i2) => (i2)/*!*/;
|
||||
Future<void> test_part_metadata() async {
|
||||
var pathContext = resourceProvider.pathContext;
|
||||
addSource(pathContext.join(pathContext.dirname(testFile), 'part.dart'), '''
|
||||
part of test;
|
||||
part of 'test.dart';
|
||||
''');
|
||||
await analyze('''
|
||||
library test;
|
||||
@deprecated
|
||||
part 'part.dart';
|
||||
''');
|
||||
@@ -5744,10 +5743,13 @@ part 'part.dart';
|
||||
Future<void> test_part_of_identifier() async {
|
||||
var pathContext = resourceProvider.pathContext;
|
||||
var testFileName = pathContext.basename(testFile);
|
||||
addSource(pathContext.join(pathContext.dirname(testFile), 'lib.dart'), '''
|
||||
var libPath = pathContext.join(pathContext.dirname(testFile), 'lib.dart');
|
||||
addSource(libPath, '''
|
||||
library test;
|
||||
part '$testFileName';
|
||||
''');
|
||||
// Discover the library for the part.
|
||||
session.getParsedUnit(libPath);
|
||||
await analyze('''
|
||||
part of test;
|
||||
''');
|
||||
@@ -5758,13 +5760,16 @@ part of test;
|
||||
Future<void> test_part_of_metadata() async {
|
||||
var pathContext = resourceProvider.pathContext;
|
||||
var testFileName = pathContext.basename(testFile);
|
||||
addSource(pathContext.join(pathContext.dirname(testFile), 'lib.dart'), '''
|
||||
library test;
|
||||
var libPath = pathContext.join(pathContext.dirname(testFile), 'lib.dart');
|
||||
addSource(libPath, '''
|
||||
part '$testFileName';
|
||||
''');
|
||||
// TODO(scheglov) This should not be necessary, we use URI, so can find it.
|
||||
// Discover the library for the part.
|
||||
session.getParsedUnit(libPath);
|
||||
await analyze('''
|
||||
@deprecated
|
||||
part of test;
|
||||
part of 'lib.dart';
|
||||
''');
|
||||
// No assertions needed; the AnnotationTracker mixin verifies that the
|
||||
// metadata was visited.
|
||||
@@ -5773,9 +5778,13 @@ part of test;
|
||||
Future<void> test_part_of_path() async {
|
||||
var pathContext = resourceProvider.pathContext;
|
||||
var testFileName = pathContext.basename(testFile);
|
||||
addSource(pathContext.join(pathContext.dirname(testFile), 'lib.dart'), '''
|
||||
var libPath = pathContext.join(pathContext.dirname(testFile), 'lib.dart');
|
||||
addSource(libPath, '''
|
||||
part '$testFileName';
|
||||
''');
|
||||
// TODO(scheglov) This should not be necessary, we use URI, so can find it.
|
||||
// Discover the library for the part.
|
||||
session.getParsedUnit(libPath);
|
||||
await analyze('''
|
||||
part of 'lib.dart';
|
||||
''');
|
||||
|
||||
Reference in New Issue
Block a user