Version 2.15.0-186.0.dev
Merge commit '198dc4307516ec4b4db4facfbd6924193a721ed3' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index 8d97c49..0e1fea0 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
name: _fe_analyzer_shared
-version: 27.0.0
+version: 28.0.0
description: Logic that is shared between the front_end and analyzer packages.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
diff --git a/pkg/analysis_server/lib/src/cider/fixes.dart b/pkg/analysis_server/lib/src/cider/fixes.dart
index e17d1cc..b3898bd 100644
--- a/pkg/analysis_server/lib/src/cider/fixes.dart
+++ b/pkg/analysis_server/lib/src/cider/fixes.dart
@@ -5,11 +5,13 @@
import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/src/services/correction/change_workspace.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/instrumentation/service.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/micro/library_graph.dart' as cider;
import 'package:analyzer/src/dart/micro/resolve_file.dart';
class CiderErrorFixes {
@@ -50,7 +52,7 @@
workspace,
resolvedUnit,
error,
- (name) => const [],
+ _topLevelDeclarations,
);
var fixes = await DartFixContributor().computeFixes(context);
@@ -65,4 +67,33 @@
return result;
}
+
+ List<TopLevelDeclaration> _topLevelDeclarations(String name) {
+ var result = <TopLevelDeclaration>[];
+ var files = _fileResolver.getFilesWithTopLevelDeclarations(name);
+ for (var fileWithKind in files) {
+ void addDeclaration(TopLevelDeclarationKind kind) {
+ var file = fileWithKind.file;
+ result.add(
+ TopLevelDeclaration(file.path, file.uri, kind, name, false),
+ );
+ }
+
+ switch (fileWithKind.kind) {
+ case cider.FileTopLevelDeclarationKind.extension:
+ addDeclaration(TopLevelDeclarationKind.extension);
+ break;
+ case cider.FileTopLevelDeclarationKind.function:
+ addDeclaration(TopLevelDeclarationKind.function);
+ break;
+ case cider.FileTopLevelDeclarationKind.type:
+ addDeclaration(TopLevelDeclarationKind.type);
+ break;
+ case cider.FileTopLevelDeclarationKind.variable:
+ addDeclaration(TopLevelDeclarationKind.variable);
+ break;
+ }
+ }
+ return result;
+ }
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_trailing_comma.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_trailing_comma.dart
new file mode 100644
index 0000000..c66a0a1
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_trailing_comma.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2021, 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 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+
+class AddTrailingComma extends CorrectionProducer {
+ @override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
+ FixKind get fixKind => DartFixKind.ADD_TRAILING_COMMA;
+
+ @override
+ FixKind get multiFixKind => DartFixKind.ADD_TRAILING_COMMA_MULTI;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ final node = this.node;
+ if (node is! ArgumentList) return;
+ final parent = node.parent;
+ if (parent == null) return;
+
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addSimpleInsertion(node.arguments.last.end, ',');
+ });
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static AddTrailingComma newInstance() => AddTrailingComma();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_block_body.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_block_body.dart
index 8ec13f6..dbbea0b 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_block_body.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_block_body.dart
@@ -5,71 +5,105 @@
import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer_plugin/utilities/assist/assist.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
-import 'package:analyzer_plugin/utilities/range_factory.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+
+import '../fix.dart';
class ConvertIntoBlockBody extends CorrectionProducer {
@override
AssistKind get assistKind => DartAssistKind.CONVERT_INTO_BLOCK_BODY;
@override
- Future<void> compute(ChangeBuilder builder) async {
- var body = getEnclosingFunctionBody();
- // prepare expression body
- if (body is! ExpressionFunctionBody || body.isGenerator) {
- return;
- }
+ FixKind get fixKind => DartFixKind.CONVERT_INTO_BLOCK_BODY;
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ final body = getEnclosingFunctionBody();
+ if (body == null || body.isGenerator) return;
+
+ List<String>? codeLines;
+
+ if (body is ExpressionFunctionBody) {
+ codeLines = _getCodeForFunctionBody(body);
+ } else if (body is EmptyFunctionBody) {
+ codeLines = _getCodeForEmptyBody(body);
+ }
+ if (codeLines == null) return;
+
+ // prepare prefix
+ var prefix = utils.getNodePrefix(body.parent!);
+ var indent = utils.getIndent(1);
+ var start = body.beginToken.previous!.end;
+ var length = body.end - start;
+
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addReplacement(SourceRange(start, length), (builder) {
+ builder.write(' ');
+ if (body.isAsynchronous) {
+ builder.write('async ');
+ }
+ builder.write('{');
+ for (var line in codeLines!) {
+ builder.write('$eol$prefix$indent');
+ builder.write(line);
+ }
+ builder.selectHere();
+ builder.write('$eol$prefix}');
+ });
+ });
+ }
+
+ List<String>? _getCodeForEmptyBody(EmptyFunctionBody body) {
+ var functionElement = _getFunctionElement(body.parent);
+ if (functionElement == null) return null;
+
+ var lines = ['// TODO: implement ${functionElement.name}'];
+
+ var returnValueType = functionElement.returnType;
+ if (!returnValueType.isVoid) {
+ lines.add('throw UnimplementedError();');
+ }
+ return lines;
+ }
+
+ List<String>? _getCodeForFunctionBody(ExpressionFunctionBody body) {
var returnValue = body.expression;
// Return expressions can be quite large, e.g. Flutter build() methods.
// It is surprising to see this Quick Assist deep in the function body.
if (selectionOffset >= returnValue.offset) {
- return;
- }
-
- DartType? getFunctionReturnType() {
- var parent = body.parent;
- if (parent is MethodDeclaration) {
- return parent.declaredElement?.returnType;
- } else if (parent is ConstructorDeclaration) {
- return parent.declaredElement?.returnType;
- } else if (parent is FunctionExpression) {
- return parent.declaredElement?.returnType;
- }
return null;
}
- var functionReturnType = getFunctionReturnType();
- if (functionReturnType == null) {
- return;
- }
+ var functionElement = _getFunctionElement(body.parent);
+ if (functionElement == null) return null;
+
var returnValueType = returnValue.typeOrThrow;
var returnValueCode = utils.getNodeText(returnValue);
- // prepare prefix
- var prefix = utils.getNodePrefix(body.parent!);
- var indent = utils.getIndent(1);
+ var returnCode = '';
+ if (!returnValueType.isVoid &&
+ !returnValueType.isBottom &&
+ !functionElement.returnType.isVoid) {
+ returnCode = 'return ';
+ }
+ returnCode += '$returnValueCode;';
+ return [returnCode];
+ }
- await builder.addDartFileEdit(file, (builder) {
- builder.addReplacement(range.node(body), (builder) {
- if (body.isAsynchronous) {
- builder.write('async ');
- }
- builder.write('{$eol$prefix$indent');
- if (!returnValueType.isVoid &&
- !returnValueType.isBottom &&
- !functionReturnType.isVoid) {
- builder.write('return ');
- }
- builder.write(returnValueCode);
- builder.write(';');
- builder.selectHere();
- builder.write('$eol$prefix}');
- });
- });
+ ExecutableElement? _getFunctionElement(AstNode? node) {
+ if (node is MethodDeclaration) {
+ return node.declaredElement;
+ } else if (node is ConstructorDeclaration) {
+ return node.declaredElement;
+ } else if (node is FunctionExpression) {
+ return node.declaredElement;
+ }
+ return null;
}
/// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index dd5593b..c9ec3cf 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -244,6 +244,16 @@
DartFixKindPriority.IN_FILE,
"Add 'break' everywhere in file",
);
+ static const ADD_TRAILING_COMMA = FixKind(
+ 'dart.fix.add.trailingComma',
+ DartFixKindPriority.DEFAULT,
+ 'Add trailing comma',
+ );
+ static const ADD_TRAILING_COMMA_MULTI = FixKind(
+ 'dart.fix.add.trailingComma.multi',
+ DartFixKindPriority.IN_FILE,
+ 'Add trailing commas everywhere in file',
+ );
static const ADD_TYPE_ANNOTATION = FixKind(
'dart.fix.add.typeAnnotation',
DartFixKindPriority.DEFAULT,
@@ -289,6 +299,11 @@
DartFixKindPriority.DEFAULT,
'Convert to child:',
);
+ static const CONVERT_INTO_BLOCK_BODY = FixKind(
+ 'dart.fix.convert.bodyToBlock',
+ DartFixKindPriority.DEFAULT,
+ 'Convert to block body',
+ );
static const CONVERT_FOR_EACH_TO_FOR_LOOP = FixKind(
'dart.fix.convert.toForLoop',
DartFixKindPriority.DEFAULT,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 7454202..6e50224 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -29,6 +29,7 @@
import 'package:analysis_server/src/services/correction/dart/add_static.dart';
import 'package:analysis_server/src/services/correction/dart/add_super_constructor_invocation.dart';
import 'package:analysis_server/src/services/correction/dart/add_switch_case_break.dart';
+import 'package:analysis_server/src/services/correction/dart/add_trailing_comma.dart';
import 'package:analysis_server/src/services/correction/dart/add_type_annotation.dart';
import 'package:analysis_server/src/services/correction/dart/change_argument_name.dart';
import 'package:analysis_server/src/services/correction/dart/change_to.dart';
@@ -40,6 +41,7 @@
import 'package:analysis_server/src/services/correction/dart/convert_documentation_into_line.dart';
import 'package:analysis_server/src/services/correction/dart/convert_flutter_child.dart';
import 'package:analysis_server/src/services/correction/dart/convert_flutter_children.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_into_block_body.dart';
import 'package:analysis_server/src/services/correction/dart/convert_into_is_not.dart';
import 'package:analysis_server/src/services/correction/dart/convert_map_from_iterable_to_for_literal.dart';
import 'package:analysis_server/src/services/correction/dart/convert_quotes.dart';
@@ -94,6 +96,7 @@
import 'package:analysis_server/src/services/correction/dart/move_type_arguments_to_class.dart';
import 'package:analysis_server/src/services/correction/dart/organize_imports.dart';
import 'package:analysis_server/src/services/correction/dart/qualify_reference.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_abstract.dart';
import 'package:analysis_server/src/services/correction/dart/remove_annotation.dart';
import 'package:analysis_server/src/services/correction/dart/remove_argument.dart';
import 'package:analysis_server/src/services/correction/dart/remove_await.dart';
@@ -181,8 +184,6 @@
import 'package:analyzer_plugin/utilities/change_builder/conflicting_edit_exception.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart' hide FixContributor;
-import 'dart/remove_abstract.dart';
-
/// A function that can be executed to create a multi-correction producer.
typedef MultiProducerGenerator = MultiCorrectionProducer Function();
@@ -553,6 +554,9 @@
LintNames.sort_child_properties_last: [
SortChildPropertyLast.newInstance,
],
+ LintNames.require_trailing_commas: [
+ AddTrailingComma.newInstance,
+ ],
LintNames.type_annotate_public_apis: [
// TODO(brianwilkerson) Consider applying in bulk.
AddTypeAnnotation.newInstance,
@@ -797,7 +801,7 @@
CreateMixin.newInstance,
],
CompileTimeErrorCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER: [
- CreateMissingOverrides.newInstance,
+ ConvertIntoBlockBody.newInstance,
CreateNoSuchMethod.newInstance,
MakeClassAbstract.newInstance,
],
@@ -1249,6 +1253,9 @@
ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE: [
AddTypeAnnotation.newInstance,
],
+ ParserErrorCode.MISSING_FUNCTION_BODY: [
+ ConvertIntoBlockBody.newInstance,
+ ],
ParserErrorCode.VAR_AS_TYPE_NAME: [
ReplaceVarWithDynamic.newInstance,
],
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index e7db85a..b43b980 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -104,6 +104,7 @@
static const String prefer_typing_uninitialized_variables =
'prefer_typing_uninitialized_variables';
static const String prefer_void_to_null = 'prefer_void_to_null';
+ static const String require_trailing_commas = 'require_trailing_commas';
static const String sized_box_for_whitespace = 'sized_box_for_whitespace';
static const String slash_for_doc_comments = 'slash_for_doc_comments';
static const String sort_child_properties_last = 'sort_child_properties_last';
diff --git a/pkg/analysis_server/test/src/cider/fixes_test.dart b/pkg/analysis_server/test/src/cider/fixes_test.dart
index 4e57e14..ff775e5 100644
--- a/pkg/analysis_server/test/src/cider/fixes_test.dart
+++ b/pkg/analysis_server/test/src/cider/fixes_test.dart
@@ -72,6 +72,128 @@
''');
}
+ Future<void> test_importLibrary_withClass() async {
+ var a_path = '/workspace/dart/test/lib/a.dart';
+ newFile(a_path, content: r'''
+class Test {}
+''');
+ fileResolver.resolve(path: a_path);
+
+ await _compute(r'''
+void f(Test a) {}^
+''');
+
+ assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, r'''
+import 'a.dart';
+
+void f(Test a) {}
+''');
+ }
+
+ Future<void> test_importLibrary_withEnum() async {
+ var a_path = '/workspace/dart/test/lib/a.dart';
+ newFile(a_path, content: r'''
+enum Test {a, b, c}
+''');
+ fileResolver.resolve(path: a_path);
+
+ await _compute(r'''
+void f(Test a) {}^
+''');
+
+ assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, r'''
+import 'a.dart';
+
+void f(Test a) {}
+''');
+ }
+
+ Future<void> test_importLibrary_withExtension() async {
+ var a_path = '/workspace/dart/test/lib/a.dart';
+ newFile(a_path, content: r'''
+extension E on int {
+ void foo() {}
+}
+''');
+ fileResolver.resolve(path: a_path);
+
+ await _compute(r'''
+void f() {
+ E(0).foo();^
+}
+''');
+
+ assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, r'''
+import 'a.dart';
+
+void f() {
+ E(0).foo();
+}
+''');
+ }
+
+ Future<void> test_importLibrary_withFunction() async {
+ var a_path = '/workspace/dart/test/lib/a.dart';
+ newFile(a_path, content: r'''
+void foo() {}
+''');
+ fileResolver.resolve(path: a_path);
+
+ await _compute(r'''
+void f() {
+ foo();^
+}
+''');
+
+ assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, r'''
+import 'a.dart';
+
+void f() {
+ foo();
+}
+''');
+ }
+
+ Future<void> test_importLibrary_withMixin() async {
+ var a_path = '/workspace/dart/test/lib/a.dart';
+ newFile(a_path, content: r'''
+mixin Test {}
+''');
+ fileResolver.resolve(path: a_path);
+
+ await _compute(r'''
+void f(Test a) {}^
+''');
+
+ assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, r'''
+import 'a.dart';
+
+void f(Test a) {}
+''');
+ }
+
+ Future<void> test_importLibrary_withTopLevelVariable() async {
+ var a_path = '/workspace/dart/test/lib/a.dart';
+ newFile(a_path, content: r'''
+var a = 0;
+''');
+ fileResolver.resolve(path: a_path);
+
+ await _compute(r'''
+void f() {
+ a;^
+}
+''');
+
+ assertHasFix(DartFixKind.IMPORT_LIBRARY_PROJECT1, r'''
+import 'a.dart';
+
+void f() {
+ a;
+}
+''');
+ }
+
Future<void> test_insertSemicolon() async {
await _compute(r'''
var v = 0^
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
new file mode 100644
index 0000000..bf7c774
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2021, 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 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test/expect.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(AddTrailingCommaBulkTest);
+ defineReflectiveTests(AddTrailingCommaInFileTest);
+ defineReflectiveTests(AddTrailingCommaTest);
+ });
+}
+
+@reflectiveTest
+class AddTrailingCommaBulkTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.require_trailing_commas;
+
+ Future<void> test_bulk() async {
+ await resolveTestCode('''
+Object f(a, b) {
+ f(f('a',
+ 'b'), 'b');
+ return a;
+}
+''');
+ await assertHasFix('''
+Object f(a, b) {
+ f(f('a',
+ 'b',), 'b',);
+ return a;
+}
+''');
+ }
+}
+
+@reflectiveTest
+class AddTrailingCommaInFileTest extends FixInFileProcessorTest {
+ Future<void> test_File() async {
+ createAnalysisOptionsFile(lints: [LintNames.require_trailing_commas]);
+ await resolveTestCode(r'''
+Object f(a, b) {
+ f(f('a',
+ 'b'), 'b');
+ return a;
+}
+''');
+ var fixes = await getFixesForFirstError();
+ expect(fixes, hasLength(1));
+ assertProduces(fixes.first, r'''
+Object f(a, b) {
+ f(f('a',
+ 'b',), 'b',);
+ return a;
+}
+''');
+ }
+}
+
+@reflectiveTest
+class AddTrailingCommaTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.ADD_TRAILING_COMMA;
+
+ @override
+ String get lintCode => LintNames.require_trailing_commas;
+
+ Future<void> test_comma() async {
+ await resolveTestCode('''
+void f(a, b) {
+ f('a',
+ 'b');
+}
+''');
+ await assertHasFix('''
+void f(a, b) {
+ f('a',
+ 'b',);
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_into_block_body_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_into_block_body_test.dart
new file mode 100644
index 0000000..8d2f3e8
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_into_block_body_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2021, 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 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConvertIntoBlockBodyTest);
+ });
+}
+
+@reflectiveTest
+class ConvertIntoBlockBodyTest extends FixProcessorTest {
+ @override
+ FixKind get kind => DartFixKind.CONVERT_INTO_BLOCK_BODY;
+
+ Future<void> test_function() async {
+ await resolveTestCode('''
+void f();
+''');
+ await assertHasFix('''
+void f() {
+ // TODO: implement f
+}
+''');
+ }
+
+ Future<void> test_method_Never() async {
+ await resolveTestCode('''
+class A {
+ Never m();
+}
+''');
+ await assertHasFix('''
+class A {
+ Never m() {
+ // TODO: implement m
+ throw UnimplementedError();
+ }
+}
+''');
+ }
+
+ Future<void> test_method_nonVoid() async {
+ await resolveTestCode('''
+class A {
+ String m(int i);
+}
+''');
+ await assertHasFix('''
+class A {
+ String m(int i) {
+ // TODO: implement m
+ throw UnimplementedError();
+ }
+}
+''');
+ }
+
+ Future<void> test_method_void() async {
+ await resolveTestCode('''
+class A {
+ void m();
+}
+''');
+ await assertHasFix('''
+class A {
+ void m() {
+ // TODO: implement m
+ }
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 7422ec8..fb32189 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -35,6 +35,7 @@
import 'add_super_constructor_invocation_test.dart'
as add_super_constructor_invocation;
import 'add_switch_case_break_test.dart' as add_switch_case_break;
+import 'add_trailing_comma_test.dart' as add_trailing_comma;
import 'add_type_annotation_test.dart' as add_type_annotation;
import 'analysis_options/test_all.dart' as analysis_options;
import 'bulk_fix_processor_test.dart' as bulk_fix_processor;
@@ -49,6 +50,7 @@
import 'convert_flutter_child_test.dart' as convert_flutter_child;
import 'convert_flutter_children_test.dart' as convert_flutter_children;
import 'convert_for_each_to_for_loop_test.dart' as convert_for_each_to_for_loop;
+import 'convert_into_block_body_test.dart' as convert_into_block_body;
import 'convert_into_expression_body_test.dart' as convert_into_expression_body;
import 'convert_into_is_not_test.dart' as convert_into_is_not;
import 'convert_quotes_test.dart' as convert_quotes;
@@ -232,6 +234,7 @@
add_static.main();
add_super_constructor_invocation.main();
add_switch_case_break.main();
+ add_trailing_comma.main();
add_type_annotation.main();
analysis_options.main();
bulk_fix_processor.main();
@@ -244,6 +247,7 @@
convert_flutter_child.main();
convert_flutter_children.main();
convert_for_each_to_for_loop.main();
+ convert_into_block_body.main();
convert_into_expression_body.main();
convert_into_is_not.main();
convert_quotes.main();
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 7007543..26adc7d 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 2.5.0
+* Updated `MockSdk` to include more declarations.
+
## 2.4.0
* Deprecated `ResourceProvider.getModificationTimes()`.
* Deprecated `MemoryResourceProvider.newDummyLink()`.
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
index a235cbb..07f0e0e 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
@@ -1375,6 +1375,7 @@
static const HintCode INVALID_USE_OF_VISIBLE_FOR_OVERRIDING_MEMBER = HintCode(
'INVALID_USE_OF_VISIBLE_FOR_OVERRIDING_MEMBER',
"The member '{0}' can only be used for overriding.",
+ hasPublishedDocs: true,
);
/**
@@ -1488,6 +1489,7 @@
static const HintCode INVALID_VISIBLE_FOR_OVERRIDING_ANNOTATION = HintCode(
'INVALID_VISIBLE_FOR_OVERRIDING_ANNOTATION',
"The declaration '{0}' is annotated with 'visibleForOverriding'. Because '{0}' isn't an interface member that could be overridden, the annotation is meaningless.",
+ hasPublishedDocs: true,
);
/**
@@ -1910,6 +1912,7 @@
'NULL_ARGUMENT_TO_NON_NULL_TYPE',
"'{0}' shouldn't be called with a null argument for the non-nullable type argument '{1}'.",
correctionMessage: "Try adding a non-null argument.",
+ hasPublishedDocs: true,
);
/**
@@ -2379,6 +2382,7 @@
"Tearing off a constructor requires the 'constructor-tearoffs' language feature.",
correctionMessage:
"Try updating your pubspec.yaml to set the minimum SDK constraint to 2.15 or higher, and running 'pub get'.",
+ hasPublishedDocs: true,
);
/**
@@ -2558,6 +2562,7 @@
'SDK_VERSION_GT_GT_GT_OPERATOR',
"The operator '>>>' wasn't supported until version 2.14.0, but this code is required to be able to run on earlier versions.",
correctionMessage: "Try updating the SDK constraints.",
+ hasPublishedDocs: true,
);
/**
@@ -3053,6 +3058,7 @@
static const HintCode UNDEFINED_REFERENCED_PARAMETER = HintCode(
'UNDEFINED_REFERENCED_PARAMETER',
"The parameter '{0}' is not defined by '{1}'.",
+ hasPublishedDocs: true,
);
/**
@@ -3205,6 +3211,7 @@
'UNNECESSARY_IMPORT',
"The import of '{0}' is unnecessary because all of the used elements are also provided by the import of '{1}'.",
correctionMessage: "Try removing the import directive.",
+ hasPublishedDocs: true,
);
/**
@@ -3363,6 +3370,7 @@
static const HintCode UNNECESSARY_QUESTION_MARK = HintCode(
'UNNECESSARY_QUESTION_MARK',
"The '?' is unnecessary because '{0}' is nullable without it.",
+ hasPublishedDocs: true,
);
/**
@@ -3810,6 +3818,7 @@
"The value of '{0}' should be used.",
correctionMessage:
"Try using the result by invoking a member, passing it to a function, or returning it from this function.",
+ hasPublishedDocs: true,
);
/**
@@ -3826,6 +3835,7 @@
"'{0}' should be used. {1}.",
correctionMessage:
"Try using the result by invoking a member, passing it to a function, or returning it from this function.",
+ hasPublishedDocs: true,
uniqueName: 'UNUSED_RESULT_WITH_MESSAGE',
);
@@ -3892,6 +3902,7 @@
'USE_OF_NATIVE_EXTENSION',
"Dart native extensions are deprecated and aren’t available in Dart 2.15.",
correctionMessage: "Try using dart:ffi for C interop.",
+ hasPublishedDocs: true,
);
/// Initialize a newly created error code to have the given [name].
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index cbee620..328c16a 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -88,6 +88,7 @@
late bool _exists;
late List<int> _apiSignature;
late UnlinkedUnit2 unlinked2;
+ late TopLevelDeclarations topLevelDeclarations;
Uint8List? informativeBytes;
LibraryCycle? _libraryCycle;
@@ -274,9 +275,18 @@
informativeBytes = informativeData!.bytes;
});
+ var decoded = CiderUnlinkedUnit.fromBuffer(unlinkedBytes!);
+ unlinked2 = decoded.unlinkedUnit!;
+
+ var unitDeclarations = decoded.topLevelDeclarations!;
+ topLevelDeclarations = TopLevelDeclarations(
+ extensionNames: unitDeclarations.extensionNames.toList(),
+ functionNames: unitDeclarations.functionNames.toList(),
+ typeNames: unitDeclarations.typeNames.toList(),
+ variableNames: unitDeclarations.variableNames.toList(),
+ );
+
performance.run('prefetch', (_) {
- var decoded = CiderUnlinkedUnit.fromBuffer(unlinkedBytes!);
- unlinked2 = decoded.unlinkedUnit!;
_prefetchDirectReferences(unlinked2);
});
}
@@ -493,6 +503,32 @@
),
);
}
+
+ var declaredExtensions = <String>[];
+ var declaredFunctions = <String>[];
+ var declaredTypes = <String>[];
+ var declaredVariables = <String>[];
+ for (var declaration in unit.declarations) {
+ if (declaration is ClassDeclaration) {
+ declaredTypes.add(declaration.name.name);
+ } else if (declaration is EnumDeclaration) {
+ declaredTypes.add(declaration.name.name);
+ } else if (declaration is ExtensionDeclaration) {
+ var name = declaration.name;
+ if (name != null) {
+ declaredExtensions.add(name.name);
+ }
+ } else if (declaration is FunctionDeclaration) {
+ declaredFunctions.add(declaration.name.name);
+ } else if (declaration is MixinDeclaration) {
+ declaredTypes.add(declaration.name.name);
+ } else if (declaration is TopLevelVariableDeclaration) {
+ for (var variable in declaration.variables.variables) {
+ declaredVariables.add(variable.name.name);
+ }
+ }
+ }
+
var unlinkedBuilder = UnlinkedUnit2Builder(
apiSignature: computeUnlinkedApiSignature(unit),
exports: exports,
@@ -505,7 +541,15 @@
lineStarts: unit.lineInfo!.lineStarts,
);
return CiderUnlinkedUnitBuilder(
- contentDigest: digest, unlinkedUnit: unlinkedBuilder);
+ contentDigest: digest,
+ unlinkedUnit: unlinkedBuilder,
+ topLevelDeclarations: CiderUnitTopLevelDeclarationsBuilder(
+ extensionNames: declaredExtensions,
+ functionNames: declaredFunctions,
+ typeNames: declaredTypes,
+ variableNames: declaredVariables,
+ ),
+ );
}
static UnlinkedNamespaceDirectiveBuilder _serializeNamespaceDirective(
@@ -712,6 +756,44 @@
return result;
}
+ /// Return files that have a top-level declaration with the [name].
+ List<FileWithTopLevelDeclaration> getFilesWithTopLevelDeclarations(
+ String name,
+ ) {
+ var result = <FileWithTopLevelDeclaration>[];
+
+ for (var file in _pathToFile.values) {
+ void addDeclaration(
+ List<String> names,
+ FileTopLevelDeclarationKind kind,
+ ) {
+ if (names.contains(name)) {
+ result.add(
+ FileWithTopLevelDeclaration(file: file, kind: kind),
+ );
+ }
+ }
+
+ addDeclaration(
+ file.topLevelDeclarations.extensionNames,
+ FileTopLevelDeclarationKind.extension,
+ );
+ addDeclaration(
+ file.topLevelDeclarations.functionNames,
+ FileTopLevelDeclarationKind.function,
+ );
+ addDeclaration(
+ file.topLevelDeclarations.typeNames,
+ FileTopLevelDeclarationKind.type,
+ );
+ addDeclaration(
+ file.topLevelDeclarations.variableNames,
+ FileTopLevelDeclarationKind.variable,
+ );
+ }
+ return result;
+ }
+
String? getPathForUri(Uri uri) {
var source = _sourceFactory.forUri2(uri);
if (source == null) {
@@ -789,6 +871,20 @@
}
}
+/// The kind in [FileWithTopLevelDeclaration].
+enum FileTopLevelDeclarationKind { extension, function, type, variable }
+
+/// The data structure for top-level declarations response.
+class FileWithTopLevelDeclaration {
+ final FileState file;
+ final FileTopLevelDeclarationKind kind;
+
+ FileWithTopLevelDeclaration({
+ required this.file,
+ required this.kind,
+ });
+}
+
/// Information about libraries that reference each other, so form a cycle.
class LibraryCycle {
/// The libraries that belong to this cycle.
@@ -824,6 +920,26 @@
}
}
+/// Kind of a top-level declaration.
+///
+/// We don't need it to be precise, just enough to support quick fixes.
+enum TopLevelDeclarationKind { type, extension, function, variable }
+
+/// Information about a single top-level declaration.
+class TopLevelDeclarations {
+ final List<String> extensionNames;
+ final List<String> functionNames;
+ final List<String> typeNames;
+ final List<String> variableNames;
+
+ TopLevelDeclarations({
+ required this.extensionNames,
+ required this.functionNames,
+ required this.typeNames,
+ required this.variableNames,
+ });
+}
+
class _FakeSource implements Source {
@override
final String fullName;
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index daf5dbd..21dc0ef 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -313,6 +313,17 @@
});
}
+ /// Return files that have a top-level declaration with the [name].
+ List<FileWithTopLevelDeclaration> getFilesWithTopLevelDeclarations(
+ String name,
+ ) {
+ final fsState = this.fsState;
+ if (fsState == null) {
+ return const [];
+ }
+ return fsState.getFilesWithTopLevelDeclarations(name);
+ }
+
LibraryElement getLibraryByUri({
required String uriStr,
OperationPerformanceImpl? performance,
diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart
index 38bf0a3..dd11f38 100644
--- a/pkg/analyzer/lib/src/error/codes.g.dart
+++ b/pkg/analyzer/lib/src/error/codes.g.dart
@@ -3137,6 +3137,7 @@
"Required named parameters can't have a default value.",
correctionMessage:
"Try removing either the default value or the 'required' modifier.",
+ hasPublishedDocs: true,
);
/**
@@ -5411,6 +5412,7 @@
"A method tear-off on a receiver whose type is 'dynamic' can't have type arguments.",
correctionMessage:
"Specify the type of the receiver, or remove the type arguments from the method tear-off.",
+ hasPublishedDocs: true,
);
/**
@@ -6478,6 +6480,7 @@
'INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER',
"Type aliases that expand to a type parameter can't be instantiated.",
correctionMessage: "Try replacing it with a class.",
+ hasPublishedDocs: true,
);
/**
@@ -6690,6 +6693,7 @@
"Constant values from a deferred library can't be used in annotations.",
correctionMessage:
"Try moving the constant from the deferred library, or removing 'deferred' from the import.",
+ hasPublishedDocs: true,
);
/**
@@ -10588,6 +10592,7 @@
static const CompileTimeErrorCode NOT_BINARY_OPERATOR = CompileTimeErrorCode(
'NOT_BINARY_OPERATOR',
"'{0}' isn't a binary operator.",
+ hasPublishedDocs: true,
);
/**
@@ -12313,6 +12318,7 @@
'REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER',
"A redirecting constructor can't redirect to a type alias that expands to a type parameter.",
correctionMessage: "Try replacing it with a class.",
+ hasPublishedDocs: true,
);
/**
@@ -13084,6 +13090,7 @@
"A generative constructor of an abstract class can't be torn off.",
correctionMessage:
"Try tearing off a constructor of a concrete class, or a non-generative constructor.",
+ hasPublishedDocs: true,
);
/**
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 6db5b7f..e59c7f2 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -3633,10 +3633,226 @@
String toString() => convert.json.encode(toJson());
}
+class CiderUnitTopLevelDeclarationsBuilder extends Object
+ with _CiderUnitTopLevelDeclarationsMixin
+ implements idl.CiderUnitTopLevelDeclarations {
+ List<String>? _extensionNames;
+ List<String>? _functionNames;
+ List<String>? _typeNames;
+ List<String>? _variableNames;
+
+ @override
+ List<String> get extensionNames => _extensionNames ??= <String>[];
+
+ set extensionNames(List<String> value) {
+ this._extensionNames = value;
+ }
+
+ @override
+ List<String> get functionNames => _functionNames ??= <String>[];
+
+ set functionNames(List<String> value) {
+ this._functionNames = value;
+ }
+
+ @override
+ List<String> get typeNames => _typeNames ??= <String>[];
+
+ set typeNames(List<String> value) {
+ this._typeNames = value;
+ }
+
+ @override
+ List<String> get variableNames => _variableNames ??= <String>[];
+
+ set variableNames(List<String> value) {
+ this._variableNames = value;
+ }
+
+ CiderUnitTopLevelDeclarationsBuilder(
+ {List<String>? extensionNames,
+ List<String>? functionNames,
+ List<String>? typeNames,
+ List<String>? variableNames})
+ : _extensionNames = extensionNames,
+ _functionNames = functionNames,
+ _typeNames = typeNames,
+ _variableNames = variableNames;
+
+ /// Flush [informative] data recursively.
+ void flushInformative() {}
+
+ /// Accumulate non-[informative] data into [signature].
+ void collectApiSignature(api_sig.ApiSignature signatureSink) {
+ var extensionNames = this._extensionNames;
+ if (extensionNames == null) {
+ signatureSink.addInt(0);
+ } else {
+ signatureSink.addInt(extensionNames.length);
+ for (var x in extensionNames) {
+ signatureSink.addString(x);
+ }
+ }
+ var functionNames = this._functionNames;
+ if (functionNames == null) {
+ signatureSink.addInt(0);
+ } else {
+ signatureSink.addInt(functionNames.length);
+ for (var x in functionNames) {
+ signatureSink.addString(x);
+ }
+ }
+ var typeNames = this._typeNames;
+ if (typeNames == null) {
+ signatureSink.addInt(0);
+ } else {
+ signatureSink.addInt(typeNames.length);
+ for (var x in typeNames) {
+ signatureSink.addString(x);
+ }
+ }
+ var variableNames = this._variableNames;
+ if (variableNames == null) {
+ signatureSink.addInt(0);
+ } else {
+ signatureSink.addInt(variableNames.length);
+ for (var x in variableNames) {
+ signatureSink.addString(x);
+ }
+ }
+ }
+
+ fb.Offset finish(fb.Builder fbBuilder) {
+ fb.Offset? offset_extensionNames;
+ fb.Offset? offset_functionNames;
+ fb.Offset? offset_typeNames;
+ fb.Offset? offset_variableNames;
+ var extensionNames = _extensionNames;
+ if (!(extensionNames == null || extensionNames.isEmpty)) {
+ offset_extensionNames = fbBuilder.writeList(
+ extensionNames.map((b) => fbBuilder.writeString(b)).toList());
+ }
+ var functionNames = _functionNames;
+ if (!(functionNames == null || functionNames.isEmpty)) {
+ offset_functionNames = fbBuilder.writeList(
+ functionNames.map((b) => fbBuilder.writeString(b)).toList());
+ }
+ var typeNames = _typeNames;
+ if (!(typeNames == null || typeNames.isEmpty)) {
+ offset_typeNames = fbBuilder
+ .writeList(typeNames.map((b) => fbBuilder.writeString(b)).toList());
+ }
+ var variableNames = _variableNames;
+ if (!(variableNames == null || variableNames.isEmpty)) {
+ offset_variableNames = fbBuilder.writeList(
+ variableNames.map((b) => fbBuilder.writeString(b)).toList());
+ }
+ fbBuilder.startTable();
+ if (offset_extensionNames != null) {
+ fbBuilder.addOffset(0, offset_extensionNames);
+ }
+ if (offset_functionNames != null) {
+ fbBuilder.addOffset(1, offset_functionNames);
+ }
+ if (offset_typeNames != null) {
+ fbBuilder.addOffset(2, offset_typeNames);
+ }
+ if (offset_variableNames != null) {
+ fbBuilder.addOffset(3, offset_variableNames);
+ }
+ return fbBuilder.endTable();
+ }
+}
+
+class _CiderUnitTopLevelDeclarationsReader
+ extends fb.TableReader<_CiderUnitTopLevelDeclarationsImpl> {
+ const _CiderUnitTopLevelDeclarationsReader();
+
+ @override
+ _CiderUnitTopLevelDeclarationsImpl createObject(
+ fb.BufferContext bc, int offset) =>
+ _CiderUnitTopLevelDeclarationsImpl(bc, offset);
+}
+
+class _CiderUnitTopLevelDeclarationsImpl extends Object
+ with _CiderUnitTopLevelDeclarationsMixin
+ implements idl.CiderUnitTopLevelDeclarations {
+ final fb.BufferContext _bc;
+ final int _bcOffset;
+
+ _CiderUnitTopLevelDeclarationsImpl(this._bc, this._bcOffset);
+
+ List<String>? _extensionNames;
+ List<String>? _functionNames;
+ List<String>? _typeNames;
+ List<String>? _variableNames;
+
+ @override
+ List<String> get extensionNames {
+ return _extensionNames ??= const fb.ListReader<String>(fb.StringReader())
+ .vTableGet(_bc, _bcOffset, 0, const <String>[]);
+ }
+
+ @override
+ List<String> get functionNames {
+ return _functionNames ??= const fb.ListReader<String>(fb.StringReader())
+ .vTableGet(_bc, _bcOffset, 1, const <String>[]);
+ }
+
+ @override
+ List<String> get typeNames {
+ return _typeNames ??= const fb.ListReader<String>(fb.StringReader())
+ .vTableGet(_bc, _bcOffset, 2, const <String>[]);
+ }
+
+ @override
+ List<String> get variableNames {
+ return _variableNames ??= const fb.ListReader<String>(fb.StringReader())
+ .vTableGet(_bc, _bcOffset, 3, const <String>[]);
+ }
+}
+
+abstract class _CiderUnitTopLevelDeclarationsMixin
+ implements idl.CiderUnitTopLevelDeclarations {
+ @override
+ Map<String, Object> toJson() {
+ Map<String, Object> _result = <String, Object>{};
+ var local_extensionNames = extensionNames;
+ if (local_extensionNames.isNotEmpty) {
+ _result["extensionNames"] = local_extensionNames;
+ }
+ var local_functionNames = functionNames;
+ if (local_functionNames.isNotEmpty) {
+ _result["functionNames"] = local_functionNames;
+ }
+ var local_typeNames = typeNames;
+ if (local_typeNames.isNotEmpty) {
+ _result["typeNames"] = local_typeNames;
+ }
+ var local_variableNames = variableNames;
+ if (local_variableNames.isNotEmpty) {
+ _result["variableNames"] = local_variableNames;
+ }
+ return _result;
+ }
+
+ @override
+ Map<String, Object?> toMap() => {
+ "extensionNames": extensionNames,
+ "functionNames": functionNames,
+ "typeNames": typeNames,
+ "variableNames": variableNames,
+ };
+
+ @override
+ String toString() => convert.json.encode(toJson());
+}
+
class CiderUnlinkedUnitBuilder extends Object
with _CiderUnlinkedUnitMixin
implements idl.CiderUnlinkedUnit {
List<int>? _contentDigest;
+ CiderUnitTopLevelDeclarationsBuilder? _topLevelDeclarations;
UnlinkedUnit2Builder? _unlinkedUnit;
@override
@@ -3649,6 +3865,15 @@
}
@override
+ CiderUnitTopLevelDeclarationsBuilder? get topLevelDeclarations =>
+ _topLevelDeclarations;
+
+ /// Top-level declarations of the unit.
+ set topLevelDeclarations(CiderUnitTopLevelDeclarationsBuilder? value) {
+ this._topLevelDeclarations = value;
+ }
+
+ @override
UnlinkedUnit2Builder? get unlinkedUnit => _unlinkedUnit;
/// Unlinked summary of the compilation unit.
@@ -3657,12 +3882,16 @@
}
CiderUnlinkedUnitBuilder(
- {List<int>? contentDigest, UnlinkedUnit2Builder? unlinkedUnit})
+ {List<int>? contentDigest,
+ CiderUnitTopLevelDeclarationsBuilder? topLevelDeclarations,
+ UnlinkedUnit2Builder? unlinkedUnit})
: _contentDigest = contentDigest,
+ _topLevelDeclarations = topLevelDeclarations,
_unlinkedUnit = unlinkedUnit;
/// Flush [informative] data recursively.
void flushInformative() {
+ _topLevelDeclarations?.flushInformative();
_unlinkedUnit?.flushInformative();
}
@@ -3677,6 +3906,8 @@
signatureSink.addInt(x);
}
}
+ signatureSink.addBool(this._topLevelDeclarations != null);
+ this._topLevelDeclarations?.collectApiSignature(signatureSink);
signatureSink.addBool(this._unlinkedUnit != null);
this._unlinkedUnit?.collectApiSignature(signatureSink);
}
@@ -3688,11 +3919,16 @@
fb.Offset finish(fb.Builder fbBuilder) {
fb.Offset? offset_contentDigest;
+ fb.Offset? offset_topLevelDeclarations;
fb.Offset? offset_unlinkedUnit;
var contentDigest = _contentDigest;
if (!(contentDigest == null || contentDigest.isEmpty)) {
offset_contentDigest = fbBuilder.writeListUint32(contentDigest);
}
+ var topLevelDeclarations = _topLevelDeclarations;
+ if (topLevelDeclarations != null) {
+ offset_topLevelDeclarations = topLevelDeclarations.finish(fbBuilder);
+ }
var unlinkedUnit = _unlinkedUnit;
if (unlinkedUnit != null) {
offset_unlinkedUnit = unlinkedUnit.finish(fbBuilder);
@@ -3701,8 +3937,11 @@
if (offset_contentDigest != null) {
fbBuilder.addOffset(0, offset_contentDigest);
}
+ if (offset_topLevelDeclarations != null) {
+ fbBuilder.addOffset(1, offset_topLevelDeclarations);
+ }
if (offset_unlinkedUnit != null) {
- fbBuilder.addOffset(1, offset_unlinkedUnit);
+ fbBuilder.addOffset(2, offset_unlinkedUnit);
}
return fbBuilder.endTable();
}
@@ -3730,6 +3969,7 @@
_CiderUnlinkedUnitImpl(this._bc, this._bcOffset);
List<int>? _contentDigest;
+ idl.CiderUnitTopLevelDeclarations? _topLevelDeclarations;
idl.UnlinkedUnit2? _unlinkedUnit;
@override
@@ -3739,9 +3979,16 @@
}
@override
+ idl.CiderUnitTopLevelDeclarations? get topLevelDeclarations {
+ return _topLevelDeclarations ??=
+ const _CiderUnitTopLevelDeclarationsReader()
+ .vTableGetOrNull(_bc, _bcOffset, 1);
+ }
+
+ @override
idl.UnlinkedUnit2? get unlinkedUnit {
return _unlinkedUnit ??=
- const _UnlinkedUnit2Reader().vTableGetOrNull(_bc, _bcOffset, 1);
+ const _UnlinkedUnit2Reader().vTableGetOrNull(_bc, _bcOffset, 2);
}
}
@@ -3753,6 +4000,10 @@
if (local_contentDigest.isNotEmpty) {
_result["contentDigest"] = local_contentDigest;
}
+ var local_topLevelDeclarations = topLevelDeclarations;
+ if (local_topLevelDeclarations != null) {
+ _result["topLevelDeclarations"] = local_topLevelDeclarations.toJson();
+ }
var local_unlinkedUnit = unlinkedUnit;
if (local_unlinkedUnit != null) {
_result["unlinkedUnit"] = local_unlinkedUnit.toJson();
@@ -3763,6 +4014,7 @@
@override
Map<String, Object?> toMap() => {
"contentDigest": contentDigest,
+ "topLevelDeclarations": topLevelDeclarations,
"unlinkedUnit": unlinkedUnit,
};
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 75c773b..18b2f2a 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -422,14 +422,28 @@
signature:[uint] (id: 0);
}
+/// Top-level declarations in a compilation unit.
+table CiderUnitTopLevelDeclarations {
+ extensionNames:[string] (id: 0);
+
+ functionNames:[string] (id: 1);
+
+ typeNames:[string] (id: 2);
+
+ variableNames:[string] (id: 3);
+}
+
/// Information about a compilation unit, contains the content hash
/// and unlinked summary.
table CiderUnlinkedUnit {
/// The hash signature of the contents of the file.
contentDigest:[uint] (id: 0);
+ /// Top-level declarations of the unit.
+ topLevelDeclarations:CiderUnitTopLevelDeclarations (id: 1);
+
/// Unlinked summary of the compilation unit.
- unlinkedUnit:UnlinkedUnit2 (id: 1);
+ unlinkedUnit:UnlinkedUnit2 (id: 2);
}
table DiagnosticMessage {
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index ee5b366..d715b69 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -463,6 +463,21 @@
List<int> get signature;
}
+/// Top-level declarations in a compilation unit.
+abstract class CiderUnitTopLevelDeclarations extends base.SummaryClass {
+ @Id(0)
+ List<String> get extensionNames;
+
+ @Id(1)
+ List<String> get functionNames;
+
+ @Id(2)
+ List<String> get typeNames;
+
+ @Id(3)
+ List<String> get variableNames;
+}
+
/// Information about a compilation unit, contains the content hash
/// and unlinked summary.
@TopLevel('CUUN')
@@ -474,8 +489,12 @@
@Id(0)
List<int> get contentDigest;
- /// Unlinked summary of the compilation unit.
+ /// Top-level declarations of the unit.
@Id(1)
+ CiderUnitTopLevelDeclarations? get topLevelDeclarations;
+
+ /// Unlinked summary of the compilation unit.
+ @Id(2)
UnlinkedUnit2? get unlinkedUnit;
}
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index 50e2280..268f0cf 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -2923,6 +2923,7 @@
DEFAULT_VALUE_ON_REQUIRED_PARAMETER:
problemMessage: "Required named parameters can't have a default value."
correctionMessage: "Try removing either the default value or the 'required' modifier."
+ hasPublishedDocs: true
comment: No parameters.
documentation: |-
#### Description
@@ -4797,6 +4798,7 @@
GENERIC_METHOD_TYPE_INSTANTIATION_ON_DYNAMIC:
problemMessage: "A method tear-off on a receiver whose type is 'dynamic' can't have type arguments."
correctionMessage: Specify the type of the receiver, or remove the type arguments from the method tear-off.
+ hasPublishedDocs: true
comment: No parameters.
documentation: |-
#### Description
@@ -5706,6 +5708,7 @@
INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER:
problemMessage: "Type aliases that expand to a type parameter can't be instantiated."
correctionMessage: Try replacing it with a class.
+ hasPublishedDocs: true
comment: No parameters.
documentation: |-
#### Description
@@ -5887,6 +5890,7 @@
INVALID_ANNOTATION_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY:
problemMessage: "Constant values from a deferred library can't be used in annotations."
correctionMessage: "Try moving the constant from the deferred library, or removing 'deferred' from the import."
+ hasPublishedDocs: true
comment: No parameters.
documentation: |-
#### Description
@@ -9129,6 +9133,7 @@
Replace the name with the name of a type.
NOT_BINARY_OPERATOR:
problemMessage: "'{0}' isn't a binary operator."
+ hasPublishedDocs: true
comment: |-
Parameters:
0: the name of the operator that is not a binary operator.
@@ -10609,6 +10614,7 @@
REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER:
problemMessage: "A redirecting constructor can't redirect to a type alias that expands to a type parameter."
correctionMessage: Try replacing it with a class.
+ hasPublishedDocs: true
comment: No parameters.
documentation: |-
#### Description
@@ -11473,6 +11479,7 @@
TEAROFF_OF_GENERATIVE_CONSTRUCTOR_OF_ABSTRACT_CLASS:
problemMessage: "A generative constructor of an abstract class can't be torn off."
correctionMessage: Try tearing off a constructor of a concrete class, or a non-generative constructor.
+ hasPublishedDocs: true
comment: No parameters.
documentation: |-
#### Description
@@ -15047,6 +15054,7 @@
1: the name of the defining class
INVALID_USE_OF_VISIBLE_FOR_OVERRIDING_MEMBER:
problemMessage: "The member '{0}' can only be used for overriding."
+ hasPublishedDocs: true
comment: |-
Parameters:
0: the name of the member
@@ -15158,6 +15166,7 @@
```
INVALID_VISIBLE_FOR_OVERRIDING_ANNOTATION:
problemMessage: "The declaration '{0}' is annotated with 'visibleForOverriding'. Because '{0}' isn't an interface member that could be overridden, the annotation is meaningless."
+ hasPublishedDocs: true
comment: No parameters.
documentation: |-
#### Description
@@ -15534,6 +15543,7 @@
NULL_ARGUMENT_TO_NON_NULL_TYPE:
problemMessage: "'{0}' shouldn't be called with a null argument for the non-nullable type argument '{1}'."
correctionMessage: Try adding a non-null argument.
+ hasPublishedDocs: true
comment: |-
Parameters:
0: the name of the method being invoked
@@ -15847,6 +15857,7 @@
SDK_VERSION_CONSTRUCTOR_TEAROFFS:
problemMessage: "Tearing off a constructor requires the 'constructor-tearoffs' language feature."
correctionMessage: "Try updating your pubspec.yaml to set the minimum SDK constraint to 2.15 or higher, and running 'pub get'."
+ hasPublishedDocs: true
comment: |-
No parameters.
@@ -16014,6 +16025,7 @@
SDK_VERSION_GT_GT_GT_OPERATOR:
problemMessage: "The operator '>>>' wasn't supported until version 2.14.0, but this code is required to be able to run on earlier versions."
correctionMessage: Try updating the SDK constraints.
+ hasPublishedDocs: true
comment: No parameters.
documentation: |-
#### Description
@@ -16483,6 +16495,7 @@
```
UNDEFINED_REFERENCED_PARAMETER:
problemMessage: "The parameter '{0}' is not defined by '{1}'."
+ hasPublishedDocs: true
comment: |-
Parameters:
0: the name of the undefined parameter
@@ -16602,6 +16615,7 @@
UNNECESSARY_IMPORT:
problemMessage: "The import of '{0}' is unnecessary because all of the used elements are also provided by the import of '{1}'."
correctionMessage: Try removing the import directive.
+ hasPublishedDocs: true
comment: |-
Parameters:
0: the uri that is not necessary
@@ -16764,6 +16778,7 @@
comment: No parameters.
UNNECESSARY_QUESTION_MARK:
problemMessage: "The '?' is unnecessary because '{0}' is nullable without it."
+ hasPublishedDocs: true
comment: |-
Parameters:
0: the name of the type
@@ -17126,6 +17141,7 @@
UNUSED_RESULT:
problemMessage: "The value of '{0}' should be used."
correctionMessage: Try using the result by invoking a member, passing it to a function, or returning it from this function.
+ hasPublishedDocs: true
comment: |-
Parameters:
0: the name of the annotated method, property or function
@@ -17200,6 +17216,7 @@
sharedName: UNUSED_RESULT
problemMessage: "'{0}' should be used. {1}."
correctionMessage: Try using the result by invoking a member, passing it to a function, or returning it from this function.
+ hasPublishedDocs: true
comment: |-
The result of invoking a method, property, or function annotated with
`@useResult` must be used (assigned, passed to a function as an argument,
@@ -17245,6 +17262,7 @@
USE_OF_NATIVE_EXTENSION:
problemMessage: Dart native extensions are deprecated and aren’t available in Dart 2.15.
correctionMessage: "Try using dart:ffi for C interop."
+ hasPublishedDocs: true
comment: No parameters.
documentation: |-
#### Description
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 8497bb1..b717171 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 2.4.0
+version: 2.5.0
description: This package provides a library that performs static analysis of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer
@@ -7,7 +7,7 @@
sdk: '>=2.14.0 <3.0.0'
dependencies:
- _fe_analyzer_shared: ^27.0.0
+ _fe_analyzer_shared: ^28.0.0
cli_util: ^0.3.0
collection: ^1.15.0
convert: ^3.0.0
@@ -25,7 +25,7 @@
path: ../analyzer_utilities
args: ^2.0.0
async: ^2.5.0
- linter: any
+ linter: ^1.12.0
matcher: ^0.12.10
test: ^1.16.0
test_reflective_loader: ^0.2.0
diff --git a/pkg/dev_compiler/lib/src/kernel/module_metadata.dart b/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
index 5669874..416f0d8 100644
--- a/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
+++ b/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
@@ -2,9 +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.
-// @dart = 2.9
-
-/// Module metadata format version
+/// Module metadata format version.
///
/// Module reader always creates the current version but is able to read
/// metadata files with later versions as long as the changes are backward
@@ -22,10 +20,10 @@
this.patchVersion,
);
- /// Current metadata version
+ /// The current metadata version.
///
- /// Version follows simple semantic versioning format 'major.minor.patch'
- /// See https://semver.org
+ /// Version follows simple semantic versioning format 'major.minor.patch'.
+ /// See: https://semver.org
///
/// TODO(annagrin): create metadata package, make version the same as the
/// metadata package version, automate updating with the package update
@@ -34,7 +32,7 @@
/// Current metadata version created by the reader
String get version => '$majorVersion.$minorVersion.$patchVersion';
- /// Is this metadata version compatible with the given version
+ /// True if this metadata version is compatible with [version].
///
/// The minor and patch version changes never remove any fields that current
/// version supports, so the reader can create current metadata version from
@@ -55,28 +53,27 @@
}
}
-/// Library metadata
+/// Metadata used by the debugger to describe a library.
///
-/// Represents library metadata used in the debugger,
-/// supports reading from and writing to json
+/// Supports reading from and writing to json.
/// See: https://goto.google.com/dart-web-debugger-metadata
class LibraryMetadata {
/// Library name as defined in pubspec.yaml
final String name;
- /// Library importUri
+ /// URI used to import the library.
///
- /// Example package:path/path.dart
+ /// Example: package:path/path.dart
final String importUri;
- /// Library fileUri
+ /// File URI for the library.
///
- /// Example file:///path/to/path/path.dart
+ /// Example: file:///path/to/path/path.dart
final String fileUri;
- /// All file uris from the library
+ /// All file URIs (include part files) from the library.
///
- /// Can be relative paths to the directory of the fileUri
+ /// Can be relative paths to the directory of the fileUri.
final List<String> partUris;
LibraryMetadata(this.name, this.importUri, this.fileUri, this.partUris);
@@ -98,37 +95,35 @@
}
}
-/// Module metadata
+/// Metadata used by the debugger to describe a module.
///
-/// Represents module metadata used in the debugger,
-/// supports reading from and writing to json
+/// Supports reading from and writing to json.
/// See: https://goto.google.com/dart-web-debugger-metadata
class ModuleMetadata {
- /// Metadata format version
- String version;
+ /// The version of this metadata.
+ final String version;
- /// Module name
+ /// Name of the js module created by the compiler.
///
- /// Used as a name of the js module created by the compiler and
- /// as key to store and load modules in the debugger and the browser
+ /// Used as a key to store and load modules in the debugger and the browser.
final String name;
- /// Name of the function enclosing the module
+ /// Name of the function enclosing the module.
///
- /// Used by debugger to determine the top dart scope
+ /// Used by debugger to determine the top dart scope.
final String closureName;
- /// Source map uri
+ /// URI of the source map for this module.
final String sourceMapUri;
- /// Module uri
+ /// URI of the module.
final String moduleUri;
- /// The uri where DDC wrote a full .dill file for this module.
+ /// The URI where DDC wrote a full .dill file for this module.
///
- /// Can be `null` if the module was compiled without the option to output the
- /// .dill fle.
- final String fullDillUri;
+ /// Will be `null` when the module was compiled without the option to output
+ /// the .dill fle.
+ final String? fullDillUri;
final Map<String, LibraryMetadata> libraries = {};
@@ -138,14 +133,13 @@
ModuleMetadata(this.name, this.closureName, this.sourceMapUri, this.moduleUri,
this.fullDillUri, this.soundNullSafety,
- {this.version}) {
- version ??= ModuleMetadataVersion.current.version;
- }
+ {String? version})
+ : version = version ??= ModuleMetadataVersion.current.version;
- /// Add [library] to metadata
+ /// Add [library] to this metadata.
///
- /// Used for filling the metadata in the compiler or for reading from
- /// stored metadata files.
+ /// Used for filling the metadata in the compiler or for reading from stored
+ /// metadata files.
void addLibrary(LibraryMetadata library) {
if (!libraries.containsKey(library.importUri)) {
libraries[library.importUri] = library;
@@ -165,9 +159,8 @@
moduleUri = json['moduleUri'] as String,
fullDillUri = json['fullDillUri'] as String,
soundNullSafety = json['soundNullSafety'] as bool {
- var fileVersion = json['version'] as String;
if (!ModuleMetadataVersion.current.isCompatibleWith(version)) {
- throw Exception('Unsupported metadata version $fileVersion');
+ throw Exception('Unsupported metadata version $version');
}
for (var l in json['libraries'] as List<dynamic>) {
diff --git a/pkg/dev_compiler/test/module_metadata_test.dart b/pkg/dev_compiler/test/module_metadata_test.dart
index 9d6c862..e3a74e0 100644
--- a/pkg/dev_compiler/test/module_metadata_test.dart
+++ b/pkg/dev_compiler/test/module_metadata_test.dart
@@ -2,19 +2,17 @@
// 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.
-// @dart = 2.9
-
import 'dart:convert';
import 'dart:io';
import 'package:dev_compiler/src/kernel/module_metadata.dart';
import 'package:test/test.dart';
-// Test creating, reading and writing debugger metadata
+/// Test creating, reading and writing debugger metadata.
void main() {
group('Module metadata', () {
- Directory tempDir;
- File file;
+ late Directory tempDir;
+ late File file;
setUpAll(() {
var systemTempDir = Directory.systemTemp;
@@ -28,16 +26,16 @@
});
test('create, write, and read', () async {
- // create metadata
+ // Create metadata.
var version = ModuleMetadataVersion.current.version;
var module = createMetadata(version);
testMetadataFields(module, version);
- // write metadata
+ // Write metadata.
file.writeAsBytesSync(utf8.encode(json.encode(module)));
expect(file.existsSync(), true);
- // read metadata
+ // Read metadata.
var moduleJson = json.decode(utf8.decode(file.readAsBytesSync()));
var newModule =
ModuleMetadata.fromJson(moduleJson as Map<String, dynamic>);
@@ -45,7 +43,7 @@
});
test('read later backward-compatible patch version', () async {
- // create metadata with next patch version
+ // Create metadata with next patch version.
var version = ModuleMetadataVersion(
ModuleMetadataVersion.current.majorVersion,
ModuleMetadataVersion.current.minorVersion,
@@ -54,11 +52,11 @@
var module = createMetadata(version);
- // write metadata
+ // Write metadata.
file.writeAsBytesSync(utf8.encode(json.encode(module)));
expect(file.existsSync(), true);
- // read metadata
+ // Read metadata.
var moduleJson = json.decode(utf8.decode(file.readAsBytesSync()));
var newModule =
ModuleMetadata.fromJson(moduleJson as Map<String, dynamic>);
@@ -66,7 +64,7 @@
});
test('read later backward-compatible minor version', () async {
- // create metadata with next minor version
+ // Create metadata with next minor version.
var version = ModuleMetadataVersion(
ModuleMetadataVersion.current.majorVersion,
ModuleMetadataVersion.current.minorVersion + 1,
@@ -74,11 +72,11 @@
.version;
var module = createMetadata(version);
- // write metadata
+ // Write metadata.
file.writeAsBytesSync(utf8.encode(json.encode(module)));
expect(file.existsSync(), true);
- // read metadata
+ // Read metadata.
var moduleJson = json.decode(utf8.decode(file.readAsBytesSync()));
var newModule =
ModuleMetadata.fromJson(moduleJson as Map<String, dynamic>);
@@ -86,7 +84,7 @@
});
test('fail to read later non-backward-compatible major version', () async {
- // create metadata with next minor version
+ // Create metadata with next minor version.
var version = ModuleMetadataVersion(
ModuleMetadataVersion.current.majorVersion + 1,
ModuleMetadataVersion.current.minorVersion + 1,
@@ -94,13 +92,13 @@
.version;
var module = createMetadata(version);
- // write metadata
+ // Write metadata.
file.writeAsBytesSync(utf8.encode(json.encode(module)));
expect(file.existsSync(), true);
- // try read metadata, expect to fail
+ // Try read metadata, expect to fail.
var moduleJson = json.decode(utf8.decode(file.readAsBytesSync()));
- ModuleMetadata newModule;
+ ModuleMetadata? newModule;
try {
newModule = ModuleMetadata.fromJson(moduleJson as Map<String, dynamic>);
} catch (e) {
@@ -120,7 +118,7 @@
'file:///source/library/lib/test.dart', ['src/test2.dart']));
void testMetadataFields(ModuleMetadata module, String version) {
- // reader always creates current metadata version
+ // Reader always creates current metadata version.
expect(module.version, version);
expect(module.name, 'module');
expect(module.closureName, 'closure');
@@ -130,8 +128,7 @@
expect(module.soundNullSafety, true);
var libUri = module.libraries.keys.first;
- var lib = module.libraries[libUri];
-
+ var lib = module.libraries[libUri]!;
expect(libUri, 'package:library/test.dart');
expect(lib.name, 'library');
expect(lib.importUri, 'package:library/test.dart');
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 0515336..a46cadc 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -180,7 +180,6 @@
ClassTable* class_table = isolate->group()->class_table();
Class& klass = Class::Handle(zone);
- Closure& closure = Closure::Handle(zone);
bool error_found = false;
Function& erroneous_closure_function = Function::Handle(zone);
@@ -205,8 +204,12 @@
ObjectPtr raw = working_set.RemoveLast();
const intptr_t cid = raw->GetClassId();
+ // Keep the list in sync with the one in message_snapshot.cc
switch (cid) {
- // List below matches the one in raw_object_snapshot.cc
+ case kRegExpCid:
+ // Can be shared, need to be explicitly listed to prevent inspection.
+ continue;
+
#define MESSAGE_SNAPSHOT_ILLEGAL(type) \
case k##type##Cid: \
error_message = \
@@ -214,27 +217,15 @@
error_found = true; \
break;
- MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
- MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
- MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
- MESSAGE_SNAPSHOT_ILLEGAL(ReceivePort);
- MESSAGE_SNAPSHOT_ILLEGAL(RegExp);
- MESSAGE_SNAPSHOT_ILLEGAL(StackTrace);
- MESSAGE_SNAPSHOT_ILLEGAL(UserTag);
+ MESSAGE_SNAPSHOT_ILLEGAL(FunctionType);
+ MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
+ MESSAGE_SNAPSHOT_ILLEGAL(ReceivePort);
+ MESSAGE_SNAPSHOT_ILLEGAL(StackTrace);
+ MESSAGE_SNAPSHOT_ILLEGAL(UserTag);
- case kClosureCid: {
- closure = Closure::RawCast(raw);
- FunctionPtr func = closure.function();
- // We only allow closure of top level methods or static functions in a
- // class to be sent in isolate messages.
- if (!Function::IsImplicitStaticClosureFunction(func)) {
- // All other closures are errors.
- erroneous_closure_function = func;
- error_found = true;
- break;
- }
- break;
- }
+ MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
+ MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
+
default:
if (cid >= kNumPredefinedCids) {
klass = class_table->At(cid);
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 9878a02..703be40 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -3995,7 +3995,6 @@
case 'NativeEntryData':
return M.ObjectPoolEntryKind.nativeEntryData;
case 'NativeFunction':
- case 'NativeFunctionWrapper':
return M.ObjectPoolEntryKind.nativeEntry;
}
throw new Exception('Unknown ObjectPoolEntryKind ($kind)');
diff --git a/runtime/observatory_2/lib/src/service/object.dart b/runtime/observatory_2/lib/src/service/object.dart
index 5e220dc..a8d3c89 100644
--- a/runtime/observatory_2/lib/src/service/object.dart
+++ b/runtime/observatory_2/lib/src/service/object.dart
@@ -4008,7 +4008,6 @@
case 'NativeEntryData':
return M.ObjectPoolEntryKind.nativeEntryData;
case 'NativeFunction':
- case 'NativeFunctionWrapper':
return M.ObjectPoolEntryKind.nativeEntry;
}
throw new Exception('Unknown ObjectPoolEntryKind ($kind)');
diff --git a/runtime/tests/vm/dart/sendandexit_test.dart b/runtime/tests/vm/dart/sendandexit_test.dart
index 235a3c2..a67858e 100644
--- a/runtime/tests/vm/dart/sendandexit_test.dart
+++ b/runtime/tests/vm/dart/sendandexit_test.dart
@@ -12,6 +12,9 @@
import "package:expect/expect.dart";
+import "isolates/fast_object_copy2_test.dart"
+ show sharableObjects, copyableClosures;
+
doNothingWorker(data) {}
spawnWorker(worker, data) async {
@@ -23,17 +26,6 @@
return await completer.future;
}
-verifyCantSendAnonymousClosure() async {
- final receivePort = ReceivePort();
- Expect.throws(
- () => Isolate.exit(receivePort.sendPort, () {}),
- (e) =>
- e.toString() ==
- 'Invalid argument: "Illegal argument in isolate message : '
- '(object is a closure - Function \'<anonymous closure>\': static.)"');
- receivePort.close();
-}
-
class NativeWrapperClass extends NativeFieldWrapperClass1 {}
verifyCantSendNative() async {
@@ -50,23 +42,40 @@
final receivePort = ReceivePort();
Expect.throws(
() => Isolate.exit(receivePort.sendPort, receivePort),
- // closure is encountered first before we reach ReceivePort instance
(e) => e.toString().startsWith(
'Invalid argument: "Illegal argument in isolate message : '
- '(object is a closure - Function \''));
+ '(object is a ReceivePort)\"'));
receivePort.close();
}
-verifyCantSendRegexp() async {
- final receivePort = ReceivePort();
- final regexp = RegExp("");
- Expect.throws(
- () => Isolate.exit(receivePort.sendPort, regexp),
- (e) =>
- e.toString() ==
- 'Invalid argument: '
- '"Illegal argument in isolate message : (object is a RegExp)"');
- receivePort.close();
+sendShareable(SendPort sendPort) {
+ Isolate.exit(sendPort, sharableObjects);
+}
+
+verifyCanSendShareable() async {
+ final port = ReceivePort();
+ final inbox = StreamIterator<dynamic>(port);
+ final isolate = await Isolate.spawn(sendShareable, port.sendPort);
+
+ await inbox.moveNext();
+ final result = inbox.current;
+ Expect.equals(sharableObjects.length, result.length);
+ port.close();
+}
+
+sendCopyable(SendPort sendPort) {
+ Isolate.exit(sendPort, copyableClosures);
+}
+
+verifyCanSendCopyableClosures() async {
+ final port = ReceivePort();
+ final inbox = StreamIterator<dynamic>(port);
+ final isolate = await Isolate.spawn(sendCopyable, port.sendPort);
+
+ await inbox.moveNext();
+ final result = inbox.current;
+ Expect.equals(copyableClosures.length, result.length);
+ port.close();
}
add(a, b) => a + b;
@@ -75,16 +84,6 @@
Isolate.exit(sendPort, add);
}
-verifyCanSendStaticMethod() async {
- final port = ReceivePort();
- final inbox = StreamIterator<dynamic>(port);
- final isolate = await Isolate.spawn(worker, port.sendPort);
-
- await inbox.moveNext();
- Expect.equals(5, (inbox.current)(2, 3));
- port.close();
-}
-
verifyExitMessageIsPostedLast() async {
final port = ReceivePort();
final inbox = new StreamIterator<dynamic>(port);
@@ -108,10 +107,9 @@
}
main() async {
- await verifyCantSendAnonymousClosure();
await verifyCantSendNative();
await verifyCantSendReceivePort();
- await verifyCantSendRegexp();
- await verifyCanSendStaticMethod();
+ await verifyCanSendShareable();
+ await verifyCanSendCopyableClosures();
await verifyExitMessageIsPostedLast();
}
diff --git a/runtime/tests/vm/dart_2/sendandexit_test.dart b/runtime/tests/vm/dart_2/sendandexit_test.dart
index 3ee64fe..f72712f 100644
--- a/runtime/tests/vm/dart_2/sendandexit_test.dart
+++ b/runtime/tests/vm/dart_2/sendandexit_test.dart
@@ -14,6 +14,9 @@
import "package:expect/expect.dart";
+import "isolates/fast_object_copy2_test.dart"
+ show sharableObjects, copyableClosures;
+
doNothingWorker(data) {}
spawnWorker(worker, data) async {
@@ -25,17 +28,6 @@
return await completer.future;
}
-verifyCantSendAnonymousClosure() async {
- final receivePort = ReceivePort();
- Expect.throws(
- () => Isolate.exit(receivePort.sendPort, () {}),
- (e) =>
- e.toString() ==
- 'Invalid argument: "Illegal argument in isolate message : '
- '(object is a closure - Function \'<anonymous closure>\': static.)"');
- receivePort.close();
-}
-
class NativeWrapperClass extends NativeFieldWrapperClass1 {}
verifyCantSendNative() async {
@@ -52,23 +44,40 @@
final receivePort = ReceivePort();
Expect.throws(
() => Isolate.exit(receivePort.sendPort, receivePort),
- // closure is encountered first before we reach ReceivePort instance
(e) => e.toString().startsWith(
'Invalid argument: "Illegal argument in isolate message : '
- '(object is a closure - Function \''));
+ '(object is a ReceivePort)\"'));
receivePort.close();
}
-verifyCantSendRegexp() async {
- final receivePort = ReceivePort();
- final regexp = RegExp("");
- Expect.throws(
- () => Isolate.exit(receivePort.sendPort, regexp),
- (e) =>
- e.toString() ==
- 'Invalid argument: '
- '"Illegal argument in isolate message : (object is a RegExp)"');
- receivePort.close();
+sendShareable(SendPort sendPort) {
+ Isolate.exit(sendPort, sharableObjects);
+}
+
+verifyCanSendShareable() async {
+ final port = ReceivePort();
+ final inbox = StreamIterator<dynamic>(port);
+ final isolate = await Isolate.spawn(sendShareable, port.sendPort);
+
+ await inbox.moveNext();
+ final result = inbox.current;
+ Expect.equals(sharableObjects.length, result.length);
+ port.close();
+}
+
+sendCopyable(SendPort sendPort) {
+ Isolate.exit(sendPort, copyableClosures);
+}
+
+verifyCanSendCopyableClosures() async {
+ final port = ReceivePort();
+ final inbox = StreamIterator<dynamic>(port);
+ final isolate = await Isolate.spawn(sendCopyable, port.sendPort);
+
+ await inbox.moveNext();
+ final result = inbox.current;
+ Expect.equals(copyableClosures.length, result.length);
+ port.close();
}
add(a, b) => a + b;
@@ -77,16 +86,6 @@
Isolate.exit(sendPort, add);
}
-verifyCanSendStaticMethod() async {
- final port = ReceivePort();
- final inbox = StreamIterator<dynamic>(port);
- final isolate = await Isolate.spawn(worker, port.sendPort);
-
- await inbox.moveNext();
- Expect.equals(5, (inbox.current)(2, 3));
- port.close();
-}
-
verifyExitMessageIsPostedLast() async {
final port = ReceivePort();
final inbox = new StreamIterator<dynamic>(port);
@@ -110,10 +109,9 @@
}
main() async {
- await verifyCantSendAnonymousClosure();
await verifyCantSendNative();
await verifyCantSendReceivePort();
- await verifyCantSendRegexp();
- await verifyCanSendStaticMethod();
+ await verifyCanSendShareable();
+ await verifyCanSendCopyableClosures();
await verifyExitMessageIsPostedLast();
}
diff --git a/runtime/vm/app_snapshot.cc b/runtime/vm/app_snapshot.cc
index 85e1bcb..c2c8b3d 100644
--- a/runtime/vm/app_snapshot.cc
+++ b/runtime/vm/app_snapshot.cc
@@ -2340,8 +2340,7 @@
s->Write<intptr_t>(entry.raw_value_);
break;
}
- case ObjectPool::EntryType::kNativeFunction:
- case ObjectPool::EntryType::kNativeFunctionWrapper: {
+ case ObjectPool::EntryType::kNativeFunction: {
// Write nothing. Will initialize with the lazy link entry.
break;
}
diff --git a/runtime/vm/compiler/assembler/assembler_base.cc b/runtime/vm/compiler/assembler/assembler_base.cc
index 9dbd0ff..07d7285 100644
--- a/runtime/vm/compiler/assembler/assembler_base.cc
+++ b/runtime/vm/compiler/assembler/assembler_base.cc
@@ -414,14 +414,6 @@
label->address(), ObjectPoolBuilderEntry::kNativeFunction, patchable));
}
-intptr_t ObjectPoolBuilder::FindNativeFunctionWrapper(
- const ExternalLabel* label,
- ObjectPoolBuilderEntry::Patchability patchable) {
- return FindObject(ObjectPoolBuilderEntry(
- label->address(), ObjectPoolBuilderEntry::kNativeFunctionWrapper,
- patchable));
-}
-
bool ObjectPoolBuilder::TryCommitToParent() {
ASSERT(parent_ != nullptr);
if (parent_->CurrentLength() != base_index_) {
diff --git a/runtime/vm/compiler/assembler/object_pool_builder.h b/runtime/vm/compiler/assembler/object_pool_builder.h
index e33ded6..7ceb222 100644
--- a/runtime/vm/compiler/assembler/object_pool_builder.h
+++ b/runtime/vm/compiler/assembler/object_pool_builder.h
@@ -29,7 +29,6 @@
kTaggedObject,
kImmediate,
kNativeFunction,
- kNativeFunctionWrapper,
// Used only during AOT snapshot serialization/deserialization.
// Denotes kImmediate entry with
@@ -166,9 +165,6 @@
intptr_t FindImmediate(uword imm);
intptr_t FindNativeFunction(const ExternalLabel* label,
ObjectPoolBuilderEntry::Patchability patchable);
- intptr_t FindNativeFunctionWrapper(
- const ExternalLabel* label,
- ObjectPoolBuilderEntry::Patchability patchable);
intptr_t CurrentLength() const {
return object_pool_.length() + used_from_parent_.length();
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
index ac2eef3..97196b1 100644
--- a/runtime/vm/message_snapshot.cc
+++ b/runtime/vm/message_snapshot.cc
@@ -3110,6 +3110,8 @@
IllegalObject(*object, chars);
}
}
+
+ // Keep the list in sync with the one in lib/isolate.cc
#define ILLEGAL(type) \
if (cid == k##type##Cid) { \
IllegalObject(*object, \
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index d793156..1fa6c99 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -14704,8 +14704,7 @@
break;
}
case compiler::ObjectPoolBuilderEntry::kImmediate:
- case compiler::ObjectPoolBuilderEntry::kNativeFunction:
- case compiler::ObjectPoolBuilderEntry::kNativeFunctionWrapper: {
+ case compiler::ObjectPoolBuilderEntry::kNativeFunction: {
compiler::ObjectPoolBuilderEntry entry(RawValueAt(i), type, patchable);
builder->AddObject(entry);
break;
@@ -14741,8 +14740,6 @@
} else {
THR_Print("0x%" Px " (native function)\n", pc);
}
- } else if (TypeAt(i) == EntryType::kNativeFunctionWrapper) {
- THR_Print("0x%" Px " (native function wrapper)\n", RawValueAt(i));
} else {
THR_Print("0x%" Px " (raw)\n", RawValueAt(i));
}
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 1685ebf..f7fe7fe 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -722,11 +722,6 @@
jsentry.AddProperty("kind", "NativeFunction");
jsentry.AddProperty64("value", imm);
break;
- case ObjectPool::EntryType::kNativeFunctionWrapper:
- imm = RawValueAt(i);
- jsentry.AddProperty("kind", "NativeFunctionWrapper");
- jsentry.AddProperty64("value", imm);
- break;
default:
UNREACHABLE();
}
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index 00b7fc6..0b16dae 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -73,7 +73,7 @@
/// Another common use of streams is for user-generated events
/// in a web app: The following code listens for mouse clicks on a button.
/// ```dart import:html
-/// querySelector('#myButton').onClick.forEach((_) => print('Click.'));
+/// querySelector('#myButton')!.onClick.forEach((_) => print('Click.'));
/// ```
/// ## Other resources
///
diff --git a/sdk/lib/async/deferred_load.dart b/sdk/lib/async/deferred_load.dart
index 81d9f80..98dda08 100644
--- a/sdk/lib/async/deferred_load.dart
+++ b/sdk/lib/async/deferred_load.dart
@@ -6,9 +6,8 @@
/// Indicates that loading of [libraryName] is deferred.
///
-/// This class is obsolete. Instead use the syntax:
-/// ```dart
-/// import "library.dart" deferred as prefix;
+/// This class is obsolete. Instead prefer the `deferred as` import directive
+/// syntax.
/// ```
@Deprecated("Dart sdk v. 1.8")
class DeferredLibrary {
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index 8ac4701..1c51340 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -690,7 +690,6 @@
/// ```dart
/// var words = ['fee', 'fi', 'fo', 'fum'];
/// var map = words.asMap(); // {0: fee, 1: fi, 2: fo, 3: fum}
- /// map[0] + map[1]; // 'feefi';
/// map.keys.toList(); // [0, 1, 2, 3]
/// ```
Map<int, E> asMap();
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 59b3461..5d53fb1 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -12997,7 +12997,7 @@
}
@pragma('dart2js:tryInline')
- void setAttribute(String name, String value) {
+ void setAttribute(String name, Object value) {
// TODO(41258): Delete these assertions after forcing strong mode.
// Protect [name] against string conversion to "null" or "undefined".
assert(name != null, 'Attribute name cannot be null');
@@ -13006,7 +13006,7 @@
}
@pragma('dart2js:tryInline')
- void setAttributeNS(String? namespaceURI, String name, String value) {
+ void setAttributeNS(String? namespaceURI, String name, Object value) {
// TODO(41258): Delete these assertions after forcing strong mode.
// Protect [name] against string conversion to "null" or "undefined".
assert(name != null, 'Attribute name cannot be null');
@@ -14860,10 +14860,10 @@
void _scrollTo_3(num? x, y) native;
@JSName('setAttribute')
- void _setAttribute(String name, String value) native;
+ void _setAttribute(String name, Object value) native;
@JSName('setAttributeNS')
- void _setAttributeNS(String? namespaceURI, String name, String value) native;
+ void _setAttributeNS(String? namespaceURI, String name, Object value) native;
void setPointerCapture(int pointerId) native;
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index 4cad26d..f504810 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -184,7 +184,7 @@
/// To read text synchronously from the command line
/// (the program blocks waiting for user to type information):
/// ```dart
-/// String inputText = stdin.readLineSync();
+/// String? inputText = stdin.readLineSync();
/// ```
/// {@category VM}
library dart.io;
diff --git a/tools/VERSION b/tools/VERSION
index 8f9bd6b..aa707b0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 185
+PRERELEASE 186
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index b33dc8d..699473c 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -521,10 +521,16 @@
[DartName=start2] void start(optional double when);
};
-// Remove operation requestFullscreen only use webKitRequestFullscreen.
[DartSupplemental]
interface Element : Node {
+ // Remove operation requestFullscreen only use webKitRequestFullscreen.
[DartSuppress] void requestFullscreen();
+ // setAttribute and setAttributeNS can take in non-string values that are
+ // then converted to strings.
+ [DartSuppress] void setAttribute(DOMString name, DOMString value);
+ [DartSuppress] void setAttributeNS(DOMString? namespaceURI, DOMString name, DOMString value);
+ void setAttribute(DOMString name, object value);
+ void setAttributeNS(DOMString? namespaceURI, DOMString name, object value);
};
[DartSupplemental]
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index fadfc3b..5f39f92 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -645,7 +645,7 @@
}
@pragma('dart2js:tryInline')
- void setAttribute(String name, String value) {
+ void setAttribute(String name, Object value) {
$if NNBD
// TODO(41258): Delete these assertions after forcing strong mode.
$endif
@@ -656,7 +656,7 @@
}
@pragma('dart2js:tryInline')
- void setAttributeNS(String$NULLABLE namespaceURI, String name, String value) {
+ void setAttributeNS(String$NULLABLE namespaceURI, String name, Object value) {
$if NNBD
// TODO(41258): Delete these assertions after forcing strong mode.
$endif