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:
Konstantin Shcheglov
2022-05-18 16:45:53 +00:00
committed by Commit Bot
parent 93f3065cac
commit e28972166c
18 changed files with 226 additions and 239 deletions
@@ -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();
@@ -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.
+79 -164
View File
@@ -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;
+2
View File
@@ -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);
+16 -7
View File
@@ -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';
''');