Version 2.19.0-4.0.dev
Merge commit '54b7f4b72a1701f8f9a0334c94ce6f59732bd261' into 'dev'
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index f6beb54..32a7b10 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -454,7 +454,7 @@
/// A helper that performs the context rebuild and waits for all watchers
/// to be fully initialized.
Future<void> performContextRebuild() async {
- _destroyAnalysisContexts();
+ await _destroyAnalysisContexts();
_fileContentCache.invalidateAll();
var watchers = <ResourceWatcher>[];
@@ -610,7 +610,6 @@
/// Clean up and destroy the context associated with the given folder.
void _destroyAnalysisContext(DriverBasedAnalysisContext context) {
- context.driver.dispose();
var rootFolder = context.contextRoot.root;
var watched = bazelWatchedPathsPerFolder.remove(rootFolder);
if (watched != null) {
@@ -623,15 +622,16 @@
driverMap.remove(rootFolder);
}
- void _destroyAnalysisContexts() {
- var collection = _collection;
+ Future<void> _destroyAnalysisContexts() async {
+ final collection = _collection;
if (collection != null) {
for (final subscription in watcherSubscriptions) {
- subscription.cancel();
+ await subscription.cancel();
}
- for (var analysisContext in collection.contexts) {
+ for (final analysisContext in collection.contexts) {
_destroyAnalysisContext(analysisContext);
}
+ await collection.dispose();
callbacks.afterContextsDestroyed();
}
}
diff --git a/pkg/analysis_server/test/analysis/set_priority_files_test.dart b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
index 6817bb5..5799297 100644
--- a/pkg/analysis_server/test/analysis/set_priority_files_test.dart
+++ b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
@@ -72,6 +72,7 @@
exclude:
- 'samples/**'
''');
+ await pumpEventQueue(times: 5000);
var file = newFile('$testPackageRootPath/samples/sample.dart', '');
// attempt to set priority file
await _setPriorityFile(file);
@@ -90,6 +91,7 @@
exclude:
- 'samples/**'
''');
+ await pumpEventQueue(times: 5000);
// attempt to set priority file
await _setPriorityFile(sampleFile);
_verifyPriorityFiles(sampleFile);
@@ -107,6 +109,7 @@
exclude:
- 'child/samples/**'
''');
+ await pumpEventQueue(times: 5000);
// attempt to set priority file
await _setPriorityFile(sampleFile);
_verifyPriorityFiles(sampleFile);
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index 1c94ed1..473113c 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -58,7 +58,7 @@
dart_package(null_safety = True)
''');
- await pumpEventQueue();
+ await pumpEventQueue(times: 5000);
await server.onAnalysisComplete;
// We have null safety enabled, so no errors.
diff --git a/pkg/analysis_server/test/edit/sort_members_test.dart b/pkg/analysis_server/test/edit/sort_members_test.dart
index 4d289c7..76318ea 100644
--- a/pkg/analysis_server/test/edit/sort_members_test.dart
+++ b/pkg/analysis_server/test/edit/sort_members_test.dart
@@ -203,10 +203,6 @@
}
Future<void> test_OK_genericFunctionType() async {
- newAnalysisOptionsYamlFile(testPackageRootPath, '''
-analyzer:
- strong-mode: true
-''');
addTestFile('''
class C {
void caller() {
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index 06ad142b..eadd2aa 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -262,11 +262,12 @@
// Send an edit request immediately after the refactor request.
final req1 = executeCodeAction(codeAction);
- await replaceFile(100, mainFileUri, 'new test content');
+ final req2 = replaceFile(100, mainFileUri, 'new test content');
// Expect the first to fail because of the modified content.
await expectLater(
req1, throwsA(isResponseError(ErrorCodes.ContentModified)));
+ await req2;
}
Future<void> test_filtersCorrectly() async {
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index d9acebe..fcf0e15 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -167,7 +167,7 @@
@override
Future sendNotificationToServer(NotificationMessage notification) async {
channel.sendNotificationToServer(notification);
- await pumpEventQueue();
+ await pumpEventQueue(times: 5000);
}
@override
diff --git a/pkg/analysis_server/test/services/completion/dart/location/directive_uri_test.dart b/pkg/analysis_server/test/services/completion/dart/location/directive_uri_test.dart
index 1c1ceb2..6a2db5b 100644
--- a/pkg/analysis_server/test/services/completion/dart/location/directive_uri_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/location/directive_uri_test.dart
@@ -4,6 +4,7 @@
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:analyzer_utilities/check/check.dart';
+import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../../client/completion_driver_test.dart';
@@ -59,6 +60,7 @@
required void Function(CompletionResponseForTesting response) validator,
}) async {
_configurePackagesFooBar();
+ await pumpEventQueue(times: 5000);
{
var response = await getTestCodeSuggestions('''
diff --git a/pkg/analyzer/lib/dart/constant/value.dart b/pkg/analyzer/lib/dart/constant/value.dart
index 12c83db..e396610 100644
--- a/pkg/analyzer/lib/dart/constant/value.dart
+++ b/pkg/analyzer/lib/dart/constant/value.dart
@@ -64,6 +64,9 @@
/// would return `false` from [hasKnownValue].
DartType? get type;
+ /// If this object is the value of a constant variable, the variable.
+ VariableElement? get variable;
+
/// Return a representation of the value of the field with the given [name].
///
/// Return `null` if either the object being represented does not have a field
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 57556ad..32454a3 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -525,6 +525,7 @@
///
/// Clients may not extend, implement or mix-in this class.
abstract class DirectiveUriWithAugmentation extends DirectiveUriWithSource {
+ /// The library augmentation referenced by the [source].
LibraryAugmentationElement get augmentation;
}
@@ -532,6 +533,7 @@
///
/// Clients may not extend, implement or mix-in this class.
abstract class DirectiveUriWithLibrary extends DirectiveUriWithSource {
+ /// The library referenced by the [source].
LibraryElement get library;
}
@@ -540,6 +542,7 @@
/// Clients may not extend, implement or mix-in this class.
abstract class DirectiveUriWithRelativeUri
extends DirectiveUriWithRelativeUriString {
+ /// The relative URI, parsed from [relativeUriString].
Uri get relativeUri;
}
@@ -547,6 +550,7 @@
///
/// Clients may not extend, implement or mix-in this class.
abstract class DirectiveUriWithRelativeUriString extends DirectiveUri {
+ /// The relative URI string specified in code.
String get relativeUriString;
}
@@ -554,6 +558,7 @@
///
/// Clients may not extend, implement or mix-in this class.
abstract class DirectiveUriWithSource extends DirectiveUriWithRelativeUri {
+ /// The result of resolving [relativeUri] against the enclosing URI.
Source get source;
}
@@ -561,6 +566,7 @@
///
/// Clients may not extend, implement or mix-in this class.
abstract class DirectiveUriWithUnit extends DirectiveUriWithSource {
+ /// The unit referenced by the [source].
CompilationUnitElement get unit;
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
index fd8131d..c7cfdc0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
@@ -140,16 +140,16 @@
throw StateError('Unable to find the context to $path');
}
- void dispose({
+ Future<void> dispose({
bool forTesting = false,
- }) {
- for (var analysisContext in contexts) {
- analysisContext.driver.dispose();
+ }) async {
+ for (final analysisContext in contexts) {
+ await analysisContext.driver.dispose2();
}
- macroExecutor.close();
+ await macroExecutor.close();
// If there are other collections, they will have to start it again.
if (!forTesting) {
- KernelCompilationService.dispose();
+ await KernelCompilationService.dispose();
}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 6a3129d..fde98ef 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -85,7 +85,7 @@
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
- static const int DATA_VERSION = 232;
+ static const int DATA_VERSION = 234;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
@@ -197,6 +197,10 @@
final _unitElementRequestedFiles =
<String, List<Completer<SomeUnitElementResult>>>{};
+ /// The list of dispose requests, added in [dispose2], almost always empty.
+ /// We expect that at most one is added, at the very end of the life cycle.
+ final List<Completer<void>> _disposeRequests = [];
+
/// The controller for the [results] stream.
final _resultController = StreamController<Object>();
@@ -397,6 +401,9 @@
@override
AnalysisDriverPriority get workPriority {
+ if (_disposeRequests.isNotEmpty) {
+ return AnalysisDriverPriority.interactive;
+ }
if (_resolveForCompletionRequests.isNotEmpty) {
return AnalysisDriverPriority.completion;
}
@@ -581,12 +588,21 @@
return _discoverAvailableFilesTask!.completer.future;
}
+ @Deprecated('Use dispose2() instead')
@override
void dispose() {
_scheduler.remove(this);
clearLibraryContext();
}
+ @override
+ Future<void> dispose2() async {
+ final completer = Completer<void>();
+ _disposeRequests.add(completer);
+ _scheduler.notify(this);
+ return completer.future;
+ }
+
/// Return the cached [ResolvedUnitResult] for the Dart file with the given
/// [path]. If there is no cached result, return `null`. Usually only results
/// of priority files are cached.
@@ -1649,6 +1665,17 @@
return _resourceProvider.pathContext.isAbsolute(path);
}
+ Future<void> _maybeDispose() async {
+ if (_disposeRequests.isNotEmpty) {
+ _scheduler.remove(this);
+ clearLibraryContext();
+
+ for (final completer in _disposeRequests.toList()) {
+ completer.complete();
+ }
+ }
+ }
+
/// We detected that one of the required `dart` libraries is missing.
/// Return the empty analysis result with the error.
AnalysisResult _newMissingDartLibraryResult(
@@ -1908,8 +1935,12 @@
void addFile(String path);
/// Notify the driver that the client is going to stop using it.
+ @Deprecated('Use dispose2() instead')
void dispose();
+ /// Notify the driver that the client is going to stop using it.
+ Future<void> dispose2();
+
/// Perform a single chunk of work and produce [results].
Future<void> performWork();
}
@@ -2055,6 +2086,12 @@
await _hasWork.signal;
+ for (final driver in _drivers.toList()) {
+ if (driver is AnalysisDriver) {
+ await driver._maybeDispose();
+ }
+ }
+
for (var driver in _drivers) {
if (driver is AnalysisDriver) {
driver._applyPendingFileChanges();
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index f370099..2fcc9f2 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -952,6 +952,8 @@
} else if (directive is AugmentationImportDirectiveImpl) {
augmentations.add(
UnlinkedImportAugmentationDirective(
+ augmentKeywordOffset: directive.augmentKeyword.offset,
+ importKeywordOffset: directive.importKeyword.offset,
uri: directive.uri.stringValue,
),
);
@@ -966,6 +968,8 @@
final uriStr = uri.stringValue;
if (uriStr != null) {
libraryAugmentationDirective = UnlinkedLibraryAugmentationDirective(
+ augmentKeywordOffset: directive.augmentKeyword.offset,
+ libraryKeywordOffset: directive.libraryKeyword.offset,
uri: uriStr,
uriRange: UnlinkedSourceRange(
offset: uri.offset,
@@ -1831,29 +1835,14 @@
file._fsState._libraryNameToFiles.add(this);
}
- /// The list of files that this library consists of, i.e. this library file
- /// itself, its [parts], and augmentations.
- List<FileState> get files {
- final files = [
- file,
- ];
+ /// All augmentations referenced by this library, in the depth-first
+ /// pre-order traversal order.
+ List<AugmentationFileStateKind> get allAugmentations {
+ final result = <AugmentationFileStateKind>[];
- // TODO(scheglov) When we include only valid parts, use this instead.
- final includeOnlyValidParts = 0 > 1;
- for (final part in parts) {
- if (part is PartDirectiveWithFile) {
- if (includeOnlyValidParts) {
- files.addIfNotNull(part.includedPart?.file);
- } else {
- files.add(part.includedFile);
- }
- }
- }
-
- // TODO(scheglov) Test how augmentations affect signatures.
void visitAugmentations(LibraryOrAugmentationFileKind kind) {
if (kind is AugmentationFileStateKind) {
- files.add(kind.file);
+ result.add(kind);
}
for (final import in kind.augmentations) {
if (import is ImportAugmentationDirectiveWithFile) {
@@ -1866,6 +1855,23 @@
}
visitAugmentations(this);
+ return result;
+ }
+
+ /// The list of files that this library consists of, i.e. this library file
+ /// itself, its [parts], and augmentations.
+ List<FileState> get files {
+ final files = [
+ file,
+ ];
+
+ for (final part in parts) {
+ if (part is PartDirectiveWithFile) {
+ files.addIfNotNull(part.includedPart?.file);
+ }
+ }
+
+ files.addAll(allAugmentations.map((e) => e.file));
return files;
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
index 1cfb843..40aacde 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
@@ -139,16 +139,19 @@
@override
List<_LibraryNode> computeDependencies() {
- final referencedLibraries = {
- ...kind.imports
- .whereType<ImportDirectiveWithFile>()
- .map((import) => import.importedLibrary)
- .whereNotNull(),
- ...kind.exports
- .whereType<ExportDirectiveWithFile>()
- .map((export) => export.exportedLibrary)
- .whereNotNull(),
- };
+ final referencedLibraries = {kind, ...kind.allAugmentations}
+ .map((container) => [
+ ...container.imports
+ .whereType<ImportDirectiveWithFile>()
+ .map((import) => import.importedLibrary),
+ ...container.exports
+ .whereType<ExportDirectiveWithFile>()
+ .map((export) => export.exportedLibrary),
+ ])
+ .expand((libraries) => libraries)
+ .whereNotNull()
+ .toSet();
+
return referencedLibraries.map(walker.getNode).toList();
}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart b/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
index b487c95..021d3e7 100644
--- a/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
@@ -161,9 +161,13 @@
}
class UnlinkedImportAugmentationDirective {
+ final int augmentKeywordOffset;
+ final int importKeywordOffset;
final String? uri;
UnlinkedImportAugmentationDirective({
+ required this.augmentKeywordOffset,
+ required this.importKeywordOffset,
required this.uri,
});
@@ -171,11 +175,15 @@
SummaryDataReader reader,
) {
return UnlinkedImportAugmentationDirective(
+ augmentKeywordOffset: reader.readUInt30(),
+ importKeywordOffset: reader.readUInt30(),
uri: reader.readOptionalStringUtf8(),
);
}
void write(BufferedSink sink) {
+ sink.writeUInt30(augmentKeywordOffset);
+ sink.writeUInt30(importKeywordOffset);
sink.writeOptionalStringUtf8(uri);
}
}
@@ -264,10 +272,14 @@
}
class UnlinkedLibraryAugmentationDirective {
+ final int augmentKeywordOffset;
+ final int libraryKeywordOffset;
final String? uri;
final UnlinkedSourceRange uriRange;
UnlinkedLibraryAugmentationDirective({
+ required this.augmentKeywordOffset,
+ required this.libraryKeywordOffset,
required this.uri,
required this.uriRange,
});
@@ -276,12 +288,16 @@
SummaryDataReader reader,
) {
return UnlinkedLibraryAugmentationDirective(
+ augmentKeywordOffset: reader.readUInt30(),
+ libraryKeywordOffset: reader.readUInt30(),
uri: reader.readOptionalStringUtf8(),
uriRange: UnlinkedSourceRange.read(reader),
);
}
void write(BufferedSink sink) {
+ sink.writeUInt30(augmentKeywordOffset);
+ sink.writeUInt30(libraryKeywordOffset);
sink.writeOptionalStringUtf8(uri);
uriRange.write(sink);
}
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 4621e73..5b205c4 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -107,6 +107,9 @@
constantInitializer,
[dartObject.type, constant.type]);
}
+
+ // Associate with the variable.
+ dartObject = DartObjectImpl.forVariable(dartObject, constant);
}
if (dartObject != null) {
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index 04506a4..dabfac8 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -159,8 +159,18 @@
/// The state of the object.
final InstanceState _state;
+ @override
+ final VariableElement? variable;
+
/// Initialize a newly created object to have the given [type] and [_state].
- DartObjectImpl(this._typeSystem, this.type, this._state);
+ DartObjectImpl(this._typeSystem, this.type, this._state, {this.variable});
+
+ /// Creates a duplicate instance of [other], tied to [variable].
+ factory DartObjectImpl.forVariable(
+ DartObjectImpl other, VariableElement variable) {
+ return DartObjectImpl(other._typeSystem, other.type, other._state,
+ variable: variable);
+ }
/// Create an object to represent an unknown value.
factory DartObjectImpl.validWithUnknownValue(
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 4c718a3..cbe272d 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3920,7 +3920,7 @@
@override
final LibraryOrAugmentationElementImpl augmented;
- LibraryElementLinkedData? linkedData;
+ LibraryAugmentationElementLinkedData? linkedData;
LibraryAugmentationElementImpl({
required this.augmented,
@@ -3932,6 +3932,12 @@
List<ExtensionElement> get accessibleExtensions => throw UnimplementedError();
@override
+ List<AugmentationImportElement> get augmentationImports {
+ linkedData?.read(this);
+ return super.augmentationImports;
+ }
+
+ @override
List<ExportElement2> get exports2 {
linkedData?.read(this);
return _exports2;
@@ -4043,6 +4049,12 @@
List<ExtensionElement> get accessibleExtensions => scope.extensions;
@override
+ List<AugmentationImportElement> get augmentationImports {
+ linkedData?.read(this);
+ return super.augmentationImports;
+ }
+
+ @override
CompilationUnitElementImpl get enclosingUnit {
return _definingCompilationUnit;
}
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index f0c804e..841cead 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -350,10 +350,55 @@
}
}
-class LibraryElementLinkedData extends ElementLinkedData<LibraryElementImpl> {
+class LibraryAugmentationElementLinkedData
+ extends LibraryOrAugmentationElementLinkedData<
+ LibraryAugmentationElementImpl> {
+ LibraryAugmentationElementLinkedData({
+ required super.reference,
+ required super.libraryReader,
+ required super.unitElement,
+ required super.offset,
+ });
+
+ @override
+ void read(ElementImpl element) {
+ final libraryData = element.library?.linkedData;
+ if (libraryData != null && !libraryData._isLocked) {
+ super.read(element);
+ }
+ }
+}
+
+class LibraryElementLinkedData
+ extends LibraryOrAugmentationElementLinkedData<LibraryElementImpl> {
+ LibraryElementLinkedData({
+ required super.reference,
+ required super.libraryReader,
+ required super.unitElement,
+ required super.offset,
+ });
+
+ @override
+ void _readAdditional(element, reader) {
+ for (final part in element.parts2) {
+ part as PartElementImpl;
+ part.metadata = reader._readAnnotationList(
+ unitElement: unitElement,
+ );
+ }
+
+ element.entryPoint = reader.readElement() as FunctionElement?;
+ }
+}
+
+class LibraryOrAugmentationElementLinkedData<
+ E extends LibraryOrAugmentationElementImpl> extends ElementLinkedData<E> {
ApplyConstantOffsets? applyConstantOffsets;
- LibraryElementLinkedData({
+ /// When we are applying offsets to a library, we want to lock it.
+ bool _isLocked = false;
+
+ LibraryOrAugmentationElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
required CompilationUnitElementImpl unitElement,
@@ -364,6 +409,23 @@
return _libraryReader._elementFactory;
}
+ void lock() {
+ assert(!_isLocked);
+ _isLocked = true;
+ }
+
+ @override
+ void read(ElementImpl element) {
+ if (!_isLocked) {
+ super.read(element);
+ }
+ }
+
+ void unlock() {
+ assert(_isLocked);
+ _isLocked = false;
+ }
+
@override
void _read(element, reader) {
element.metadata = reader._readAnnotationList(
@@ -392,17 +454,14 @@
}
}
- for (final part in element.parts2) {
- part as PartElementImpl;
- part.metadata = reader._readAnnotationList(
- unitElement: unitElement,
- );
- }
+ // TODO(scheglov) metadata on augmentation imports
- element.entryPoint = reader.readElement() as FunctionElement?;
+ _readAdditional(element, reader);
applyConstantOffsets?.perform();
}
+
+ void _readAdditional(E element, ResolutionReader reader) {}
}
class LibraryReader {
@@ -451,33 +510,11 @@
libraryElement.reference = _reference;
libraryElement.languageVersion = _readLanguageVersion();
- libraryElement.imports2 = _reader.readTypedList(() {
- return _readImportElement(
- libraryElement: libraryElement,
- );
- });
- libraryElement.exports2 = _reader.readTypedList(() {
- return _readExportElement(
- libraryElement: libraryElement,
- );
- });
- libraryElement.augmentationImports = _reader.readTypedList(() {
- return _readAugmentationImportElement(
- libraryElement: libraryElement,
- );
- });
+ _readLibraryOrAugmentationElement(libraryElement);
LibraryElementFlags.read(_reader, libraryElement);
- for (final import in libraryElement.imports2) {
- final prefixElement = import.prefix?.element;
- if (prefixElement is PrefixElementImpl) {
- libraryElement.encloseElement(prefixElement);
- }
- }
-
libraryElement.definingCompilationUnit = _readUnitElement(
- libraryElement: libraryElement,
- librarySource: librarySource,
+ containerSource: librarySource,
unitSource: librarySource,
);
@@ -516,12 +553,10 @@
LibraryAugmentationElementImpl _readAugmentationElement({
required LibraryOrAugmentationElementImpl augmented,
- required LibraryElementImpl libraryElement,
required Source unitSource,
}) {
final definingUnit = _readUnitElement(
- libraryElement: libraryElement,
- librarySource: unitSource,
+ containerSource: unitSource,
unitSource: unitSource,
);
@@ -531,14 +566,24 @@
);
augmentation.definingCompilationUnit = definingUnit;
+ final resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
+ _readLibraryOrAugmentationElement(augmentation);
+
+ augmentation.linkedData = LibraryAugmentationElementLinkedData(
+ reference: _reference,
+ libraryReader: this,
+ unitElement: definingUnit,
+ offset: resolutionOffset,
+ );
+
return augmentation;
}
AugmentationImportElementImpl _readAugmentationImportElement({
- required LibraryElementImpl libraryElement,
+ required LibraryOrAugmentationElementImpl container,
}) {
final uri = _readDirectiveUri(
- libraryElement: libraryElement,
+ container: container,
);
return AugmentationImportElementImpl(
importKeywordOffset: -1, // TODO(scheglov) implement, test
@@ -635,7 +680,7 @@
}
DirectiveUri _readDirectiveUri({
- required LibraryElementImpl libraryElement,
+ required LibraryOrAugmentationElementImpl container,
}) {
DirectiveUriWithRelativeUriStringImpl readWithRelativeUriString() {
final relativeUriString = _reader.readStringReference();
@@ -679,8 +724,7 @@
case DirectiveUriKind.withAugmentation:
final parent = readWithSource();
final augmentation = _readAugmentationElement(
- augmented: libraryElement,
- libraryElement: libraryElement,
+ augmented: container,
unitSource: parent.source,
);
return DirectiveUriWithAugmentationImpl(
@@ -699,8 +743,7 @@
case DirectiveUriKind.withUnit:
final parent = readWithSource();
final unitElement = _readUnitElement(
- libraryElement: libraryElement,
- librarySource: libraryElement.source,
+ containerSource: container.source,
unitSource: parent.source,
);
return DirectiveUriWithUnitImpl(
@@ -786,10 +829,10 @@
}
ExportElement2Impl _readExportElement({
- required LibraryElementImpl libraryElement,
+ required LibraryOrAugmentationElementImpl container,
}) {
final uri = _readDirectiveUri(
- libraryElement: libraryElement,
+ container: container,
);
// TODO(scheglov) pass to the constructor
final combinators = _reader.readTypedList(_readNamespaceCombinator);
@@ -941,10 +984,10 @@
}
ImportElement2Impl _readImportElement({
- required LibraryElementImpl libraryElement,
+ required LibraryOrAugmentationElementImpl container,
}) {
final uri = _readDirectiveUri(
- libraryElement: libraryElement,
+ container: container,
);
final prefix = _readImportElementPrefix();
final combinators = _reader.readTypedList(_readNamespaceCombinator);
@@ -1002,6 +1045,35 @@
return LibraryLanguageVersion(package: package, override: override);
}
+ void _readLibraryOrAugmentationElement(
+ LibraryOrAugmentationElementImpl container,
+ ) {
+ container.imports2 = _reader.readTypedList(() {
+ return _readImportElement(
+ container: container,
+ );
+ });
+
+ container.exports2 = _reader.readTypedList(() {
+ return _readExportElement(
+ container: container,
+ );
+ });
+
+ container.augmentationImports = _reader.readTypedList(() {
+ return _readAugmentationImportElement(
+ container: container,
+ );
+ });
+
+ for (final import in container.imports2) {
+ final prefixElement = import.prefix?.element;
+ if (prefixElement is PrefixElementImpl) {
+ container.encloseElement(prefixElement);
+ }
+ }
+ }
+
List<MethodElementImpl> _readMethods(
CompilationUnitElementImpl unitElement,
ElementImpl enclosingElement,
@@ -1160,7 +1232,7 @@
required LibraryElementImpl libraryElement,
}) {
final uri = _readDirectiveUri(
- libraryElement: libraryElement,
+ container: libraryElement,
);
return PartElementImpl(
@@ -1383,15 +1455,14 @@
}
CompilationUnitElementImpl _readUnitElement({
- required LibraryElementImpl libraryElement,
- required Source librarySource,
+ required Source containerSource,
required Source unitSource,
}) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
var unitElement = CompilationUnitElementImpl(
source: unitSource,
- librarySource: librarySource,
+ librarySource: containerSource,
lineInfo: LineInfo([0]),
);
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index c8b469e..43a2151 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -101,13 +101,7 @@
_sink._writeStringReference(libraryElement.name);
_writeFeatureSet(libraryElement.featureSet);
_writeLanguageVersion(libraryElement.languageVersion);
- _resolutionSink._writeAnnotationList(libraryElement.metadata);
- _writeList(libraryElement.imports2, _writeImportElement);
- _writeList(libraryElement.exports2, _writeExportElement);
- _writeList(
- libraryElement.augmentationImports,
- _writeAugmentationImportElement,
- );
+ _writeLibraryOrAugmentationElement(libraryElement);
for (final partElement in libraryElement.parts2) {
_resolutionSink._writeAnnotationList(partElement.metadata);
}
@@ -130,6 +124,8 @@
void _writeAugmentationElement(LibraryAugmentationElement augmentation) {
augmentation as LibraryAugmentationElementImpl;
_writeUnitElement(augmentation.definingCompilationUnit);
+ _sink.writeUInt30(_resolutionSink.offset);
+ _writeLibraryOrAugmentationElement(augmentation);
}
void _writeAugmentationImportElement(AugmentationImportElement element) {
@@ -371,6 +367,18 @@
}
}
+ void _writeLibraryOrAugmentationElement(
+ LibraryOrAugmentationElementImpl container,
+ ) {
+ _resolutionSink._writeAnnotationList(container.metadata);
+ _writeList(container.imports2, _writeImportElement);
+ _writeList(container.exports2, _writeExportElement);
+ _writeList(
+ container.augmentationImports,
+ _writeAugmentationImportElement,
+ );
+ }
+
void _writeList<T>(List<T> elements, void Function(T) writeElement) {
_sink.writeUInt30(elements.length);
for (var element in elements) {
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index 2451694..c21d763 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -21,6 +21,7 @@
class ElementBuilder extends ThrowingAstVisitor<void> {
final LibraryBuilder _libraryBuilder;
+ final LibraryOrAugmentationElementImpl _container;
final CompilationUnitElementImpl _unitElement;
var _isFirstLibraryDirective = true;
@@ -34,14 +35,14 @@
ElementBuilder({
required LibraryBuilder libraryBuilder,
+ required LibraryOrAugmentationElementImpl container,
required Reference unitReference,
required CompilationUnitElementImpl unitElement,
}) : _libraryBuilder = libraryBuilder,
+ _container = container,
_unitElement = unitElement,
_enclosingContext = _EnclosingContext(unitReference, unitElement);
- LibraryElementImpl get _libraryElement => _libraryBuilder.element;
-
Linker get _linker => _libraryBuilder.linker;
void buildDeclarationElements(CompilationUnit unit) {
@@ -58,7 +59,7 @@
_unitElement.typeAliases = _enclosingContext.typeAliases;
}
- /// Build exports and imports, metadata into [_libraryElement].
+ /// Build exports and imports, metadata into [_container].
void buildLibraryElementChildren(CompilationUnit unit) {
unit.directives.accept(this);
@@ -66,12 +67,12 @@
_isFirstLibraryDirective = false;
var firstDirective = unit.directives.firstOrNull;
if (firstDirective != null) {
- _libraryElement.documentationComment = getCommentNodeRawText(
+ _container.documentationComment = getCommentNodeRawText(
firstDirective.documentationComment,
);
var firstDirectiveMetadata = firstDirective.element?.metadata;
if (firstDirectiveMetadata != null) {
- _libraryElement.metadata = firstDirectiveMetadata;
+ _container.metadata = firstDirectiveMetadata;
}
}
}
@@ -80,7 +81,7 @@
@override
void visitAugmentationImportDirective(AugmentationImportDirective node) {
final index = _augmentationDirectiveIndex++;
- final element = _libraryElement.augmentationImports[index];
+ final element = _container.augmentationImports[index];
element as AugmentationImportElementImpl;
element.metadata = _buildAnnotations(node.metadata);
}
@@ -375,7 +376,7 @@
@override
void visitExportDirective(covariant ExportDirectiveImpl node) {
final index = _exportDirectiveIndex++;
- final exportElement = _libraryElement.exports2[index];
+ final exportElement = _container.exports2[index];
exportElement as ExportElement2Impl;
exportElement.metadata = _buildAnnotations(node.metadata);
node.element = exportElement;
@@ -742,7 +743,7 @@
@override
void visitImportDirective(covariant ImportDirectiveImpl node) {
final index = _importDirectiveIndex++;
- final importElement = _libraryElement.imports2[index];
+ final importElement = _container.imports2[index];
importElement as ImportElement2Impl;
importElement.metadata = _buildAnnotations(node.metadata);
node.element = importElement;
@@ -758,11 +759,11 @@
void visitLibraryDirective(covariant LibraryDirectiveImpl node) {
if (_isFirstLibraryDirective) {
_isFirstLibraryDirective = false;
- node.element = _libraryElement;
- _libraryElement.documentationComment = getCommentNodeRawText(
+ node.element = _container;
+ _container.documentationComment = getCommentNodeRawText(
node.documentationComment,
);
- _libraryElement.metadata = _buildAnnotations(node.metadata);
+ _container.metadata = _buildAnnotations(node.metadata);
}
}
@@ -882,15 +883,21 @@
@override
void visitPartDirective(PartDirective node) {
- final index = _partDirectiveIndex++;
- final partElement = _libraryElement.parts2[index];
- partElement as PartElementImpl;
- partElement.metadata = _buildAnnotations(node.metadata);
+ final libraryElement = _container;
+ if (libraryElement is LibraryElementImpl) {
+ final index = _partDirectiveIndex++;
+ final partElement = libraryElement.parts2[index];
+ partElement as PartElementImpl;
+ partElement.metadata = _buildAnnotations(node.metadata);
+ }
}
@override
void visitPartOfDirective(PartOfDirective node) {
- _libraryElement.hasPartOfDirective = true;
+ final libraryElement = _container;
+ if (libraryElement is LibraryElementImpl) {
+ libraryElement.hasPartOfDirective = true;
+ }
}
@override
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index 26451c7..95cb3b4 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -67,6 +67,7 @@
throw StateError('Unexpected recursion.');
}
_elementFactory.isApplyingInformativeData = true;
+ libraryElement.linkedData?.lock();
var unitElements = libraryElement.units;
for (var i = 0; i < unitElements.length; i++) {
@@ -139,6 +140,7 @@
}
}
+ libraryElement.linkedData?.unlock();
_elementFactory.isApplyingInformativeData = false;
}
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 0ad9d076..7c5be86 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -33,6 +33,7 @@
required super.reference,
required super.node,
required super.element,
+ required super.container,
});
}
@@ -149,6 +150,7 @@
for (var linkingUnit in units) {
var elementBuilder = ElementBuilder(
libraryBuilder: this,
+ container: linkingUnit.container,
unitReference: linkingUnit.reference,
unitElement: linkingUnit.element,
);
@@ -239,6 +241,7 @@
final elementBuilder = ElementBuilder(
libraryBuilder: this,
+ container: element,
unitReference: unitReference,
unitElement: unitElement,
);
@@ -348,6 +351,7 @@
ElementBuilder(
libraryBuilder: this,
+ container: element,
unitReference: unitReference,
unitElement: unitElement,
).buildDeclarationElements(unitNode);
@@ -359,6 +363,7 @@
LinkingUnit(
reference: unitReference,
node: unitNode,
+ container: element,
element: unitElement,
),
);
@@ -438,17 +443,9 @@
reference.getChild('@augmentation').getChild(importedFile.uriStr);
_bindReference(unitReference, unitElement);
- units.add(
- DefiningLinkingUnit(
- reference: unitReference,
- node: unitNode,
- element: unitElement,
- ),
- );
-
final augmentation = LibraryAugmentationElementImpl(
augmented: augmentedElement,
- nameOffset: -1, // TODO(scheglov) fix it
+ nameOffset: importedAugmentation.directive.libraryKeywordOffset,
);
augmentation.definingCompilationUnit = unitElement;
@@ -463,6 +460,15 @@
source: importedFile.source,
augmentation: augmentation,
);
+
+ units.add(
+ DefiningLinkingUnit(
+ reference: unitReference,
+ node: unitNode,
+ element: unitElement,
+ container: augmentation,
+ ),
+ );
} else {
uri = DirectiveUriWithSourceImpl(
relativeUriString: state.uri.relativeUriStr,
@@ -487,7 +493,7 @@
}
return AugmentationImportElementImpl(
- importKeywordOffset: -1, // TODO(scheglov) fix it
+ importKeywordOffset: state.directive.importKeywordOffset,
uri: uri,
);
}
@@ -764,6 +770,7 @@
reference: unitReference,
node: libraryUnitNode,
element: unitElement,
+ container: libraryElement,
),
);
@@ -796,6 +803,7 @@
LinkingUnit(
reference: unitReference,
node: partUnitNode,
+ container: libraryElement,
element: unitElement,
),
);
@@ -861,11 +869,13 @@
class LinkingUnit {
final Reference reference;
final ast.CompilationUnitImpl node;
+ final LibraryOrAugmentationElementImpl container;
final CompilationUnitElementImpl element;
LinkingUnit({
required this.reference,
required this.node,
+ required this.container,
required this.element,
});
}
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index e4a67c3..bc1414f 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -66,6 +66,7 @@
var x_result = findElement.topVar('x').evaluationResult;
assertDartObjectText(x_result.value, r'''
dynamic <unknown>
+ variable: self::@variable::x
''');
}
@@ -404,12 +405,14 @@
E
_name: String v1
index: int 0
+ variable: self::@variable::x1
''');
_assertTopVarConstValue('x2', r'''
E
_name: String v2
index: int 1
+ variable: self::@variable::x2
''');
}
@@ -430,7 +433,9 @@
_name: String v1
a: int 42
index: int 0
+ variable: self::@enum::E::@field::v1
index: int 1
+ variable: self::@enum::E::@field::v2
''');
}
@@ -452,6 +457,7 @@
_name: String v1
f: double 10.0
index: int 0
+ variable: self::@variable::x1
''');
_assertTopVarConstValue('x2', r'''
@@ -459,6 +465,7 @@
_name: String v2
f: int 20
index: int 1
+ variable: self::@variable::x2
''');
}
@@ -482,6 +489,7 @@
_name: String v1
f: int 10
index: int 0
+ variable: self::@variable::x1
''');
_assertTopVarConstValue('x2', r'''
@@ -489,6 +497,7 @@
_name: String v2
f: int 20
index: int 1
+ variable: self::@variable::x2
''');
_assertTopVarConstValue('x3', r'''
@@ -496,6 +505,7 @@
_name: String v3
f: String abc
index: int 2
+ variable: self::@variable::x3
''');
}
@@ -594,6 +604,7 @@
a: int 1
b: int 2
c: int 3
+ variable: self::@variable::x
''');
}
@@ -620,6 +631,7 @@
a: int 1
b: int 2
c: int 3
+ variable: self::@variable::x
''');
}
@@ -644,6 +656,7 @@
(super): A
a: int 1
b: int 2
+ variable: self::@variable::x
''');
}
@@ -668,6 +681,7 @@
(super): A
a: int 1
b: int 2
+ variable: self::@variable::x
''');
}
@@ -692,6 +706,7 @@
(super): A
a: int 1
b: int 2
+ variable: self::@variable::x
''');
}
@@ -716,6 +731,7 @@
(super): A
a: int 1
b: int 2
+ variable: self::@variable::x
''');
}
@@ -740,6 +756,7 @@
(super): A
a: int 1
b: int 2
+ variable: self::@variable::x
''');
}
@@ -764,6 +781,7 @@
(super): A
a: int 1
b: int 2
+ variable: self::@variable::x
''');
}
@@ -788,6 +806,7 @@
(super): A
a: int 1
b: int 2
+ variable: self::@variable::x
''');
}
@@ -812,6 +831,47 @@
(super): A
a: int 1
b: int 2
+ variable: self::@variable::x
+''');
+ }
+
+ test_variable_alias() async {
+ await resolveTestCode('''
+const a = 42;
+const b = a;
+''');
+
+ final a_result = findElement.topVar('a').evaluationResult;
+ assertDartObjectText(a_result.value, r'''
+int 42
+ variable: self::@variable::a
+''');
+
+ final b_result = findElement.topVar('b').evaluationResult;
+ assertDartObjectText(b_result.value, r'''
+int 42
+ variable: self::@variable::b
+''');
+ }
+
+ test_variable_list_elements() async {
+ await resolveTestCode('''
+const a = 0;
+const b = 2;
+const c = [a, 1, b];
+''');
+
+ final b_result = findElement.topVar('c').evaluationResult;
+ assertDartObjectText(b_result.value, r'''
+List
+ elementType: int
+ elements
+ int 0
+ variable: self::@variable::a
+ int 1
+ int 2
+ variable: self::@variable::b
+ variable: self::@variable::c
''');
}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
index e73428f..b484abe 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
@@ -64,7 +64,7 @@
assertErrorsInList(await _computeTestFileErrors(), []);
// Configure `strict-casts: true`.
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
writeTestPackageAnalysisOptionsFile(
AnalysisOptionsFileConfig(
strictCasts: true,
@@ -155,7 +155,7 @@
// Dispose the collection, with its driver.
// The next analysis will recreate it.
// We will reuse the byte store, so can reuse summaries.
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
newFile(testFilePath, r'''
class A {
@@ -193,7 +193,7 @@
// Dispose the collection, with its driver.
// The next analysis will recreate it.
// We will reuse the byte store, so can reuse summaries.
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
newFile(testFilePath, r'''
void f() {
@@ -299,7 +299,7 @@
// We will recreate it with new pubspec.yaml content.
// But we will reuse the byte store, so can reuse summaries.
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
// Add dependency on `package:aaa`.
writeTestPackagePubspecYamlFile(
@@ -341,7 +341,7 @@
// We will recreate it with new analysis options.
// But we will reuse the byte store, so can reuse summaries.
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
// Configure to run a lint.
writeTestPackageAnalysisOptionsFile(
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index f158a29..0e05ff1 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -1491,6 +1491,150 @@
''');
}
+ test_newFile_library_augmentations_imports() {
+ newFile('$testPackageLibPath/a.dart', '');
+
+ newFile('$testPackageLibPath/b.dart', r'''
+library augment 'c.dart';
+import 'a.dart';
+''');
+
+ final c = newFile('$testPackageLibPath/c.dart', r'''
+import augment 'b.dart';
+''');
+
+ fileStateFor(c);
+
+ // `a.dart` is imported by the augmentation `b.dart`, so it becomes a
+ // dependency for the library `c.dart` cycle.
+ assertDriverStateString(testFile, r'''
+files
+ /home/test/lib/a.dart
+ uri: package:test/a.dart
+ current
+ id: file_0
+ kind: library_0
+ imports
+ library_3 dart:core synthetic
+ cycle_0
+ dependencies: dart:core
+ libraries: library_0
+ apiSignature_0
+ users: cycle_1
+ referencingFiles: file_1
+ unlinkedKey: k00
+ /home/test/lib/b.dart
+ uri: package:test/b.dart
+ current
+ id: file_1
+ kind: augmentation_1
+ augmented: library_2
+ library: library_2
+ imports
+ library_0
+ library_3 dart:core synthetic
+ referencingFiles: file_2
+ unlinkedKey: k01
+ /home/test/lib/c.dart
+ uri: package:test/c.dart
+ current
+ id: file_2
+ kind: library_2
+ imports
+ library_3 dart:core synthetic
+ augmentations
+ augmentation_1
+ cycle_1
+ dependencies: cycle_0 dart:core
+ libraries: library_2
+ apiSignature_1
+ unlinkedKey: k02
+libraryCycles
+elementFactory
+''');
+ }
+
+ test_newFile_library_augmentations_imports2() {
+ newFile('$testPackageLibPath/a.dart', '');
+
+ newFile('$testPackageLibPath/b.dart', r'''
+library augment 'c.dart';
+import 'a.dart';
+''');
+
+ newFile('$testPackageLibPath/c.dart', r'''
+library augment 'd.dart';
+import augment 'b.dart';
+''');
+
+ final d = newFile('$testPackageLibPath/d.dart', r'''
+import augment 'c.dart';
+''');
+
+ fileStateFor(d);
+
+ // `a.dart` is transitively imported by augmentations into `d.dart`, so it
+ // becomes a dependency for the library `d.dart` cycle.
+ assertDriverStateString(testFile, r'''
+files
+ /home/test/lib/a.dart
+ uri: package:test/a.dart
+ current
+ id: file_0
+ kind: library_0
+ imports
+ library_4 dart:core synthetic
+ cycle_0
+ dependencies: dart:core
+ libraries: library_0
+ apiSignature_0
+ users: cycle_1
+ referencingFiles: file_1
+ unlinkedKey: k00
+ /home/test/lib/b.dart
+ uri: package:test/b.dart
+ current
+ id: file_1
+ kind: augmentation_1
+ augmented: augmentation_2
+ library: library_3
+ imports
+ library_0
+ library_4 dart:core synthetic
+ referencingFiles: file_2
+ unlinkedKey: k01
+ /home/test/lib/c.dart
+ uri: package:test/c.dart
+ current
+ id: file_2
+ kind: augmentation_2
+ augmented: library_3
+ library: library_3
+ imports
+ library_4 dart:core synthetic
+ augmentations
+ augmentation_1
+ referencingFiles: file_3
+ unlinkedKey: k02
+ /home/test/lib/d.dart
+ uri: package:test/d.dart
+ current
+ id: file_3
+ kind: library_3
+ imports
+ library_4 dart:core synthetic
+ augmentations
+ augmentation_2
+ cycle_1
+ dependencies: cycle_0 dart:core
+ libraries: library_3
+ apiSignature_1
+ unlinkedKey: k03
+libraryCycles
+elementFactory
+''');
+ }
+
test_newFile_library_augmentations_invalidUri_cannotParse() async {
final a = newFile('$testPackageLibPath/a.dart', r'''
import augment 'da:';
@@ -1711,7 +1855,7 @@
sdkSummaryFile = await _writeSdkSummary();
this.librarySummaryFiles = librarySummaryFiles;
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
final a = newFile('$testPackageLibPath/a.dart', r'''
export 'dart:async';
@@ -1804,7 +1948,7 @@
sdkSummaryFile = await _writeSdkSummary();
this.librarySummaryFiles = librarySummaryFiles;
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
final a = newFile('$testPackageLibPath/a.dart', r'''
export 'package:foo/foo2.dart';
@@ -2235,7 +2379,7 @@
sdkSummaryFile = await _writeSdkSummary();
this.librarySummaryFiles = librarySummaryFiles;
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
final a = newFile('$testPackageLibPath/a.dart', r'''
import 'dart:async';
@@ -2327,7 +2471,7 @@
sdkSummaryFile = await _writeSdkSummary();
this.librarySummaryFiles = librarySummaryFiles;
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
final a = newFile('$testPackageLibPath/a.dart', r'''
import 'package:foo/foo2.dart';
@@ -4063,6 +4207,90 @@
''');
}
+ test_refresh_augmentation_renameClass() {
+ final a = newFile('$testPackageLibPath/a.dart', r'''
+library augment 'b.dart';
+class A {}
+''');
+
+ final b = newFile('$testPackageLibPath/b.dart', r'''
+import augment 'a.dart';
+''');
+
+ fileStateFor(b);
+
+ assertDriverStateString(testFile, r'''
+files
+ /home/test/lib/a.dart
+ uri: package:test/a.dart
+ current
+ id: file_0
+ kind: augmentation_0
+ augmented: library_1
+ library: library_1
+ imports
+ library_2 dart:core synthetic
+ referencingFiles: file_1
+ unlinkedKey: k00
+ /home/test/lib/b.dart
+ uri: package:test/b.dart
+ current
+ id: file_1
+ kind: library_1
+ imports
+ library_2 dart:core synthetic
+ augmentations
+ augmentation_0
+ cycle_0
+ dependencies: dart:core
+ libraries: library_1
+ apiSignature_0
+ unlinkedKey: k01
+libraryCycles
+elementFactory
+''');
+
+ newFile(a.path, r'''
+library augment 'b.dart';
+class A2 {}
+''');
+ fileStateFor(a).refresh();
+
+ // The augmentation `a.dart` has a different unlinked key, and its
+ // refresh invalidated the library cycle `b.dart`, which has a differrent
+ // signature now.
+ assertDriverStateString(testFile, r'''
+files
+ /home/test/lib/a.dart
+ uri: package:test/a.dart
+ current
+ id: file_0
+ kind: augmentation_7
+ augmented: library_1
+ library: library_1
+ imports
+ library_2 dart:core synthetic
+ referencingFiles: file_1
+ unlinkedKey: k02
+ /home/test/lib/b.dart
+ uri: package:test/b.dart
+ current
+ id: file_1
+ kind: library_1
+ imports
+ library_2 dart:core synthetic
+ augmentations
+ augmentation_7
+ cycle_2
+ dependencies: dart:core
+ libraries: library_1
+ apiSignature_1
+ unlinkedKey: k01
+libraryCycles
+elementFactory
+''');
+ }
+
test_refresh_augmentation_to_library() async {
final a = newFile('$testPackageLibPath/a.dart', r'''
import augment 'b.dart';
@@ -4480,6 +4708,124 @@
''');
}
+ test_refresh_library_importedBy_augmentation() {
+ final a = newFile('$testPackageLibPath/a.dart', r'''
+class A {}
+''');
+
+ newFile('$testPackageLibPath/b.dart', r'''
+library augment 'c.dart';
+import 'a.dart';
+''');
+
+ final c = newFile('$testPackageLibPath/c.dart', r'''
+import augment 'b.dart';
+''');
+
+ fileStateFor(c);
+
+ // `a.dart` is imported by the augmentation `b.dart`, so it is a dependency
+ // of `c.dart`.
+ assertDriverStateString(testFile, r'''
+files
+ /home/test/lib/a.dart
+ uri: package:test/a.dart
+ current
+ id: file_0
+ kind: library_0
+ imports
+ library_3 dart:core synthetic
+ cycle_0
+ dependencies: dart:core
+ libraries: library_0
+ apiSignature_0
+ users: cycle_1
+ referencingFiles: file_1
+ unlinkedKey: k00
+ /home/test/lib/b.dart
+ uri: package:test/b.dart
+ current
+ id: file_1
+ kind: augmentation_1
+ augmented: library_2
+ library: library_2
+ imports
+ library_0
+ library_3 dart:core synthetic
+ referencingFiles: file_2
+ unlinkedKey: k01
+ /home/test/lib/c.dart
+ uri: package:test/c.dart
+ current
+ id: file_2
+ kind: library_2
+ imports
+ library_3 dart:core synthetic
+ augmentations
+ augmentation_1
+ cycle_1
+ dependencies: cycle_0 dart:core
+ libraries: library_2
+ apiSignature_1
+ unlinkedKey: k02
+libraryCycles
+elementFactory
+''');
+
+ newFile(a.path, r'''
+class A2 {}
+''');
+ fileStateFor(a).refresh();
+
+ // Updated `a.dart` invalidates the library cycle for `c.dart`, both
+ // have now different signatures.
+ assertDriverStateString(testFile, r'''
+files
+ /home/test/lib/a.dart
+ uri: package:test/a.dart
+ current
+ id: file_0
+ kind: library_8
+ imports
+ library_3 dart:core synthetic
+ cycle_3
+ dependencies: dart:core
+ libraries: library_8
+ apiSignature_2
+ users: cycle_4
+ referencingFiles: file_1
+ unlinkedKey: k03
+ /home/test/lib/b.dart
+ uri: package:test/b.dart
+ current
+ id: file_1
+ kind: augmentation_1
+ augmented: library_2
+ library: library_2
+ imports
+ library_8
+ library_3 dart:core synthetic
+ referencingFiles: file_2
+ unlinkedKey: k01
+ /home/test/lib/c.dart
+ uri: package:test/c.dart
+ current
+ id: file_2
+ kind: library_2
+ imports
+ library_3 dart:core synthetic
+ augmentations
+ augmentation_1
+ cycle_4
+ dependencies: cycle_3 dart:core
+ libraries: library_2
+ apiSignature_3
+ unlinkedKey: k02
+libraryCycles
+elementFactory
+''');
+ }
+
test_refresh_library_removePart_partOfName() async {
newFile('$testPackageLibPath/a.dart', r'''
part of my;
@@ -5304,8 +5650,8 @@
// `a.dart` is still a part.
// ...but the unlinked signature of `a.dart` is different.
- // API signatures of both `b.dart` and `c.dart` changed.
- // Even though `a.dart` is not a valid part of `c.dart`.
+ // The API signatures of `b.dart` is changed, because `a.dart` is its part.
+ // But `c.dart` still has the previous API signature.
assertDriverStateString(testFile, r'''
files
/home/test/lib/a.dart
@@ -5342,7 +5688,7 @@
cycle_4
dependencies: dart:core
libraries: library_7
- apiSignature_3
+ apiSignature_1
unlinkedKey: k01
libraryCycles
elementFactory
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index 40c4384..d0708d1 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -395,19 +395,11 @@
var session = contextFor(testFilePath).currentSession;
var parsedLibrary = session.getParsedLibraryValid(test.path);
- expect(parsedLibrary.units, hasLength(3));
+ expect(parsedLibrary.units, hasLength(1));
expect(
parsedLibrary.units[0].path,
convertPath('/home/test/lib/test.dart'),
);
- expect(
- parsedLibrary.units[1].path,
- convertPath('/home/test/lib/a.dart'),
- );
- expect(
- parsedLibrary.units[2].path,
- convertPath('/home/test/lib/c.dart'),
- );
}
test_getParsedLibrary_invalidPath_notAbsolute() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 222e523..ef1870b 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -212,10 +212,10 @@
return _contextFor(path);
}
- void disposeAnalysisContextCollection() {
+ Future<void> disposeAnalysisContextCollection() async {
final analysisContextCollection = _analysisContextCollection;
if (analysisContextCollection != null) {
- analysisContextCollection.dispose(
+ await analysisContextCollection.dispose(
forTesting: true,
);
_analysisContextCollection = null;
@@ -258,7 +258,7 @@
@mustCallSuper
Future<void> tearDown() async {
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
KernelCompilationService.disposeDelayed(
const Duration(milliseconds: 500),
);
@@ -492,7 +492,7 @@
await resolveTestCode(code);
assertNoErrorsInResult();
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
writeTestPackageAnalysisOptionsFile(
AnalysisOptionsFileConfig(
@@ -539,7 +539,7 @@
await resolveTestCode(code);
assertNoErrorsInResult();
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
writeTestPackageAnalysisOptionsFile(
AnalysisOptionsFileConfig(
diff --git a/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart b/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart
index 8124576..ec37e39 100644
--- a/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart
+++ b/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart
@@ -2,20 +2,27 @@
// 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 'dart:collection';
-
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/constant/value.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+import 'package:collection/collection.dart';
/// Prints [DartObjectImpl] as a tree, with values and fields.
class DartObjectPrinter {
final StringBuffer sink;
+ final String selfUriStr;
- DartObjectPrinter(this.sink);
+ String indent = '';
- void write(DartObjectImpl? object, String indent) {
+ DartObjectPrinter({
+ required this.sink,
+ required this.selfUriStr,
+ });
+
+ void write(DartObjectImpl? object) {
if (object != null) {
- var type = object.type;
+ final type = object.type;
if (object.isUnknown) {
sink.write(
type.getDisplayString(
@@ -33,34 +40,86 @@
sink.write('String ');
sink.writeln(object.toStringValue());
} else if (type.isDartCoreList) {
- var newIndent = '$indent ';
+ type as InterfaceType;
sink.writeln('List');
- sink.write(newIndent);
- sink.writeln(
- 'elementType: ${(type as InterfaceType).typeArguments[0]}');
- var elements = object.toListValue()!;
- for (int i = 0; i < elements.length; i++) {
- sink.write(newIndent);
- write(elements[i] as DartObjectImpl, newIndent);
- }
- } else if (object.isUserDefinedObject) {
- var newIndent = '$indent ';
- var typeStr = type.getDisplayString(withNullability: true);
- sink.writeln(typeStr);
- var fields = object.fields;
- if (fields != null) {
- var sortedFields = SplayTreeMap.of(fields);
- for (var entry in sortedFields.entries) {
- sink.write(newIndent);
- sink.write('${entry.key}: ');
- write(entry.value, newIndent);
+ _withIndent(() {
+ _writelnWithIndent('elementType: ${type.typeArguments[0]}');
+ final elements = object.toListValue()!;
+ if (elements.isNotEmpty) {
+ _writelnWithIndent('elements');
+ _withIndent(() {
+ for (final element in elements) {
+ sink.write(indent);
+ write(element as DartObjectImpl);
+ }
+ });
}
- }
+ });
+ } else if (object.isUserDefinedObject) {
+ final typeStr = type.getDisplayString(withNullability: true);
+ sink.writeln(typeStr);
+ _withIndent(() {
+ final fields = object.fields;
+ if (fields != null) {
+ final sortedFields = fields.entries.sortedBy((e) => e.key);
+ for (final entry in sortedFields) {
+ sink.write(indent);
+ sink.write('${entry.key}: ');
+ write(entry.value);
+ }
+ }
+ });
} else {
throw UnimplementedError();
}
+ _writeVariable(object);
} else {
sink.writeln('<null>');
}
}
+
+ String _referenceToString(Reference reference) {
+ final parent = reference.parent!;
+ if (parent.parent == null) {
+ final libraryUriStr = reference.name;
+ if (libraryUriStr == selfUriStr) {
+ return 'self';
+ }
+ return libraryUriStr;
+ }
+
+ // Ignore the unit, skip to the library.
+ if (parent.name == '@unit') {
+ return _referenceToString(parent.parent!);
+ }
+
+ var name = reference.name;
+ if (name.isEmpty) {
+ name = '•';
+ }
+ return '${_referenceToString(parent)}::$name';
+ }
+
+ void _withIndent(void Function() f) {
+ var savedIndent = indent;
+ indent = '$savedIndent ';
+ f();
+ indent = savedIndent;
+ }
+
+ void _writelnWithIndent(String line) {
+ sink.write(indent);
+ sink.writeln(line);
+ }
+
+ void _writeVariable(DartObjectImpl object) {
+ final variable = object.variable;
+ if (variable is VariableElementImpl) {
+ _withIndent(() {
+ final reference = variable.reference!;
+ final referenceStr = _referenceToString(reference);
+ _writelnWithIndent('variable: $referenceStr');
+ });
+ }
+ }
}
diff --git a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
index 8da2b07..08b5846 100644
--- a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
@@ -39,6 +39,7 @@
''');
_assertAnnotationValueText(annotation, '''
int 42
+ variable: self::@variable::a
''');
}
@@ -67,6 +68,7 @@
var annotationElement = annotation.elementAnnotation!;
_assertElementAnnotationValueText(annotationElement, r'''
int 42
+ variable: self::@variable::foo
''');
}
@@ -102,6 +104,7 @@
var annotationElement = annotation.elementAnnotation!;
_assertElementAnnotationValueText(annotationElement, r'''
int 42
+ variable: self::@variable::foo
''');
}
@@ -128,6 +131,7 @@
E
_name: String v
index: int 0
+ variable: self::@enum::E::@field::v
''');
}
@@ -413,6 +417,7 @@
_assertElementAnnotationValueText(
findElement.function('f').metadata[0], r'''
int 42
+ variable: package:test/a.dart::@class::A::@field::foo
''');
}
@@ -446,6 +451,7 @@
_assertElementAnnotationValueText(
findElement.function('f').metadata[0], r'''
int 42
+ variable: package:test/a.dart::@variable::foo
''');
}
@@ -707,6 +713,7 @@
''');
_assertAnnotationValueText(annotation, '''
int 42
+ variable: self::@class::A::@field::foo
''');
}
@@ -1678,6 +1685,7 @@
''');
_assertAnnotationValueText(annotation, '''
int 42
+ variable: package:test/a.dart::@class::A::@field::foo
''');
}
@@ -1979,6 +1987,7 @@
''');
_assertAnnotationValueText(annotation, '''
int 42
+ variable: self::@class::A::@field::foo
''');
}
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index d80f3d2..7ff2297 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -119,7 +119,10 @@
void assertDartObjectText(DartObject? object, String expected) {
var buffer = StringBuffer();
- DartObjectPrinter(buffer).write(object as DartObjectImpl?, '');
+ DartObjectPrinter(
+ sink: buffer,
+ selfUriStr: '${result.libraryElement.source.uri}',
+ ).write(object as DartObjectImpl?);
var actual = buffer.toString();
if (actual != expected) {
print(buffer);
diff --git a/pkg/analyzer/test/src/summary/elements_test.dart b/pkg/analyzer/test/src/summary/elements_test.dart
index 9fd06aa..c9bab89 100644
--- a/pkg/analyzer/test/src/summary/elements_test.dart
+++ b/pkg/analyzer/test/src/summary/elements_test.dart
@@ -40,6 +40,110 @@
}
abstract class ElementsTest extends ElementsBaseTest {
+ test_augmentation_augmentationImports_augmentation() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+import augment 'b.dart';
+class A {}
+''');
+ newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+class B {}
+''');
+ final library = await buildLibrary(r'''
+import augment 'a.dart';
+class C {}
+''');
+ checkElementText(library, r'''
+library
+ augmentationImports
+ package:test/a.dart
+ augmentationImports
+ package:test/b.dart
+ definingUnit
+ classes
+ class B @32
+ constructors
+ synthetic @-1
+ definingUnit
+ classes
+ class A @60
+ constructors
+ synthetic @-1
+ definingUnit
+ classes
+ class C @31
+ constructors
+ synthetic @-1
+''');
+ }
+
+ test_augmentation_libraryExports_library() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+export 'dart:async';
+''');
+ newFile('$testPackageLibPath/b.dart', r'''
+library augment 'test.dart';
+export 'dart:collection';
+export 'dart:math';
+''');
+ final library = await buildLibrary(r'''
+import 'dart:io';
+import augment 'a.dart';
+import augment 'b.dart';
+''');
+ checkElementText(library, r'''
+library
+ imports
+ dart:io
+ augmentationImports
+ package:test/a.dart
+ exports
+ dart:async
+ definingUnit
+ package:test/b.dart
+ exports
+ dart:collection
+ dart:math
+ definingUnit
+ definingUnit
+''');
+ }
+
+ test_augmentation_libraryImports_library() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+import 'dart:async';
+''');
+ newFile('$testPackageLibPath/b.dart', r'''
+library augment 'test.dart';
+import 'dart:collection';
+import 'dart:math';
+''');
+ final library = await buildLibrary(r'''
+import 'dart:io';
+import augment 'a.dart';
+import augment 'b.dart';
+''');
+ checkElementText(library, r'''
+library
+ imports
+ dart:io
+ augmentationImports
+ package:test/a.dart
+ imports
+ dart:async
+ definingUnit
+ package:test/b.dart
+ imports
+ dart:collection
+ dart:math
+ definingUnit
+ definingUnit
+''');
+ }
+
test_class_abstract() async {
var library = await buildLibrary('abstract class C {}');
checkElementText(library, r'''
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index dedd656..c6edd7f 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -1766,27 +1766,27 @@
''';
await _assertNoErrors(
build(declared: "MyFuture", downwards: "Future", upwards: "Future"));
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await _assertNoErrors(
build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture"));
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await _assertNoErrors(
build(declared: "MyFuture", downwards: "MyFuture", upwards: "Future"));
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await _assertNoErrors(build(
declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture"));
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await _assertNoErrors(
build(declared: "Future", downwards: "Future", upwards: "MyFuture"));
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await _assertNoErrors(
build(declared: "Future", downwards: "Future", upwards: "Future"));
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
}
test_futureThen_downwardsMethodTarget() async {
@@ -1860,7 +1860,7 @@
error(HintCode.UNNECESSARY_CAST, 480, 47),
],
);
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await assertErrorsInCode(
build(declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture"),
@@ -1871,7 +1871,7 @@
error(HintCode.UNNECESSARY_CAST, 484, 49),
],
);
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await assertErrorsInCode(
build(declared: "Future", downwards: "Future", upwards: "Future"),
@@ -1882,7 +1882,7 @@
error(HintCode.UNNECESSARY_CAST, 480, 47),
],
);
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
}
test_futureThen_upwardsFromBlock() async {
@@ -1927,12 +1927,12 @@
await assertNoErrorsInCode(
build(downwards: "Future", upwards: "Future", expectedInfo: ''),
);
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await assertNoErrorsInCode(
build(downwards: "Future", upwards: "MyFuture"),
);
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
}
test_futureUnion_downwards() async {
@@ -1975,7 +1975,7 @@
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 338, 4),
],
);
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await assertErrorsInCode(
build(
@@ -1985,7 +1985,7 @@
),
[],
);
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await assertErrorsInCode(
build(
@@ -1998,7 +1998,7 @@
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 336, 4),
],
);
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
await assertErrorsInCode(
build(
@@ -2008,7 +2008,7 @@
),
[],
);
- disposeAnalysisContextCollection();
+ await disposeAnalysisContextCollection();
}
test_futureUnion_downwardsGenericMethodWithFutureReturn() async {
diff --git a/pkg/analyzer_plugin/lib/plugin/plugin.dart b/pkg/analyzer_plugin/lib/plugin/plugin.dart
index 3f7bb5d..a721865 100644
--- a/pkg/analyzer_plugin/lib/plugin/plugin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/plugin.dart
@@ -258,7 +258,7 @@
await beforeContextCollectionDispose(
contextCollection: currentContextCollection,
);
- currentContextCollection.dispose();
+ await currentContextCollection.dispose();
}
final includedPaths = parameters.roots.map((e) => e.root).toList();
diff --git a/pkg/dartdev/test/commands/language_server_test.dart b/pkg/dartdev/test/commands/language_server_test.dart
index 06d75dc..8429677 100644
--- a/pkg/dartdev/test/commands/language_server_test.dart
+++ b/pkg/dartdev/test/commands/language_server_test.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 'dart:async';
import 'dart:convert';
import 'dart:io';
@@ -31,9 +32,6 @@
process = await project.start(args);
- final Stream<String> inStream =
- process!.stdout.transform<String>(utf8.decoder);
-
// Send an LSP init.
final String message = jsonEncode({
'jsonrpc': '2.0',
@@ -51,12 +49,10 @@
process!.stdin.write('\r\n');
process!.stdin.write(message);
- List<String> responses = await inStream.take(2).toList();
- expect(responses, hasLength(2));
+ // Expect
+ final response = await _readLspMessage(process!.stdout);
- expect(responses[0], startsWith('Content-Length: '));
-
- final json = jsonDecode(responses[1]);
+ final json = jsonDecode(response);
expect(json['id'], 1);
expect(json['result'], isNotNull);
final result = json['result'];
@@ -99,3 +95,42 @@
process = null;
});
}
+
+/// Reads the first LSP message from [stream].
+Future<String> _readLspMessage(Stream<List<int>> stream) {
+ // Headers are complete if there are 2x '\r\n\'. The '\r' is part of the LSP
+ // spec for headers and included on all platforms, not just Windows.
+ const lspHeaderBodySeperator = '\r\n\r\n';
+ final contentLengthRegExp = RegExp(r'Content-Length: (\d+)\r\n');
+
+ final completer = Completer<String>();
+ final buffer = StringBuffer();
+ late final StreamSubscription<String> inSubscription;
+ inSubscription = stream.transform<String>(utf8.decoder).listen(
+ (data) {
+ // Collect the output into the buffer.
+ buffer.write(data);
+
+ // Check whether the buffer has a complete message.
+ final bufferString = buffer.toString();
+
+ // To know if we have a complete message, we need to check we have the
+ // headers, extract the content-length, then check we have that many
+ // bytes in the body.
+ if (bufferString.contains(lspHeaderBodySeperator)) {
+ final parts = bufferString.split(lspHeaderBodySeperator);
+ final headers = parts[0];
+ final body = parts[1];
+ final length =
+ int.parse(contentLengthRegExp.firstMatch(headers)!.group(1)!);
+ // Check if we're already had the full payload.
+ if (body.length >= length) {
+ completer.complete(body.substring(0, length));
+ inSubscription.cancel();
+ }
+ }
+ },
+ );
+
+ return completer.future;
+}
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 727e2cd..71f07cb 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog
+## 9.2.0
+- Update to version `3.59` of the spec.
+- Add `abstract` flag to `FuncRef`.
+
## 9.1.0
- Remove `required` keyword from most of the named parameters in the
constructors of the Dart API objects.
diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties
index 8aee343..cf92a35 100644
--- a/pkg/vm_service/java/version.properties
+++ b/pkg/vm_service/java/version.properties
@@ -1 +1 @@
-version=3.58
+version=3.59
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 1533b40..45dd4ee 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -26,7 +26,7 @@
HeapSnapshotObjectNoData,
HeapSnapshotObjectNullData;
-const String vmServiceVersion = '3.58.0';
+const String vmServiceVersion = '3.59.0';
/// @optional
const String optional = 'optional';
@@ -4675,6 +4675,9 @@
/// Is this function implicitly defined (e.g., implicit getter/setter)?
bool? implicit;
+ /// Is this function an abstract method?
+ bool? isAbstract;
+
/// The location of this function in the source code.
///
/// Note: this may not agree with the location of `owner` if this is a
@@ -4689,6 +4692,7 @@
this.isStatic,
this.isConst,
this.implicit,
+ this.isAbstract,
required String id,
this.location,
}) : super(
@@ -4702,6 +4706,7 @@
isStatic = json['static'] ?? false;
isConst = json['const'] ?? false;
implicit = json['implicit'] ?? false;
+ isAbstract = json['abstract'] ?? false;
location = createServiceObject(json['location'], const ['SourceLocation'])
as SourceLocation?;
}
@@ -4719,6 +4724,7 @@
'static': isStatic,
'const': isConst,
'implicit': implicit,
+ 'abstract': isAbstract,
});
_setIfNotNull(json, 'location', location?.toJson());
return json;
@@ -4730,7 +4736,7 @@
String toString() => '[FuncRef ' //
'id: ${id}, name: ${name}, owner: ${owner}, isStatic: ${isStatic}, ' //
- 'isConst: ${isConst}, implicit: ${implicit}]';
+ 'isConst: ${isConst}, implicit: ${implicit}, isAbstract: ${isAbstract}]';
}
/// A `Func` represents a Dart language function.
@@ -4759,6 +4765,9 @@
/// Is this function implicitly defined (e.g., implicit getter/setter)?
bool? implicit;
+ /// Is this function an abstract method?
+ bool? isAbstract;
+
/// The location of this function in the source code.
///
/// Note: this may not agree with the location of `owner` if this is a
@@ -4780,6 +4789,7 @@
this.isStatic,
this.isConst,
this.implicit,
+ this.isAbstract,
this.signature,
required String id,
this.location,
@@ -4795,6 +4805,7 @@
isStatic = json['static'] ?? false;
isConst = json['const'] ?? false;
implicit = json['implicit'] ?? false;
+ isAbstract = json['abstract'] ?? false;
location = createServiceObject(json['location'], const ['SourceLocation'])
as SourceLocation?;
signature = createServiceObject(json['signature'], const ['InstanceRef'])
@@ -4815,6 +4826,7 @@
'static': isStatic,
'const': isConst,
'implicit': implicit,
+ 'abstract': isAbstract,
'signature': signature?.toJson(),
});
_setIfNotNull(json, 'location', location?.toJson());
@@ -4828,7 +4840,7 @@
String toString() => '[Func ' //
'id: ${id}, name: ${name}, owner: ${owner}, isStatic: ${isStatic}, ' //
- 'isConst: ${isConst}, implicit: ${implicit}, signature: ${signature}]';
+ 'isConst: ${isConst}, implicit: ${implicit}, isAbstract: ${isAbstract}, signature: ${signature}]';
}
/// `InstanceRef` is a reference to an `Instance`.
@@ -6322,7 +6334,9 @@
return json;
}
- String toString() => '[LogRecord]';
+ String toString() => '[LogRecord ' //
+ 'message: ${message}, time: ${time}, level: ${level}, sequenceNumber: ${sequenceNumber}, ' //
+ 'loggerName: ${loggerName}, zone: ${zone}, error: ${error}, stackTrace: ${stackTrace}]';
}
class MapAssociation {
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 0f11496..e7c8f3b 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -1,5 +1,5 @@
name: vm_service
-version: 9.1.0
+version: 9.2.0
description: >-
A library to communicate with a service implementing the Dart VM
service protocol.
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index ee8df6c..5475adc 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -1611,7 +1611,8 @@
// toString()
Iterable<TypeField> toStringFields =
getAllFields().where((f) => !f.optional);
- if (toStringFields.length <= 7) {
+ const maxFieldsShownInToString = 8;
+ if (toStringFields.length <= maxFieldsShownInToString) {
String properties = toStringFields
.map(
(TypeField f) => "${f.generatableName}: \${${f.generatableName}}")
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index a1f0582..774c855 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -11,12 +11,17 @@
import 'service_test_common.dart';
import 'test_helper.dart';
-class _DummyClass {
+abstract class _DummyAbstractBaseClass {
+ void dummyFunction(int a, [bool b = false]);
+}
+
+class _DummyClass extends _DummyAbstractBaseClass {
static var dummyVar = 11;
final List<String> dummyList = new List<String>.filled(20, '');
static var dummyVarWithInit = foo();
late String dummyLateVarWithInit = 'bar';
late String dummyLateVar;
+ @override
void dummyFunction(int a, [bool b = false]) {}
void dummyGenericFunction<K, V>(K a, {required V param}) {}
static List foo() => List<String>.filled(20, '');
@@ -889,6 +894,7 @@
expect(result['static'], equals(false));
expect(result['const'], equals(false));
expect(result['implicit'], equals(false));
+ expect(result['abstract'], equals(false));
expect(result['signature']['typeParameters'], isNull);
expect(result['signature']['returnType'], isNotNull);
expect(result['signature']['parameters'].length, 3);
@@ -923,6 +929,7 @@
expect(result['static'], equals(false));
expect(result['const'], equals(false));
expect(result['implicit'], equals(false));
+ expect(result['abstract'], equals(false));
expect(result['signature']['typeParameters'].length, 2);
expect(result['signature']['returnType'], isNotNull);
expect(result['signature']['parameters'].length, 3);
@@ -943,6 +950,60 @@
expect(result['_deoptimizations'], isZero);
},
+ // abstract function.
+ (Isolate isolate) async {
+ // Call eval to get a class id.
+ var evalResult = await invoke(isolate, 'getDummyClass');
+ var result = await isolate.invokeRpcNoUpgrade('getObject', {
+ 'objectId': evalResult['class']['id'],
+ });
+ expect(result['type'], equals('Class'));
+ expect(result['id'], startsWith('classes/'));
+ expect(result['name'], equals('_DummyClass'));
+ expect(result['abstract'], equals(false));
+
+ // Get the super class.
+ var superClass = await isolate.invokeRpcNoUpgrade('getObject', {
+ 'objectId': result['super']['id'],
+ });
+ expect(superClass['type'], equals('Class'));
+ expect(superClass['id'], startsWith('classes/'));
+ expect(superClass['name'], equals('_DummyAbstractBaseClass'));
+ expect(superClass['abstract'], equals(true));
+
+ // Find the abstract dummyFunction on the super class.
+ var funcId = superClass['functions']
+ .firstWhere((f) => f['name'] == 'dummyFunction')['id'];
+ var funcResult = await isolate.invokeRpcNoUpgrade('getObject', {
+ 'objectId': funcId,
+ });
+
+ expect(funcResult['type'], equals('Function'));
+ expect(funcResult['id'], equals(funcId));
+ expect(funcResult['name'], equals('dummyFunction'));
+ expect(funcResult['_kind'], equals('RegularFunction'));
+ expect(funcResult['static'], equals(false));
+ expect(funcResult['const'], equals(false));
+ expect(funcResult['implicit'], equals(false));
+ expect(funcResult['abstract'], equals(true));
+ expect(funcResult['signature']['typeParameters'], isNull);
+ expect(funcResult['signature']['returnType'], isNotNull);
+ expect(funcResult['signature']['parameters'].length, 3);
+ expect(funcResult['signature']['parameters'][1]['parameterType']['name'],
+ equals('int'));
+ expect(funcResult['signature']['parameters'][1]['fixed'], isTrue);
+ expect(funcResult['signature']['parameters'][2]['parameterType']['name'],
+ equals('bool'));
+ expect(funcResult['signature']['parameters'][2]['fixed'], isFalse);
+ expect(funcResult['location']['type'], equals('SourceLocation'));
+ expect(funcResult['code']['type'], equals('@Code'));
+ expect(funcResult['_optimizable'], equals(true));
+ expect(funcResult['_inlinable'], equals(true));
+ expect(funcResult['_usageCounter'], isZero);
+ expect(funcResult['_optimizedCallSiteCount'], isZero);
+ expect(funcResult['_deoptimizations'], isZero);
+ },
+
// invalid function.
(Isolate isolate) async {
// Call eval to get a class id.
@@ -1002,6 +1063,7 @@
expect(result['static'], equals(true));
expect(result['const'], equals(false));
expect(result['implicit'], equals(false));
+ expect(result['abstract'], equals(false));
expect(result['signature']['typeParameters'], isNull);
expect(result['signature']['returnType'], isNotNull);
expect(result['signature']['parameters'].length, 0);
@@ -1030,6 +1092,7 @@
expect(result['static'], equals(false));
expect(result['const'], equals(false));
expect(result['implicit'], equals(false));
+ expect(result['abstract'], equals(false));
expect(result['signature']['typeParameters'], isNull);
expect(result['signature']['returnType'], isNotNull);
expect(result['signature']['parameters'].length, 1);
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 2e89731..bf51c64 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], 'Version');
expect(result['major'], 3);
- expect(result['minor'], 57);
+ expect(result['minor'], 59);
expect(result['_privateMajor'], 0);
expect(result['_privateMinor'], 0);
},
diff --git a/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
index 9c45a9e..20c65ff 100644
--- a/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
@@ -11,10 +11,15 @@
import 'service_test_common.dart';
import 'test_helper.dart';
-class _DummyClass {
+abstract class _DummyAbstractBaseClass {
+ void dummyFunction(int a, [bool b = false]);
+}
+
+class _DummyClass extends _DummyAbstractBaseClass {
static var dummyVar = 11;
final List<String> dummyList = new List<String>.filled(20, null);
static var dummyVarWithInit = foo();
+ @override
void dummyFunction(int a, [bool b = false]) {}
void dummyGenericFunction<K, V>(K a, {V param}) {}
static List foo() => List<String>.filled(20, '');
@@ -886,6 +891,7 @@
expect(result['static'], equals(false));
expect(result['const'], equals(false));
expect(result['implicit'], equals(false));
+ expect(result['abstract'], equals(false));
expect(result['signature']['typeParameters'], isNull);
expect(result['signature']['returnType'], isNotNull);
expect(result['signature']['parameters'].length, 3);
@@ -920,6 +926,7 @@
expect(result['static'], equals(false));
expect(result['const'], equals(false));
expect(result['implicit'], equals(false));
+ expect(result['abstract'], equals(false));
expect(result['signature']['typeParameters'].length, 2);
expect(result['signature']['returnType'], isNotNull);
expect(result['signature']['parameters'].length, 3);
@@ -940,6 +947,60 @@
expect(result['_deoptimizations'], isZero);
},
+ // abstract function.
+ (Isolate isolate) async {
+ // Call eval to get a class id.
+ var evalResult = await invoke(isolate, 'getDummyClass');
+ var result = await isolate.invokeRpcNoUpgrade('getObject', {
+ 'objectId': evalResult['class']['id'],
+ });
+ expect(result['type'], equals('Class'));
+ expect(result['id'], startsWith('classes/'));
+ expect(result['name'], equals('_DummyClass'));
+ expect(result['abstract'], equals(false));
+
+ // Get the super class.
+ var superClass = await isolate.invokeRpcNoUpgrade('getObject', {
+ 'objectId': result['super']['id'],
+ });
+ expect(superClass['type'], equals('Class'));
+ expect(superClass['id'], startsWith('classes/'));
+ expect(superClass['name'], equals('_DummyAbstractBaseClass'));
+ expect(superClass['abstract'], equals(true));
+
+ // Find the abstract dummyFunction on the super class.
+ var funcId = superClass['functions']
+ .firstWhere((f) => f['name'] == 'dummyFunction')['id'];
+ var funcResult = await isolate.invokeRpcNoUpgrade('getObject', {
+ 'objectId': funcId,
+ });
+
+ expect(funcResult['type'], equals('Function'));
+ expect(funcResult['id'], equals(funcId));
+ expect(funcResult['name'], equals('dummyFunction'));
+ expect(funcResult['_kind'], equals('RegularFunction'));
+ expect(funcResult['static'], equals(false));
+ expect(funcResult['const'], equals(false));
+ expect(funcResult['implicit'], equals(false));
+ expect(funcResult['abstract'], equals(true));
+ expect(funcResult['signature']['typeParameters'], isNull);
+ expect(funcResult['signature']['returnType'], isNotNull);
+ expect(funcResult['signature']['parameters'].length, 3);
+ expect(funcResult['signature']['parameters'][1]['parameterType']['name'],
+ equals('int'));
+ expect(funcResult['signature']['parameters'][1]['fixed'], isTrue);
+ expect(funcResult['signature']['parameters'][2]['parameterType']['name'],
+ equals('bool'));
+ expect(funcResult['signature']['parameters'][2]['fixed'], isFalse);
+ expect(funcResult['location']['type'], equals('SourceLocation'));
+ expect(funcResult['code']['type'], equals('@Code'));
+ expect(funcResult['_optimizable'], equals(true));
+ expect(funcResult['_inlinable'], equals(true));
+ expect(funcResult['_usageCounter'], isZero);
+ expect(funcResult['_optimizedCallSiteCount'], isZero);
+ expect(funcResult['_deoptimizations'], isZero);
+ },
+
// invalid function.
(Isolate isolate) async {
// Call eval to get a class id.
@@ -1032,6 +1093,7 @@
expect(result['static'], equals(true));
expect(result['const'], equals(false));
expect(result['implicit'], equals(false));
+ expect(result['abstract'], equals(false));
expect(result['signature']['typeParameters'], isNull);
expect(result['signature']['returnType'], isNotNull);
expect(result['signature']['parameters'].length, 0);
diff --git a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
index 451c93e..4bb45af 100644
--- a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], equals('Version'));
expect(result['major'], equals(3));
- expect(result['minor'], equals(57));
+ expect(result['minor'], equals(59));
expect(result['_privateMajor'], equals(0));
expect(result['_privateMinor'], equals(0));
},
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 8af3c49..c6f1d55 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -5194,12 +5194,16 @@
// if (controller.add(<expr>)) {
// return;
// }
- // suspend();
+ // if (suspend()) {
+ // return;
+ // }
//
// Generate the following code for yield* <expr>:
//
// _AsyncStarStreamController controller = :suspend_state._functionData;
- // controller.addStream(<expr>);
+ // if (controller.addStream(<expr>)) {
+ // return;
+ // }
// if (suspend()) {
// return;
// }
@@ -5215,31 +5219,25 @@
instructions +=
StaticCall(TokenPosition::kNoSource, add_method, 2, ICData::kNoRebind);
- if (is_yield_star) {
- // Discard result of _AsyncStarStreamController.addStream().
- instructions += Drop();
- // Suspend and test value passed to the resumed async* body.
- instructions += NullConstant();
- instructions += B->Suspend(pos, SuspendInstr::StubId::kYieldAsyncStar);
- } else {
- // Test value returned by _AsyncStarStreamController.add().
- }
+ TargetEntryInstr *return1, *continue1;
+ instructions += BranchIfTrue(&return1, &continue1, false);
+ JoinEntryInstr* return_join = BuildJoinEntry();
+ Fragment(return1) + Goto(return_join);
+ instructions = Fragment(instructions.entry, continue1);
- TargetEntryInstr* exit;
- TargetEntryInstr* continue_execution;
- instructions += BranchIfTrue(&exit, &continue_execution, false);
+ // Suspend and test value passed to the resumed async* body.
+ instructions += NullConstant();
+ instructions += B->Suspend(pos, SuspendInstr::StubId::kYieldAsyncStar);
- Fragment do_exit(exit);
- do_exit += TranslateFinallyFinalizers(nullptr, -1);
- do_exit += NullConstant();
- do_exit += Return(TokenPosition::kNoSource);
+ TargetEntryInstr *return2, *continue2;
+ instructions += BranchIfTrue(&return2, &continue2, false);
+ Fragment(return2) + Goto(return_join);
+ instructions = Fragment(instructions.entry, continue2);
- instructions = Fragment(instructions.entry, continue_execution);
- if (!is_yield_star) {
- instructions += NullConstant();
- instructions += B->Suspend(pos, SuspendInstr::StubId::kYieldAsyncStar);
- instructions += Drop();
- }
+ Fragment do_return(return_join);
+ do_return += TranslateFinallyFinalizers(nullptr, -1);
+ do_return += NullConstant();
+ do_return += Return(TokenPosition::kNoSource);
} else if (parsed_function()->function().IsSyncGenerator()) {
// In the sync* functions, generate the following code for yield <expr>:
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 1d11933..41da4b4 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -341,6 +341,7 @@
jsobj.AddProperty("static", is_static());
jsobj.AddProperty("const", is_const());
jsobj.AddProperty("implicit", IsImplicitGetterOrSetter());
+ jsobj.AddProperty("abstract", is_abstract());
jsobj.AddProperty("_intrinsic", is_intrinsic());
jsobj.AddProperty("_native", is_native());
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index b168abc..2df9119 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -5890,7 +5890,7 @@
"\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
"\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
"\"_kind\":\"RegularFunction\",\"static\":false,\"const\":false,"
- "\"implicit\":false,"
+ "\"implicit\":false,\"abstract\":false,"
"\"_intrinsic\":false,\"_native\":false,"
"\"location\":{\"type\":\"SourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index b8e3124..38a0bf6 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -17,7 +17,7 @@
namespace dart {
#define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 57
+#define SERVICE_PROTOCOL_MINOR_VERSION 59
class Array;
class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 4c873ec..622ea1d 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,4 +1,4 @@
-# Dart VM Service Protocol 3.58
+# Dart VM Service Protocol 3.59
> Please post feedback to the [observatory-discuss group][discuss-list]
@@ -2596,6 +2596,9 @@
// Is this function implicitly defined (e.g., implicit getter/setter)?
bool implicit;
+ // Is this function an abstract method?
+ bool abstract;
+
// The location of this function in the source code.
//
// Note: this may not agree with the location of `owner` if this is a function
@@ -2628,6 +2631,9 @@
// Is this function implicitly defined (e.g., implicit getter/setter)?
bool implicit;
+ // Is this function an abstract method?
+ bool abstract;
+
// The location of this function in the source code.
//
// Note: this may not agree with the location of `owner` if this is a function
@@ -4372,5 +4378,6 @@
3.56 | Added optional `line` and `column` properties to `SourceLocation`. Added a new `SourceReportKind`, `BranchCoverage`, which reports branch level coverage information.
3.57 | Added optional `libraryFilters` parameter to `getSourceReport` RPC.
3.58 | Added optional `local` parameter to `lookupResolvedPackageUris` RPC.
+3.59 | Added `abstract` property to `@Function` and `Function`.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
index 34a00bf..22ef9de 100644
--- a/runtime/vm/source_report_test.cc
+++ b/runtime/vm/source_report_test.cc
@@ -603,7 +603,7 @@
"\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
"\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},"
"\"_kind\":\"RegularFunction\",\"static\":true,\"const\":false,"
- "\"implicit\":false,"
+ "\"implicit\":false,\"abstract\":false,"
"\"_intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
"\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
"\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
@@ -687,8 +687,8 @@
"\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
"\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
"},\"_kind\":\"RegularFunction\","
- "\"static\":false,\"const\":false,\"implicit\":false,\"_intrinsic\":"
- "false,"
+ "\"static\":false,\"const\":false,\"implicit\":false,\"abstract\":"
+ "false,\"_intrinsic\":false,"
"\"_native\":false,"
"\"location\":{\"type\":\"SourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
@@ -723,8 +723,8 @@
"\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
"\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
"},\"_kind\":\"RegularFunction\","
- "\"static\":false,\"const\":false,\"implicit\":false,\"_intrinsic\":"
- "false,"
+ "\"static\":false,\"const\":false,\"implicit\":false,\"abstract\":"
+ "false,\"_intrinsic\":false,"
"\"_native\":false,"
"\"location\":{\"type\":\"SourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
@@ -782,7 +782,7 @@
"\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
"\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},\"_"
"kind\":\"RegularFunction\",\"static\":true,\"const\":false,\"implicit\":"
- "false,\"_"
+ "false,\"abstract\":false,\"_"
"intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
"\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
"\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index c0d480e..4e27366 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -46,13 +46,6 @@
bool isSuspendedAtYield = false;
_Future? cancellationFuture = null;
- /// Argument passed to the generator when it is resumed after an addStream.
- ///
- /// `true` if the generator should exit after `yield*` resumes.
- /// `false` if the generator should continue after `yield*` resumes.
- /// `null` otherwies.
- bool? continuationArgument = null;
-
Stream<T> get stream {
final Stream<T> local = controller.stream;
if (local is _StreamImpl<T>) {
@@ -64,9 +57,7 @@
void runBody() {
isScheduled = false;
isSuspendedAtYield = false;
- final bool? argument = continuationArgument;
- continuationArgument = null;
- asyncStarBody!(argument);
+ asyncStarBody!(!controller.hasListener);
}
void scheduleGenerator() {
@@ -77,16 +68,8 @@
scheduleMicrotask(runBody);
}
- // Adds element to stream, returns true if the caller should terminate
- // execution of the generator.
- //
- // TODO(hausner): Per spec, the generator should be suspended before
- // exiting when the stream is closed. We could add a getter like this:
- // get isCancelled => controller.hasListener;
- // The generator would translate a 'yield e' statement to
- // controller.add(e);
- // suspend;
- // if (controller.isCancelled) return;
+ // Adds element to stream.
+ // Returns true if the caller should terminate execution of the generator.
@pragma("vm:entry-point", "call")
bool add(T event) {
if (!onListenReceived) _fatal("yield before stream is listened to");
@@ -104,40 +87,23 @@
// Adds the elements of stream into this controller's stream.
// The generator will be scheduled again when all of the
// elements of the added stream have been consumed.
+ // Returns true if the caller should terminate execution of the generator.
@pragma("vm:entry-point", "call")
- void addStream(Stream<T> stream) {
+ bool addStream(Stream<T> stream) {
if (!onListenReceived) _fatal("yield before stream is listened to");
-
- if (exitAfterYieldStarIfCancelled()) return;
+ if (!controller.hasListener) {
+ return true;
+ }
isAdding = true;
final whenDoneAdding = controller.addStream(stream, cancelOnError: false);
whenDoneAdding.then((_) {
isAdding = false;
- if (exitAfterYieldStarIfCancelled()) return;
- resumeNormallyAfterYieldStar();
- });
- }
-
- /// Schedules the generator to exit after `yield*` if stream was cancelled.
- ///
- /// Returns `true` if generator is told to exit and `false` otherwise.
- bool exitAfterYieldStarIfCancelled() {
- // If consumer cancelled subscription we should tell async* generator to
- // finish (i.e. run finally clauses and return).
- if (!controller.hasListener) {
- continuationArgument = true;
scheduleGenerator();
- return true;
- }
- return false;
- }
+ if (!isScheduled) isSuspendedAtYield = true;
+ });
- /// Schedules the generator to resume normally after `yield*`.
- void resumeNormallyAfterYieldStar() {
- continuationArgument = false;
- scheduleGenerator();
- if (!isScheduled) isSuspendedAtYield = true;
+ return false;
}
void addError(Object error, StackTrace stackTrace) {
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index 3da1875..b6a2a6d 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -194,7 +194,7 @@
///
/// The result `r` of this operation satisfies:
/// `this == (this ~/ other) * other + r`.
- /// As a consequence, the remainder `r` has the same sign as the divider
+ /// As a consequence, the remainder `r` has the same sign as the dividend
/// `this`.
///
/// The result is an [int], as described by [int.remainder],
diff --git a/tests/language/language_precompiled.status b/tests/language/language_precompiled.status
index 4850aa0..dc151ee 100644
--- a/tests/language/language_precompiled.status
+++ b/tests/language/language_precompiled.status
@@ -15,8 +15,6 @@
[ $compiler == dartkp && $runtime == dart_precompiled ]
async_star/async_star_await_for_test: RuntimeError
-async_star/async_star_cancel_test: RuntimeError
-async_star/async_star_test: RuntimeError
[ $runtime == dart_precompiled && $minified ]
enum/duplicate_test/*: Skip # Uses Enum.toString()
diff --git a/tests/language/language_vm.status b/tests/language/language_vm.status
index 2d01341..2112263 100644
--- a/tests/language/language_vm.status
+++ b/tests/language/language_vm.status
@@ -18,8 +18,6 @@
[ $runtime == vm ]
async_star/async_star_await_for_test: RuntimeError
-async_star/async_star_cancel_test: RuntimeError
-async_star/async_star_test: RuntimeError
[ $arch == arm64 && $runtime == vm ]
class/large_class_declaration_test: SkipSlow # Uses too much memory.
diff --git a/tests/language_2/language_2_precompiled.status b/tests/language_2/language_2_precompiled.status
index 4850aa0..dc151ee 100644
--- a/tests/language_2/language_2_precompiled.status
+++ b/tests/language_2/language_2_precompiled.status
@@ -15,8 +15,6 @@
[ $compiler == dartkp && $runtime == dart_precompiled ]
async_star/async_star_await_for_test: RuntimeError
-async_star/async_star_cancel_test: RuntimeError
-async_star/async_star_test: RuntimeError
[ $runtime == dart_precompiled && $minified ]
enum/duplicate_test/*: Skip # Uses Enum.toString()
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index 2d01341..2112263 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -18,8 +18,6 @@
[ $runtime == vm ]
async_star/async_star_await_for_test: RuntimeError
-async_star/async_star_cancel_test: RuntimeError
-async_star/async_star_test: RuntimeError
[ $arch == arm64 && $runtime == vm ]
class/large_class_declaration_test: SkipSlow # Uses too much memory.
diff --git a/tools/VERSION b/tools/VERSION
index 62109bd..184c75e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 19
PATCH 0
-PRERELEASE 3
+PRERELEASE 4
PRERELEASE_PATCH 0
\ No newline at end of file