Version 2.18.0-18.0.dev
Merge commit 'c50940b56b1ec2232e135954dc84bc223ce45348' into 'dev'
diff --git a/DEPS b/DEPS
index 3c0b60d..db8fe96 100644
--- a/DEPS
+++ b/DEPS
@@ -152,7 +152,7 @@
"shelf_web_socket_rev": "24fb8a04befa75a94ac63a27047b231d1a22aab4",
"source_map_stack_trace_rev": "8eabd96b1811e30a11d3c54c9b4afae4fb72e98f",
"source_maps-0.9.4_rev": "38524",
- "source_maps_rev": "6499ee3adac8d469e2953e2e8ba4bdb4c2fbef90",
+ "source_maps_rev": "c07a01b8d5547ce3a47ee7a7a2b938a2bc09afe3",
"source_span_rev": "8ae724c3e67f5afaacead44e93ff145bfb8775c7",
"sse_rev": "9084339389eb441d0c0518cddac211a097e78657",
"stack_trace_rev": "5220580872625ddee41e9ca9a5f3364789b2f0f6",
diff --git a/build/config/linux/BUILD.gn b/build/config/linux/BUILD.gn
index 06aabec..cf3f77a5 100644
--- a/build/config/linux/BUILD.gn
+++ b/build/config/linux/BUILD.gn
@@ -35,10 +35,6 @@
]
}
}
-
- if (is_qemu) {
- cflags += [ "-DDART_RUN_IN_QEMU_ARMv7" ]
- }
}
config("executable_config") {
diff --git a/pkg/_js_interop_checks/lib/src/transformations/js_util_wasm_optimizer.dart b/pkg/_js_interop_checks/lib/src/transformations/js_util_wasm_optimizer.dart
index eb6de83..220d07b 100644
--- a/pkg/_js_interop_checks/lib/src/transformations/js_util_wasm_optimizer.dart
+++ b/pkg/_js_interop_checks/lib/src/transformations/js_util_wasm_optimizer.dart
@@ -8,7 +8,11 @@
import 'package:kernel/type_environment.dart';
import '../js_interop.dart'
- show getJSName, hasStaticInteropAnnotation, hasJSInteropAnnotation;
+ show
+ getJSName,
+ hasAnonymousAnnotation,
+ hasStaticInteropAnnotation,
+ hasJSInteropAnnotation;
/// Replaces:
/// 1) Factory constructors in classes with `@staticInterop` annotations with
@@ -29,6 +33,15 @@
/// trampolines based off the interop type, to avoid megamorphic behavior.
/// This would have code size implications though, so we would need to
/// proceed carefully.
+/// TODO(joshualitt): A few of the functions in this file use js_utils in a
+/// naive way, and could be optimized further. In particular, there are a few
+/// complex operations in [JsUtilWasmOptimizer] where it is obvious a value is
+/// flowing from / to JS, and we have a few options for optimization:
+/// 1) Integrate with `js_ast` and emit custom JavaScript for each of these
+/// operations.
+/// 2) Use the `raw` variants of the js_util calls.
+/// 3) Move more of the logic for these calls into JS where it will likely be
+/// faster.
class JsUtilWasmOptimizer extends Transformer {
final Procedure _callMethodTarget;
final Procedure _callConstructorTarget;
@@ -37,6 +50,7 @@
final Procedure _setPropertyTarget;
final Procedure _jsifyTarget;
final Procedure _dartifyTarget;
+ final Procedure _newObjectTarget;
final Class _jsValueClass;
final CoreTypes _coreTypes;
@@ -59,6 +73,8 @@
_coreTypes.index.getTopLevelProcedure('dart:js_util_wasm', 'jsify'),
_dartifyTarget = _coreTypes.index
.getTopLevelProcedure('dart:js_util_wasm', 'dartify'),
+ _newObjectTarget = _coreTypes.index
+ .getTopLevelProcedure('dart:js_util_wasm', 'newObject'),
_jsValueClass =
_coreTypes.index.getClass('dart:js_util_wasm', 'JSValue'),
_staticTypeContext = StatefulStaticTypeContext.stacked(
@@ -85,15 +101,19 @@
@override
Procedure visitProcedure(Procedure node) {
_staticTypeContext.enterMember(node);
- ReturnStatement? transformedBody;
+ Statement? transformedBody;
if (node.isExternal) {
if (node.isFactory) {
Class cls = node.enclosingClass!;
if (hasStaticInteropAnnotation(cls)) {
- String jsName = getJSName(cls);
- String constructorName = jsName == '' ? cls.name : jsName;
- transformedBody =
- _getExternalCallConstructorBody(node, constructorName);
+ if (hasAnonymousAnnotation(cls)) {
+ transformedBody = _getExternalAnonymousConstructorBody(node);
+ } else {
+ String jsName = getJSName(cls);
+ String constructorName = jsName == '' ? cls.name : jsName;
+ transformedBody =
+ _getExternalCallConstructorBody(node, constructorName);
+ }
}
} else if (node.isExtensionMember) {
var index = _extensionMemberIndex ??=
@@ -161,6 +181,9 @@
DartType get _nullableJSValueType =>
_jsValueClass.getThisType(_coreTypes, Nullability.nullable);
+ DartType get _nonNullableJSValueType =>
+ _jsValueClass.getThisType(_coreTypes, Nullability.nonNullable);
+
Expression _jsifyVariable(VariableDeclaration variable) =>
StaticInvocation(_jsifyTarget, Arguments([VariableGet(variable)]));
@@ -173,13 +196,30 @@
Expression getObjectOffGlobalThis(Procedure node, List<String> selectors) {
Expression currentTarget = _globalThis;
for (String selector in selectors) {
- currentTarget = _dartify(StaticInvocation(_getPropertyTarget,
- Arguments([currentTarget, StringLiteral(selector)])))
- ..fileOffset = node.fileOffset;
+ currentTarget = _getProperty(node, currentTarget, selector);
}
return currentTarget;
}
+ /// Returns a new function body for the given [node] external factory method
+ /// for a class annotated with `@anonymous`.
+ ///
+ /// This lowers a factory function with named arguments to the creation of a
+ /// new object literal, and a series of `setProperty` calls.
+ Block _getExternalAnonymousConstructorBody(Procedure node) {
+ List<Statement> body = [];
+ final object = VariableDeclaration('|anonymousObject',
+ initializer: StaticInvocation(_newObjectTarget, Arguments([])),
+ type: _nonNullableJSValueType);
+ body.add(object);
+ for (VariableDeclaration variable in node.function.namedParameters) {
+ body.add(ExpressionStatement(
+ _setProperty(node, VariableGet(object), variable.name!, variable)));
+ }
+ body.add(ReturnStatement(VariableGet(object)));
+ return Block(body);
+ }
+
/// Returns a new function body for the given [node] external method.
///
/// The new function body will call `js_util_wasm.callConstructorVarArgs`
@@ -194,7 +234,7 @@
StringLiteral(constructorName),
ListLiteral(
function.positionalParameters.map(_jsifyVariable).toList(),
- typeArgument: _nullableJSValueType)
+ typeArgument: _nonNullableJSValueType)
]))
..fileOffset = node.fileOffset;
return ReturnStatement(callConstructorInvocation);
@@ -203,17 +243,20 @@
Expression _dartify(Expression expression) =>
StaticInvocation(_dartifyTarget, Arguments([expression]));
- /// Returns a new function body for the given [node] external getter.
+ /// Returns a new [Expression] for the given [node] external getter.
///
- /// The new function body is equivalent to:
+ /// The new [Expression] is equivalent to:
/// `js_util_wasm.getProperty([object], [getterName])`.
+ Expression _getProperty(
+ Procedure node, Expression object, String getterName) =>
+ StaticInvocation(
+ _getPropertyTarget, Arguments([object, StringLiteral(getterName)]))
+ ..fileOffset = node.fileOffset;
+
+ /// Returns a new function body for the given [node] external getter.
ReturnStatement _getExternalGetterBody(
- Procedure node, Expression object, String getterName) {
- final getPropertyInvocation = _dartify(StaticInvocation(
- _getPropertyTarget, Arguments([object, StringLiteral(getterName)])))
- ..fileOffset = node.fileOffset;
- return ReturnStatement(getPropertyInvocation);
- }
+ Procedure node, Expression object, String getterName) =>
+ ReturnStatement(_dartify(_getProperty(node, object, getterName)));
ReturnStatement _getExternalExtensionGetterBody(Procedure node) =>
_getExternalGetterBody(
@@ -225,17 +268,20 @@
Procedure node, Expression target) =>
_getExternalGetterBody(node, target, node.name.text);
- /// Returns a new function body for the given [node] external setter.
+ /// Returns a new [Expression] for the given [node] external setter.
///
- /// The new function body is equivalent to:
+ /// The new [Expression] is equivalent to:
/// `js_util_wasm.setProperty([object], [setterName], [value])`.
+ Expression _setProperty(Procedure node, Expression object, String setterName,
+ VariableDeclaration value) =>
+ StaticInvocation(_setPropertyTarget,
+ Arguments([object, StringLiteral(setterName), _jsifyVariable(value)]))
+ ..fileOffset = node.fileOffset;
+
+ /// Returns a new function body for the given [node] external setter.
ReturnStatement _getExternalSetterBody(Procedure node, Expression object,
- String setterName, VariableDeclaration value) {
- final setPropertyInvocation = _dartify(StaticInvocation(_setPropertyTarget,
- Arguments([object, StringLiteral(setterName), _jsifyVariable(value)])))
- ..fileOffset = node.fileOffset;
- return ReturnStatement(setPropertyInvocation);
- }
+ String setterName, VariableDeclaration value) =>
+ ReturnStatement(_dartify(_setProperty(node, object, setterName, value)));
ReturnStatement _getExternalExtensionSetterBody(Procedure node) {
final parameters = node.function.positionalParameters;
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 20795bf..9eda1d5 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -3,7 +3,7 @@
publish_to: none
environment:
- sdk: '>=2.15.0 <3.0.0'
+ sdk: '>=2.17.0 <3.0.0'
dependencies:
_fe_analyzer_shared:
diff --git a/pkg/analysis_server/test/completion_test_support.dart b/pkg/analysis_server/test/completion_test_support.dart
index 7de6d30..cba131c 100644
--- a/pkg/analysis_server/test/completion_test_support.dart
+++ b/pkg/analysis_server/test/completion_test_support.dart
@@ -81,17 +81,19 @@
Future runTest(LocationSpec spec, [Map<String, String>? extraFiles]) async {
await super.setUp();
- return Future(() {
- var content = spec.source;
- newFile2(testFile, content);
- testCode = content;
+
+ try {
+ extraFiles?.forEach((String fileName, String content) {
+ newFile2(fileName, content);
+ });
+
+ newFile2(testFile.path, spec.source);
completionOffset = spec.testLocation;
- if (extraFiles != null) {
- extraFiles.forEach((String fileName, String content) {
- newFile2(fileName, content);
- });
- }
- }).then((_) => getSuggestions()).then((_) {
+ await getSuggestions(
+ path: testFile.path,
+ completionOffset: completionOffset,
+ );
+
filterResults(spec.source);
for (var result in spec.positiveResults) {
assertHasCompletion(result);
@@ -99,9 +101,9 @@
for (var result in spec.negativeResults) {
assertHasNoCompletion(result);
}
- }).whenComplete(() {
+ } finally {
super.tearDown();
- });
+ }
}
}
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 7503258..78c3b52 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -1989,28 +1989,25 @@
extends AbstractCompletionDomainTest {
Future<void> test_ArgumentList_constructor_named_fieldFormalParam() async {
// https://github.com/dart-lang/sdk/issues/31023
- addTestFile('''
+ await getTestCodeSuggestions('''
void f() { new A(field: ^);}
class A {
A({this.field: -1}) {}
}
''');
- await getSuggestions();
}
Future<void> test_ArgumentList_constructor_named_param_label() async {
- addTestFile('void f() { new A(^);}'
+ await getTestCodeSuggestions('void f() { new A(^);}'
'class A { A({one, two}) {} }');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'one: ');
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'two: ');
expect(suggestions, hasLength(2));
}
Future<void> test_ArgumentList_factory_named_param_label() async {
- addTestFile('void f() { new A(^);}'
+ await getTestCodeSuggestions('void f() { new A(^);}'
'class A { factory A({one, two}) => throw 0; }');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'one: ');
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'two: ');
expect(suggestions, hasLength(2));
@@ -2018,9 +2015,8 @@
Future<void>
test_ArgumentList_function_named_fromPositionalNumeric_withoutSpace() async {
- addTestFile('void f(int a, {int b = 0}) {}'
+ await getTestCodeSuggestions('void f(int a, {int b = 0}) {}'
'void g() { f(2, ^3); }');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'b: ');
expect(suggestions, hasLength(1));
// Ensure we don't try to replace the following arg.
@@ -2030,9 +2026,8 @@
Future<void>
test_ArgumentList_function_named_fromPositionalNumeric_withSpace() async {
- addTestFile('void f(int a, {int b = 0}) {}'
+ await getTestCodeSuggestions('void f(int a, {int b = 0}) {}'
'void g() { f(2, ^ 3); }');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'b: ');
expect(suggestions, hasLength(1));
// Ensure we don't try to replace the following arg.
@@ -2042,10 +2037,9 @@
Future<void>
test_ArgumentList_function_named_fromPositionalVariable_withoutSpace() async {
- addTestFile('void f(int a, {int b = 0}) {}'
+ await getTestCodeSuggestions('void f(int a, {int b = 0}) {}'
'var foo = 1;'
'void g() { f(2, ^foo); }');
- await getSuggestions();
expect(suggestions, hasLength(1));
// The named arg "b: " should not replace anything.
@@ -2055,10 +2049,9 @@
Future<void>
test_ArgumentList_function_named_fromPositionalVariable_withSpace() async {
- addTestFile('void f(int a, {int b = 0}) {}'
+ await getTestCodeSuggestions('void f(int a, {int b = 0}) {}'
'var foo = 1;'
'void g() { f(2, ^ foo); }');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'b: ');
expect(suggestions, hasLength(1));
// Ensure we don't try to replace the following arg.
@@ -2067,7 +2060,7 @@
}
Future<void> test_ArgumentList_function_named_partiallyTyped() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
void m(String firstString, {String secondString}) {}
@@ -2076,7 +2069,6 @@
}
}
''');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'secondString: ');
expect(suggestions, hasLength(1));
// Ensure we replace the correct section.
@@ -2085,48 +2077,42 @@
}
Future<void> test_ArgumentList_imported_function_named_param() async {
- addTestFile('void f() { int.parse("16", ^);}');
- await getSuggestions();
+ await getTestCodeSuggestions('void f() { int.parse("16", ^);}');
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'radix: ');
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'onError: ');
expect(suggestions, hasLength(2));
}
Future<void> test_ArgumentList_imported_function_named_param1() async {
- addTestFile('void f() { foo(o^);} foo({one, two}) {}');
- await getSuggestions();
+ await getTestCodeSuggestions('void f() { foo(o^);} foo({one, two}) {}');
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'one: ');
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'two: ');
expect(suggestions, hasLength(2));
}
Future<void> test_ArgumentList_imported_function_named_param2() async {
- addTestFile('void f() {A a = new A(); a.foo(one: 7, ^);}'
+ await getTestCodeSuggestions('void f() {A a = new A(); a.foo(one: 7, ^);}'
'class A { foo({one, two}) {} }');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'two: ');
expect(suggestions, hasLength(1));
}
Future<void> test_ArgumentList_imported_function_named_param_label1() async {
- addTestFile('void f() { int.parse("16", r^: 16);}');
- await getSuggestions();
+ await getTestCodeSuggestions('void f() { int.parse("16", r^: 16);}');
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'radix');
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'onError');
expect(suggestions, hasLength(2));
}
Future<void> test_ArgumentList_imported_function_named_param_label3() async {
- addTestFile('void f() { int.parse("16", ^: 16);}');
- await getSuggestions();
+ await getTestCodeSuggestions('void f() { int.parse("16", ^: 16);}');
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'radix');
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'onError');
expect(suggestions, hasLength(2));
}
Future<void> test_catch() async {
- addTestFile('void f() {try {} ^}');
- await getSuggestions();
+ await getTestCodeSuggestions('void f() {try {} ^}');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'on');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'catch');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'finally');
@@ -2134,8 +2120,7 @@
}
Future<void> test_catch2() async {
- addTestFile('void f() {try {} on Foo {} ^}');
- await getSuggestions();
+ await getTestCodeSuggestions('void f() {try {} on Foo {} ^}');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'on');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'catch');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'finally');
@@ -2148,8 +2133,7 @@
}
Future<void> test_catch3() async {
- addTestFile('void f() {try {} catch (e) {} finally {} ^}');
- await getSuggestions();
+ await getTestCodeSuggestions('void f() {try {} catch (e) {} finally {} ^}');
assertNoResult('on');
assertNoResult('catch');
assertNoResult('finally');
@@ -2162,8 +2146,7 @@
}
Future<void> test_catch4() async {
- addTestFile('void f() {try {} finally {} ^}');
- await getSuggestions();
+ await getTestCodeSuggestions('void f() {try {} finally {} ^}');
assertNoResult('on');
assertNoResult('catch');
assertNoResult('finally');
@@ -2176,57 +2159,51 @@
}
Future<void> test_catch5() async {
- addTestFile('void f() {try {} ^ finally {}}');
- await getSuggestions();
+ await getTestCodeSuggestions('void f() {try {} ^ finally {}}');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'on');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'catch');
expect(suggestions, hasLength(2));
}
Future<void> test_constructor() async {
- addTestFile('class A {bool foo; A() : ^;}');
- await getSuggestions();
+ await getTestCodeSuggestions('class A {bool foo; A() : ^;}');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
}
Future<void> test_constructor2() async {
- addTestFile('class A {bool foo; A() : s^;}');
- await getSuggestions();
+ await getTestCodeSuggestions('class A {bool foo; A() : s^;}');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
}
Future<void> test_constructor3() async {
- addTestFile('class A {bool foo; A() : a=7,^;}');
- await getSuggestions();
+ await getTestCodeSuggestions('class A {bool foo; A() : a=7,^;}');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
}
Future<void> test_constructor4() async {
- addTestFile('class A {bool foo; A() : a=7,s^;}');
- await getSuggestions();
+ await getTestCodeSuggestions('class A {bool foo; A() : a=7,s^;}');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
}
Future<void> test_constructor5() async {
- addTestFile('class A {bool foo; A() : a=7,s^}');
- await getSuggestions();
+ await getTestCodeSuggestions('class A {bool foo; A() : a=7,s^}');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
}
Future<void> test_constructor6() async {
- addTestFile('class A {bool foo; A() : a=7,^ void bar() {}}');
- await getSuggestions();
+ await getTestCodeSuggestions(
+ 'class A {bool foo; A() : a=7,^ void bar() {}}');
assertHasResult(CompletionSuggestionKind.KEYWORD, 'super');
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
}
Future<void> test_extension() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class MyClass {
void foo() {
ba^
@@ -2237,71 +2214,67 @@
void bar() {}
}
''');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.INVOCATION, 'bar');
}
- Future<void> test_html() {
+ Future<void> test_html() async {
//
// We no longer support the analysis of non-dart files.
//
- testFile = convertPath('/project/web/test.html');
- addTestFile('''
- <html>^</html>
- ''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- expect(suggestions, hasLength(0));
- });
+ await getCodeSuggestions(
+ path: convertPath('$testPackageLibPath/test.html'),
+ content: '<html>^</html>',
+ );
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ expect(suggestions, hasLength(0));
}
- Future<void> test_import_uri_with_trailing() {
+ Future<void> test_import_uri_with_trailing() async {
final filePath = '/project/bin/testA.dart';
final incompleteImportText = toUriStr('/project/bin/t');
newFile2(filePath, 'library libA;');
- addTestFile('''
+ await getTestCodeSuggestions('''
import "$incompleteImportText^.dart";
void f() {}''');
- return getSuggestions().then((_) {
- expect(replacementOffset,
- equals(completionOffset - incompleteImportText.length));
- expect(replacementLength, equals(5 + incompleteImportText.length));
- assertHasResult(CompletionSuggestionKind.IMPORT, toUriStr(filePath));
- assertNoResult('test');
- });
+ expect(replacementOffset,
+ equals(completionOffset - incompleteImportText.length));
+ expect(replacementLength, equals(5 + incompleteImportText.length));
+ assertHasResult(CompletionSuggestionKind.IMPORT, toUriStr(filePath));
+ assertNoResult('test');
}
- Future<void> test_imports() {
- addTestFile('''
+ Future<void> test_imports() async {
+ await getTestCodeSuggestions('''
import 'dart:html';
void f() {^}
''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
- elementKind: ElementKind.CLASS);
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement',
- elementKind: ElementKind.CLASS);
- assertNoResult('test');
- });
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
+ elementKind: ElementKind.CLASS);
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement',
+ elementKind: ElementKind.CLASS);
+ assertNoResult('test');
}
Future<void> test_imports_aborted_new_request() async {
addTestFile('''
class foo { }
- c^''');
+ c''');
+ completionOffset = 31;
// Make a request for suggestions
- var request1 = CompletionGetSuggestionsParams(testFile, completionOffset)
- .toRequest('7');
- var responseFuture1 = waitResponse(request1);
+ var request1 =
+ CompletionGetSuggestionsParams(testFile.path, completionOffset)
+ .toRequest('7');
+ var responseFuture1 = serverChannel.sendRequest(request1);
// Make another request before the first request completes
- var request2 = CompletionGetSuggestionsParams(testFile, completionOffset)
- .toRequest('8');
- var responseFuture2 = waitResponse(request2);
+ var request2 =
+ CompletionGetSuggestionsParams(testFile.path, completionOffset)
+ .toRequest('8');
+ var responseFuture2 = serverChannel.sendRequest(request2);
// Await first response
var response1 = await responseFuture1;
@@ -2314,7 +2287,7 @@
assertValidId(result2.id);
// Wait for all processing to be complete
- await analysisHandler.server.onAnalysisComplete;
+ await server.onAnalysisComplete;
await pumpEventQueue();
// Assert that first request has been aborted
@@ -2336,14 +2309,17 @@
c^''');
// Make a request for suggestions
- var request = CompletionGetSuggestionsParams(testFile, completionOffset)
- .toRequest('0');
- var responseFuture = waitResponse(request);
+ var request =
+ CompletionGetSuggestionsParams(testFile.path, completionOffset)
+ .toRequest('0');
+ var responseFuture = handleSuccessfulRequest(request);
// Simulate user deleting text after request but before suggestions returned
- server.updateContent('uc1', {testFile: AddContentOverlay(testCode)});
+ server.updateContent(
+ 'uc1', {testFile.path: AddContentOverlay(testFileContent)});
server.updateContent('uc2', {
- testFile: ChangeContentOverlay([SourceEdit(completionOffset - 1, 1, '')])
+ testFile.path:
+ ChangeContentOverlay([SourceEdit(completionOffset - 1, 1, '')])
});
// Await a response
@@ -2352,7 +2328,7 @@
assertValidId(completionId);
// Wait for all processing to be complete
- await analysisHandler.server.onAnalysisComplete;
+ await server.onAnalysisComplete;
await pumpEventQueue();
// Assert that request has been aborted
@@ -2366,13 +2342,19 @@
import "dart:async";
import "package:foo/foo.dart";
class foo { }''');
+ completionOffset = 20;
await waitForTasksFinished();
- server.updateContent('uc1', {testFile: AddContentOverlay(testCode)});
+ server.updateContent(
+ 'uc1', {testFile.path: AddContentOverlay(testFileContent)});
server.updateContent('uc2', {
- testFile: ChangeContentOverlay([SourceEdit(completionOffset, 0, 'xp')])
+ testFile.path:
+ ChangeContentOverlay([SourceEdit(completionOffset, 0, 'xp')])
});
completionOffset += 2;
- await getSuggestions();
+ await getSuggestions(
+ path: testFile.path,
+ completionOffset: completionOffset,
+ );
expect(replacementOffset, completionOffset - 3);
expect(replacementLength, 3);
assertHasResult(CompletionSuggestionKind.KEYWORD, 'export \'\';',
@@ -2384,22 +2366,24 @@
}
Future<void> test_imports_partial() async {
- addTestFile('''^
+ addTestFile('''
import "package:foo/foo.dart";
import "package:bar/bar.dart";
class Baz { }''');
+ completionOffset = 0;
// Wait for analysis then edit the content
await waitForTasksFinished();
- var revisedContent =
- '${testCode.substring(0, completionOffset)}i${testCode.substring(completionOffset)}';
+ var revisedContent = testFileContent.substring(0, 0) +
+ 'i' +
+ testFileContent.substring(completionOffset);
++completionOffset;
server.handleRequest(AnalysisUpdateContentParams(
- {testFile: AddContentOverlay(revisedContent)}).toRequest('add1'));
+ {testFile.path: AddContentOverlay(revisedContent)}).toRequest('add1'));
// Request code completion immediately after edit
- var response = await waitResponse(
- CompletionGetSuggestionsParams(testFile, completionOffset)
+ var response = await handleSuccessfulRequest(
+ CompletionGetSuggestionsParams(testFile.path, completionOffset)
.toRequest('0'));
completionId = response.id;
assertValidId(completionId);
@@ -2422,123 +2406,110 @@
assertNoResult('extends');
}
- Future<void> test_imports_prefixed() {
- addTestFile('''
+ Future<void> test_imports_prefixed() async {
+ await getTestCodeSuggestions('''
import 'dart:html' as foo;
void f() {^}
''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
- elementKind: ElementKind.CLASS);
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
- assertNoResult('HtmlElement');
- assertNoResult('test');
- });
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
+ elementKind: ElementKind.CLASS);
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
+ assertNoResult('HtmlElement');
+ assertNoResult('test');
}
- Future<void> test_imports_prefixed2() {
- addTestFile('''
+ Future<void> test_imports_prefixed2() async {
+ await getTestCodeSuggestions('''
import 'dart:html' as foo;
void f() {foo.^}
''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement');
- assertNoResult('test');
- });
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement');
+ assertNoResult('test');
}
Future<void> test_inComment_block_beforeDartDoc() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
/* text ^ */
/// some doc comments
class SomeClass {}
''');
- await getSuggestions();
expect(suggestions, isEmpty);
}
Future<void> test_inComment_block_beforeNode() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(aaa, bbb) {
/* text ^ */
print(42);
}
''');
- await getSuggestions();
expect(suggestions, isEmpty);
}
Future<void> test_inComment_endOfFile_withNewline() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
// text ^
''');
- await getSuggestions();
expect(suggestions, isEmpty);
}
Future<void> test_inComment_endOfFile_withoutNewline() async {
- addTestFile('// text ^');
- await getSuggestions();
+ await getTestCodeSuggestions('// text ^');
expect(suggestions, isEmpty);
}
Future<void> test_inComment_endOfLine_beforeDartDoc() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
// text ^
/// some doc comments
class SomeClass {}
''');
- await getSuggestions();
expect(suggestions, isEmpty);
}
Future<void> test_inComment_endOfLine_beforeNode() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(aaa, bbb) {
// text ^
print(42);
}
''');
- await getSuggestions();
expect(suggestions, isEmpty);
}
Future<void> test_inComment_endOfLine_beforeToken() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(aaa, bbb) {
// text ^
}
''');
- await getSuggestions();
expect(suggestions, isEmpty);
}
Future<void> test_inDartDoc1() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
/// ^
void f(aaa, bbb) {}
''');
- await getSuggestions();
expect(suggestions, isEmpty);
}
Future<void> test_inDartDoc2() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
/// Some text^
void f(aaa, bbb) {}
''');
- await getSuggestions();
expect(suggestions, isEmpty);
}
Future<void> test_inDartDoc3() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class MyClass {
/// ^
void foo() {}
@@ -2550,7 +2521,6 @@
void baz() {}
}
''');
- await getSuggestions();
expect(suggestions, isEmpty);
}
@@ -2558,30 +2528,28 @@
newFile2('/testA.dart', '''
part of libA;
foo(bar) => 0;''');
- addTestFile('''
+ await getTestCodeSuggestions('''
library libA;
part "${toUriStr('/testA.dart')}";
import "dart:math";
/// The [^]
void f(aaa, bbb) {}
''');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'f');
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'foo');
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'min');
}
Future<void> test_inDartDoc_reference2() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
/// The [m^]
void f(aaa, bbb) {}
''');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'f');
}
Future<void> test_inDartDoc_reference3() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class MyClass {
/// [^]
void foo() {}
@@ -2593,13 +2561,12 @@
void baz() {}
}
''');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'bar');
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'baz');
}
- Future<void> test_inherited() {
- addTestFile('''
+ Future<void> test_inherited() async {
+ await getTestCodeSuggestions('''
class A {
m() {}
}
@@ -2607,19 +2574,18 @@
x() {^}
}
''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.INVOCATION, 'm');
- });
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.INVOCATION, 'm');
}
Future<void> test_invalidFilePathFormat_notAbsolute() async {
var request = CompletionGetSuggestionsParams('test.dart', 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,
);
}
@@ -2627,52 +2593,47 @@
var request =
CompletionGetSuggestionsParams(convertPath('/foo/../bar/test.dart'), 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,
);
}
- Future<void> test_invocation() {
- addTestFile('class A {b() {}} void f() {A a; a.^}');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.INVOCATION, 'b');
- });
+ Future<void> test_invocation() async {
+ await getTestCodeSuggestions('class A {b() {}} void f() {A a; a.^}');
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.INVOCATION, 'b');
}
- Future<void> test_invocation_withTrailingStmt() {
- addTestFile('class A {b() {}} void f() {A a; a.^ int x = 7;}');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.INVOCATION, 'b');
- });
+ Future<void> test_invocation_withTrailingStmt() async {
+ await getTestCodeSuggestions(
+ 'class A {b() {}} void f() {A a; a.^ int x = 7;}');
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.INVOCATION, 'b');
}
Future<void> test_is_asPrefixedIdentifierStart() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A { var isVisible;}
void f(A p) { var v1 = p.is^; }''');
- await getSuggestions();
assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'isVisible');
}
- Future<void> test_keyword() {
- addTestFile('library A; cl^');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset - 2));
- expect(replacementLength, equals(2));
- assertHasResult(CompletionSuggestionKind.KEYWORD, 'export \'\';',
- selectionOffset: 8);
- assertHasResult(CompletionSuggestionKind.KEYWORD, 'class');
- });
+ Future<void> test_keyword() async {
+ await getTestCodeSuggestions('library A; cl^');
+ expect(replacementOffset, equals(completionOffset - 2));
+ expect(replacementLength, equals(2));
+ assertHasResult(CompletionSuggestionKind.KEYWORD, 'export \'\';',
+ selectionOffset: 8);
+ assertHasResult(CompletionSuggestionKind.KEYWORD, 'class');
}
Future<void> test_local_implicitCreation() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A {
A();
A.named();
@@ -2681,7 +2642,6 @@
^
}
''');
- await getSuggestions();
expect(replacementOffset, equals(completionOffset));
expect(replacementLength, equals(0));
@@ -2697,34 +2657,30 @@
elementKind: ElementKind.CONSTRUCTOR);
}
- Future<void> test_local_named_constructor() {
- addTestFile('class A {A.c(); x() {new A.^}}');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.INVOCATION, 'c');
- assertNoResult('A');
- });
+ Future<void> test_local_named_constructor() async {
+ await getTestCodeSuggestions('class A {A.c(); x() {new A.^}}');
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.INVOCATION, 'c');
+ assertNoResult('A');
}
- Future<void> test_local_override() {
+ Future<void> test_local_override() async {
newFile2('/project/bin/a.dart', 'class A {m() {}}');
- addTestFile('''
+ await getTestCodeSuggestions('''
import 'a.dart';
class B extends A {
m() {}
x() {^}
}
''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.INVOCATION, 'm');
- });
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.INVOCATION, 'm');
}
Future<void> test_local_shadowClass() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A {
A();
A.named();
@@ -2734,7 +2690,6 @@
^
}
''');
- await getSuggestions();
expect(replacementOffset, equals(completionOffset));
expect(replacementLength, equals(0));
@@ -2748,149 +2703,145 @@
assertNoResult('A.named', elementKind: ElementKind.CONSTRUCTOR);
}
- Future<void> test_locals() {
- addTestFile('class A {var a; x() {var b;^}} class DateTime { }');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A',
- elementKind: ElementKind.CLASS);
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'a');
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'b');
- assertHasResult(CompletionSuggestionKind.INVOCATION, 'x');
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'DateTime',
- elementKind: ElementKind.CLASS);
- });
+ Future<void> test_locals() async {
+ await getTestCodeSuggestions(
+ 'class A {var a; x() {var b;^}} class DateTime { }');
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A',
+ elementKind: ElementKind.CLASS);
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'a');
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'b');
+ assertHasResult(CompletionSuggestionKind.INVOCATION, 'x');
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'DateTime',
+ elementKind: ElementKind.CLASS);
}
Future<void> test_offset_past_eof() async {
- addTestFile('void f() { }', offset: 300);
- var request = CompletionGetSuggestionsParams(testFile, completionOffset)
- .toRequest('0');
- var response = await waitResponse(request);
- expect(response.id, '0');
- expect(response.error!.code, RequestErrorCode.INVALID_PARAMETER);
+ addTestFile('void f() { }');
+ var request =
+ CompletionGetSuggestionsParams(testFile.path, 300).toRequest('0');
+ var response = await handleRequest(request);
+ assertResponseFailure(
+ response,
+ requestId: '0',
+ errorCode: RequestErrorCode.INVALID_PARAMETER,
+ );
}
- Future<void> test_overrides() {
+ Future<void> test_overrides() async {
newFile2('/project/bin/a.dart', 'class A {m() {}}');
- addTestFile('''
+ await getTestCodeSuggestions('''
import 'a.dart';
class B extends A {m() {^}}
''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.INVOCATION, 'm');
- });
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.INVOCATION, 'm');
}
- Future<void> test_partFile() {
- newFile2('/project/bin/a.dart', '''
+ Future<void> test_partFile() async {
+ newFile2('$testPackageLibPath/a.dart', '''
library libA;
import 'dart:html';
part 'test.dart';
class A { }
''');
- addTestFile('''
+ await getTestCodeSuggestions('''
part of libA;
void f() {^}''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
- elementKind: ElementKind.CLASS);
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement',
- elementKind: ElementKind.CLASS);
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A',
- elementKind: ElementKind.CLASS);
- assertNoResult('test');
- });
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
+ elementKind: ElementKind.CLASS);
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement',
+ elementKind: ElementKind.CLASS);
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A',
+ elementKind: ElementKind.CLASS);
+ assertNoResult('test');
}
- Future<void> test_partFile2() {
- newFile2('/project/bin/a.dart', '''
+ Future<void> test_partFile2() async {
+ newFile2('$testPackageLibPath/a.dart', '''
part of libA;
class A { }''');
- addTestFile('''
+ await getTestCodeSuggestions('''
library libA;
part "a.dart";
import 'dart:html';
void f() {^}
''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
- elementKind: ElementKind.CLASS);
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement',
- elementKind: ElementKind.CLASS);
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A',
- elementKind: ElementKind.CLASS);
- assertNoResult('test');
- });
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
+ elementKind: ElementKind.CLASS);
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'HtmlElement',
+ elementKind: ElementKind.CLASS);
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'A',
+ elementKind: ElementKind.CLASS);
+ assertNoResult('test');
}
Future<void> test_sentToPlugins() async {
addTestFile('''
void f() {
- ^
+
}
''');
PluginInfo info = DiscoveredPluginInfo('a', 'b', 'c',
TestNotificationManager(), InstrumentationService.NULL_SERVICE);
var result = plugin.CompletionGetSuggestionsResult(
- testFile.indexOf('^'), 0, <CompletionSuggestion>[
+ testFileContent.indexOf('^'), 0, <CompletionSuggestion>[
CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER,
DART_RELEVANCE_DEFAULT, 'plugin completion', 3, 0, false, false)
]);
pluginManager.broadcastResults = <PluginInfo, Future<plugin.Response>>{
info: Future.value(result.toResponse('-', 1))
};
- await getSuggestions();
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'plugin completion',
- selectionOffset: 3);
- }
-
- Future<void> test_simple() {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f() {
^
}
''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset));
- expect(replacementLength, equals(0));
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
- elementKind: ElementKind.CLASS);
- assertNoResult('HtmlElement');
- assertNoResult('test');
- });
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'plugin completion',
+ selectionOffset: 3);
+ }
+
+ Future<void> test_simple() async {
+ await getTestCodeSuggestions('''
+ void f() {
+ ^
+ }
+ ''');
+ expect(replacementOffset, equals(completionOffset));
+ expect(replacementLength, equals(0));
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'Object',
+ elementKind: ElementKind.CLASS);
+ assertNoResult('HtmlElement');
+ assertNoResult('test');
}
Future<void> test_static() async {
- addTestFile('class A {static b() {} c() {}} void f() {A.^}');
- await getSuggestions();
+ await getTestCodeSuggestions(
+ 'class A {static b() {} c() {}} void f() {A.^}');
expect(replacementOffset, equals(completionOffset));
expect(replacementLength, equals(0));
assertHasResult(CompletionSuggestionKind.INVOCATION, 'b');
assertNoResult('c');
}
- Future<void> test_topLevel() {
- addTestFile('''
+ Future<void> test_topLevel() async {
+ await getTestCodeSuggestions('''
typedef foo();
var test = '';
void f() {tes^t}
''');
- return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset - 3));
- expect(replacementLength, equals(4));
- // Suggestions based upon imported elements are partially filtered
- //assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object');
- assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'test');
- assertNoResult('HtmlElement');
- });
+ expect(replacementOffset, equals(completionOffset - 3));
+ expect(replacementLength, equals(4));
+ // Suggestions based upon imported elements are partially filtered
+ //assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object');
+ assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'test');
+ assertNoResult('HtmlElement');
}
}
diff --git a/pkg/analysis_server/test/domain_completion_util.dart b/pkg/analysis_server/test/domain_completion_util.dart
index 1d02ab8..19086f3 100644
--- a/pkg/analysis_server/test/domain_completion_util.dart
+++ b/pkg/analysis_server/test/domain_completion_util.dart
@@ -7,16 +7,15 @@
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
-import 'package:analysis_server/src/domain_completion.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
-import 'analysis_abstract.dart';
+import 'analysis_server_base.dart';
import 'constants.dart';
-class AbstractCompletionDomainTest extends AbstractAnalysisTest {
+class AbstractCompletionDomainTest extends PubPackageAnalysisServerTest {
late String completionId;
- late int completionOffset;
+ late int completionOffset; // TODO(scheglov) remove it
int? replacementOffset;
late int replacementLength;
Map<String, Completer<void>> receivedSuggestionsCompleters = {};
@@ -24,21 +23,6 @@
bool suggestionsDone = false;
Map<String, List<CompletionSuggestion>> allSuggestions = {};
- @override
- String addTestFile(String content, {int? offset}) {
- completionOffset = content.indexOf('^');
- if (offset != null) {
- expect(completionOffset, -1, reason: 'cannot supply offset and ^');
- completionOffset = offset;
- return super.addTestFile(content);
- }
- expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
- var nextOffset = content.indexOf('^', completionOffset + 1);
- expect(nextOffset, equals(-1), reason: 'too many ^');
- return super.addTestFile(content.substring(0, completionOffset) +
- content.substring(completionOffset + 1));
- }
-
void assertHasResult(CompletionSuggestionKind kind, String completion,
{bool isDeprecated = false,
bool isPotential = false,
@@ -92,12 +76,35 @@
expect(id.isNotEmpty, isTrue);
}
- Future getSuggestions() async {
- await waitForTasksFinished();
+ Future<void> getCodeSuggestions({
+ required String path,
+ required String content,
+ }) async {
+ completionOffset = content.indexOf('^');
+ expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
- var request = CompletionGetSuggestionsParams(testFile, completionOffset)
- .toRequest('0');
- var response = await waitResponse(request);
+ var nextOffset = content.indexOf('^', completionOffset + 1);
+ expect(nextOffset, equals(-1), reason: 'too many ^');
+
+ newFile2(
+ path,
+ content.substring(0, completionOffset) +
+ content.substring(completionOffset + 1),
+ );
+
+ return await getSuggestions(
+ path: path,
+ completionOffset: completionOffset,
+ );
+ }
+
+ Future<void> getSuggestions({
+ required String path,
+ required int completionOffset,
+ }) async {
+ var request =
+ CompletionGetSuggestionsParams(path, completionOffset).toRequest('0');
+ var response = await handleSuccessfulRequest(request);
var result = CompletionGetSuggestionsResult.fromResponse(response);
completionId = result.id;
assertValidId(completionId);
@@ -105,6 +112,13 @@
expect(suggestionsDone, isTrue);
}
+ Future<void> getTestCodeSuggestions(String content) {
+ return getCodeSuggestions(
+ path: testFile.path,
+ content: content,
+ );
+ }
+
@override
Future<void> processNotification(Notification notification) async {
if (notification.event == COMPLETION_RESULTS) {
@@ -127,8 +141,7 @@
@override
Future<void> setUp() async {
super.setUp();
- await createProject();
- handler = CompletionDomainHandler(server);
+ await setRoots(included: [workspaceRootPath], excluded: []);
}
Completer<void> _getResultsCompleter(String id) {
diff --git a/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart b/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
index b6ad6a1..f5d703b 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
@@ -31,7 +31,7 @@
@reflectiveTest
class ArgumentListCompletionTest extends CompletionTestCase {
Future<void> test_functionWithVoidReturnType_optionalNamed() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(C c) {
c.m(handler: ^);
}
@@ -42,12 +42,11 @@
void m({void Function()? handler}) {}
}
''');
- await getSuggestions();
assertHasCompletion('g');
}
Future<void> test_functionWithVoidReturnType_requiredPositional() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(C c) {
c.m(^);
}
@@ -58,12 +57,11 @@
void m(void Function() handler) {}
}
''');
- await getSuggestions();
assertHasCompletion('g');
}
Future<void> test_privateStaticField() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
extension on int {
static int _x = 0;
@@ -72,7 +70,6 @@
}
}
''');
- await getSuggestions();
assertHasCompletion('_x');
}
}
@@ -80,12 +77,11 @@
@reflectiveTest
class AsExpressionCompletionTest extends CompletionTestCase {
Future<void> test_type_dynamic() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(Object o) {
var x = o as ^;
}
''');
- await getSuggestions();
assertHasCompletion('dynamic');
}
}
@@ -94,14 +90,13 @@
class AssertStatementCompletionTest extends CompletionTestCase {
@failingTest
Future<void> test_message() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f() {
assert(true, ^);
}
const c = <int>[];
''');
- await getSuggestions();
assertHasCompletion('c');
}
}
@@ -109,7 +104,7 @@
@reflectiveTest
class ConstructorCompletionTest extends CompletionTestCase {
Future<void> test_constructor_abstract() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f() {
g(^);
}
@@ -118,7 +113,6 @@
C.c();
}
''');
- await getSuggestions();
assertHasNoCompletion('C.c');
}
}
@@ -126,26 +120,24 @@
@reflectiveTest
class DeclaredIdentifierCompletionTest extends CompletionTestCase {
Future<void> test_afterFinal_withIdentifier() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
void m(List<C> cs) {
for (final ^ x in cs) {}
}
}
''');
- await getSuggestions();
assertHasCompletion('C');
}
Future<void> test_afterFinal_withoutIdentifier() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
void m(List<C> cs) {
for (final ^) {}
}
}
''');
- await getSuggestions();
assertHasCompletion('C');
}
}
@@ -153,7 +145,7 @@
@reflectiveTest
class ExpressionFunctionBodyCompletionTest extends CompletionTestCase {
Future<void> test_voidReturn_localFunction() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
void m() {
void f() => ^;
@@ -162,29 +154,26 @@
void g() {}
''');
- await getSuggestions();
assertHasCompletion('g');
}
Future<void> test_voidReturn_method() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
void m() => ^;
}
void g() {}
''');
- await getSuggestions();
assertHasCompletion('g');
}
Future<void> test_voidReturn_topLevelFunction() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f() => ^;
void g() {}
''');
- await getSuggestions();
assertHasCompletion('g');
}
}
@@ -192,7 +181,7 @@
@reflectiveTest
class ExtensionCompletionTest extends CompletionTestCase {
Future<void> test_explicitTarget_getter_sameUnit() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(String s) {
s.^;
}
@@ -200,56 +189,52 @@
int get g => length;
}
''');
- await getSuggestions();
assertHasCompletion('g');
}
Future<void> test_explicitTarget_method_imported() async {
- newFile2(convertPath('/project/bin/lib.dart'), '''
+ newFile2(convertPath('$testPackageLibPath/lib.dart'), '''
extension E on String {
void m() {}
}
''');
- addTestFile('''
+ await getTestCodeSuggestions('''
import 'lib.dart';
void f(String s) {
s.^;
}
''');
- await getSuggestions();
assertHasCompletion('m');
}
Future<void> test_explicitTarget_method_inLibrary() async {
- newFile2(convertPath('/project/bin/lib.dart'), '''
+ newFile2(convertPath('$testPackageLibPath/lib.dart'), '''
part 'test.dart';
extension E on String {
void m() {}
}
''');
- addTestFile('''
+ await getTestCodeSuggestions('''
part of 'lib.dart';
void f(String s) {
s.^;
}
''');
- await getSuggestions();
assertHasCompletion('m');
}
Future<void> test_explicitTarget_method_inPart() async {
- newFile2(convertPath('/project/bin/part.dart'), '''
+ newFile2(convertPath('$testPackageLibPath/part.dart'), '''
extension E on String {
void m() {}
}
''');
- addTestFile('''
+ await getTestCodeSuggestions('''
part 'part.dart';
void f(String s) {
s.^;
}
''');
- await getSuggestions();
assertHasCompletion('m');
}
@@ -262,17 +247,16 @@
void m() {}
}
''');
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(String s) {
s.^;
}
''');
- await getSuggestions();
assertHasCompletion('m');
}
Future<void> test_explicitTarget_method_sameUnit() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(String s) {
s.^;
}
@@ -280,12 +264,11 @@
void m() {}
}
''');
- await getSuggestions();
assertHasCompletion('m');
}
Future<void> test_explicitTarget_setter_sameUnit() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(String s) {
s.^;
}
@@ -293,12 +276,11 @@
set e(int v) {}
}
''');
- await getSuggestions();
assertHasCompletion('e');
}
Future<void> test_implicitTarget_inClass_method_sameUnit() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
void c() {
^
@@ -308,19 +290,17 @@
void m() {}
}
''');
- await getSuggestions();
assertHasCompletion('m');
}
Future<void> test_implicitTarget_inExtension_method_sameUnit() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
extension E on String {
void m() {
^
}
}
''');
- await getSuggestions();
assertHasCompletion('m');
}
}
@@ -328,10 +308,9 @@
@reflectiveTest
class FormalParameterCompletionTest extends CompletionTestCase {
Future<void> test_named_last() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f({int? a, ^}) {}
''');
- await getSuggestions();
assertHasCompletion('covariant');
assertHasCompletion('dynamic');
assertHasCompletion('required');
@@ -339,10 +318,9 @@
}
Future<void> test_named_last_afterCovariant() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f({covariant ^}) {}
''');
- await getSuggestions();
assertHasNoCompletion('covariant');
assertHasCompletion('dynamic');
assertHasNoCompletion('required');
@@ -350,10 +328,9 @@
}
Future<void> test_named_last_afterRequired() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f({required ^}) {}
''');
- await getSuggestions();
assertHasCompletion('covariant');
assertHasCompletion('dynamic');
assertHasNoCompletion('required');
@@ -361,10 +338,9 @@
}
Future<void> test_named_only() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f({^}) {}
''');
- await getSuggestions();
assertHasCompletion('covariant');
assertHasCompletion('dynamic');
assertHasCompletion('required');
@@ -372,10 +348,9 @@
}
Future<void> test_optionalPositional_last() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f([int a, ^]) {}
''');
- await getSuggestions();
assertHasCompletion('covariant');
assertHasCompletion('dynamic');
assertHasNoCompletion('required');
@@ -383,10 +358,9 @@
}
Future<void> test_optionalPositional_only() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f([^]) {}
''');
- await getSuggestions();
assertHasCompletion('covariant');
assertHasCompletion('dynamic');
assertHasNoCompletion('required');
@@ -394,10 +368,9 @@
}
Future<void> test_requiredPositional_only() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(^) {}
''');
- await getSuggestions();
assertHasCompletion('covariant');
assertHasCompletion('dynamic');
assertHasNoCompletion('required');
@@ -408,50 +381,44 @@
@reflectiveTest
class GenericFunctionTypeCompletionTest extends CompletionTestCase {
Future<void> test_returnType_beforeType() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f({^vo Function() p}) {}
''');
- await getSuggestions();
assertHasCompletion('void');
}
Future<void> test_returnType_beforeType_afterRequired() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f({required ^vo Function() p}) {}
''');
- await getSuggestions();
assertHasCompletion('void');
}
Future<void> test_returnType_inType() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f({v^o Function() p}) {}
''');
- await getSuggestions();
assertHasCompletion('void');
}
Future<void> test_returnType_inType_afterRequired() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f({required v^o Function() p}) {}
''');
- await getSuggestions();
assertHasCompletion('void');
}
Future<void> test_returnType_partialFunctionType() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f({^ Function() p}) {}
''');
- await getSuggestions();
assertHasCompletion('void');
}
Future<void> test_returnType_partialFunctionType_afterRequired() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f({required ^ Function() p}) {}
''');
- await getSuggestions();
assertHasCompletion('void');
}
}
@@ -459,10 +426,9 @@
@reflectiveTest
class GenericTypeAliasCompletionTest extends CompletionTestCase {
Future<void> test_returnType_void() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
typedef F = ^
''');
- await getSuggestions();
assertHasCompletion('void');
}
}
@@ -470,7 +436,7 @@
@reflectiveTest
class PropertyAccessCompletionTest extends CompletionTestCase {
Future<void> test_nullSafe_extension() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(C c) {
c.a?.^;
}
@@ -481,12 +447,11 @@
int get b => 0;
}
''');
- await getSuggestions();
assertHasCompletion('b');
}
Future<void> test_setter_deprecated() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(C c) {
c.^;
}
@@ -495,13 +460,12 @@
set x(int x) {}
}
''');
- await getSuggestions();
assertHasCompletion('x',
elementKind: ElementKind.SETTER, isDeprecated: true);
}
Future<void> test_setter_deprecated_withNonDeprecatedGetter() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f(C c) {
c.^;
}
@@ -511,7 +475,6 @@
set x(int x) {}
}
''');
- await getSuggestions();
assertHasCompletion('x',
elementKind: ElementKind.GETTER, isDeprecated: false);
}
@@ -521,7 +484,7 @@
class RedirectedConstructorCompletionTest extends CompletionTestCase {
@failingTest
Future<void> test_keywords() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A {
factory A() = ^
}
@@ -529,14 +492,13 @@
B();
}
''');
- await getSuggestions();
assertHasNoCompletion('assert');
assertHasNoCompletion('super');
assertHasNoCompletion('this');
}
Future<void> test_namedConstructor_private() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A {
factory A() = ^
}
@@ -544,12 +506,11 @@
B._();
}
''');
- await getSuggestions();
assertHasCompletion('B._');
}
Future<void> test_namedConstructor_public() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A {
factory A() = ^
}
@@ -557,12 +518,11 @@
B.b();
}
''');
- await getSuggestions();
assertHasCompletion('B.b');
}
Future<void> test_sameConstructor() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A {
factory A() = ^
}
@@ -570,12 +530,11 @@
B();
}
''');
- await getSuggestions();
assertHasNoCompletion('A');
}
Future<void> test_unnamedConstructor() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A {
factory A() = ^
}
@@ -583,7 +542,6 @@
B();
}
''');
- await getSuggestions();
assertHasCompletion('B');
}
@@ -594,14 +552,13 @@
B();
}
''');
- addTestFile('''
+ await getTestCodeSuggestions('''
import 'b.dart';
class A {
factory A() = ^
}
''');
- await getSuggestions();
assertHasCompletion('B');
}
}
@@ -611,56 +568,51 @@
extends CompletionTestCase {
@failingTest
Future<void> test_instanceMember() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
C.c() {}
C() : this.^
}
''');
- await getSuggestions();
assertHasNoCompletion('toString');
}
Future<void> test_namedConstructor_private() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
C._() {}
C() : this.^
}
''');
- await getSuggestions();
assertHasCompletion('_');
}
Future<void> test_namedConstructor_public() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
C.c() {}
C() : this.^
}
''');
- await getSuggestions();
assertHasCompletion('c');
}
Future<void> test_sameConstructor() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
C.c() : this.^
}
''');
- await getSuggestions();
assertHasNoCompletion('c');
}
Future<void> test_unnamedConstructor() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
C() {}
C.c() : this.^
}
''');
- await getSuggestions();
assertHasNoCompletion('');
}
}
@@ -668,7 +620,7 @@
@reflectiveTest
class ReturnStatementTest extends CompletionTestCase {
Future<void> test_voidFromVoid_localFunction() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
void m() {
void f() {
@@ -678,12 +630,11 @@
void g() {}
}
''');
- await getSuggestions();
assertHasCompletion('g');
}
Future<void> test_voidFromVoid_method() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
void f() {
return ^
@@ -691,18 +642,16 @@
void g() {}
}
''');
- await getSuggestions();
assertHasCompletion('g');
}
Future<void> test_voidFromVoid_topLevelFunction() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
void f() {
return ^
}
void g() {}
''');
- await getSuggestions();
assertHasCompletion('g');
}
}
@@ -715,19 +664,18 @@
A._() {}
}
''');
- addTestFile('''
+ await getTestCodeSuggestions('''
import 'a.dart';
class B extends A {
B() : super.^
}
''');
- await getSuggestions();
assertHasNoCompletion('_');
}
Future<void> test_namedConstructor_private() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A {
A._() {}
}
@@ -735,12 +683,11 @@
B() : super.^
}
''');
- await getSuggestions();
assertHasCompletion('_');
}
Future<void> test_namedConstructor_public() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A {
A.a() {}
}
@@ -748,12 +695,11 @@
B() : super.^
}
''');
- await getSuggestions();
assertHasCompletion('a');
}
Future<void> test_unnamedConstructor() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class A {
A() {}
}
@@ -761,7 +707,6 @@
B() : super.^
}
''');
- await getSuggestions();
assertHasNoCompletion('');
}
}
@@ -769,12 +714,11 @@
@reflectiveTest
class VariableDeclarationListCompletionTest extends CompletionTestCase {
Future<void> test_type_voidAfterFinal() async {
- addTestFile('''
+ await getTestCodeSuggestions('''
class C {
final ^
}
''');
- await getSuggestions();
assertHasCompletion('void');
}
}
diff --git a/pkg/compiler/lib/src/common/elements.dart b/pkg/compiler/lib/src/common/elements.dart
index d4e4c7b..f7d3f71 100644
--- a/pkg/compiler/lib/src/common/elements.dart
+++ b/pkg/compiler/lib/src/common/elements.dart
@@ -1520,7 +1520,7 @@
/// Returns the 'raw type' of [cls]. That is, the instantiation of [cls]
/// where all types arguments are `dynamic`.
- InterfaceType getRawType(ClassEntity cls);
+ InterfaceType /*!*/ getRawType(ClassEntity /*!*/ cls);
/// Returns the 'JS-interop type' of [cls]; that is, the instantiation of
/// [cls] where all type arguments are 'any'.
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index d1999fa..55d0d01 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -70,7 +70,7 @@
KernelFrontendStrategy frontendStrategy;
JsBackendStrategy backendStrategy;
- DiagnosticReporter _reporter;
+ /*late*/ DiagnosticReporter _reporter;
Map<Entity, WorldImpact> _impactCache;
GenericTask userHandlerTask;
GenericTask userProviderTask;
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index a109bc5..afc17fe 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -104,9 +104,9 @@
bool get isNegativeInfinity => false;
// TODO(johnniwinther): Replace with a 'type' getter.
- DartType getType(CommonElements types);
+ DartType /*!*/ getType(CommonElements types);
- List<ConstantValue> getDependencies();
+ List<ConstantValue /*!*/ > /*!*/ getDependencies();
accept(ConstantValueVisitor visitor, arg);
@@ -135,9 +135,9 @@
}
class FunctionConstantValue extends ConstantValue {
- final FunctionEntity element;
+ final FunctionEntity /*!*/ element;
// TODO(johnniwinther): Should the type be derived from [element].
- final FunctionType type;
+ final FunctionType /*!*/ type;
FunctionConstantValue(this.element, this.type);
@@ -244,7 +244,7 @@
}
class IntConstantValue extends NumConstantValue {
- final BigInt intValue;
+ final BigInt /*!*/ intValue;
// Caching IntConstantValues representing -2 through 10 so that we don't have
// to create new ones every time those values are used.
@@ -253,7 +253,7 @@
@override
double get doubleValue => intValue.toDouble();
- factory IntConstantValue(BigInt value) {
+ factory IntConstantValue(BigInt /*!*/ value) {
var existing = _cachedValues[value];
if (existing != null) return existing;
var intConstantVal = IntConstantValue._internal(value);
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 92e8499..e66e57d 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -1004,20 +1004,24 @@
..run();
var allInfo = buildDumpInfoDataNew(closedWorld, kernelInfoCollector);
+ // TODO(markzipan): Filter DumpInfo here instead of passing a filter
+ // filter flag through the serializers.
if (useBinaryFormat) {
- dumpInfoBinary(allInfo);
+ dumpInfoBinary(allInfo, filterTreeshaken: true);
} else {
- dumpInfoJson(allInfo);
+ dumpInfoJson(allInfo, filterTreeshaken: true);
}
});
}
- void dumpInfoJson(AllInfo data) {
+ void dumpInfoJson(AllInfo data, {bool filterTreeshaken = false}) {
StringBuffer jsonBuffer = StringBuffer();
JsonEncoder encoder = const JsonEncoder.withIndent(' ');
ChunkedConversionSink<Object> sink = encoder.startChunkedConversion(
StringConversionSink.fromStringSink(jsonBuffer));
- sink.add(AllInfoJsonCodec(isBackwardCompatible: true).encode(data));
+ sink.add(AllInfoJsonCodec(
+ isBackwardCompatible: true, filterTreeshaken: filterTreeshaken)
+ .encode(data));
compiler.outputProvider.createOutputSink(
compiler.options.outputUri.pathSegments.last,
'info.json',
@@ -1031,8 +1035,10 @@
});
}
- void dumpInfoBinary(AllInfo data) {
+ void dumpInfoBinary(AllInfo data, {bool filterTreeshaken = false}) {
var name = compiler.options.outputUri.pathSegments.last + ".info.data";
+ // TODO(markzipan): Plumb [filterTreeshaken] through
+ // [BinaryOutputSinkAdapter].
Sink<List<int>> sink = BinaryOutputSinkAdapter(compiler.outputProvider
.createBinarySink(compiler.options.outputUri.resolve(name)));
dump_info.encode(data, sink);
@@ -1137,6 +1143,7 @@
// Don't register dart2js builtin functions that are not recorded.
Info useInfo = infoCollector._entityToInfo[selection.selectedEntity];
if (useInfo == null) continue;
+ if (useInfo.treeShakenStatus != TreeShakenStatus.Live) continue;
info.uses.add(
DependencyInfo(useInfo, selection.receiverConstraint?.toString()));
}
@@ -1152,6 +1159,7 @@
for (Selection selection in uses) {
Info useInfo = infoCollector._entityToInfo[selection.selectedEntity];
if (useInfo == null) continue;
+ if (useInfo.treeShakenStatus != TreeShakenStatus.Live) continue;
info.uses.add(
DependencyInfo(useInfo, selection.receiverConstraint?.toString()));
}
@@ -1164,6 +1172,7 @@
for (Entity inlined in inlineMap[entity]) {
Info inlinedInfo = infoCollector._entityToInfo[inlined];
if (inlinedInfo == null) continue;
+ if (inlinedInfo.treeShakenStatus != TreeShakenStatus.Live) continue;
outerInfo.uses.add(DependencyInfo(inlinedInfo, 'inlined'));
}
}
diff --git a/pkg/compiler/lib/src/elements/entities.dart b/pkg/compiler/lib/src/elements/entities.dart
index d363a30..0451c39 100644
--- a/pkg/compiler/lib/src/elements/entities.dart
+++ b/pkg/compiler/lib/src/elements/entities.dart
@@ -34,7 +34,7 @@
/// and/or Dart-in-JS classes.
abstract class LibraryEntity extends Entity {
/// Return the canonical uri that identifies this library.
- Uri get canonicalUri;
+ Uri /*!*/ get canonicalUri;
/// Returns whether or not this library has opted into null safety.
bool get isNonNullableByDefault;
@@ -125,14 +125,14 @@
bool get isSetter;
/// Whether this member is assignable, i.e. a non-final, non-const field.
- bool get isAssignable;
+ bool /*!*/ get isAssignable;
/// Whether this member is constant, i.e. a constant field or constructor.
- bool get isConst;
+ bool /*!*/ get isConst;
/// Whether this member is abstract, i.e. an abstract method, getter or
/// setter.
- bool get isAbstract;
+ bool /*!*/ get isAbstract;
/// The enclosing class if this is a constructor, instance member or
/// static member of a class.
@@ -156,7 +156,7 @@
abstract class FunctionEntity extends MemberEntity {
/// Whether this function is external, i.e. the body is not defined in terms
/// of Dart code.
- bool get isExternal;
+ bool /*!*/ get isExternal;
/// The structure of the function parameters.
ParameterStructure get parameterStructure;
diff --git a/pkg/compiler/lib/src/hash/sha1.dart b/pkg/compiler/lib/src/hash/sha1.dart
index 4c4e65b..e8698a0 100644
--- a/pkg/compiler/lib/src/hash/sha1.dart
+++ b/pkg/compiler/lib/src/hash/sha1.dart
@@ -47,7 +47,7 @@
Digest _value;
/// The value added to the sink, if any.
- Digest get value {
+ Digest /*!*/ get value {
assert(_value != null);
return _value;
}
diff --git a/pkg/compiler/lib/src/ir/element_map.dart b/pkg/compiler/lib/src/ir/element_map.dart
index e021596..6d8c86a 100644
--- a/pkg/compiler/lib/src/ir/element_map.dart
+++ b/pkg/compiler/lib/src/ir/element_map.dart
@@ -54,7 +54,7 @@
/// [node].
TypeVariableEntity getTypeVariable(ir.TypeParameter node);
- CommonElements get commonElements;
+ CommonElements /*!*/ get commonElements;
DiagnosticReporter get reporter;
ir.CoreTypes get coreTypes;
InterfaceType getThisType(IndexedClass cls);
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index a85e726..aea9e7d 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -43,7 +43,7 @@
}
/// Visitor that converts kernel dart types into [DartType].
-class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
+class DartTypeConverter extends ir.DartTypeVisitor<DartType /*!*/ > {
final IrToElementMap elementMap;
final Map<ir.TypeParameter, DartType> currentFunctionTypeParameters =
<ir.TypeParameter, DartType>{};
diff --git a/pkg/compiler/lib/src/js/js_debug.dart b/pkg/compiler/lib/src/js/js_debug.dart
index df828b6..c50a232 100644
--- a/pkg/compiler/lib/src/js/js_debug.dart
+++ b/pkg/compiler/lib/src/js/js_debug.dart
@@ -11,8 +11,6 @@
import 'package:js_ast/js_ast.dart';
import 'package:kernel/text/indentation.dart' show Indentation, Tagging;
-import '../io/code_output.dart' show BufferedCodeOutput;
-
/// Unparse the JavaScript [node].
String nodeToString(Node node, {bool pretty = false}) {
JavaScriptPrintingOptions options = JavaScriptPrintingOptions(
@@ -64,8 +62,7 @@
}
/// Simple printing context that doesn't throw on errors.
-class LenientPrintingContext extends SimpleJavaScriptPrintingContext
- implements BufferedCodeOutput {
+class LenientPrintingContext extends SimpleJavaScriptPrintingContext {
@override
void error(String message) {
buffer.write('>>$message<<');
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 5b3a396..fcc9618 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -10,7 +10,6 @@
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
-import '../io/code_output.dart';
import '../js/js.dart' as jsAst;
import '../js/js.dart' show js;
import '../js_backend/field_analysis.dart';
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 6b64172..a90587d 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -83,7 +83,7 @@
final JsKernelToElementMap elementMap;
@override
final RuntimeTypesNeed rtiNeed;
- AbstractValueDomain _abstractValueDomain;
+ AbstractValueDomain /*!*/ _abstractValueDomain;
@override
final JFieldAnalysis fieldAnalysis;
@override
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 4b9a722..42536ed 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -66,7 +66,7 @@
final NativeBasicDataBuilder nativeBasicDataBuilder =
NativeBasicDataBuilder();
NativeBasicData _nativeBasicData;
- KCommonElements _commonElements;
+ KCommonElements /*!*/ _commonElements;
KernelElementEnvironment _elementEnvironment;
DartTypeConverter _typeConverter;
KernelDartTypes _types;
@@ -1686,7 +1686,9 @@
IndexedFunction createGetter(LibraryEntity library,
ClassEntity enclosingClass, Name name, AsyncMarker asyncMarker,
- {bool isStatic, bool isExternal, bool isAbstract}) {
+ {/*required*/ bool isStatic,
+ /*required*/ bool isExternal,
+ /*required*/ bool isAbstract}) {
return KGetter(library, enclosingClass, name, asyncMarker,
isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
}
@@ -1697,9 +1699,9 @@
Name name,
ParameterStructure parameterStructure,
AsyncMarker asyncMarker,
- {bool isStatic,
- bool isExternal,
- bool isAbstract}) {
+ {/*required*/ bool isStatic,
+ /*required*/ bool isExternal,
+ /*required*/ bool isAbstract}) {
return KMethod(
library, enclosingClass, name, parameterStructure, asyncMarker,
isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
@@ -1707,14 +1709,18 @@
IndexedFunction createSetter(
LibraryEntity library, ClassEntity enclosingClass, Name name,
- {bool isStatic, bool isExternal, bool isAbstract}) {
+ {/*required*/ bool isStatic,
+ /*required*/ bool isExternal,
+ /*required*/ bool isAbstract}) {
return KSetter(library, enclosingClass, name,
isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
}
IndexedField createField(
LibraryEntity library, ClassEntity enclosingClass, Name name,
- {bool isStatic, bool isAssignable, bool isConst}) {
+ {/*required*/ bool isStatic,
+ /*required*/ bool isAssignable,
+ /*required*/ bool isConst}) {
return KField(library, enclosingClass, name,
isStatic: isStatic, isAssignable: isAssignable, isConst: isConst);
}
diff --git a/pkg/compiler/lib/src/kernel/kelements.dart b/pkg/compiler/lib/src/kernel/kelements.dart
index 8d37d9f..bb67948 100644
--- a/pkg/compiler/lib/src/kernel/kelements.dart
+++ b/pkg/compiler/lib/src/kernel/kelements.dart
@@ -187,7 +187,9 @@
KMethod(KLibrary library, KClass enclosingClass, Name name,
ParameterStructure parameterStructure, AsyncMarker asyncMarker,
- {bool isStatic, bool isExternal, this.isAbstract})
+ {/*required*/ bool isStatic,
+ /*required*/ bool isExternal,
+ /*required*/ this.isAbstract})
: super(library, enclosingClass, name, parameterStructure, asyncMarker,
isStatic: isStatic, isExternal: isExternal);
@@ -204,7 +206,9 @@
KGetter(KLibrary library, KClass enclosingClass, Name name,
AsyncMarker asyncMarker,
- {bool isStatic, bool isExternal, this.isAbstract})
+ {/*required*/ bool isStatic,
+ /*required*/ bool isExternal,
+ /*required*/ this.isAbstract})
: super(library, enclosingClass, name, ParameterStructure.getter,
asyncMarker,
isStatic: isStatic, isExternal: isExternal);
@@ -221,7 +225,9 @@
final bool isAbstract;
KSetter(KLibrary library, KClass enclosingClass, Name name,
- {bool isStatic, bool isExternal, this.isAbstract})
+ {/*required*/ bool isStatic,
+ /*required*/ bool isExternal,
+ /*required*/ this.isAbstract})
: super(library, enclosingClass, name, ParameterStructure.setter,
AsyncMarker.SYNC,
isStatic: isStatic, isExternal: isExternal);
@@ -243,7 +249,9 @@
final bool isConst;
KField(KLibrary library, KClass enclosingClass, Name name,
- {bool isStatic, this.isAssignable, this.isConst})
+ {/*required*/ bool isStatic,
+ /*required*/ this.isAssignable,
+ /*required*/ this.isConst})
: super(library, enclosingClass, name, isStatic: isStatic);
@override
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index 0a7cda9..94f87ab 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -53,7 +53,7 @@
class KernelFrontendStrategy {
final CompilerOptions _options;
final CompilerTask _compilerTask;
- KernelToElementMap _elementMap;
+ /*late*/ KernelToElementMap _elementMap;
RuntimeTypesNeedBuilder _runtimeTypesNeedBuilder;
KernelAnnotationProcessor _annotationProcessor;
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index f5e81f0..dbdf302 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -392,7 +392,7 @@
/// If the [instruction] is not `null` it will be used to attach the position
/// to the [expression].
- push(js.Expression expression) {
+ push(js.Expression /*!*/ expression) {
expressionStack.add(expression);
}
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 1eb9226..16ac75c 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -185,7 +185,7 @@
}
}
- visitBasicBlock(HBasicBlock block);
+ visitBasicBlock(HBasicBlock /*!*/ block);
}
class _Frame {
@@ -1032,9 +1032,9 @@
SourceInformation sourceInformation;
final int id = idCounter++;
- static int idCounter;
+ static int idCounter = 0;
- final List<HInstruction> inputs;
+ final List<HInstruction /*!*/ > inputs;
final List<HInstruction> usedBy = [];
HBasicBlock block;
diff --git a/pkg/dart2js_info/lib/info.dart b/pkg/dart2js_info/lib/info.dart
index 1ebb2a7..d5d64bf 100644
--- a/pkg/dart2js_info/lib/info.dart
+++ b/pkg/dart2js_info/lib/info.dart
@@ -26,9 +26,15 @@
/// Info of the enclosing element.
Info parent;
+ /// At which stage of the compiler this component was treeshaken.
+ TreeShakenStatus treeShakenStatus;
+
T accept<T>(InfoVisitor<T> visitor);
}
+/// Indicates at what stage of compilation the [Info] element was treeshaken.
+enum TreeShakenStatus { Dead, Live }
+
/// Common information used for most kind of elements.
// TODO(sigmund): add more:
// - inputSize: bytes used in the Dart source program
@@ -42,6 +48,8 @@
int size;
@override
Info parent;
+ @override
+ TreeShakenStatus treeShakenStatus = TreeShakenStatus.Dead;
@override
String name;
diff --git a/pkg/dart2js_info/lib/json_info_codec.dart b/pkg/dart2js_info/lib/json_info_codec.dart
index 1b741a7..40d0332 100644
--- a/pkg/dart2js_info/lib/json_info_codec.dart
+++ b/pkg/dart2js_info/lib/json_info_codec.dart
@@ -11,10 +11,6 @@
import 'info.dart';
import 'src/util.dart';
-List<String> _toSortedSerializedIds(
- Iterable<Info> infos, Id Function(Info) getId) =>
- infos.map((i) => getId(i).serializedId).toList()..sort(compareNatural);
-
// TODO(sigmund): add unit tests.
class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
// Using `MashMap` here because it's faster than the default `LinkedHashMap`.
@@ -349,10 +345,14 @@
implements InfoVisitor<Map> {
/// Whether to generate json compatible with format 5.1
final bool isBackwardCompatible;
+
+ /// Whether to filter all treeshaken elements.
+ final bool filterTreeshaken;
final Map<Info, Id> ids = HashMap<Info, Id>();
final Set<int> usedIds = <int>{};
- AllInfoToJsonConverter({this.isBackwardCompatible = false});
+ AllInfoToJsonConverter(
+ {this.isBackwardCompatible = false, this.filterTreeshaken = false});
Id idFor(Info info) {
var serializedId = ids[info];
@@ -391,6 +391,12 @@
// Using SplayTree to maintain a consistent order of keys
var map = SplayTreeMap<String, Map>(compareNatural);
for (var info in infos) {
+ if (info is BasicInfo) {
+ if (filterTreeshaken &&
+ info.treeShakenStatus != TreeShakenStatus.Live) {
+ continue;
+ }
+ }
map[idFor(info).id] = info.accept(this);
}
return map;
@@ -500,15 +506,13 @@
Map visitLibrary(LibraryInfo info) {
return _visitBasicInfo(info)
..addAll(<String, Object>{
- 'children': _toSortedSerializedIds(
- [
- info.topLevelFunctions,
- info.topLevelVariables,
- info.classes,
- info.classTypes,
- info.typedefs
- ].expand((i) => i),
- idFor),
+ 'children': _toSortedSerializedIds([
+ ...info.topLevelFunctions,
+ ...info.topLevelVariables,
+ ...info.classes,
+ ...info.classTypes,
+ ...info.typedefs
+ ], idFor),
'canonicalUri': '${info.uri}',
});
}
@@ -519,8 +523,8 @@
..addAll(<String, Object>{
// TODO(sigmund): change format, include only when abstract is true.
'modifiers': {'abstract': info.isAbstract},
- 'children': _toSortedSerializedIds(
- [info.fields, info.functions].expand((i) => i), idFor)
+ 'children':
+ _toSortedSerializedIds([...info.fields, ...info.functions], idFor)
});
}
@@ -613,6 +617,15 @@
})
.toList();
}
+
+ List<String> _toSortedSerializedIds(
+ Iterable<Info> infos, Id Function(Info) getId) =>
+ infos
+ .where((i) =>
+ !filterTreeshaken || i.treeShakenStatus == TreeShakenStatus.Live)
+ .map((i) => getId(i).serializedId)
+ .toList()
+ ..sort(compareNatural);
}
class AllInfoJsonCodec extends Codec<AllInfo, Map> {
@@ -621,9 +634,11 @@
@override
final Converter<Map, AllInfo> decoder = JsonToAllInfoConverter();
- AllInfoJsonCodec({bool isBackwardCompatible = false})
- : encoder =
- AllInfoToJsonConverter(isBackwardCompatible: isBackwardCompatible);
+ AllInfoJsonCodec(
+ {bool isBackwardCompatible = false, bool filterTreeshaken = false})
+ : encoder = AllInfoToJsonConverter(
+ isBackwardCompatible: isBackwardCompatible,
+ filterTreeshaken: filterTreeshaken);
}
class Id {
diff --git a/pkg/js_ast/lib/src/nodes.dart b/pkg/js_ast/lib/src/nodes.dart
index fab2e1b..661efd6 100644
--- a/pkg/js_ast/lib/src/nodes.dart
+++ b/pkg/js_ast/lib/src/nodes.dart
@@ -580,7 +580,7 @@
/// Returns a node equivalent to [this], but with new source position and end
/// source position.
Node withSourceInformation(
- JavaScriptNodeSourceInformation sourceInformation) {
+ JavaScriptNodeSourceInformation? sourceInformation) {
if (sourceInformation == _sourceInformation) {
return this;
}
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index eef1084..ce9a8ff 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -20,6 +20,10 @@
#elif defined(DART_HOST_OS_WINDOWS)
#include <processthreadsapi.h>
#endif
+#if !defined(DART_HOST_OS_WINDOWS)
+#include <string.h> /* NOLINT */
+#include <sys/utsname.h> /* NOLINT */
+#endif
#endif
// ARM version differences.
@@ -145,20 +149,27 @@
CpuInfo::Init();
hardware_ = CpuInfo::GetCpuModel();
+ // QEMU may report host cpuinfo instead of emulated cpuinfo, use uname as a
+ // fallback for checking if CPU is AArch64 or ARMv7.
+ struct utsname uname_;
+ int ret_ = uname(&uname_);
+
// Check for ARMv7, or aarch64.
// It can be in either the Processor or Model information fields.
if (CpuInfo::FieldContains(kCpuInfoProcessor, "aarch64") ||
CpuInfo::FieldContains(kCpuInfoModel, "aarch64") ||
CpuInfo::FieldContains(kCpuInfoArchitecture, "8") ||
- CpuInfo::FieldContains(kCpuInfoArchitecture, "AArch64")) {
+ CpuInfo::FieldContains(kCpuInfoArchitecture, "AArch64") ||
+ (ret_ == 0 && (strstr(uname_.machine, "aarch64") != NULL ||
+ strstr(uname_.machine, "arm64") != NULL ||
+ strstr(uname_.machine, "armv8") != NULL))) {
// pretend that this arm64 cpu is really an ARMv7
is_arm64 = true;
} else if (!CpuInfo::FieldContains(kCpuInfoProcessor, "ARMv7") &&
!CpuInfo::FieldContains(kCpuInfoModel, "ARMv7") &&
- !CpuInfo::FieldContains(kCpuInfoArchitecture, "7")) {
-#if !defined(DART_RUN_IN_QEMU_ARMv7)
+ !CpuInfo::FieldContains(kCpuInfoArchitecture, "7") &&
+ !(ret_ == 0 && strstr(uname_.machine, "armv7") != NULL)) {
FATAL("Unrecognized ARM CPU architecture.");
-#endif
}
// Has integer division.
@@ -203,7 +214,7 @@
// Use the cross-compiler's predefined macros to determine whether we should
// use the hard or soft float ABI.
-#if defined(__ARM_PCS_VFP) || defined(DART_RUN_IN_QEMU_ARMv7)
+#if defined(__ARM_PCS_VFP)
hardfp_supported_ = true;
#else
hardfp_supported_ = false;
diff --git a/sdk/lib/js/js_wasm.dart b/sdk/lib/js/js_wasm.dart
index 847e6e0..28fa458 100644
--- a/sdk/lib/js/js_wasm.dart
+++ b/sdk/lib/js/js_wasm.dart
@@ -9,8 +9,14 @@
const JS([this.name]);
}
+class _Anonymous {
+ const _Anonymous();
+}
+
class _StaticInterop {
const _StaticInterop();
}
+const _Anonymous anonymous = _Anonymous();
+
const _StaticInterop staticInterop = _StaticInterop();
diff --git a/tests/web/wasm/static_interop_test.dart b/tests/web/wasm/static_interop_test.dart
index c1be1eb..97bb80f 100644
--- a/tests/web/wasm/static_interop_test.dart
+++ b/tests/web/wasm/static_interop_test.dart
@@ -138,9 +138,31 @@
Expect.equals(fooBar('hello'), 'hello world!');
}
+@JS()
+@anonymous
+@staticInterop
+class AnonymousJSClass {
+ external factory AnonymousJSClass.factory(
+ {String? foo, String bar = 'baz', String? bleep});
+}
+
+extension AnonymousJSClassExtension on AnonymousJSClass {
+ external String? get foo;
+ external String get bar;
+ external String? get bleep;
+}
+
+void anonymousTest() {
+ final anonymousJSClass = AnonymousJSClass.factory(foo: 'boo');
+ Expect.equals('boo', anonymousJSClass.foo);
+ Expect.equals('baz', anonymousJSClass.bar);
+ Expect.equals(null, anonymousJSClass.bleep);
+}
+
void main() {
createClassTest();
setInteropPropertyTest();
setDartObjectPropertyTest();
topLevelMethodsTest();
+ anonymousTest();
}
diff --git a/tools/VERSION b/tools/VERSION
index 822343f..fd91a2d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 17
+PRERELEASE 18
PRERELEASE_PATCH 0
\ No newline at end of file