Version 2.18.0-23.0.dev
Merge commit '169365f9530252bdf1131e6bff3fa8c4233d7aba' into 'dev'
diff --git a/pkg/analysis_server/test/edit/bulk_fixes_test.dart b/pkg/analysis_server/test/edit/bulk_fixes_test.dart
index 00c07ca..b728b9b 100644
--- a/pkg/analysis_server/test/edit/bulk_fixes_test.dart
+++ b/pkg/analysis_server/test/edit/bulk_fixes_test.dart
@@ -267,6 +267,7 @@
}
Future<EditBulkFixesResult> _getBulkFixes() async {
+ // TODO(scheglov) Remove this, we want to see if lines change.
var request = EditBulkFixesParams([workspaceRoot.path]).toRequest('0');
var response = await handleSuccessfulRequest(request);
return EditBulkFixesResult.fromResponse(response);
diff --git a/pkg/analysis_server/test/edit/refactoring_test.dart b/pkg/analysis_server/test/edit/refactoring_test.dart
index 910154e..df8fe1c 100644
--- a/pkg/analysis_server/test/edit/refactoring_test.dart
+++ b/pkg/analysis_server/test/edit/refactoring_test.dart
@@ -10,7 +10,6 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../analysis_abstract.dart';
import '../analysis_server_base.dart';
import '../mocks.dart';
import '../src/utilities/mock_packages.dart';
@@ -841,16 +840,14 @@
}
@reflectiveTest
-class GetAvailableRefactoringsTest extends AbstractAnalysisTest {
+class GetAvailableRefactoringsTest extends PubPackageAnalysisServerTest {
late List<RefactoringKind> kinds;
void addFlutterPackage() {
var flutterLib = MockPackages.instance.addFlutter(resourceProvider);
- newPackageConfigJsonFile(
- projectPath,
- (PackageConfigFileBuilder()
- ..add(name: 'flutter', rootPath: flutterLib.parent.path))
- .toContent(toUriStr: toUriStr),
+ writeTestPackageConfig(
+ config: PackageConfigFileBuilder()
+ ..add(name: 'flutter', rootPath: flutterLib.parent.path),
);
}
@@ -877,8 +874,9 @@
/// Returns the list of available refactorings for the given [offset] and
/// [length].
Future getRefactorings(int offset, int length) async {
- var request = EditGetAvailableRefactoringsParams(testFile, offset, length)
- .toRequest('0');
+ var request =
+ EditGetAvailableRefactoringsParams(testFile.path, offset, length)
+ .toRequest('0');
serverChannel.sendRequest(request);
var response = await serverChannel.waitForResponse(request);
var result = EditGetAvailableRefactoringsResult.fromResponse(response);
@@ -899,9 +897,7 @@
@override
Future<void> setUp() async {
super.setUp();
- await createProject();
- handler = EditDomainHandler(server);
- server.handlers = [handler];
+ await setRoots(included: [workspaceRootPath], excluded: []);
}
Future test_convertMethodToGetter_hasElement() {
@@ -954,10 +950,11 @@
Future<void> test_invalidFilePathFormat_notAbsolute() async {
var request =
EditGetAvailableRefactoringsParams('test.dart', 0, 0).toRequest('0');
- var response = await waitResponse(request);
- expect(
+ var response = await handleRequest(request);
+ assertResponseFailure(
response,
- isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+ requestId: '0',
+ errorCode: RequestErrorCode.INVALID_FILE_PATH_FORMAT,
);
}
@@ -965,10 +962,11 @@
var request = EditGetAvailableRefactoringsParams(
convertPath('/foo/../bar/test.dart'), 0, 0)
.toRequest('0');
- var response = await waitResponse(request);
- expect(
+ var response = await handleRequest(request);
+ assertResponseFailure(
response,
- isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+ requestId: '0',
+ errorCode: RequestErrorCode.INVALID_FILE_PATH_FORMAT,
);
}
diff --git a/pkg/analysis_server/test/src/domain_abstract_test.dart b/pkg/analysis_server/test/src/domain_abstract_test.dart
index 33c09fa..12e9cf5 100644
--- a/pkg/analysis_server/test/src/domain_abstract_test.dart
+++ b/pkg/analysis_server/test/src/domain_abstract_test.dart
@@ -13,7 +13,7 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../analysis_abstract.dart';
+import '../analysis_server_base.dart';
import 'plugin/plugin_manager_test.dart';
void main() {
@@ -23,7 +23,7 @@
}
@reflectiveTest
-class AbstractRequestHandlerTest extends AbstractAnalysisTest {
+class AbstractRequestHandlerTest extends PubPackageAnalysisServerTest {
Future<void> test_waitForResponses_empty_noTimeout() async {
AbstractRequestHandler handler = TestAbstractRequestHandler(server);
var futures = <PluginInfo, Future<plugin.Response>>{};
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
index 9fee7ee..5f057a3 100644
--- a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
@@ -5,21 +5,20 @@
import 'dart:convert';
import 'package:analysis_server/protocol/protocol_constants.dart';
-import 'package:analysis_server/src/domain_completion.dart';
import 'package:analysis_server/src/protocol_server.dart';
-import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
+import 'package:analyzer/file_system/file_system.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../../../analysis_abstract.dart';
+import '../../../analysis_server_base.dart';
import '../../../constants.dart';
@reflectiveTest
-class AvailableSuggestionsBase extends AbstractAnalysisTest {
+class AvailableSuggestionsBase extends PubPackageAnalysisServerTest {
final Map<int, AvailableSuggestionSet> idToSetMap = {};
final Map<String, AvailableSuggestionSet> uriToSetMap = {};
final Map<String, CompletionResultsParams> idToSuggestions = {};
- final Map<String, ExistingImports> fileToExistingImports = {};
+ final Map<File, ExistingImports> fileToExistingImports = {};
void assertJsonText(Object object, String expected) {
expected = expected.trimRight();
@@ -59,7 +58,7 @@
var params = CompletionExistingImportsParams.fromNotification(
notification,
);
- fileToExistingImports[params.file] = params.imports;
+ fileToExistingImports[getFile(params.file)] = params.imports;
} else if (notification.event == SERVER_NOTIFICATION_ERROR) {
fail('${notification.toJson()}');
}
@@ -75,19 +74,16 @@
@override
Future<void> setUp() async {
super.setUp();
- projectPath = convertPath('/home');
- testFile = convertPath('/home/test/lib/test.dart');
- newPubspecYamlFile('/home/test', '');
- newPackageConfigJsonFile(
- '/home/test',
- (PackageConfigFileBuilder()..add(name: 'test', rootPath: '/home/test'))
- .toContent(toUriStr: toUriStr),
+ newPubspecYamlFile(testPackageRootPath, '');
+ writeTestPackageConfig();
+ await setRoots(included: [workspaceRootPath], excluded: []);
+
+ await handleSuccessfulRequest(
+ CompletionSetSubscriptionsParams([
+ CompletionService.AVAILABLE_SUGGESTION_SETS,
+ ]).toRequest('0'),
);
-
- await createProject();
- handler = server.handlers.whereType<CompletionDomainHandler>().single;
- _setCompletionSubscriptions([CompletionService.AVAILABLE_SUGGESTION_SETS]);
}
Future<CompletionResultsParams> waitForGetSuggestions(String id) async {
@@ -119,10 +115,4 @@
await Future.delayed(const Duration(milliseconds: 1));
}
}
-
- void _setCompletionSubscriptions(List<CompletionService> subscriptions) {
- handleSuccessfulRequest(
- CompletionSetSubscriptionsParams(subscriptions).toRequest('0'),
- );
- }
}
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
index 75ae254..1f6eae4 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/file_system/file_system.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -31,7 +32,7 @@
_buildRequest(
id: set.id,
label: 'MyEnum.aaa',
- offset: testCode.indexOf('} // ref'),
+ offset: testFileContent.indexOf('} // ref'),
),
);
@@ -55,7 +56,7 @@
_buildRequest(
id: mathSet.id,
label: 'sin',
- offset: testCode.indexOf('} // ref'),
+ offset: testFileContent.indexOf('} // ref'),
),
);
@@ -75,7 +76,7 @@
_buildRequest(
id: mathSet.id,
label: 'sin',
- offset: testCode.indexOf('} // ref'),
+ offset: testFileContent.indexOf('} // ref'),
),
);
@@ -86,10 +87,14 @@
Future<void> test_invalid_library() async {
addTestFile('');
- var response = await waitResponse(
+ var response = await handleRequest(
_buildRequest(id: -1, label: 'foo', offset: 0),
);
- expect(response.error!.code, RequestErrorCode.INVALID_PARAMETER);
+ assertResponseFailure(
+ response,
+ requestId: '0',
+ errorCode: RequestErrorCode.INVALID_PARAMETER,
+ );
}
Future<void> test_newImport() async {
@@ -102,7 +107,7 @@
_buildRequest(
id: mathSet.id,
label: 'sin',
- offset: testCode.indexOf('} // ref'),
+ offset: testFileContent.indexOf('} // ref'),
),
);
@@ -131,7 +136,7 @@
_buildRequest(
id: mathSet.id,
label: 'sin',
- offset: testCode.indexOf('} // ref'),
+ offset: testFileContent.indexOf('} // ref'),
),
);
@@ -165,7 +170,7 @@
_buildRequest(
id: mathSet.id,
label: 'sin',
- offset: testCode.indexOf('} // ref'),
+ offset: testFileContent.indexOf('} // ref'),
),
);
@@ -197,7 +202,7 @@
_buildRequest(
id: mathSet.id,
label: 'sin',
- offset: testCode.indexOf('} // ref'),
+ offset: testFileContent.indexOf('} // ref'),
),
);
@@ -218,7 +223,7 @@
main() {} // ref
''';
- var partPath = newFile2('/home/test/lib/a.dart', partCode).path;
+ var partFile = newFile2('/home/test/lib/a.dart', partCode);
addTestFile(r'''
part 'a.dart';
''');
@@ -226,7 +231,7 @@
var mathSet = await waitForSetWithUri('dart:math');
var result = await _getSuggestionDetails(
_buildRequest(
- file: partPath,
+ file: partFile,
id: mathSet.id,
label: 'sin',
offset: partCode.indexOf('} // ref'),
@@ -250,20 +255,20 @@
expect(fileEdits, hasLength(1));
var fileEdit = fileEdits[0];
- expect(fileEdit.file, testFile);
+ expect(fileEdit.file, testFile.path);
var edits = fileEdit.edits;
- expect(SourceEdit.applySequence(testCode, edits), expected);
+ expect(SourceEdit.applySequence(testFileContent, edits), expected);
}
Request _buildRequest({
- String? file,
+ File? file,
required int id,
required String label,
required int offset,
}) {
return CompletionGetSuggestionDetailsParams(
- file ?? testFile,
+ (file ?? testFile).path,
id,
label,
offset,
@@ -272,7 +277,7 @@
Future<CompletionGetSuggestionDetailsResult> _getSuggestionDetails(
Request request) async {
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
return CompletionGetSuggestionDetailsResult.fromResponse(response);
}
}
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
index 8a1b392..725ebab 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/file_system/file_system.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -110,7 +111,7 @@
}
Future<void> test_defaultArgumentListString() async {
- newFile2('/home/test/lib/a.dart', r'''
+ newFile2('$testPackageLibPath/a.dart', r'''
void fff(int aaa, int bbb) {}
void ggg({int aaa, @required int bbb, @required int ccc}) {}
@@ -128,13 +129,13 @@
}
Future<void> test_displayUri_file() async {
- var aPath = '/home/test/test/a.dart';
+ var aPath = '$testPackageRootPath/test/a.dart';
newFile2(aPath, 'class A {}');
var aSet = await waitForSetWithUri(toUriStr(aPath));
- var testPath = newFile2('/home/test/test/sub/test.dart', '').path;
- var results = await _getSuggestions(testPath, 0);
+ var file = newFile2('$testPackageRootPath/test/sub/test.dart', '');
+ var results = await _getSuggestions(file, 0);
expect(
results.includedSuggestionSets!.singleWhere((set) {
@@ -145,13 +146,12 @@
}
Future<void> test_displayUri_package() async {
- var aPath = '/home/test/lib/a.dart';
- newFile2(aPath, 'class A {}');
+ newFile2('$testPackageLibPath/a.dart', 'class A {}');
var aSet = await waitForSetWithUri('package:test/a.dart');
- var testPath = newFile2('/home/test/lib/test.dart', '').path;
+ var file = newFile2('$testPackageLibPath/test.dart', '');
- var results = await _getSuggestions(testPath, 0);
+ var results = await _getSuggestions(file, 0);
expect(
results.includedSuggestionSets!.singleWhere((set) {
return set.id == aSet.id;
@@ -167,7 +167,7 @@
var results = await _getSuggestions(
testFile,
- testCode.indexOf('{} // ref'),
+ testFileContent.indexOf('{} // ref'),
);
expect(
@@ -192,7 +192,7 @@
var results = await _getSuggestions(
testFile,
- testCode.indexOf('); // ref'),
+ testFileContent.indexOf('); // ref'),
);
expect(
@@ -217,13 +217,12 @@
}
Future<void> test_inHtml() async {
- newFile2('/home/test/lib/a.dart', 'class A {}');
+ newFile2('$testPackageLibPath/a.dart', 'class A {}');
- var path = convertPath('/home/test/doc/a.html');
- newFile2(path, '<html></html>');
+ var file = newFile2('$testPackageRoot/doc/a.html', '<html></html>');
- await waitResponse(
- CompletionGetSuggestionsParams(path, 0).toRequest('0'),
+ await handleSuccessfulRequest(
+ CompletionGetSuggestionsParams(file.path, 0).toRequest('0'),
);
}
@@ -238,7 +237,7 @@
var results = await _getSuggestions(
testFile,
- testCode.indexOf('); // ref'),
+ testFileContent.indexOf('); // ref'),
);
var includedTags = results.includedSuggestionRelevanceTags!;
@@ -272,7 +271,7 @@
var results = await _getSuggestions(
testFile,
- testCode.indexOf(' // ref'),
+ testFileContent.indexOf(' // ref'),
);
assertJsonText(results.includedSuggestionRelevanceTags!, r'''
@@ -336,7 +335,7 @@
var results = await _getSuggestions(
testFile,
- testCode.indexOf('); // ref'),
+ testFileContent.indexOf('); // ref'),
);
assertJsonText(results.includedSuggestionRelevanceTags!, r'''
@@ -400,7 +399,7 @@
var results = await _getSuggestions(
testFile,
- testCode.indexOf('); // ref'),
+ testFileContent.indexOf('); // ref'),
);
assertJsonText(results.includedSuggestionRelevanceTags!, r'''
@@ -471,7 +470,7 @@
var results = await _getSuggestions(
testFile,
- testCode.indexOf(' // ref'),
+ testFileContent.indexOf(' // ref'),
);
assertJsonText(results.includedSuggestionRelevanceTags!, r'''
@@ -531,7 +530,7 @@
var results = await _getSuggestions(
testFile,
- testCode.indexOf(' // ref'),
+ testFileContent.indexOf(' // ref'),
);
assertJsonText(results.includedSuggestionRelevanceTags!, r'''
@@ -601,7 +600,7 @@
var results = await _getSuggestions(
testFile,
- testCode.indexOf(']; // ref'),
+ testFileContent.indexOf(']; // ref'),
);
assertJsonText(results.includedSuggestionRelevanceTags!, r'''
@@ -617,12 +616,12 @@
abstract class GetSuggestionsBase extends AvailableSuggestionsBase {
Future<CompletionResultsParams> _getSuggestions(
- String path,
+ File file,
int offset,
) async {
var response = CompletionGetSuggestionsResult.fromResponse(
- await waitResponse(
- CompletionGetSuggestionsParams(path, offset).toRequest('0'),
+ await handleSuccessfulRequest(
+ CompletionGetSuggestionsParams(file.path, offset).toRequest('0'),
),
);
return await waitForGetSuggestions(response.id);
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index ed88f0c..683238e 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1405,7 +1405,8 @@
_provider.setOverlay(filePath,
content: overlayContents,
modificationStamp: overlayModificationStamp++);
- context.driver.changeFile(filePath);
+ context.changeFile(filePath);
+ await context.applyPendingFileChanges();
resolvedUnitResult = await context.currentSession
.getResolvedUnit(filePath) as ResolvedUnitResult;
}
diff --git a/pkg/analyzer/lib/src/summary2/macro_application.dart b/pkg/analyzer/lib/src/summary2/macro_application.dart
index 5ef25c0..2e9a109 100644
--- a/pkg/analyzer/lib/src/summary2/macro_application.dart
+++ b/pkg/analyzer/lib/src/summary2/macro_application.dart
@@ -79,27 +79,7 @@
}
macro.ClassDeclaration getClassDeclaration(ClassDeclaration node) {
- return _classDeclarations[node] ??= _createClassDeclaration(node);
- }
-
- macro.ClassDeclaration _createClassDeclaration(ClassDeclaration node) {
- return macro.ClassDeclarationImpl(
- id: macro.RemoteInstance.uniqueId,
- identifier: _IdentifierImpl(
- id: macro.RemoteInstance.uniqueId,
- name: node.name.name,
- ),
- // TODO(scheglov): Support typeParameters
- typeParameters: [],
- // TODO(scheglov): Support interfaces
- interfaces: [],
- isAbstract: node.abstractKeyword != null,
- isExternal: false,
- // TODO(scheglov): Support mixins
- mixins: [],
- // TODO(scheglov): Support superclass
- superclass: null,
- );
+ return _classDeclarations[node] ??= _buildClassDeclaration(node);
}
macro.TypeAnnotation _inferOmittedType(
@@ -127,6 +107,79 @@
);
return await macroInstance.executeTypesPhase();
}
+
+ static macro.ClassDeclarationImpl _buildClassDeclaration(
+ ClassDeclaration node,
+ ) {
+ return macro.ClassDeclarationImpl(
+ id: macro.RemoteInstance.uniqueId,
+ identifier: _buildIdentifier(node.name),
+ typeParameters: _buildTypeParameters(node.typeParameters),
+ interfaces: _buildTypeAnnotations(node.implementsClause?.interfaces),
+ isAbstract: node.abstractKeyword != null,
+ isExternal: false,
+ mixins: _buildTypeAnnotations(node.withClause?.mixinTypes),
+ superclass: node.extendsClause?.superclass.mapOrNull(
+ _buildTypeAnnotation,
+ ),
+ );
+ }
+
+ static macro.IdentifierImpl _buildIdentifier(Identifier node) {
+ final String name;
+ if (node is SimpleIdentifier) {
+ name = node.name;
+ } else {
+ name = (node as PrefixedIdentifier).identifier.name;
+ }
+ return _IdentifierImpl(
+ id: macro.RemoteInstance.uniqueId,
+ name: name,
+ );
+ }
+
+ static macro.TypeAnnotationImpl _buildTypeAnnotation(TypeAnnotation node) {
+ if (node is NamedType) {
+ return macro.NamedTypeAnnotationImpl(
+ id: macro.RemoteInstance.uniqueId,
+ identifier: _buildIdentifier(node.name),
+ isNullable: node.question != null,
+ typeArguments: _buildTypeAnnotations(node.typeArguments?.arguments),
+ );
+ } else {
+ throw UnimplementedError('(${node.runtimeType}) $node');
+ }
+ }
+
+ static List<macro.TypeAnnotationImpl> _buildTypeAnnotations(
+ List<TypeAnnotation>? elements,
+ ) {
+ if (elements != null) {
+ return elements.map(_buildTypeAnnotation).toList();
+ } else {
+ return const [];
+ }
+ }
+
+ static macro.TypeParameterDeclarationImpl _buildTypeParameter(
+ TypeParameter node,
+ ) {
+ return macro.TypeParameterDeclarationImpl(
+ id: macro.RemoteInstance.uniqueId,
+ identifier: _buildIdentifier(node.name),
+ bound: node.bound?.mapOrNull(_buildTypeAnnotation),
+ );
+ }
+
+ static List<macro.TypeParameterDeclarationImpl> _buildTypeParameters(
+ TypeParameterList? typeParameterList,
+ ) {
+ if (typeParameterList != null) {
+ return typeParameterList.typeParameters.map(_buildTypeParameter).toList();
+ } else {
+ return const [];
+ }
+ }
}
class _FakeIdentifierResolver extends macro.IdentifierResolver {
@@ -146,3 +199,10 @@
bool get isNotEmpty =>
libraryAugmentations.isNotEmpty || classAugmentations.isNotEmpty;
}
+
+extension _IfNotNull<T> on T? {
+ R? mapOrNull<R>(R Function(T) mapper) {
+ final self = this;
+ return self != null ? mapper(self) : null;
+ }
+}
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 5790c59..cfe45a8 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -109,7 +109,7 @@
// Print the actual text to simplify copy/paste into the expectation.
// if (actualText != expected) {
// print('-------- Actual --------');
- // print(actualText + '------------------------');
+ // print('$actualText------------------------');
// }
expect(actualText, expected);
diff --git a/pkg/analyzer/test/src/summary/macro/declaration_text.dart b/pkg/analyzer/test/src/summary/macro/declaration_text.dart
new file mode 100644
index 0000000..066c9b6
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/macro/declaration_text.dart
@@ -0,0 +1,179 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+/*macro*/ class DeclarationTextMacro implements ClassTypesMacro {
+ const DeclarationTextMacro();
+
+ @override
+ FutureOr<void> buildTypesForClass(declaration, builder) {
+ final printer = _DeclarationPrinter();
+ printer.writeClassDeclaration(declaration);
+ final text = printer._sink.toString();
+
+ builder.declareType(
+ 'x',
+ DeclarationCode.fromString(
+ 'const x = r"""$text""";',
+ ),
+ );
+ }
+}
+
+class _DeclarationPrinter {
+ final StringBuffer _sink = StringBuffer();
+ String _indent = '';
+
+ void writeClassDeclaration(ClassDeclaration e) {
+ _writeIf(e.isAbstract, 'abstract ');
+ _writeIf(e.isExternal, 'external ');
+
+ _writeln('class ${e.identifier.name}');
+
+ _withIndent(() {
+ var superclass = e.superclass;
+ if (superclass != null) {
+ _writeTypeAnnotation('superclass', superclass);
+ }
+
+ _writeTypeParameters(e.typeParameters);
+ _writeTypeAnnotations('mixins', e.mixins);
+ _writeTypeAnnotations('interfaces', e.interfaces);
+ });
+ }
+
+ void _withIndent(void Function() f) {
+ var savedIndent = _indent;
+ _indent = '$savedIndent ';
+ f();
+ _indent = savedIndent;
+ }
+
+ void _writeElements<T>(
+ String name,
+ Iterable<T> elements,
+ void Function(T) f,
+ ) {
+ if (elements.isNotEmpty) {
+ _writelnWithIndent(name);
+ _withIndent(() {
+ for (var element in elements) {
+ f(element);
+ }
+ });
+ }
+ }
+
+ void _writeIf(bool flag, String str) {
+ if (flag) {
+ _sink.write(str);
+ }
+ }
+
+ void _writeln(String line) {
+ _sink.writeln(line);
+ }
+
+ void _writelnWithIndent(String line) {
+ _sink.write(_indent);
+ _sink.writeln(line);
+ }
+
+ void _writeTypeAnnotation(String name, TypeAnnotation? type) {
+ _sink.write(_indent);
+ _sink.write('$name: ');
+
+ if (type != null) {
+ _writeln(_typeStr(type));
+ } else {
+ _writeln('null');
+ }
+ }
+
+ void _writeTypeAnnotationLine(TypeAnnotation type) {
+ var typeStr = _typeStr(type);
+ _writelnWithIndent(typeStr);
+ }
+
+ void _writeTypeAnnotations(String name, Iterable<TypeAnnotation> elements) {
+ _writeElements(name, elements, _writeTypeAnnotationLine);
+ }
+
+ void _writeTypeParameter(TypeParameterDeclaration e) {
+ _writelnWithIndent(e.identifier.name);
+
+ _withIndent(() {
+ var bound = e.bound;
+ if (bound != null) {
+ _writeTypeAnnotation('bound', bound);
+ }
+ });
+ }
+
+ void _writeTypeParameters(Iterable<TypeParameterDeclaration> elements) {
+ _writeElements('typeParameters', elements, _writeTypeParameter);
+ }
+
+ static String _typeStr(TypeAnnotation type) {
+ final buffer = StringBuffer();
+ _TypeStringBuilder(buffer).write(type);
+ return buffer.toString();
+ }
+}
+
+class _TypeStringBuilder {
+ final StringSink _sink;
+
+ _TypeStringBuilder(this._sink);
+
+ void write(TypeAnnotation type) {
+ if (type is NamedTypeAnnotation) {
+ _sink.write(type.identifier.name);
+ _sink.writeList(
+ elements: type.typeArguments,
+ write: write,
+ separator: ', ',
+ open: '<',
+ close: '>',
+ );
+ } else {
+ throw UnimplementedError('(${type.runtimeType}) $type');
+ }
+ if (type.isNullable) {
+ _sink.write('?');
+ }
+ }
+}
+
+extension on StringSink {
+ void writeList<T>({
+ required Iterable<T> elements,
+ required void Function(T element) write,
+ required String separator,
+ String? open,
+ String? close,
+ }) {
+ elements = elements.toList();
+ if (elements.isNotEmpty) {
+ if (open != null) {
+ this.write(open);
+ }
+ var isFirst = true;
+ for (var element in elements) {
+ if (isFirst) {
+ isFirst = false;
+ } else {
+ this.write(separator);
+ }
+ write(element);
+ }
+ if (close != null) {
+ this.write(close);
+ }
+ }
+ }
+}
diff --git a/pkg/analyzer/test/src/summary/macro_test.dart b/pkg/analyzer/test/src/summary/macro_test.dart
index c46dce0..c32eac5 100644
--- a/pkg/analyzer/test/src/summary/macro_test.dart
+++ b/pkg/analyzer/test/src/summary/macro_test.dart
@@ -4,6 +4,8 @@
import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
as macro;
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -46,6 +48,14 @@
/// The path for external packages.
String get packagesRootPath => '/packages';
+ /// Return the code for `DeclarationTextMacro`.
+ String get _declarationTextCode {
+ var code = MacrosEnvironment.instance.packageAnalyzerFolder
+ .getChildAssumingFile('test/src/summary/macro/declaration_text.dart')
+ .readAsStringSync();
+ return code.replaceAll('/*macro*/', 'macro');
+ }
+
Future<void> setUp() async {
writeTestPackageConfig(
PackageConfigFileBuilder(),
@@ -87,7 +97,9 @@
{'package:test/a.dart'}
]);
- checkElementText(library, r'''
+ checkElementText(
+ library,
+ r'''
library
imports
package:test/a.dart
@@ -113,10 +125,83 @@
class MyClass @6
constructors
synthetic @-1
+ exportScope
+ A: package:test/test.dart;A
+ MyClass: package:test/test.dart;package:test/_macro_types.dart;MyClass
+''',
+ withExportScope: true);
+ }
+
+ test_introspect_types_ClassDeclaration_interfaces() async {
+ await _assertTypesPhaseIntrospectionText(r'''
+class A implements B, C<int, String> {}
+''', r'''
+class A
+ interfaces
+ B
+ C<int, String>
''');
}
- test_class_macro() async {
+ test_introspect_types_ClassDeclaration_isAbstract() async {
+ await _assertTypesPhaseIntrospectionText(r'''
+abstract class A {}
+''', r'''
+abstract class A
+''');
+ }
+
+ test_introspect_types_ClassDeclaration_mixins() async {
+ await _assertTypesPhaseIntrospectionText(r'''
+class A with B, C<int, String> {}
+''', r'''
+class A
+ mixins
+ B
+ C<int, String>
+''');
+ }
+
+ test_introspect_types_ClassDeclaration_superclass() async {
+ await _assertTypesPhaseIntrospectionText(r'''
+class A extends B {}
+''', r'''
+class A
+ superclass: B
+''');
+ }
+
+ test_introspect_types_ClassDeclaration_superclass_nullable() async {
+ await _assertTypesPhaseIntrospectionText(r'''
+class A extends B<int?> {}
+''', r'''
+class A
+ superclass: B<int?>
+''');
+ }
+
+ test_introspect_types_ClassDeclaration_superclass_typeArguments() async {
+ await _assertTypesPhaseIntrospectionText(r'''
+class A extends B<String, List<int>> {}
+''', r'''
+class A
+ superclass: B<String, List<int>>
+''');
+ }
+
+ test_introspect_types_ClassDeclaration_typeParameters() async {
+ await _assertTypesPhaseIntrospectionText(r'''
+class A<T, U extends List<T>> {}
+''', r'''
+class A
+ typeParameters
+ T
+ U
+ bound: List<T>
+''');
+ }
+
+ test_macroFlag_class() async {
var library = await buildLibrary(r'''
macro class A {}
''');
@@ -130,7 +215,7 @@
''');
}
- test_classAlias_macro() async {
+ test_macroFlag_classAlias() async {
var library = await buildLibrary(r'''
mixin M {}
macro class A = Object with M;
@@ -186,4 +271,46 @@
),
);
}
+
+ /// Assert that the textual dump of the introspection information for
+ /// the first declaration in [declarationCode] is the same as [expected].
+ Future<void> _assertTypesPhaseIntrospectionText(
+ String declarationCode, String expected) async {
+ var actual = await _getDeclarationText(declarationCode);
+ if (actual != expected) {
+ print(actual);
+ }
+ expect(actual, expected);
+ }
+
+ /// The [declarationCode] is expected to start with a declaration. It may
+ /// include other declaration below, for example to reference them in
+ /// the first declaration.
+ ///
+ /// Use `DeclarationTextMacro` to generate a library that produces exactly
+ /// one part, with exactly one top-level constant `x`, with a string
+ /// literal initializer. We expect that the value of this literal is
+ /// the textual dump of the introspection information for the first
+ /// declaration.
+ Future<String> _getDeclarationText(String declarationCode) async {
+ newFile2(
+ '$testPackageLibPath/declaration_text.dart',
+ _declarationTextCode,
+ );
+
+ var library = await buildLibrary('''
+import 'declaration_text.dart';
+
+@DeclarationTextMacro()
+$declarationCode
+''', preBuildSequence: [
+ {'package:test/declaration_text.dart'}
+ ]);
+
+ var x = library.parts.single.topLevelVariables.single;
+ expect(x.name, 'x');
+ x as ConstTopLevelVariableElementImpl;
+ var x_literal = x.constantInitializer as SimpleStringLiteral;
+ return x_literal.value;
+ }
}
diff --git a/pkg/analyzer/test/src/summary/repository_macro_kernel_builder.dart b/pkg/analyzer/test/src/summary/repository_macro_kernel_builder.dart
index 8af654a..e178097 100644
--- a/pkg/analyzer/test/src/summary/repository_macro_kernel_builder.dart
+++ b/pkg/analyzer/test/src/summary/repository_macro_kernel_builder.dart
@@ -96,6 +96,7 @@
final _resourceProvider = MemoryResourceProvider(context: package_path.posix);
late final Uint8List platformDillBytes;
+ late final Folder packageAnalyzerFolder;
MacrosEnvironment._() {
var physical = PhysicalResourceProvider.INSTANCE;
@@ -107,6 +108,8 @@
.copyTo(
packageSharedFolder.getChildAssumingFolder('lib/src'),
);
+ packageAnalyzerFolder =
+ physical.getFolder(packageRoot).getChildAssumingFolder('analyzer');
platformDillBytes = physical
.getFile(io.Platform.resolvedExecutable)
diff --git a/pkg/analyzer_utilities/analysis_options.yaml b/pkg/analyzer_utilities/analysis_options.yaml
index f848bc6..9639f05 100644
--- a/pkg/analyzer_utilities/analysis_options.yaml
+++ b/pkg/analyzer_utilities/analysis_options.yaml
@@ -1,4 +1,4 @@
-include: package:pedantic/analysis_options.1.9.0.yaml
+include: package:lints/recommended.yaml
analyzer:
strong-mode:
diff --git a/pkg/analyzer_utilities/lib/check/check_target.dart b/pkg/analyzer_utilities/lib/check/check_target.dart
index d22a1ac..c7e33f5 100644
--- a/pkg/analyzer_utilities/lib/check/check_target.dart
+++ b/pkg/analyzer_utilities/lib/check/check_target.dart
@@ -17,7 +17,7 @@
String get _indent => ' ' * (_depth + 1);
Never fail(String message) {
- test_package.fail(_describe() + '\n' + _indent + message);
+ test_package.fail('${_describe()}\n$_indent$message');
}
/// Chains to the given [value]; if a subsequent check fails, [describe]
@@ -27,7 +27,7 @@
String Function(U value) describe,
) {
return CheckTarget(value, _depth + 1, () {
- return _describe() + '\n' + _indent + describe(value);
+ return '${_describe()}\n$_indent${describe(value)}';
});
}
diff --git a/pkg/analyzer_utilities/lib/tools.dart b/pkg/analyzer_utilities/lib/tools.dart
index 00724c7..aae7a2a 100644
--- a/pkg/analyzer_utilities/lib/tools.dart
+++ b/pkg/analyzer_utilities/lib/tools.dart
@@ -549,7 +549,7 @@
var lines = text.split('\n');
if (lines.last.isEmpty) {
lines.removeLast();
- buffer.add(dom.Text(lines.join('\n$indent') + '\n'));
+ buffer.add(dom.Text('${lines.join('\n$indent')}\n'));
indentNeeded = true;
} else {
buffer.add(dom.Text(lines.join('\n$indent')));
diff --git a/pkg/analyzer_utilities/pubspec.yaml b/pkg/analyzer_utilities/pubspec.yaml
index d0aac18..2eac4b1 100644
--- a/pkg/analyzer_utilities/pubspec.yaml
+++ b/pkg/analyzer_utilities/pubspec.yaml
@@ -13,3 +13,6 @@
path: ../meta
path: any
test: any
+
+dev_dependencies:
+ lints: any
diff --git a/pkg/analyzer_utilities/test/check/check_test.dart b/pkg/analyzer_utilities/test/check/check_test.dart
index b88501c..9e5ee83 100644
--- a/pkg/analyzer_utilities/test/check/check_test.dart
+++ b/pkg/analyzer_utilities/test/check/check_test.dart
@@ -269,6 +269,7 @@
});
});
group('nullability', () {
+ // ignore: unnecessary_nullable_for_final_variable_declarations
const int? notNullable = 0;
const int? nullable = null;
test('isNotNull', () {
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 6f5106a..dbcb79d 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -30,7 +30,7 @@
List<DartType> _readDartTypes(
List<FunctionTypeVariable> functionTypeVariables) {
int count = readInt();
- List<DartType> types = List<DartType>.filled(count, null);
+ List<DartType> types = List<DartType>.filled(count, const NeverType._());
for (int index = 0; index < count; index++) {
types[index] = DartType.readFromDataSource(this, functionTypeVariables);
}
@@ -51,7 +51,14 @@
abstract class DartType {
const DartType();
- factory DartType.readFromDataSource(DataSourceReader source,
+ static DartType readFromDataSource(DataSourceReader source,
+ List<FunctionTypeVariable> functionTypeVariables) {
+ DartType type = readFromDataSourceOrNull(source, functionTypeVariables);
+ if (type == null) throw StateError('Unexpected null DartType');
+ return type;
+ }
+
+ static DartType readFromDataSourceOrNull(DataSourceReader source,
List<FunctionTypeVariable> functionTypeVariables) {
DartTypeKind kind = source.readEnum(DartTypeKind.values);
switch (kind) {
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index 245b922..7e08bd6 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -369,7 +369,7 @@
Set<RuntimeTypeUse> runtimeTypeUses = source.readList(() {
RuntimeTypeUseKind kind = source.readEnum(RuntimeTypeUseKind.values);
DartType receiverType = source.readDartType();
- DartType argumentType = source.readDartType(allowNull: true);
+ DartType /*?*/ argumentType = source.readDartTypeOrNull();
return RuntimeTypeUse(kind, receiverType, argumentType);
}).toSet();
bool needToInitializeIsolateAffinityTag = source.readBool();
@@ -407,7 +407,7 @@
sink.writeList(runtimeTypeUses, (RuntimeTypeUse runtimeTypeUse) {
sink.writeEnum(runtimeTypeUse.kind);
sink.writeDartType(runtimeTypeUse.receiverType);
- sink.writeDartType(runtimeTypeUse.argumentType, allowNull: true);
+ sink.writeDartTypeOrNull(runtimeTypeUse.argumentType);
});
sink.writeBool(needToInitializeIsolateAffinityTag);
sink.writeBool(needToInitializeDispatchProperty);
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index d8e2b26..cb36eb7 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -1227,7 +1227,8 @@
source.begin(tag);
ClosureMemberDefinition definition =
MemberDefinition.readFromDataSource(source);
- InterfaceType memberThisType = source.readDartType(allowNull: true);
+ InterfaceType /*?*/ memberThisType =
+ source.readDartTypeOrNull() as InterfaceType /*?*/;
FunctionType functionType = source.readDartType();
ir.FunctionNode functionNode = source.readTreeNode();
ClassTypeVariableAccess classTypeVariableAccess =
@@ -1242,7 +1243,7 @@
sink.writeEnum(JMemberDataKind.closureFunction);
sink.begin(tag);
definition.writeToDataSink(sink);
- sink.writeDartType(memberThisType, allowNull: true);
+ sink.writeDartTypeOrNull(memberThisType);
sink.writeDartType(functionType);
sink.writeTreeNode(functionNode);
sink.writeEnum(classTypeVariableAccess);
@@ -1280,7 +1281,8 @@
factory ClosureFieldData.readFromDataSource(DataSourceReader source) {
source.begin(tag);
MemberDefinition definition = MemberDefinition.readFromDataSource(source);
- InterfaceType memberThisType = source.readDartType(allowNull: true);
+ InterfaceType /*?*/ memberThisType =
+ source.readDartTypeOrNull() as InterfaceType /*?*/;
source.end(tag);
return ClosureFieldData(definition, memberThisType);
}
@@ -1290,7 +1292,7 @@
sink.writeEnum(JMemberDataKind.closureField);
sink.begin(tag);
definition.writeToDataSink(sink);
- sink.writeDartType(memberThisType, allowNull: true);
+ sink.writeDartTypeOrNull(memberThisType);
sink.end(tag);
}
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index 258eb0f..c987921 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -753,7 +753,8 @@
factory SignatureFunctionData.readFromDataSource(DataSourceReader source) {
source.begin(tag);
MemberDefinition definition = MemberDefinition.readFromDataSource(source);
- InterfaceType memberThisType = source.readDartType(allowNull: true);
+ InterfaceType /*?*/ memberThisType =
+ source.readDartTypeOrNull() as InterfaceType /*?*/;
List<ir.TypeParameter> typeParameters = source.readTypeParameterNodes();
ClassTypeVariableAccess classTypeVariableAccess =
source.readEnum(ClassTypeVariableAccess.values);
@@ -767,7 +768,7 @@
sink.writeEnum(JMemberDataKind.signature);
sink.begin(tag);
definition.writeToDataSink(sink);
- sink.writeDartType(memberThisType, allowNull: true);
+ sink.writeDartTypeOrNull(memberThisType);
sink.writeTypeParameterNodes(typeParameters);
sink.writeEnum(classTypeVariableAccess);
sink.end(tag);
diff --git a/pkg/compiler/lib/src/js_model/type_recipe.dart b/pkg/compiler/lib/src/js_model/type_recipe.dart
index 3a84def..6b3025e 100644
--- a/pkg/compiler/lib/src/js_model/type_recipe.dart
+++ b/pkg/compiler/lib/src/js_model/type_recipe.dart
@@ -282,9 +282,9 @@
static FullTypeEnvironmentRecipe _readFromDataSource(
DataSourceReader source) {
- InterfaceType classType =
- source.readDartType(allowNull: true) as InterfaceType;
- List<DartType> types = source.readDartTypes(emptyAsNull: true) ?? const [];
+ InterfaceType /*?*/ classType =
+ source.readDartTypeOrNull() as InterfaceType /*?*/;
+ List<DartType> types = source.readDartTypes();
return FullTypeEnvironmentRecipe(classType: classType, types: types);
}
@@ -293,8 +293,8 @@
@override
void _writeToDataSink(DataSinkWriter sink) {
- sink.writeDartType(classType, allowNull: true);
- sink.writeDartTypes(types, allowNull: false);
+ sink.writeDartTypeOrNull(classType);
+ sink.writeDartTypes(types);
}
@override
diff --git a/pkg/compiler/lib/src/serialization/sink.dart b/pkg/compiler/lib/src/serialization/sink.dart
index 83a5af9..e7dfec8 100644
--- a/pkg/compiler/lib/src/serialization/sink.dart
+++ b/pkg/compiler/lib/src/serialization/sink.dart
@@ -589,40 +589,43 @@
}
}
- /// Writes the type [value] to this data sink. If [allowNull] is `true`,
- /// [value] is allowed to be `null`.
- void writeDartType(DartType value, {bool allowNull = false}) {
+ /// Writes the type [value] to this data sink.
+ void writeDartType(DartType value) {
_writeDataKind(DataKind.dartType);
- _writeDartType(value, [], allowNull: allowNull);
+ value.writeToDataSink(this, []);
}
- void _writeDartType(
- DartType value, List<FunctionTypeVariable> functionTypeVariables,
- {bool allowNull = false}) {
+ /// Writes the optional type [value] to this data sink.
+ void writeDartTypeOrNull(DartType /*?*/ value) {
+ _writeDataKind(DataKind.dartType);
if (value == null) {
- if (!allowNull) {
- throw UnsupportedError("Missing DartType is not allowed.");
- }
writeEnum(DartTypeKind.none);
} else {
- value.writeToDataSink(this, functionTypeVariables);
+ value.writeToDataSink(this, []);
}
}
- /// Writes the type [values] to this data sink. If [allowNull] is `true`,
- /// [values] is allowed to be `null`.
+ /// Writes the types [values] to this data sink. If [values] is null, write a
+ /// zero-length iterable.
+ ///
+ /// This is a convenience method to be used together with
+ /// [DataSourceReader.readDartTypesOrNull].
+ void writeDartTypesOrNull(Iterable<DartType> /*?*/ values) {
+ if (values == null) {
+ writeInt(0);
+ } else {
+ writeDartTypes(values);
+ }
+ }
+
+ /// Writes the types [values] to this data sink.
///
/// This is a convenience method to be used together with
/// [DataSourceReader.readDartTypes].
- void writeDartTypes(Iterable<DartType> values, {bool allowNull = false}) {
- if (values == null) {
- assert(allowNull);
- writeInt(0);
- } else {
- writeInt(values.length);
- for (DartType value in values) {
- writeDartType(value);
- }
+ void writeDartTypes(Iterable<DartType> values) {
+ writeInt(values.length);
+ for (DartType value in values) {
+ writeDartType(value);
}
}
diff --git a/pkg/compiler/lib/src/serialization/source.dart b/pkg/compiler/lib/src/serialization/source.dart
index ee1b7e0..ed758d94 100644
--- a/pkg/compiler/lib/src/serialization/source.dart
+++ b/pkg/compiler/lib/src/serialization/source.dart
@@ -633,23 +633,35 @@
return list;
}
- /// Reads a type from this data source. If [allowNull], the returned type is
- /// allowed to be `null`.
- DartType readDartType({bool allowNull = false}) {
+ /// Reads a type from this data source.
+ DartType /*!*/ readDartType() {
_checkDataKind(DataKind.dartType);
- DartType type = DartType.readFromDataSource(this, []);
- assert(type != null || allowNull);
- return type;
+ return DartType.readFromDataSource(this, []);
}
- /// Reads a list of types from this data source. If [emptyAsNull] is `true`,
- /// `null` is returned instead of an empty list.
+ /// Reads a nullable type from this data source.
+ DartType /*?*/ readDartTypeOrNull() {
+ _checkDataKind(DataKind.dartType);
+ return DartType.readFromDataSourceOrNull(this, []);
+ }
+
+ /// Reads a list of types from this data source.
///
/// This is a convenience method to be used together with
/// [DataSinkWriter.writeDartTypes].
- List<DartType> readDartTypes({bool emptyAsNull = false}) {
+ List<DartType> readDartTypes() {
+ // Share the list when empty.
+ return readDartTypesOrNull() ?? const [];
+ }
+
+ /// Reads a list of types from this data source. Returns `null` instead of an
+ /// empty list.
+ ///
+ /// This is a convenience method to be used together with
+ /// [DataSinkWriter.writeDartTypes].
+ List<DartType> /*?*/ readDartTypesOrNull() {
int count = readInt();
- if (count == 0 && emptyAsNull) return null;
+ if (count == 0) return null;
List<DartType> list = List<DartType>.filled(count, null);
for (int i = 0; i < count; i++) {
list[i] = readDartType();
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 2d7159a..9ddd60d 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -69,7 +69,7 @@
if (hasConstraint) {
receiverConstraint = source.readAbstractValue();
}
- List<DartType> typeArguments = source.readDartTypes(emptyAsNull: true);
+ List<DartType> typeArguments = source.readDartTypesOrNull();
source.end(tag);
return DynamicUse(selector, receiverConstraint, typeArguments);
}
@@ -86,7 +86,7 @@
"Unsupported receiver constraint: ${receiverConstraint}");
}
}
- sink.writeDartTypes(_typeArguments, allowNull: true);
+ sink.writeDartTypesOrNull(_typeArguments);
sink.end(tag);
}
@@ -221,12 +221,13 @@
source.begin(tag);
MemberEntity element = source.readMember();
StaticUseKind kind = source.readEnum(StaticUseKind.values);
- InterfaceType type = source.readDartType(allowNull: true);
+ InterfaceType /*?*/ type =
+ source.readDartTypeOrNull() as InterfaceType /*?*/;
CallStructure callStructure =
source.readValueOrNull(() => CallStructure.readFromDataSource(source));
ImportEntity deferredImport = source.readImportOrNull();
ConstantValue constant = source.readConstantOrNull();
- List<DartType> typeArguments = source.readDartTypes(emptyAsNull: true);
+ List<DartType> typeArguments = source.readDartTypesOrNull();
source.end(tag);
return StaticUse.internal(element, kind,
type: type,
@@ -241,12 +242,12 @@
assert(element is MemberEntity, "Unsupported entity: $element");
sink.writeMember(element);
sink.writeEnum(kind);
- sink.writeDartType(type, allowNull: true);
+ sink.writeDartTypeOrNull(type);
sink.writeValueOrNull(
callStructure, (CallStructure c) => c.writeToDataSink(sink));
sink.writeImportOrNull(deferredImport);
sink.writeConstantOrNull(constant);
- sink.writeDartTypes(typeArguments, allowNull: true);
+ sink.writeDartTypesOrNull(typeArguments);
sink.end(tag);
}
diff --git a/pkg/dds/analysis_options.yaml b/pkg/dds/analysis_options.yaml
index 6b1919a..8f7435b 100644
--- a/pkg/dds/analysis_options.yaml
+++ b/pkg/dds/analysis_options.yaml
@@ -1,4 +1,4 @@
-include: package:pedantic/analysis_options.1.8.0.yaml
+include: package:lints/core.yaml
linter:
rules:
diff --git a/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart b/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart
index 1c8be40..eecc025 100644
--- a/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart
@@ -8,7 +8,6 @@
import 'dart:math' as math;
import 'package:path/path.dart' as path;
-import 'package:pedantic/pedantic.dart';
import 'package:vm_service/vm_service.dart' as vm;
import '../logging.dart';
diff --git a/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart b/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart
index 0a2b63c..468ea09 100644
--- a/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart
@@ -7,7 +7,6 @@
import 'dart:io';
import 'dart:math' as math;
-import 'package:pedantic/pedantic.dart';
import 'package:vm_service/vm_service.dart' as vm;
import '../logging.dart';
diff --git a/pkg/dds/lib/src/dap/adapters/mixins.dart b/pkg/dds/lib/src/dap/adapters/mixins.dart
index 53de6fc..8ecf1eb 100644
--- a/pkg/dds/lib/src/dap/adapters/mixins.dart
+++ b/pkg/dds/lib/src/dap/adapters/mixins.dart
@@ -7,7 +7,6 @@
import 'dart:io';
import 'package:path/path.dart' as path;
-import 'package:pedantic/pedantic.dart';
import '../logging.dart';
import '../protocol_common.dart';
diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart
index 8de53ff..a52fd13 100644
--- a/pkg/dds/lib/src/dds_impl.dart
+++ b/pkg/dds/lib/src/dds_impl.dart
@@ -11,7 +11,6 @@
import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
import 'package:meta/meta.dart';
-import 'package:pedantic/pedantic.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_proxy/shelf_proxy.dart';
diff --git a/pkg/dds/lib/src/utils/mutex.dart b/pkg/dds/lib/src/utils/mutex.dart
index 9aff468..dcbbf59 100644
--- a/pkg/dds/lib/src/utils/mutex.dart
+++ b/pkg/dds/lib/src/utils/mutex.dart
@@ -36,7 +36,7 @@
// Reinitialize if this is the only weakly guarded scope.
_outstandingReadersCompleter = Completer<void>();
}
- final result;
+ final T result;
try {
await _acquireLock(strong: false);
result = await criticalSection();
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 1430222..bfb5a961 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -8,7 +8,7 @@
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds
environment:
- sdk: '>=2.13.0 <3.0.0'
+ sdk: '>=2.14.0 <3.0.0'
dependencies:
args: ^2.0.0
@@ -21,7 +21,6 @@
json_rpc_2: ^3.0.0
meta: ^1.1.8
path: ^1.8.0
- pedantic: ^1.7.0
shelf: ^1.0.0
shelf_proxy: ^1.0.0
shelf_static: ^1.0.0
@@ -34,5 +33,6 @@
dev_dependencies:
http: ^0.13.0
+ lints: any
test: ^1.0.0
webdriver: ^3.0.0
diff --git a/pkg/dds/test/dap/integration/debug_eval_test.dart b/pkg/dds/test/dap/integration/debug_eval_test.dart
index 9d6ff1b..a21b5cb 100644
--- a/pkg/dds/test/dap/integration/debug_eval_test.dart
+++ b/pkg/dds/test/dap/integration/debug_eval_test.dart
@@ -19,7 +19,7 @@
group('debug mode evaluation', () {
test('evaluates expressions with simple results', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
var a = 1;
var b = 2;
@@ -37,7 +37,7 @@
test('evaluates expressions with complex results', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(simpleBreakpointProgram);
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
final breakpointLine = lineWith(testFile, breakpointMarker);
final stop = await client.hitBreakpoint(testFile, breakpointLine);
@@ -60,7 +60,7 @@
test('evaluates expressions ending with semicolons', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
var a = 1;
var b = 2;
@@ -77,7 +77,7 @@
'evaluates complex expressions expressions with evaluateToStringInDebugViews=true',
() async {
final client = dap.client;
- final testFile = await dap.createTestFile(simpleBreakpointProgram);
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
final breakpointLine = lineWith(testFile, breakpointMarker);
final stop = await client.hitBreakpoint(
@@ -99,7 +99,7 @@
'evaluates $threadExceptionExpression to the threads exception (simple type)',
() async {
final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) {
throw 'my error';
}''');
@@ -118,7 +118,7 @@
'evaluates $threadExceptionExpression to the threads exception (complex type)',
() async {
final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) {
throw Exception('my error');
}''');
@@ -137,7 +137,7 @@
'evaluates $threadExceptionExpression.x.y to x.y on the threads exception',
() async {
final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) {
throw Exception('12345');
}
@@ -154,7 +154,7 @@
test('can evaluate expressions in non-top frames', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
var a = 999;
foo();
@@ -175,7 +175,7 @@
test('returns the full message for evaluation errors', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(simpleBreakpointProgram);
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
final breakpointLine = lineWith(testFile, breakpointMarker);
final stop = await client.hitBreakpoint(testFile, breakpointLine);
@@ -198,7 +198,7 @@
test('returns short errors for evaluation in "watch" context', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(simpleBreakpointProgram);
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
final breakpointLine = lineWith(testFile, breakpointMarker);
final stop = await client.hitBreakpoint(testFile, breakpointLine);
diff --git a/pkg/dds/test/dap/integration/debug_services_test.dart b/pkg/dds/test/dap/integration/debug_services_test.dart
index 98f698e..99dd7f6 100644
--- a/pkg/dds/test/dap/integration/debug_services_test.dart
+++ b/pkg/dds/test/dap/integration/debug_services_test.dart
@@ -19,7 +19,7 @@
group('debug mode', () {
test('reports the VM Service URI to the client', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(simpleBreakpointProgram);
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
final breakpointLine = lineWith(testFile, breakpointMarker);
await client.hitBreakpoint(testFile, breakpointLine);
@@ -31,7 +31,7 @@
test('exposes VM services to the client', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(simpleBreakpointProgram);
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
final breakpointLine = lineWith(testFile, breakpointMarker);
// Capture our test service registration.
@@ -68,7 +68,7 @@
test('exposes VM service extensions to the client', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(serviceExtensionProgram);
+ final testFile = dap.createTestFile(serviceExtensionProgram);
// Capture our test service registration.
final serviceExtensionAddedFuture = client.serviceExtensionAddedEvents
diff --git a/pkg/dds/test/dap/integration/debug_stack_test.dart b/pkg/dds/test/dap/integration/debug_stack_test.dart
index 72f2cb5..e14458f 100644
--- a/pkg/dds/test/dap/integration/debug_stack_test.dart
+++ b/pkg/dds/test/dap/integration/debug_stack_test.dart
@@ -18,7 +18,7 @@
group('debug mode stack trace', () {
test('includes expected names and async boundaries', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(simpleAsyncProgram);
+ final testFile = dap.createTestFile(simpleAsyncProgram);
final breakpointLine = lineWith(testFile, breakpointMarker);
final stop = await client.hitBreakpoint(testFile, breakpointLine);
@@ -60,7 +60,7 @@
test('only sets canRestart where VM can rewind', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(simpleAsyncProgram);
+ final testFile = dap.createTestFile(simpleAsyncProgram);
final breakpointLine = lineWith(testFile, breakpointMarker);
final stop = await client.hitBreakpoint(testFile, breakpointLine);
@@ -91,7 +91,7 @@
test('deemphasizes SDK frames when debugSdk=false', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(sdkStackFrameProgram);
+ final testFile = dap.createTestFile(sdkStackFrameProgram);
final breakpointLine = lineWith(testFile, breakpointMarker);
final stop = await client.hitBreakpoint(
@@ -123,7 +123,7 @@
test('does not deemphasize SDK frames when debugSdk=true', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(sdkStackFrameProgram);
+ final testFile = dap.createTestFile(sdkStackFrameProgram);
final breakpointLine = lineWith(testFile, breakpointMarker);
final stop = await client.hitBreakpoint(
diff --git a/pkg/dds/test/dap/integration/debug_test.dart b/pkg/dds/test/dap/integration/debug_test.dart
index 974692f..9044657 100644
--- a/pkg/dds/test/dap/integration/debug_test.dart
+++ b/pkg/dds/test/dap/integration/debug_test.dart
@@ -114,7 +114,7 @@
], eagerError: true);
// Resume and expect termination.
- await await Future.wait([
+ await Future.wait([
dap.client.event('terminated'),
dap.client.continue_((await stop).threadId!),
], eagerError: true);
diff --git a/pkg/dds/test/dap/integration/debug_variables_test.dart b/pkg/dds/test/dap/integration/debug_variables_test.dart
index 86f4412..e78ecd0 100644
--- a/pkg/dds/test/dap/integration/debug_variables_test.dart
+++ b/pkg/dds/test/dap/integration/debug_variables_test.dart
@@ -18,7 +18,7 @@
group('debug mode variables', () {
test('provides variable list for frames', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
final myVariable = 1;
foo();
@@ -58,7 +58,7 @@
test('provides simple exception types for frames', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) {
throw 'my error';
}
@@ -80,7 +80,7 @@
test('provides complex exception types for frames', () async {
final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) {
throw ArgumentError.notNull('args');
}
@@ -104,7 +104,7 @@
test('includes simple variable fields', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
final myVariable = DateTime(2000, 1, 1);
print('Hello!'); $breakpointMarker
@@ -126,7 +126,7 @@
test('includes variable getters when evaluateGettersInDebugViews=true',
() async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
final myVariable = DateTime(2000, 1, 1);
print('Hello!'); $breakpointMarker
@@ -172,7 +172,7 @@
test('renders a simple list', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
final myVariable = ["first", "second", "third"];
print('Hello!'); $breakpointMarker
@@ -195,7 +195,7 @@
test('renders a simple list subset', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
final myVariable = ["first", "second", "third"];
print('Hello!'); $breakpointMarker
@@ -218,7 +218,7 @@
test('renders a simple map with keys/values', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
final myVariable = {
'zero': 0,
@@ -261,7 +261,7 @@
test('renders a simple map subset', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
final myVariable = {
'zero': 0,
@@ -291,7 +291,7 @@
test('renders a complex map with keys/values', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
void main(List<String> args) {
final myVariable = {
DateTime(2000, 1, 1): Exception("my error")
@@ -349,7 +349,7 @@
test('calls toString() on custom classes', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
class Foo {
toString() => 'Bar!';
}
@@ -386,7 +386,7 @@
//
// myVariable: Foo (Instance of Foo)
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
class Foo {}
void main() {
@@ -416,7 +416,7 @@
test('handles errors in getters', () async {
final client = dap.client;
- final testFile = await dap.createTestFile('''
+ final testFile = dap.createTestFile('''
class Foo {
String get doesNotThrow => "success";
String get throws => throw Exception('err');
diff --git a/pkg/dds/test/dap/integration/test_server.dart b/pkg/dds/test/dap/integration/test_server.dart
index ccb4c1d..519f5e1 100644
--- a/pkg/dds/test/dap/integration/test_server.dart
+++ b/pkg/dds/test/dap/integration/test_server.dart
@@ -10,7 +10,6 @@
import 'package:dds/src/dap/logging.dart';
import 'package:dds/src/dap/server.dart';
import 'package:path/path.dart' as path;
-import 'package:pedantic/pedantic.dart';
/// Enable to run from local source (useful in development).
const runFromSource = false;
@@ -94,7 +93,7 @@
@override
Future<void> stop() async {
_isShuttingDown = true;
- await _process.kill();
+ _process.kill();
await _process.exitCode;
}
diff --git a/pkg/dds/test/handles_client_disconnect_state_error_test.dart b/pkg/dds/test/handles_client_disconnect_state_error_test.dart
index c9d35fa..9359389 100644
--- a/pkg/dds/test/handles_client_disconnect_state_error_test.dart
+++ b/pkg/dds/test/handles_client_disconnect_state_error_test.dart
@@ -8,7 +8,6 @@
import 'package:dds/src/dds_impl.dart';
import 'package:dds/src/rpc_error_codes.dart';
import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
-import 'package:pedantic/pedantic.dart';
import 'package:test/test.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
@@ -49,7 +48,7 @@
test('StateError handled by _StreamManager.clientDisconnect', () async {
final dds = await DartDevelopmentService.startDartDevelopmentService(
Uri(scheme: 'http'));
- final ws = await WebSocketChannel.connect(dds.uri!.replace(scheme: 'ws'));
+ final ws = WebSocketChannel.connect(dds.uri!.replace(scheme: 'ws'));
// Create a VM service client that connects to DDS.
final client = json_rpc.Client(ws.cast<String>());
@@ -76,7 +75,7 @@
() async {
final dds = await DartDevelopmentService.startDartDevelopmentService(
Uri(scheme: 'http'));
- final ws = await WebSocketChannel.connect(dds.uri!.replace(scheme: 'ws'));
+ final ws = WebSocketChannel.connect(dds.uri!.replace(scheme: 'ws'));
// Create a VM service client that connects to DDS.
final client = json_rpc.Client(ws.cast<String>());
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 462413c..68b49e4 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -234,8 +234,8 @@
P(use_field_guards, bool, true, "Use field guards and track field types") \
C(use_osr, false, true, bool, true, "Use OSR") \
P(use_slow_path, bool, false, "Whether to avoid inlined fast paths.") \
- P(verbose_gc, bool, false, "Enables verbose GC.") \
- P(verbose_gc_hdr, int, 40, "Print verbose GC header interval.") \
+ R(verbose_gc, false, bool, false, "Enables verbose GC.") \
+ R(verbose_gc_hdr, 40, int, 40, "Print verbose GC header interval.") \
R(verify_after_gc, false, bool, false, \
"Enables heap verification after GC.") \
R(verify_before_gc, false, bool, false, \
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index a57bcfc..481bafe 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -522,8 +522,7 @@
? VMTag::kGCIdleTagId
: VMTag::kGCOldSpaceTagId);
TIMELINE_FUNCTION_GC_DURATION(thread, "CollectOldGeneration");
- old_space_.CollectGarbage(thread, /*compact=*/type == GCType::kMarkCompact,
- /*finalize=*/true);
+ old_space_.CollectGarbage(type == GCType::kMarkCompact, true /* finish */);
RecordAfterGC(type);
PrintStats();
#if defined(SUPPORT_TIMELINE)
@@ -624,7 +623,7 @@
? VMTag::kGCIdleTagId
: VMTag::kGCOldSpaceTagId);
TIMELINE_FUNCTION_GC_DURATION(thread, "StartConcurrentMarking");
- old_space_.CollectGarbage(thread, /*compact=*/false, /*finalize=*/false);
+ old_space_.CollectGarbage(/*compact=*/false, /*finalize=*/false);
RecordAfterGC(GCType::kStartConcurrentMark);
PrintStats();
#if defined(SUPPORT_TIMELINE)
@@ -1020,7 +1019,8 @@
stats_.before_.micros_ = OS::GetCurrentMonotonicMicros();
stats_.before_.new_ = new_space_.GetCurrentUsage();
stats_.before_.old_ = old_space_.GetCurrentUsage();
- stats_.before_.store_buffer_ = isolate_group_->store_buffer()->Size();
+ for (int i = 0; i < GCStats::kTimeEntries; i++)
+ stats_.times_[i] = 0;
}
static double AvgCollectionPeriod(int64_t run_time, intptr_t collections) {
@@ -1043,7 +1043,6 @@
}
stats_.after_.new_ = new_space_.GetCurrentUsage();
stats_.after_.old_ = old_space_.GetCurrentUsage();
- stats_.after_.store_buffer_ = isolate_group_->store_buffer()->Size();
#ifndef PRODUCT
// For now we'll emit the same GC events on all isolates.
if (Service::gc_stream.enabled()) {
@@ -1115,20 +1114,24 @@
}
void Heap::PrintStats() {
+#if !defined(PRODUCT)
if (!FLAG_verbose_gc) return;
if ((FLAG_verbose_gc_hdr != 0) &&
(((stats_.num_ - 1) % FLAG_verbose_gc_hdr) == 0)) {
OS::PrintErr(
- "[ | | | | | new "
- "gen | new gen | new gen | old gen | old gen | old "
- "gen | store | delta used ]\n"
- "[ GC isolate | space (reason) | GC# | start | time | used "
- "(MB) | capacity MB | external| used (MB) | capacity (MB) | "
- "external MB | buffer | new | old ]\n"
+ "[ | | | | "
+ "| new gen | new gen | new gen "
+ "| old gen | old gen | old gen "
+ "| sweep | safe- | roots/| stbuf/| tospc/| weaks/ ]\n"
+ "[ GC isolate | space (reason) | GC# | start | time "
+ "| used (MB) | capacity MB | external"
+ "| used (MB) | capacity (MB) | external MB "
+ "| thread| point |marking| reset | sweep |swplrge ]\n"
"[ | | | (s) | (ms) "
- "|before| after|before| after| b4 |aftr| before| after | before| after "
- "|before| after| b4 |aftr| (MB) | (MB) ]\n");
+ "|before| after|before| after| b4 |aftr"
+ "| before| after | before| after |before| after"
+ "| (ms) | (ms) | (ms) | (ms) | (ms) | (ms) ]\n");
}
// clang-format off
@@ -1143,8 +1146,7 @@
"%6.1f, %6.1f, " // old gen: in use before/after
"%6.1f, %6.1f, " // old gen: capacity before/after
"%5.1f, %5.1f, " // old gen: external before/after
- "%3" Pd ", %3" Pd ", " // store buffer: before/after
- "%5.1f, %6.1f, " // delta used: new gen/old gen
+ "%6.2f, %6.2f, %6.2f, %6.2f, %6.2f, %6.2f, " // times
"]\n", // End with a comma to make it easier to import in spreadsheets.
isolate_group()->source()->name,
GCTypeToString(stats_.type_),
@@ -1165,13 +1167,14 @@
WordsToMB(stats_.after_.old_.capacity_in_words),
WordsToMB(stats_.before_.old_.external_in_words),
WordsToMB(stats_.after_.old_.external_in_words),
- stats_.before_.store_buffer_,
- stats_.after_.store_buffer_,
- WordsToMB(stats_.after_.new_.used_in_words -
- stats_.before_.new_.used_in_words),
- WordsToMB(stats_.after_.old_.used_in_words -
- stats_.before_.old_.used_in_words));
+ MicrosecondsToMilliseconds(stats_.times_[0]),
+ MicrosecondsToMilliseconds(stats_.times_[1]),
+ MicrosecondsToMilliseconds(stats_.times_[2]),
+ MicrosecondsToMilliseconds(stats_.times_[3]),
+ MicrosecondsToMilliseconds(stats_.times_[4]),
+ MicrosecondsToMilliseconds(stats_.times_[5]));
// clang-format on
+#endif // !defined(PRODUCT)
}
void Heap::PrintStatsToTimeline(TimelineEventScope* event, GCReason reason) {
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 112c59f..179122d 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -256,6 +256,12 @@
void ForwardWeakEntries(ObjectPtr before_object, ObjectPtr after_object);
void ForwardWeakTables(ObjectPointerVisitor* visitor);
+ // Stats collection.
+ void RecordTime(int id, int64_t micros) {
+ ASSERT((id >= 0) && (id < GCStats::kTimeEntries));
+ stats_.times_[id] = micros;
+ }
+
void UpdateGlobalMaxUsed();
static bool IsAllocatableInNewSpace(intptr_t size) {
@@ -308,14 +314,16 @@
int64_t micros_;
SpaceUsage new_;
SpaceUsage old_;
- intptr_t store_buffer_;
private:
DISALLOW_COPY_AND_ASSIGN(Data);
};
+ enum { kTimeEntries = 6 };
+
Data before_;
Data after_;
+ int64_t times_[kTimeEntries];
private:
DISALLOW_COPY_AND_ASSIGN(GCStats);
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index f1c3ed4..6c7c909 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -1100,7 +1100,7 @@
}
}
-void PageSpace::CollectGarbage(Thread* thread, bool compact, bool finalize) {
+void PageSpace::CollectGarbage(bool compact, bool finalize) {
ASSERT(GrowthControlState());
if (!finalize) {
@@ -1112,11 +1112,16 @@
#endif
}
+ Thread* thread = Thread::Current();
+ const int64_t pre_safe_point = OS::GetCurrentMonotonicMicros();
GcSafepointOperationScope safepoint_scope(thread);
+ const int64_t pre_wait_for_sweepers = OS::GetCurrentMonotonicMicros();
// Wait for pending tasks to complete and then account for the driver task.
+ Phase waited_for;
{
MonitorLocker locker(tasks_lock());
+ waited_for = phase();
if (!finalize &&
(phase() == kMarking || phase() == kAwaitingFinalization)) {
// Concurrent mark is already running.
@@ -1131,11 +1136,26 @@
set_tasks(1);
}
+ if (FLAG_verbose_gc) {
+ const int64_t wait =
+ OS::GetCurrentMonotonicMicros() - pre_wait_for_sweepers;
+ if (waited_for == kMarking) {
+ THR_Print("Waited %" Pd64 " us for concurrent marking to finish.\n",
+ wait);
+ } else if (waited_for == kSweepingRegular || waited_for == kSweepingLarge) {
+ THR_Print("Waited %" Pd64 " us for concurrent sweeping to finish.\n",
+ wait);
+ }
+ }
+
// Ensure that all threads for this isolate are at a safepoint (either
// stopped or in native code). We have guards around Newgen GC and oldgen GC
// to ensure that if two threads are racing to collect at the same time the
// loser skips collection and goes straight to allocation.
- CollectGarbageHelper(thread, compact, finalize);
+ {
+ CollectGarbageHelper(compact, finalize, pre_wait_for_sweepers,
+ pre_safe_point);
+ }
// Done, reset the task count.
{
@@ -1145,9 +1165,11 @@
}
}
-void PageSpace::CollectGarbageHelper(Thread* thread,
- bool compact,
- bool finalize) {
+void PageSpace::CollectGarbageHelper(bool compact,
+ bool finalize,
+ int64_t pre_wait_for_sweepers,
+ int64_t pre_safe_point) {
+ Thread* thread = Thread::Current();
ASSERT(thread->IsAtSafepoint());
auto isolate_group = heap_->isolate_group();
ASSERT(isolate_group == IsolateGroup::Current());
@@ -1160,7 +1182,7 @@
[&](Isolate* isolate) { isolate->field_table()->FreeOldTables(); },
/*at_safepoint=*/true);
- NoSafepointScope no_safepoints(thread);
+ NoSafepointScope no_safepoints;
if (FLAG_print_free_list_before_gc) {
for (intptr_t i = 0; i < num_freelists_; i++) {
@@ -1202,6 +1224,8 @@
delete marker_;
marker_ = NULL;
+ int64_t mid1 = OS::GetCurrentMonotonicMicros();
+
// Abandon the remainder of the bump allocation block.
AbandonBumpAllocation();
// Reset the freelists and setup sweeping.
@@ -1209,15 +1233,19 @@
freelists_[i].Reset();
}
- if (FLAG_verify_before_gc) {
- OS::PrintErr("Verifying before sweeping...");
- heap_->VerifyGC(kAllowMarked);
- OS::PrintErr(" done.\n");
- }
+ int64_t mid2 = OS::GetCurrentMonotonicMicros();
+ int64_t mid3 = 0;
{
+ if (FLAG_verify_before_gc) {
+ OS::PrintErr("Verifying before sweeping...");
+ heap_->VerifyGC(kAllowMarked);
+ OS::PrintErr(" done.\n");
+ }
+
// Executable pages are always swept immediately to simplify
// code protection.
+
TIMELINE_FUNCTION_GC_DURATION(thread, "SweepExecutable");
GCSweeper sweeper;
OldPage* prev_page = NULL;
@@ -1235,6 +1263,8 @@
// Advance to the next page.
page = next_page;
}
+
+ mid3 = OS::GetCurrentMonotonicMicros();
}
bool has_reservation = MarkReservation();
@@ -1285,6 +1315,13 @@
page_space_controller_.EvaluateGarbageCollection(
usage_before, GetCurrentUsage(), start, end);
+ heap_->RecordTime(kConcurrentSweep, pre_safe_point - pre_wait_for_sweepers);
+ heap_->RecordTime(kSafePoint, start - pre_safe_point);
+ heap_->RecordTime(kMarkObjects, mid1 - start);
+ heap_->RecordTime(kResetFreeLists, mid2 - mid1);
+ heap_->RecordTime(kSweepPages, mid3 - mid2);
+ heap_->RecordTime(kSweepLargePages, end - mid3);
+
if (FLAG_print_free_list_after_gc) {
for (intptr_t i = 0; i < num_freelists_; i++) {
OS::PrintErr("After GC: Freelist %" Pd "\n", i);
@@ -1711,8 +1748,8 @@
if (FLAG_log_growth || FLAG_verbose_gc) {
THR_Print("%s: threshold=%" Pd "kB, idle_threshold=%" Pd "kB, reason=%s\n",
heap_->isolate_group()->source()->name,
- RoundWordsToKB(hard_gc_threshold_in_words_),
- RoundWordsToKB(idle_gc_threshold_in_words_), reason);
+ hard_gc_threshold_in_words_ / KBInWords,
+ idle_gc_threshold_in_words_ / KBInWords, reason);
}
}
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index fca17a2..5a3c5c0 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -408,7 +408,7 @@
OldPage::PageType type) const;
// Collect the garbage in the page space using mark-sweep or mark-compact.
- void CollectGarbage(Thread* thread, bool compact, bool finalize);
+ void CollectGarbage(bool compact, bool finalize);
void AddRegionsToObjectSet(ObjectSet* set) const;
@@ -573,7 +573,10 @@
void FreeLargePage(OldPage* page, OldPage* previous_page);
void FreePages(OldPage* pages);
- void CollectGarbageHelper(Thread* thread, bool compact, bool finalize);
+ void CollectGarbageHelper(bool compact,
+ bool finalize,
+ int64_t pre_wait_for_sweepers,
+ int64_t pre_safe_point);
void SweepLarge();
void Sweep(bool exclusive);
void ConcurrentSweep(IsolateGroup* isolate_group);
diff --git a/runtime/vm/heap/pointer_block.cc b/runtime/vm/heap/pointer_block.cc
index 672bdc0..daedab8 100644
--- a/runtime/vm/heap/pointer_block.cc
+++ b/runtime/vm/heap/pointer_block.cc
@@ -228,11 +228,6 @@
return (full_.length() + partial_.length()) > kMaxNonEmpty;
}
-intptr_t StoreBuffer::Size() {
- MonitorLocker ml(&monitor_);
- return full_.length() + partial_.length();
-}
-
void StoreBuffer::VisitObjectPointers(ObjectPointerVisitor* visitor) {
for (Block* block = full_.Peek(); block != NULL; block = block->next()) {
block->VisitObjectPointers(visitor);
diff --git a/runtime/vm/heap/pointer_block.h b/runtime/vm/heap/pointer_block.h
index 1b6fd5a..fb10fa6 100644
--- a/runtime/vm/heap/pointer_block.h
+++ b/runtime/vm/heap/pointer_block.h
@@ -268,7 +268,6 @@
// Check whether non-empty blocks have exceeded kMaxNonEmpty (but takes no
// action).
bool Overflowed();
- intptr_t Size();
void VisitObjectPointers(ObjectPointerVisitor* visitor);
};
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index c94c042..d2f7de4 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -1742,6 +1742,9 @@
Thread* thread = Thread::Current();
GcSafepointOperationScope safepoint_scope(thread);
+ int64_t safe_point = OS::GetCurrentMonotonicMicros();
+ heap_->RecordTime(kSafePoint, safe_point - start);
+
// Scavenging is not reentrant. Make sure that is the case.
ASSERT(!scavenging_);
scavenging_ = true;
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index bfd8fc5..5a93aec 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -180,13 +180,6 @@
bool Contains(uword addr) const;
void WriteProtect(bool read_only);
- intptr_t used_in_words() const {
- intptr_t size = 0;
- for (const NewPage* p = head_; p != nullptr; p = p->next()) {
- size += (p->object_end() - p->object_start());
- }
- return size >> kWordSizeLog2;
- }
intptr_t capacity_in_words() const { return capacity_in_words_; }
intptr_t max_capacity_in_words() const { return max_capacity_in_words_; }
@@ -291,7 +284,7 @@
int64_t UsedInWords() const {
MutexLocker ml(&space_lock_);
- return to_->used_in_words();
+ return to_->capacity_in_words();
}
int64_t CapacityInWords() const { return to_->max_capacity_in_words(); }
int64_t ExternalInWords() const { return external_size_ >> kWordSizeLog2; }
diff --git a/tools/VERSION b/tools/VERSION
index e3b18d0..32f8ad6 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 22
+PRERELEASE 23
PRERELEASE_PATCH 0
\ No newline at end of file