Version 2.18.0-17.0.dev
Merge commit '3f9898cb5c684e519e31af514a59caf7fb1d6aab' into 'dev'
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 f2a2aaa..eb6de83 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
@@ -7,7 +7,8 @@
import 'package:kernel/core_types.dart';
import 'package:kernel/type_environment.dart';
-import '../js_interop.dart' show getJSName, hasStaticInteropAnnotation;
+import '../js_interop.dart'
+ show getJSName, hasStaticInteropAnnotation, hasJSInteropAnnotation;
/// Replaces:
/// 1) Factory constructors in classes with `@staticInterop` annotations with
@@ -101,14 +102,31 @@
if (nodeDescriptor != null) {
if (!nodeDescriptor.isStatic) {
if (nodeDescriptor.kind == ExtensionMemberKind.Getter) {
- transformedBody = _getExternalGetterBody(node);
+ transformedBody = _getExternalExtensionGetterBody(node);
} else if (nodeDescriptor.kind == ExtensionMemberKind.Setter) {
- transformedBody = _getExternalSetterBody(node);
+ transformedBody = _getExternalExtensionSetterBody(node);
} else if (nodeDescriptor.kind == ExtensionMemberKind.Method) {
- transformedBody = _getExternalMethodBody(node);
+ transformedBody = _getExternalExtensionMethodBody(node);
}
}
}
+ } else if (hasJSInteropAnnotation(node)) {
+ String selectorString = getJSName(node);
+ late Expression target;
+ if (selectorString.isEmpty) {
+ target = _globalThis;
+ } else {
+ List<String> selectors = selectorString.split('.');
+ target = getObjectOffGlobalThis(node, selectors);
+ }
+ if (node.isGetter) {
+ transformedBody = _getExternalTopLevelGetterBody(node, target);
+ } else if (node.isSetter) {
+ transformedBody = _getExternalTopLevelSetterBody(node, target);
+ } else {
+ assert(node.kind == ProcedureKind.Method);
+ transformedBody = _getExternalTopLevelMethodBody(node, target);
+ }
}
}
if (transformedBody != null) {
@@ -146,6 +164,22 @@
Expression _jsifyVariable(VariableDeclaration variable) =>
StaticInvocation(_jsifyTarget, Arguments([VariableGet(variable)]));
+ StaticInvocation get _globalThis =>
+ StaticInvocation(_globalThisTarget, Arguments([]));
+
+ /// Takes a list of [selectors] and returns an object off of
+ /// `globalThis`. We could optimize this with a custom method built with
+ /// js_ast.
+ 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;
+ }
+ return currentTarget;
+ }
+
/// Returns a new function body for the given [node] external method.
///
/// The new function body will call `js_util_wasm.callConstructorVarArgs`
@@ -156,7 +190,7 @@
var callConstructorInvocation = StaticInvocation(
_callConstructorTarget,
Arguments([
- StaticInvocation(_globalThisTarget, Arguments([])),
+ _globalThis,
StringLiteral(constructorName),
ListLiteral(
function.positionalParameters.map(_jsifyVariable).toList(),
@@ -171,62 +205,80 @@
/// Returns a new function body for the given [node] external getter.
///
- /// The new function body will call `js_util_wasm.getProperty` for the
- /// given external getter.
- ReturnStatement _getExternalGetterBody(Procedure node) {
- var function = node.function;
- assert(function.positionalParameters.length == 1);
- var getPropertyInvocation = _dartify(StaticInvocation(
- _getPropertyTarget,
- Arguments([
- VariableGet(function.positionalParameters.first),
- StringLiteral(_getExtensionMemberName(node))
- ])))
+ /// The new function body is equivalent to:
+ /// `js_util_wasm.getProperty([object], [getterName])`.
+ ReturnStatement _getExternalGetterBody(
+ Procedure node, Expression object, String getterName) {
+ final getPropertyInvocation = _dartify(StaticInvocation(
+ _getPropertyTarget, Arguments([object, StringLiteral(getterName)])))
..fileOffset = node.fileOffset;
return ReturnStatement(getPropertyInvocation);
}
+ ReturnStatement _getExternalExtensionGetterBody(Procedure node) =>
+ _getExternalGetterBody(
+ node,
+ VariableGet(node.function.positionalParameters.single),
+ _getExtensionMemberName(node));
+
+ ReturnStatement _getExternalTopLevelGetterBody(
+ Procedure node, Expression target) =>
+ _getExternalGetterBody(node, target, node.name.text);
+
/// Returns a new function body for the given [node] external setter.
///
- /// The new function body will call `js_util_wasm.setProperty` for
- /// the given external setter.
- ReturnStatement _getExternalSetterBody(Procedure node) {
- var function = node.function;
- assert(function.positionalParameters.length == 2);
- var value = function.positionalParameters.last;
- var setPropertyInvocation = _dartify(StaticInvocation(
- _setPropertyTarget,
- Arguments([
- VariableGet(function.positionalParameters.first),
- StringLiteral(_getExtensionMemberName(node)),
- _jsifyVariable(value)
- ])))
+ /// The new function body is equivalent to:
+ /// `js_util_wasm.setProperty([object], [setterName], [value])`.
+ 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);
}
+ ReturnStatement _getExternalExtensionSetterBody(Procedure node) {
+ final parameters = node.function.positionalParameters;
+ assert(parameters.length == 2);
+ return _getExternalSetterBody(node, VariableGet(parameters.first),
+ _getExtensionMemberName(node), parameters.last);
+ }
+
+ ReturnStatement _getExternalTopLevelSetterBody(
+ Procedure node, Expression target) =>
+ _getExternalSetterBody(node, target, node.name.text,
+ node.function.positionalParameters.single);
+
/// Returns a new function body for the given [node] external method.
///
- /// The new function body will call `js_util_wasm.callMethodVarArgs` for
- /// the given external method.
- ReturnStatement _getExternalMethodBody(Procedure node) {
- var function = node.function;
- var callMethodInvocation = _dartify(StaticInvocation(
+ /// The new function body is equivalent to:
+ /// `js_util_wasm.callMethodVarArgs([object], [methodName], [values])`.
+ ReturnStatement _getExternalMethodBody(Procedure node, Expression object,
+ String methodName, List<VariableDeclaration> values) {
+ final callMethodInvocation = _dartify(StaticInvocation(
_callMethodTarget,
Arguments([
- VariableGet(function.positionalParameters.first),
- StringLiteral(_getExtensionMemberName(node)),
- ListLiteral(
- function.positionalParameters
- .sublist(1)
- .map(_jsifyVariable)
- .toList(),
+ object,
+ StringLiteral(methodName),
+ ListLiteral(values.map(_jsifyVariable).toList(),
typeArgument: _nullableJSValueType)
])))
..fileOffset = node.fileOffset;
return ReturnStatement(callMethodInvocation);
}
+ ReturnStatement _getExternalExtensionMethodBody(Procedure node) {
+ final parameters = node.function.positionalParameters;
+ assert(parameters.length > 0);
+ return _getExternalMethodBody(node, VariableGet(parameters.first),
+ _getExtensionMemberName(node), parameters.sublist(1));
+ }
+
+ ReturnStatement _getExternalTopLevelMethodBody(
+ Procedure node, Expression target) =>
+ _getExternalMethodBody(
+ node, target, node.name.text, node.function.positionalParameters);
+
/// Returns the extension member name.
///
/// Returns either the name from the `@JS` annotation if non-empty, or the
diff --git a/pkg/analysis_server/test/analysis_server_base.dart b/pkg/analysis_server/test/analysis_server_base.dart
index bdbd4ea..69ddef5 100644
--- a/pkg/analysis_server/test/analysis_server_base.dart
+++ b/pkg/analysis_server/test/analysis_server_base.dart
@@ -91,6 +91,9 @@
EnableString.super_parameters,
];
+ /// The path that is not in [workspaceRootPath], contains external packages.
+ String get packagesRootPath => '/packages';
+
Folder get sdkRoot => newFolder('/sdk');
File get testFile => getFile(testFilePath);
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index 8705302..5b6ffbe 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -7,13 +7,13 @@
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:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'analysis_abstract.dart';
import 'analysis_server_base.dart';
import 'mocks.dart';
@@ -1465,23 +1465,29 @@
}
@reflectiveTest
-class SetSubscriptionsTest extends AbstractAnalysisTest {
- Map<String, List<HighlightRegion>> filesHighlights = {};
+class SetSubscriptionsTest extends PubPackageAnalysisServerTest {
+ Map<File, List<HighlightRegion>> filesHighlights = {};
final Completer<void> _resultsAvailable = Completer();
@override
void processNotification(Notification notification) {
+ super.processNotification(notification);
if (notification.event == ANALYSIS_NOTIFICATION_HIGHLIGHTS) {
var params = AnalysisHighlightsParams.fromNotification(notification);
- filesHighlights[params.file] = params.regions;
+ filesHighlights[getFile(params.file)] = params.regions;
_resultsAvailable.complete();
}
}
+ @override
+ Future<void> setUp() async {
+ super.setUp();
+ await setRoots(included: [workspaceRootPath], excluded: []);
+ }
+
Future<void> test_afterAnalysis() async {
addTestFile('int V = 42;');
- await createProject();
// wait for analysis, no results initially
await waitForTasksFinished();
expect(filesHighlights[testFile], isNull);
@@ -1493,9 +1499,8 @@
}
Future<void> test_afterAnalysis_noSuchFile() async {
- var file = convertPath('/no-such-file.dart');
+ var file = getFile('/no-such-file.dart');
addTestFile('// no matter');
- await createProject();
// wait for analysis, no results initially
await waitForTasksFinished();
expect(filesHighlights[testFile], isNull);
@@ -1510,7 +1515,7 @@
var pkgFile = newFile2('/packages/pkgA/lib/libA.dart', '''
library lib_a;
class A {}
-''').path;
+''');
newPackageConfigJsonFile(
'/project',
(PackageConfigFileBuilder()
@@ -1524,7 +1529,6 @@
new A();
}
''');
- await createProject();
// wait for analysis, no results initially
await waitForTasksFinished();
expect(filesHighlights[pkgFile], isNull);
@@ -1541,7 +1545,7 @@
var pkgFileA = newFile2('$pkgA/lib/libA.dart', '''
library lib_a;
class A {}
-''').path;
+''');
newFile2('$pkgA/lib/libB.dart', '''
import 'package:pkgA/libA.dart';
main() {
@@ -1549,7 +1553,6 @@
}
''');
// add 'pkgA' and 'pkgB' as projects
- newFolder(projectPath);
await setRoots(included: [pkgA, pkgB], excluded: []);
// wait for analysis, no results initially
await waitForTasksFinished();
@@ -1565,7 +1568,7 @@
var pkgFile = newFile2('/packages/pkgA/lib/libA.dart', '''
library lib_a;
class A {}
-''').path;
+''');
newPackageConfigJsonFile(
'/project',
(PackageConfigFileBuilder()
@@ -1574,12 +1577,11 @@
);
//
addTestFile('// no "pkgA" reference');
- await createProject();
// wait for analysis, no results initially
await waitForTasksFinished();
expect(filesHighlights[pkgFile], isNull);
// make it a priority file, so make analyzable
- server.setPriorityFiles('0', [pkgFile]);
+ server.setPriorityFiles('0', [pkgFile.path]);
// subscribe
await addAnalysisSubscription(AnalysisService.HIGHLIGHTS, pkgFile);
await _resultsAvailable.future;
@@ -1588,9 +1590,8 @@
}
Future<void> test_afterAnalysis_sdkFile() async {
- var file = convertPath('/sdk/lib/core/core.dart');
+ var file = getFile('/sdk/lib/core/core.dart');
addTestFile('// no matter');
- await createProject();
// wait for analysis, no results initially
await waitForTasksFinished();
expect(filesHighlights[file], isNull);
@@ -1603,7 +1604,6 @@
Future<void> test_beforeAnalysis() async {
addTestFile('int V = 42;');
- await createProject();
// subscribe
await addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
// wait for analysis
@@ -1613,7 +1613,6 @@
Future<void> test_sentToPlugins() async {
addTestFile('int V = 42;');
- await createProject();
// subscribe
await addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
// wait for analysis
@@ -1622,7 +1621,7 @@
var subscriptions = params.subscriptions;
expect(subscriptions, hasLength(1));
var files = subscriptions[plugin.AnalysisService.HIGHLIGHTS];
- expect(files, [testFile]);
+ expect(files, [testFile.path]);
}
}
diff --git a/pkg/analysis_server/test/domain_diagnostic_test.dart b/pkg/analysis_server/test/domain_diagnostic_test.dart
index dd79a90..bffbea1 100644
--- a/pkg/analysis_server/test/domain_diagnostic_test.dart
+++ b/pkg/analysis_server/test/domain_diagnostic_test.dart
@@ -6,7 +6,7 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'analysis_abstract.dart';
+import 'analysis_server_base.dart';
void main() {
defineReflectiveSuite(() {
@@ -15,23 +15,20 @@
}
@reflectiveTest
-class DiagnosticDomainTest extends AbstractAnalysisTest {
+class DiagnosticDomainTest extends PubPackageAnalysisServerTest {
Future<void> test_getDiagnostics() async {
- newPubspecYamlFile('/project', 'name: project');
- newFile2('/project/bin/test.dart', 'main() {}');
+ newPubspecYamlFile(testPackageRootPath, 'name: project');
+ newFile2('$testPackageLibPath/test.dart', 'main() {}');
- await server.setAnalysisRoots('0', [convertPath('/project')], []);
-
+ await setRoots(included: [workspaceRootPath], excluded: []);
await server.onAnalysisComplete;
var request = DiagnosticGetDiagnosticsParams().toRequest('0');
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
var result = DiagnosticGetDiagnosticsResult.fromResponse(response);
- expect(result.contexts, hasLength(1));
-
- var context = result.contexts[0];
- expect(context.name, convertPath('/project'));
+ var context = result.contexts
+ .singleWhere((context) => context.name == testPackageRoot.path);
expect(context.explicitFileCount, 1); /* test.dart */
expect(context.implicitFileCount, 5);
@@ -41,7 +38,7 @@
Future<void> test_getDiagnostics_noRoot() async {
var request = DiagnosticGetDiagnosticsParams().toRequest('0');
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
var result = DiagnosticGetDiagnosticsResult.fromResponse(response);
expect(result.contexts, isEmpty);
}
diff --git a/pkg/analysis_server/test/domain_execution_test.dart b/pkg/analysis_server/test/domain_execution_test.dart
index e1ec249..ce4b54c 100644
--- a/pkg/analysis_server/test/domain_execution_test.dart
+++ b/pkg/analysis_server/test/domain_execution_test.dart
@@ -4,10 +4,11 @@
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/file_system/file_system.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'analysis_abstract.dart';
+import 'analysis_server_base.dart';
import 'mocks.dart';
void main() {
@@ -116,13 +117,13 @@
}
@reflectiveTest
-class ExecutionDomainTest extends AbstractAnalysisTest {
+class ExecutionDomainTest extends PubPackageAnalysisServerTest {
late String contextId;
@override
Future<void> setUp() async {
super.setUp();
- await createProject();
+ await setRoots(included: [workspaceRootPath], excluded: []);
await _createExecutionContext(testFile);
}
@@ -134,13 +135,13 @@
Future<void> test_createAndDeleteMultipleContexts() async {
var request = ExecutionCreateContextParams('/a/b.dart').toRequest('0');
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
expect(response, isResponseSuccess('0'));
var result = ExecutionCreateContextResult.fromResponse(response);
var id0 = result.id;
request = ExecutionCreateContextParams('/c/d.dart').toRequest('1');
- response = await waitResponse(request);
+ response = await handleSuccessfulRequest(request);
expect(response, isResponseSuccess('1'));
result = ExecutionCreateContextResult.fromResponse(response);
var id1 = result.id;
@@ -148,17 +149,17 @@
expect(id0 == id1, isFalse);
request = ExecutionDeleteContextParams(id0).toRequest('2');
- response = await waitResponse(request);
+ response = await handleSuccessfulRequest(request);
expect(response, isResponseSuccess('2'));
request = ExecutionDeleteContextParams(id1).toRequest('3');
- response = await waitResponse(request);
+ response = await handleSuccessfulRequest(request);
expect(response, isResponseSuccess('3'));
}
Future<void> test_deleteNonExistentContext() async {
var request = ExecutionDeleteContextParams('13').toRequest('0');
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
// TODO(brianwilkerson) It isn't currently specified to be an error if a
// client attempts to delete a context that doesn't exist. Should it be?
// expect(response, isResponseFailure('0'));
@@ -186,7 +187,7 @@
path,
code.indexOf('// context line'),
<RuntimeCompletionVariable>[]).toRequest('0');
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
var result = ExecutionGetSuggestionsResult.fromResponse(response);
// expect(result.suggestions, isNotEmpty);
@@ -225,9 +226,9 @@
expect(result.uri, isNull);
}
- Future<void> _createExecutionContext(String path) async {
- var request = ExecutionCreateContextParams(path).toRequest('0');
- var response = await waitResponse(request);
+ Future<void> _createExecutionContext(File file) async {
+ var request = ExecutionCreateContextParams(file.path).toRequest('0');
+ var response = await handleSuccessfulRequest(request);
expect(response, isResponseSuccess('0'));
var result = ExecutionCreateContextResult.fromResponse(response);
contextId = result.id;
@@ -235,14 +236,14 @@
Future<void> _disposeExecutionContext() async {
var request = ExecutionDeleteContextParams(contextId).toRequest('1');
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
expect(response, isResponseSuccess('1'));
}
Future<ExecutionMapUriResult> _mapUri({String? file, String? uri}) async {
var request =
ExecutionMapUriParams(contextId, file: file, uri: uri).toRequest('2');
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
expect(response, isResponseSuccess('2'));
return ExecutionMapUriResult.fromResponse(response);
}
diff --git a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
index 4184735..d0e219f 100644
--- a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
@@ -15,7 +15,6 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(FixesCodeActionsTest);
- defineReflectiveTests(FixesCodeActionsWithNullSafetyTest);
});
}
@@ -158,6 +157,85 @@
expect(await ofKind(CodeActionKind.Refactor), isEmpty);
}
+ Future<void> test_fixAll_notWhenNoBatchFix() async {
+ // Some fixes (for example 'create function foo') are not available in the
+ // batch processor, so should not generate fix-all-in-file fixes even if there
+ // are multiple instances.
+ const content = '''
+var a = [[foo]]();
+var b = bar();
+ ''';
+
+ newFile2(mainFilePath, withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+ );
+
+ final allFixes = await getCodeActions(mainFileUri.toString(),
+ range: rangeFromMarkers(content));
+
+ // Expect only the single-fix, there should be no apply-all.
+ expect(allFixes, hasLength(1));
+ final fixTitle = allFixes.first.map((f) => f.title, (f) => f.title);
+ expect(fixTitle, equals("Create function 'foo'"));
+ }
+
+ Future<void> test_fixAll_notWhenSingle() async {
+ const content = '''
+void f(String a) {
+ [[print(a!)]];
+}
+ ''';
+
+ newFile2(mainFilePath, withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+ );
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ range: rangeFromMarkers(content));
+ final fixAction = findEditAction(
+ codeActions, CodeActionKind('quickfix'), "Remove '!'s in file");
+
+ // Should not appear if there was only a single error.
+ expect(fixAction, isNull);
+ }
+
+ Future<void> test_fixAll_whenMultiple() async {
+ const content = '''
+void f(String a) {
+ [[print(a!!)]];
+ print(a!!);
+}
+ ''';
+
+ const expectedContent = '''
+void f(String a) {
+ print(a);
+ print(a);
+}
+ ''';
+ newFile2(mainFilePath, withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+ );
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ range: rangeFromMarkers(content));
+ final fixAction = findEditAction(
+ codeActions, CodeActionKind('quickfix'), "Remove '!'s in file")!;
+
+ // Ensure applying the changes will give us the expected content.
+ final contents = {
+ mainFilePath: withoutMarkers(content),
+ };
+ applyChanges(contents, fixAction.edit!.changes!);
+ expect(contents[mainFilePath], equals(expectedContent));
+ }
+
Future<void> test_ignoreDiagnosticForFile() async {
const content = '''
// Header comment
@@ -239,6 +317,42 @@
expect(contents[mainFilePath], equals(expectedContent));
}
+ Future<void> test_noDuplicates_differentFix() async {
+ // For convenience, quick-fixes are usually returned for the entire line,
+ // though this can lead to duplicate entries (by title) when multiple
+ // diagnostics have their own fixes of the same type.
+ //
+ // Expect only the only one nearest to the start of the range to be returned.
+ const content = '''
+ main() {
+ var a = [];
+ print(a!!);^
+ }
+ ''';
+
+ newFile2(mainFilePath, withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+ );
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ position: positionFromMarker(content));
+ final removeNnaAction = findEditActions(codeActions,
+ CodeActionKind('quickfix.remove.nonNullAssertion'), "Remove the '!'");
+
+ // Expect only one of the fixes.
+ expect(removeNnaAction, hasLength(1));
+
+ // Ensure the action is for the diagnostic on the second bang which was
+ // closest to the range requested.
+ final secondBangPos =
+ positionFromOffset(withoutMarkers(content).indexOf('!);'), content);
+ expect(removeNnaAction.first.diagnostics, hasLength(1));
+ final diagStart = removeNnaAction.first.diagnostics!.first.range.start;
+ expect(diagStart, equals(secondBangPos));
+ }
+
Future<void> test_noDuplicates_sameFix() async {
const content = '''
var a = [Test, Test, Te[[]]st];
@@ -554,124 +668,3 @@
expect(contents[mainFilePath], equals(expectedContent));
}
}
-
-@reflectiveTest
-class FixesCodeActionsWithNullSafetyTest extends AbstractCodeActionsTest {
- @override
- String get testPackageLanguageVersion => latestLanguageVersion;
-
- Future<void> test_fixAll_notWhenNoBatchFix() async {
- // Some fixes (for example 'create function foo') are not available in the
- // batch processor, so should not generate fix-all-in-file fixes even if there
- // are multiple instances.
- const content = '''
-var a = [[foo]]();
-var b = bar();
- ''';
-
- newFile2(mainFilePath, withoutMarkers(content));
- await initialize(
- textDocumentCapabilities: withCodeActionKinds(
- emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
- );
-
- final allFixes = await getCodeActions(mainFileUri.toString(),
- range: rangeFromMarkers(content));
-
- // Expect only the single-fix, there should be no apply-all.
- expect(allFixes, hasLength(1));
- final fixTitle = allFixes.first.map((f) => f.title, (f) => f.title);
- expect(fixTitle, equals("Create function 'foo'"));
- }
-
- Future<void> test_fixAll_notWhenSingle() async {
- const content = '''
-void f(String a) {
- [[print(a!)]];
-}
- ''';
-
- newFile2(mainFilePath, withoutMarkers(content));
- await initialize(
- textDocumentCapabilities: withCodeActionKinds(
- emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
- );
-
- final codeActions = await getCodeActions(mainFileUri.toString(),
- range: rangeFromMarkers(content));
- final fixAction = findEditAction(
- codeActions, CodeActionKind('quickfix'), "Remove '!'s in file");
-
- // Should not appear if there was only a single error.
- expect(fixAction, isNull);
- }
-
- Future<void> test_fixAll_whenMultiple() async {
- const content = '''
-void f(String a) {
- [[print(a!!)]];
- print(a!!);
-}
- ''';
-
- const expectedContent = '''
-void f(String a) {
- print(a);
- print(a);
-}
- ''';
- newFile2(mainFilePath, withoutMarkers(content));
- await initialize(
- textDocumentCapabilities: withCodeActionKinds(
- emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
- );
-
- final codeActions = await getCodeActions(mainFileUri.toString(),
- range: rangeFromMarkers(content));
- final fixAction = findEditAction(
- codeActions, CodeActionKind('quickfix'), "Remove '!'s in file")!;
-
- // Ensure applying the changes will give us the expected content.
- final contents = {
- mainFilePath: withoutMarkers(content),
- };
- applyChanges(contents, fixAction.edit!.changes!);
- expect(contents[mainFilePath], equals(expectedContent));
- }
-
- Future<void> test_noDuplicates_differentFix() async {
- // For convenience, quick-fixes are usually returned for the entire line,
- // though this can lead to duplicate entries (by title) when multiple
- // diagnostics have their own fixes of the same type.
- //
- // Expect only the only one nearest to the start of the range to be returned.
- const content = '''
- main() {
- var a = [];
- print(a!!);^
- }
- ''';
-
- newFile2(mainFilePath, withoutMarkers(content));
- await initialize(
- textDocumentCapabilities: withCodeActionKinds(
- emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
- );
-
- final codeActions = await getCodeActions(mainFileUri.toString(),
- position: positionFromMarker(content));
- final removeNnaAction = findEditActions(codeActions,
- CodeActionKind('quickfix.remove.nonNullAssertion'), "Remove the '!'");
-
- // Expect only one of the fixes.
- expect(removeNnaAction, hasLength(1));
-
- // Ensure the action is for the diagnostic on the second bang which was
- // closest to the range requested.
- final secondBangPos =
- positionFromOffset(withoutMarkers(content).indexOf('!);'), content);
- expect(removeNnaAction.first.diagnostics, hasLength(1));
- final diagStart = removeNnaAction.first.diagnostics!.first.range.start;
- expect(diagStart, equals(secondBangPos));
- }
-}
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index a175f49..d508645 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -18,6 +18,8 @@
defineReflectiveSuite(() {
defineReflectiveTests(ExtractMethodRefactorCodeActionsTest);
defineReflectiveTests(ExtractWidgetRefactorCodeActionsTest);
+ defineReflectiveTests(
+ ExtractWidgetRefactorCodeActionsWithoutNullSafetyTest);
defineReflectiveTests(ExtractVariableRefactorCodeActionsTest);
defineReflectiveTests(InlineLocalVariableRefactorCodeActionsTest);
defineReflectiveTests(InlineMethodRefactorCodeActionsTest);
@@ -579,6 +581,9 @@
class ExtractWidgetRefactorCodeActionsTest extends AbstractCodeActionsTest {
final extractWidgetTitle = 'Extract Widget';
+ /// Nullability suffix expected in this test class.
+ String get expectedNullableSuffix => '?';
+
@override
void setUp() {
super.setUp();
@@ -610,7 +615,7 @@
}
}
''';
- const expectedContent = '''
+ final expectedContent = '''
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
@@ -628,7 +633,7 @@
class NewWidget extends StatelessWidget {
const NewWidget({
- Key key,
+ Key$expectedNullableSuffix key,
}) : super(key: key);
@override
@@ -671,6 +676,16 @@
}
@reflectiveTest
+class ExtractWidgetRefactorCodeActionsWithoutNullSafetyTest
+ extends ExtractWidgetRefactorCodeActionsTest {
+ @override
+ String get expectedNullableSuffix => '';
+
+ @override
+ String get testPackageLanguageVersion => '2.9';
+}
+
+@reflectiveTest
class InlineLocalVariableRefactorCodeActionsTest
extends AbstractCodeActionsTest {
final inlineVariableTitle = 'Inline Local Variable';
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index b91f9e7..c593f01 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -23,9 +23,7 @@
defineReflectiveTests(CompletionTest);
defineReflectiveTests(DartSnippetCompletionTest);
defineReflectiveTests(FlutterSnippetCompletionTest);
- defineReflectiveTests(
- FlutterSnippetCompletionWithLatestLanguageVersionTest);
- defineReflectiveTests(CompletionTestWithNullSafetyTest);
+ defineReflectiveTests(FlutterSnippetCompletionWithoutNullSafetyTest);
});
}
@@ -421,6 +419,77 @@
);
}
+ Future<void> test_completeFunctionCalls_requiredNamed() async {
+ final content = '''
+ void myFunction(String a, int b, {required String c, String d = ''}) {}
+
+ void f() {
+ [[myFu^]]
+ }
+ ''';
+
+ await provideConfig(
+ () => initialize(
+ textDocumentCapabilities: withCompletionItemSnippetSupport(
+ emptyTextDocumentClientCapabilities),
+ workspaceCapabilities:
+ withConfigurationSupport(emptyWorkspaceClientCapabilities),
+ ),
+ {'completeFunctionCalls': true},
+ );
+ await openFile(mainFileUri, withoutMarkers(content));
+ final res = await getCompletion(mainFileUri, positionFromMarker(content));
+ final item = res.singleWhere((c) => c.label == 'myFunction(…)');
+ // Ensure the snippet comes through in the expected format with the expected
+ // placeholders.
+ expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
+ expect(item.insertText, equals(r'myFunction(${1:a}, ${2:b}, c: ${3:c})'));
+ final textEdit = toTextEdit(item.textEdit!);
+ expect(textEdit.newText, equals(item.insertText));
+ expect(textEdit.range, equals(rangeFromMarkers(content)));
+ }
+
+ Future<void> test_completeFunctionCalls_requiredNamed_suggestionSet() async {
+ final otherFile = join(projectFolderPath, 'lib', 'other.dart');
+ newFile2(
+ otherFile,
+ "void myFunction(String a, int b, {required String c, String d = ''}) {}",
+ );
+ final content = '''
+ void f() {
+ [[myFu^]]
+ }
+ ''';
+
+ final initialAnalysis = waitForAnalysisComplete();
+ await provideConfig(
+ () => initialize(
+ textDocumentCapabilities: withCompletionItemSnippetSupport(
+ emptyTextDocumentClientCapabilities),
+ workspaceCapabilities: withApplyEditSupport(
+ withConfigurationSupport(emptyWorkspaceClientCapabilities)),
+ ),
+ {'completeFunctionCalls': true},
+ );
+ await openFile(mainFileUri, withoutMarkers(content));
+ await initialAnalysis;
+
+ final res = await getCompletion(mainFileUri, positionFromMarker(content));
+ final item = res.singleWhere((c) => c.label == 'myFunction(…)');
+ // Ensure the snippet comes through in the expected format with the expected
+ // placeholders.
+ expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
+ expect(item.insertText, equals(r'myFunction(${1:a}, ${2:b}, c: ${3:c})'));
+ expect(item.textEdit, isNull);
+
+ // Ensure the item can be resolved and gets a proper TextEdit.
+ final resolved = await resolveCompletion(item);
+ expect(resolved.textEdit, isNotNull);
+ final textEdit = toTextEdit(resolved.textEdit!);
+ expect(textEdit.newText, equals(item.insertText));
+ expect(textEdit.range, equals(rangeFromMarkers(content)));
+ }
+
Future<void> test_completeFunctionCalls_show() async {
final content = '''
import 'dart:math' show mi^
@@ -1254,6 +1323,25 @@
expect(res, isEmpty);
}
+ Future<void> test_nullableTypes() async {
+ final content = '''
+ String? foo(int? a, [int b = 1]) {}
+
+ void f() {
+ fo^
+ }
+ ''';
+
+ final initialAnalysis = waitForAnalysisComplete();
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content));
+ await initialAnalysis;
+ final res = await getCompletion(mainFileUri, positionFromMarker(content));
+
+ final completion = res.singleWhere((c) => c.label.startsWith('foo'));
+ expect(completion.detail, '(int? a, [int b = 1]) → String?');
+ }
+
Future<void> test_parensNotInFilterTextInsertText() async {
final content = '''
class MyClass {}
@@ -2359,102 +2447,6 @@
}
@reflectiveTest
-class CompletionTestWithNullSafetyTest extends AbstractLspAnalysisServerTest {
- @override
- String get testPackageLanguageVersion => latestLanguageVersion;
-
- Future<void> test_completeFunctionCalls_requiredNamed() async {
- final content = '''
- void myFunction(String a, int b, {required String c, String d = ''}) {}
-
- void f() {
- [[myFu^]]
- }
- ''';
-
- await provideConfig(
- () => initialize(
- textDocumentCapabilities: withCompletionItemSnippetSupport(
- emptyTextDocumentClientCapabilities),
- workspaceCapabilities:
- withConfigurationSupport(emptyWorkspaceClientCapabilities),
- ),
- {'completeFunctionCalls': true},
- );
- await openFile(mainFileUri, withoutMarkers(content));
- final res = await getCompletion(mainFileUri, positionFromMarker(content));
- final item = res.singleWhere((c) => c.label == 'myFunction(…)');
- // Ensure the snippet comes through in the expected format with the expected
- // placeholders.
- expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
- expect(item.insertText, equals(r'myFunction(${1:a}, ${2:b}, c: ${3:c})'));
- final textEdit = toTextEdit(item.textEdit!);
- expect(textEdit.newText, equals(item.insertText));
- expect(textEdit.range, equals(rangeFromMarkers(content)));
- }
-
- Future<void> test_completeFunctionCalls_requiredNamed_suggestionSet() async {
- final otherFile = join(projectFolderPath, 'lib', 'other.dart');
- newFile2(
- otherFile,
- "void myFunction(String a, int b, {required String c, String d = ''}) {}",
- );
- final content = '''
- void f() {
- [[myFu^]]
- }
- ''';
-
- final initialAnalysis = waitForAnalysisComplete();
- await provideConfig(
- () => initialize(
- textDocumentCapabilities: withCompletionItemSnippetSupport(
- emptyTextDocumentClientCapabilities),
- workspaceCapabilities: withApplyEditSupport(
- withConfigurationSupport(emptyWorkspaceClientCapabilities)),
- ),
- {'completeFunctionCalls': true},
- );
- await openFile(mainFileUri, withoutMarkers(content));
- await initialAnalysis;
-
- final res = await getCompletion(mainFileUri, positionFromMarker(content));
- final item = res.singleWhere((c) => c.label == 'myFunction(…)');
- // Ensure the snippet comes through in the expected format with the expected
- // placeholders.
- expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
- expect(item.insertText, equals(r'myFunction(${1:a}, ${2:b}, c: ${3:c})'));
- expect(item.textEdit, isNull);
-
- // Ensure the item can be resolved and gets a proper TextEdit.
- final resolved = await resolveCompletion(item);
- expect(resolved.textEdit, isNotNull);
- final textEdit = toTextEdit(resolved.textEdit!);
- expect(textEdit.newText, equals(item.insertText));
- expect(textEdit.range, equals(rangeFromMarkers(content)));
- }
-
- Future<void> test_nullableTypes() async {
- final content = '''
- String? foo(int? a, [int b = 1]) {}
-
- void f() {
- fo^
- }
- ''';
-
- final initialAnalysis = waitForAnalysisComplete();
- await initialize();
- await openFile(mainFileUri, withoutMarkers(content));
- await initialAnalysis;
- final res = await getCompletion(mainFileUri, positionFromMarker(content));
-
- final completion = res.singleWhere((c) => c.label.startsWith('foo'));
- expect(completion.detail, '(int? a, [int b = 1]) → String?');
- }
-}
-
-@reflectiveTest
class DartSnippetCompletionTest extends SnippetCompletionTest {
Future<void> test_snippets_class() async {
final content = '''
@@ -2796,18 +2788,17 @@
class FlutterSnippetCompletionTest extends SnippetCompletionTest {
/// Standard import statements expected for basic Widgets.
String get expectedImports => '''
-import 'package:flutter/src/foundation/key.dart';
import 'package:flutter/src/widgets/framework.dart';''';
/// Nullability suffix expected in this test class.
///
/// Used to allow all tests to be run in both modes without having to
- /// duplicate all tests ([FlutterSnippetCompletionWithLatestLanguageVersionTest]
+ /// duplicate all tests ([FlutterSnippetCompletionWithoutNullSafetyTest]
/// overrides this).
- String get expectedNullableSuffix => '';
+ String get expectedNullableSuffix => '?';
/// Constructor params expected on Widget classes.
- String get expectedWidgetConstructorParams => '({Key key}) : super(key: key)';
+ String get expectedWidgetConstructorParams => '({super.key})';
@override
void setUp() {
@@ -3069,20 +3060,21 @@
}
@reflectiveTest
-class FlutterSnippetCompletionWithLatestLanguageVersionTest
+class FlutterSnippetCompletionWithoutNullSafetyTest
extends FlutterSnippetCompletionTest {
@override
String get expectedImports => '''
+import 'package:flutter/src/foundation/key.dart';
import 'package:flutter/src/widgets/framework.dart';''';
@override
- String get expectedNullableSuffix => '?';
+ String get expectedNullableSuffix => '';
@override
- String get expectedWidgetConstructorParams => '({super.key})';
+ String get expectedWidgetConstructorParams => '({Key key}) : super(key: key)';
@override
- String get testPackageLanguageVersion => latestLanguageVersion;
+ String get testPackageLanguageVersion => '2.9';
}
abstract class SnippetCompletionTest extends AbstractLspAnalysisServerTest
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index 3a7f8e0..e93fe89d 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -128,7 +128,7 @@
newFile2(mainFilePath, '''
void f() {
x = 0;
- int x;
+ int? x;
print(x);
}
''');
@@ -174,7 +174,7 @@
Future<void> test_diagnosticTag_deprecated() async {
newFile2(mainFilePath, '''
@deprecated
- int dep;
+ int? dep;
void main() => print(dep);
''');
@@ -193,7 +193,7 @@
Future<void> test_diagnosticTag_notSupported() async {
newFile2(mainFilePath, '''
@deprecated
- int dep;
+ int? dep;
void main() => print(dep);
''');
diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart
index 9ac1ce2..967e185 100644
--- a/pkg/analysis_server/test/lsp/hover_test.dart
+++ b/pkg/analysis_server/test/lsp/hover_test.dart
@@ -13,7 +13,6 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(HoverTest);
- defineReflectiveTests(HoverWithNullSafetyTest);
});
}
@@ -139,6 +138,29 @@
expect(hover, isNull);
}
+ Future<void> test_nullableTypes() async {
+ final content = '''
+ String? [[a^bc]];
+ ''';
+
+ final expectedHoverContent = '''
+```dart
+String? abc
+```
+Type: `String?`
+*package:test/main.dart*
+ '''
+ .trim();
+
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content));
+ final hover = await getHover(mainFileUri, positionFromMarker(content));
+ expect(hover, isNotNull);
+ expect(hover!.range, equals(rangeFromMarkers(content)));
+ expect(hover.contents, isNotNull);
+ expect(_getStringContents(hover), equals(expectedHoverContent));
+ }
+
Future<void> test_plainText_simple() async {
final content = '''
/// This is a string.
@@ -340,32 +362,3 @@
);
}
}
-
-@reflectiveTest
-class HoverWithNullSafetyTest extends HoverTest {
- @override
- String get testPackageLanguageVersion => latestLanguageVersion;
-
- Future<void> test_nullableTypes() async {
- final content = '''
- String? [[a^bc]];
- ''';
-
- final expectedHoverContent = '''
-```dart
-String? abc
-```
-Type: `String?`
-*package:test/main.dart*
- '''
- .trim();
-
- await initialize();
- await openFile(mainFileUri, withoutMarkers(content));
- final hover = await getHover(mainFileUri, positionFromMarker(content));
- expect(hover, isNotNull);
- expect(hover!.range, equals(rangeFromMarkers(content)));
- expect(hover.contents, isNotNull);
- expect(_getStringContents(hover), equals(expectedHoverContent));
- }
-}
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 0873411..bb5e2d7 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -561,7 +561,7 @@
'${ExperimentStatus.currentVersion.major}.'
'${ExperimentStatus.currentVersion.minor}';
- String get testPackageLanguageVersion => '2.9';
+ String get testPackageLanguageVersion => latestLanguageVersion;
void writePackageConfig(
String projectFolderPath, {
diff --git a/pkg/analysis_server/test/lsp/signature_help_test.dart b/pkg/analysis_server/test/lsp/signature_help_test.dart
index 17ffa43..9a59150 100644
--- a/pkg/analysis_server/test/lsp/signature_help_test.dart
+++ b/pkg/analysis_server/test/lsp/signature_help_test.dart
@@ -11,7 +11,6 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(SignatureHelpTest);
- defineReflectiveTests(SignatureHelpWithNullSafetyTest);
});
}
@@ -411,6 +410,34 @@
);
}
+ Future<void> test_params_requiredNamed() async {
+ // This test requires support for the "required" keyword.
+ final content = '''
+ /// Does foo.
+ foo(String s, {bool? b = true, required bool a}) {
+ foo(^);
+ }
+ ''';
+
+ final expectedLabel = 'foo(String s, {bool? b = true, required bool a})';
+ final expectedDoc = 'Does foo.';
+
+ await initialize(
+ textDocumentCapabilities: withSignatureHelpContentFormat(
+ emptyTextDocumentClientCapabilities, [MarkupKind.Markdown]));
+ await openFile(mainFileUri, withoutMarkers(content));
+ await testSignature(
+ content,
+ expectedLabel,
+ expectedDoc,
+ [
+ ParameterInformation(label: 'String s'),
+ ParameterInformation(label: 'bool? b = true'),
+ ParameterInformation(label: 'required bool a'),
+ ],
+ );
+ }
+
Future<void> test_simple() async {
final content = '''
/// Does foo.
@@ -597,38 +624,3 @@
);
}
}
-
-@reflectiveTest
-class SignatureHelpWithNullSafetyTest extends AbstractLspAnalysisServerTest
- with SignatureHelpMixin {
- @override
- String get testPackageLanguageVersion => latestLanguageVersion;
-
- Future<void> test_params_requiredNamed() async {
- // This test requires support for the "required" keyword.
- final content = '''
- /// Does foo.
- foo(String s, {bool? b = true, required bool a}) {
- foo(^);
- }
- ''';
-
- final expectedLabel = 'foo(String s, {bool? b = true, required bool a})';
- final expectedDoc = 'Does foo.';
-
- await initialize(
- textDocumentCapabilities: withSignatureHelpContentFormat(
- emptyTextDocumentClientCapabilities, [MarkupKind.Markdown]));
- await openFile(mainFileUri, withoutMarkers(content));
- await testSignature(
- content,
- expectedLabel,
- expectedDoc,
- [
- ParameterInformation(label: 'String s'),
- ParameterInformation(label: 'bool? b = true'),
- ParameterInformation(label: 'required bool a'),
- ],
- );
- }
-}
diff --git a/pkg/analysis_server/test/search/abstract_search_domain.dart b/pkg/analysis_server/test/search/abstract_search_domain.dart
index 15cba77..85ffa59 100644
--- a/pkg/analysis_server/test/search/abstract_search_domain.dart
+++ b/pkg/analysis_server/test/search/abstract_search_domain.dart
@@ -5,13 +5,13 @@
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/search/search_domain.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import '../analysis_abstract.dart';
+import '../analysis_server_base.dart';
-class AbstractSearchDomainTest extends AbstractAnalysisTest {
+class AbstractSearchDomainTest extends PubPackageAnalysisServerTest {
final Map<String, _ResultSet> resultSets = {};
String? searchId;
List<SearchResult> results = <SearchResult>[];
@@ -20,13 +20,13 @@
void assertHasResult(SearchResultKind kind, String search, [int? length]) {
var offset = findOffset(search);
length ??= findIdentifierLength(search);
- findResult(kind, testFile, offset, length, true);
+ findResult(kind, testFile.path, offset, length, true);
}
void assertNoResult(SearchResultKind kind, String search, [int? length]) {
var offset = findOffset(search);
length ??= findIdentifierLength(search);
- findResult(kind, testFile, offset, length, false);
+ findResult(kind, testFile.path, offset, length, false);
}
void findResult(SearchResultKind kind, String file, int offset, int length,
@@ -81,10 +81,7 @@
@override
Future<void> setUp() async {
super.setUp();
- await createProject();
- server.handlers = [
- SearchDomainHandler(server),
- ];
+ await setRoots(included: [workspaceRootPath], excluded: []);
}
Future waitForSearchResults() {
diff --git a/pkg/analysis_server/test/search/declarations_test.dart b/pkg/analysis_server/test/search/declarations_test.dart
index c5f71ad..1fc44a1 100644
--- a/pkg/analysis_server/test/search/declarations_test.dart
+++ b/pkg/analysis_server/test/search/declarations_test.dart
@@ -22,7 +22,7 @@
ElementDeclaration assertHas(String name, ElementKind kind,
{String? className, String? mixinName}) {
return declarationsResult.declarations.singleWhere((ElementDeclaration d) =>
- declarationsResult.files[d.fileIndex] == testFile &&
+ declarationsResult.files[d.fileIndex] == testFile.path &&
d.name == name &&
d.kind == kind &&
d.className == className &&
@@ -33,7 +33,7 @@
expect(
declarationsResult.declarations,
isNot(contains(predicate((ElementDeclaration d) =>
- declarationsResult.files[d.fileIndex] == testFile &&
+ declarationsResult.files[d.fileIndex] == testFile.path &&
d.name == name))));
}
@@ -83,11 +83,11 @@
}
Future<void> test_maxResults() async {
- newFile2(join(testFolder, 'a.dart'), r'''
+ newFile2('$testPackageLibPath/a.dart', r'''
class A {}
class B {}
''').path;
- newFile2(join(testFolder, 'b.dart'), r'''
+ newFile2('$testPackageLibPath/b.dart', r'''
class C {}
class D {}
''').path;
@@ -124,8 +124,8 @@
}
Future<void> test_multipleFiles() async {
- var a = newFile2(join(testFolder, 'a.dart'), 'class A {}').path;
- var b = newFile2(join(testFolder, 'b.dart'), 'class B {}').path;
+ var a = newFile2('$testPackageLibPath/a.dart', 'class A {}').path;
+ var b = newFile2('$testPackageLibPath/b.dart', 'class B {}').path;
await _getDeclarations();
@@ -153,8 +153,8 @@
}
Future<void> test_onlyForFile() async {
- var a = newFile2(join(testFolder, 'a.dart'), 'class A {}').path;
- newFile2(join(testFolder, 'b.dart'), 'class B {}').path;
+ var a = newFile2('$testPackageLibPath/a.dart', 'class A {}').path;
+ newFile2('$testPackageLibPath/b.dart', 'class B {}').path;
await _getDeclarations(file: a);
@@ -218,7 +218,7 @@
var request = SearchGetElementDeclarationsParams(
file: file, pattern: pattern, maxResults: maxResults)
.toRequest('0');
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
declarationsResult =
SearchGetElementDeclarationsResult.fromResponse(response);
diff --git a/pkg/analysis_server/test/search/element_references_test.dart b/pkg/analysis_server/test/search/element_references_test.dart
index 2902a26..de8f23e 100644
--- a/pkg/analysis_server/test/search/element_references_test.dart
+++ b/pkg/analysis_server/test/search/element_references_test.dart
@@ -28,10 +28,10 @@
String search, bool includePotential) async {
var offset = findOffset(search);
await waitForTasksFinished();
- var request =
- SearchFindElementReferencesParams(testFile, offset, includePotential)
- .toRequest('0');
- var response = await waitResponse(request);
+ var request = SearchFindElementReferencesParams(
+ testFile.path, offset, includePotential)
+ .toRequest('0');
+ var response = await handleSuccessfulRequest(request);
var result = SearchFindElementReferencesResult.fromResponse(response);
searchId = result.id;
searchElement = result.element;
diff --git a/pkg/analysis_server/test/search/member_declarations_test.dart b/pkg/analysis_server/test/search/member_declarations_test.dart
index 42be69a..9d4a783 100644
--- a/pkg/analysis_server/test/search/member_declarations_test.dart
+++ b/pkg/analysis_server/test/search/member_declarations_test.dart
@@ -28,7 +28,7 @@
Future findMemberDeclarations(String name) async {
await waitForTasksFinished();
var request = SearchFindMemberDeclarationsParams(name).toRequest('0');
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
var result = SearchFindMemberDeclarationsResult.fromResponse(response);
searchId = result.id;
return waitForSearchResults();
diff --git a/pkg/analysis_server/test/search/member_references_test.dart b/pkg/analysis_server/test/search/member_references_test.dart
index b5df9ae..a3a5d94 100644
--- a/pkg/analysis_server/test/search/member_references_test.dart
+++ b/pkg/analysis_server/test/search/member_references_test.dart
@@ -24,7 +24,7 @@
Future findMemberReferences(String name) async {
await waitForTasksFinished();
var request = SearchFindMemberReferencesParams(name).toRequest('0');
- var response = await waitResponse(request);
+ var response = await handleSuccessfulRequest(request);
searchId = SearchFindMemberReferencesResult.fromResponse(response).id;
return waitForSearchResults();
}
diff --git a/pkg/analysis_server/test/search/top_level_declarations_test.dart b/pkg/analysis_server/test/search/top_level_declarations_test.dart
index 6fd2959..c6d28b3 100644
--- a/pkg/analysis_server/test/search/top_level_declarations_test.dart
+++ b/pkg/analysis_server/test/search/top_level_declarations_test.dart
@@ -35,7 +35,7 @@
Future findTopLevelDeclarations(String pattern) async {
await waitForTasksFinished();
var request = SearchFindTopLevelDeclarationsParams(pattern).toRequest('0');
- var response = await waitResponse(request);
+ var response = await handleRequest(request);
if (response.error != null) {
return response.error;
}
diff --git a/pkg/analysis_server/test/search/type_hierarchy_test.dart b/pkg/analysis_server/test/search/type_hierarchy_test.dart
index 589e9a5..296fb20 100644
--- a/pkg/analysis_server/test/search/type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/search/type_hierarchy_test.dart
@@ -4,13 +4,11 @@
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
-import 'package:analysis_server/src/domain_analysis.dart';
-import 'package:analysis_server/src/search/search_domain.dart';
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../analysis_abstract.dart';
+import '../analysis_server_base.dart';
void main() {
defineReflectiveSuite(() {
@@ -19,17 +17,13 @@
}
@reflectiveTest
-class GetTypeHierarchyTest extends AbstractAnalysisTest {
+class GetTypeHierarchyTest extends PubPackageAnalysisServerTest {
static const String requestId = 'test-getTypeHierarchy';
@override
Future<void> setUp() async {
super.setUp();
- await createProject();
- server.handlers = [
- AnalysisDomainHandler(server),
- SearchDomainHandler(server),
- ];
+ await setRoots(included: [workspaceRootPath], excluded: []);
}
Future<void> test_bad_function() async {
@@ -164,22 +158,22 @@
Future<void> test_class_extends_fileAndPackageUris() async {
// prepare packages
- newFile2('/packages/pkgA/lib/libA.dart', '''
+ newFile2('$packagesRootPath/pkgA/lib/libA.dart', '''
library lib_a;
class A {}
class B extends A {}
''');
newPackageConfigJsonFile(
- '/packages/pkgA',
+ '$packagesRootPath/pkgA',
(PackageConfigFileBuilder()
- ..add(name: 'pkgA', rootPath: '/packages/pkgA'))
+ ..add(name: 'pkgA', rootPath: '$packagesRootPath/pkgA'))
.toContent(toUriStr: toUriStr),
);
// reference the package from a project
newPackageConfigJsonFile(
- projectPath,
+ testPackageRootPath,
(PackageConfigFileBuilder()
- ..add(name: 'pkgA', rootPath: '/packages/pkgA'))
+ ..add(name: 'pkgA', rootPath: '$packagesRootPath/pkgA'))
.toContent(toUriStr: toUriStr),
);
addTestFile('''
@@ -189,7 +183,9 @@
await waitForTasksFinished();
// configure roots
await setRoots(
- included: [projectPath, convertPath('/packages/pkgA')], excluded: []);
+ included: [workspaceRootPath, '$packagesRootPath/pkgA'],
+ excluded: [],
+ );
// test A type hierarchy
var items = await _getTypeHierarchy('A {}');
var names = _toClassNames(items);
@@ -652,7 +648,7 @@
}
Future<void> test_class_member_method_private_differentLib() async {
- newFile2(join(testFolder, 'lib.dart'), r'''
+ newFile2('$testPackageLibPath/lib.dart', r'''
import 'test.dart';
class A {
void _m() {}
@@ -1473,7 +1469,7 @@
}
Request _createGetTypeHierarchyRequest(String search, {bool? superOnly}) {
- return SearchGetTypeHierarchyParams(testFile, findOffset(search),
+ return SearchGetTypeHierarchyParams(testFile.path, findOffset(search),
superOnly: superOnly)
.toRequest(requestId);
}
diff --git a/pkg/analysis_server/test/src/domains/flutter/base.dart b/pkg/analysis_server/test/src/domains/flutter/base.dart
index 39d724f..ab24425 100644
--- a/pkg/analysis_server/test/src/domains/flutter/base.dart
+++ b/pkg/analysis_server/test/src/domains/flutter/base.dart
@@ -2,17 +2,16 @@
// 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/flutter/flutter_domain.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../../../analysis_abstract.dart';
+import '../../../analysis_server_base.dart';
import '../../utilities/mock_packages.dart';
@reflectiveTest
-class FlutterBase extends AbstractAnalysisTest {
+class FlutterBase extends PubPackageAnalysisServerTest {
FlutterWidgetProperty getProperty(
FlutterGetWidgetDescriptionResult result,
String name,
@@ -32,32 +31,29 @@
Future<Response> getWidgetDescriptionResponse(String search) async {
var request = FlutterGetWidgetDescriptionParams(
- testFile,
+ testFile.path,
findOffset(search),
).toRequest('0');
- return await waitResponse(request);
+ return await handleRequest(request);
}
@override
Future<void> setUp() async {
super.setUp();
- projectPath = convertPath('/home');
- testFile = convertPath('/home/test/lib/test.dart');
- newPubspecYamlFile('/home/test', '');
+ newPubspecYamlFile(testPackageRootPath, '');
var metaLib = MockPackages.instance.addMeta(resourceProvider);
var flutterLib = MockPackages.instance.addFlutter(resourceProvider);
newPackageConfigJsonFile(
'/home/test',
(PackageConfigFileBuilder()
- ..add(name: 'test', rootPath: '/home/test')
+ ..add(name: 'test', rootPath: testPackageRootPath)
..add(name: 'meta', rootPath: metaLib.parent.path)
..add(name: 'flutter', rootPath: flutterLib.parent.path))
.toContent(toUriStr: toUriStr),
);
- await createProject();
- handler = server.handlers.whereType<FlutterDomainHandler>().single;
+ await setRoots(included: [workspaceRootPath], excluded: []);
}
}
diff --git a/pkg/analysis_server/test/src/domains/flutter/get_widget_description_test.dart b/pkg/analysis_server/test/src/domains/flutter/get_widget_description_test.dart
index 39baacd..b926395 100644
--- a/pkg/analysis_server/test/src/domains/flutter/get_widget_description_test.dart
+++ b/pkg/analysis_server/test/src/domains/flutter/get_widget_description_test.dart
@@ -43,9 +43,10 @@
''');
var response = await getWidgetDescriptionResponse('42');
- expect(
- response.error!.code,
- RequestErrorCode.FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET,
+ assertResponseFailure(
+ response,
+ requestId: '0',
+ errorCode: RequestErrorCode.FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET,
);
}
@@ -57,9 +58,10 @@
''');
var response = await getWidgetDescriptionResponse('new Foo');
- expect(
- response.error!.code,
- RequestErrorCode.FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET,
+ assertResponseFailure(
+ response,
+ requestId: '0',
+ errorCode: RequestErrorCode.FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET,
);
}
}
diff --git a/pkg/analysis_server/test/src/domains/flutter/set_property_value_test.dart b/pkg/analysis_server/test/src/domains/flutter/set_property_value_test.dart
index 56a8c90..af74a41 100644
--- a/pkg/analysis_server/test/src/domains/flutter/set_property_value_test.dart
+++ b/pkg/analysis_server/test/src/domains/flutter/set_property_value_test.dart
@@ -125,10 +125,10 @@
expect(fileEdits, hasLength(1));
var fileEdit = fileEdits[0];
- expect(fileEdit.file, testFile);
+ expect(fileEdit.file, testFile.path);
var edits = fileEdit.edits;
- expect(SourceEdit.applySequence(testCode, edits), expected);
+ expect(SourceEdit.applySequence(testFileContent, edits), expected);
}
Future<FlutterSetWidgetPropertyValueResult> _setValue(
@@ -148,6 +148,6 @@
property.id,
value: value,
).toRequest('0');
- return await waitResponse(request);
+ return await handleSuccessfulRequest(request);
}
}
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart
index 96c2b66..cd23e2a 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart
@@ -7,13 +7,12 @@
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/flutter/flutter_domain.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../../analysis_abstract.dart';
+import '../../analysis_server_base.dart';
import '../utilities/mock_packages.dart';
void main() {
@@ -23,42 +22,31 @@
}
@reflectiveTest
-class FlutterNotificationOutlineTest extends AbstractAnalysisTest {
+class FlutterNotificationOutlineTest extends PubPackageAnalysisServerTest {
late Folder flutterFolder;
- final Map<FlutterService, List<String>> flutterSubscriptions = {};
-
final Completer<void> _outlineReceived = Completer();
late FlutterOutline outline;
- FlutterDomainHandler get flutterHandler =>
- server.handlers.singleWhere((handler) => handler is FlutterDomainHandler)
- as FlutterDomainHandler;
-
- void addFlutterSubscription(FlutterService service, String file) {
- // add file to subscription
- var files = analysisSubscriptions[service];
- if (files == null) {
- files = <String>[];
- flutterSubscriptions[service] = files;
- }
- files.add(file);
- // set subscriptions
- var request =
- FlutterSetSubscriptionsParams(flutterSubscriptions).toRequest('0');
- handleSuccessfulRequest(request, handler: flutterHandler);
+ Future<void> addFlutterSubscription(FlutterService service, File file) async {
+ await handleSuccessfulRequest(
+ FlutterSetSubscriptionsParams({
+ service: [file.path],
+ }).toRequest('0'),
+ );
}
- Future prepareOutline() {
- addFlutterSubscription(FlutterService.OUTLINE, testFile);
+ Future<void> prepareOutline() async {
+ await addFlutterSubscription(FlutterService.OUTLINE, testFile);
return _outlineReceived.future;
}
@override
void processNotification(Notification notification) {
+ super.processNotification(notification);
if (notification.event == FLUTTER_NOTIFICATION_OUTLINE) {
var params = FlutterOutlineParams.fromNotification(notification);
- if (params.file == testFile) {
+ if (params.file == testFile.path) {
outline = params.outline;
_outlineReceived.complete();
}
@@ -68,18 +56,18 @@
@override
Future<void> setUp() async {
super.setUp();
- await createProject();
+ await setRoots(included: [workspaceRootPath], excluded: []);
flutterFolder = MockPackages.instance.addFlutter(resourceProvider);
}
Future<void> test_children() async {
newPackageConfigJsonFile(
- projectPath,
+ testPackageRootPath,
(PackageConfigFileBuilder()
..add(name: 'flutter', rootPath: flutterFolder.parent.path))
.toContent(toUriStr: toUriStr),
);
- newAnalysisOptionsYamlFile2(projectPath, '''
+ newAnalysisOptionsYamlFile2(testPackageRootPath, '''
analyzer:
strong-mode: true
''');
diff --git a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
index 8b99bb3..1edef57 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
@@ -318,8 +318,7 @@
}
Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
_createTearOffBody(tearOff, target, arguments);
- return new DelayedDefaultValueCloner(
- substitutionMap, target.function!, tearOff.function,
+ return new DelayedDefaultValueCloner(target, tearOff, substitutionMap,
identicalSignatures: false, libraryBuilder: libraryBuilder);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
index 42c969f..75a94cf 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
@@ -26,11 +26,11 @@
// variable types in default values be a compile time error?
final Map<TypeParameter, DartType> _typeSubstitution;
- /// The original function node.
- final FunctionNode _original;
+ /// The original constructor or procedure.
+ final Member original;
- /// The synthesized function node.
- final FunctionNode _synthesized;
+ /// The synthesized constructor or procedure.
+ final Member synthesized;
/// If `true`, the [_synthesized] is guaranteed to have the same parameters in
/// the same order as [_original]. Otherwise [_original] is only guaranteed to
@@ -49,8 +49,12 @@
CloneVisitorNotMembers? _cloner;
+ /// Set to `true` we default values have been cloned, ensuring that cloning
+ /// isn't performed twice.
+ bool _hasCloned = false;
+
DelayedDefaultValueCloner(
- this._typeSubstitution, this._original, this._synthesized,
+ this.original, this.synthesized, this._typeSubstitution,
{this.identicalSignatures: true,
List<int?>? positionalSuperParameters: null,
List<String>? namedSuperParameters: null,
@@ -88,10 +92,12 @@
// same order as the named parameters of [_synthesized].
int superParameterIndex = 0;
for (int namedParameterIndex = 0;
- namedParameterIndex < _synthesized.namedParameters.length &&
+ namedParameterIndex <
+ synthesized.function!.namedParameters.length &&
superParameterIndex < namedSuperParameters.length;
namedParameterIndex++) {
- if (_synthesized.namedParameters[namedParameterIndex].name ==
+ if (synthesized
+ .function!.namedParameters[namedParameterIndex].name ==
namedSuperParameters[superParameterIndex]) {
++superParameterIndex;
}
@@ -100,6 +106,8 @@
}());
void cloneDefaultValues(TypeEnvironment typeEnvironment) {
+ if (_hasCloned) return;
+
// TODO(ahe): It is unclear if it is legal to use type variables in
// default values, but Fasta is currently allowing it, and the VM
// accepts it. If it isn't legal, the we can speed this up by using a
@@ -110,6 +118,9 @@
// can be less than that of the redirection target or, in errors cases, be
// unrelated.
+ FunctionNode _original = original.function!;
+ FunctionNode _synthesized = synthesized.function!;
+
if (identicalSignatures) {
assert(_positionalSuperParameters != null ||
_synthesized.positionalParameters.length ==
@@ -199,6 +210,7 @@
}
}
}
+ _hasCloned = true;
}
void _cloneInitializer(VariableDeclaration originalParameter,
@@ -215,10 +227,9 @@
VariableDeclaration originalParameter,
VariableDeclaration synthesizedParameter,
TypeEnvironment typeEnvironment) {
- Member member = _synthesized.parent as Member;
Expression? originalParameterInitializer = originalParameter.initializer;
DartType? originalParameterInitializerType = originalParameterInitializer
- ?.getStaticType(new StaticTypeContext(member, typeEnvironment));
+ ?.getStaticType(new StaticTypeContext(synthesized, typeEnvironment));
DartType synthesizedParameterType = synthesizedParameter.type;
if (originalParameterInitializerType != null &&
typeEnvironment.isSubtypeOf(originalParameterInitializerType,
@@ -241,8 +252,8 @@
@override
String toString() {
- return "DelayedDefaultValueCloner(original=${_original.parent}, "
- "synthesized=${_synthesized.parent})";
+ return "DelayedDefaultValueCloner(original=${original}, "
+ "synthesized=${synthesized})";
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 0e6687b..c8f0d25 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -139,8 +139,7 @@
final bool errorOnUnevaluatedConstant =
CompilerContext.current.options.errorOnUnevaluatedConstant;
- final List<DelayedDefaultValueCloner> _delayedDefaultValueCloners =
- <DelayedDefaultValueCloner>[];
+ final Map<Member, DelayedDefaultValueCloner> _delayedDefaultValueCloners = {};
final UriTranslator uriTranslator;
@@ -544,8 +543,11 @@
loader.checkMixins(sourceClassBuilders);
benchmarker?.enterPhase(BenchmarkPhases.outline_buildOutlineExpressions);
+ // TODO(johnniwinther): Add an interface for registering delayed actions.
+ List<DelayedDefaultValueCloner> delayedDefaultValueCloners = [];
loader.buildOutlineExpressions(
- loader.hierarchy, _delayedDefaultValueCloners);
+ loader.hierarchy, delayedDefaultValueCloners);
+ delayedDefaultValueCloners.forEach(registerDelayedDefaultValueCloner);
benchmarker?.enterPhase(BenchmarkPhases.outline_checkTypes);
loader.checkTypes();
@@ -1048,19 +1050,6 @@
returnType: makeConstructorReturnType(cls));
SuperInitializer initializer = new SuperInitializer(
superConstructor, new Arguments(positional, named: named));
- DelayedDefaultValueCloner delayedDefaultValueCloner =
- new DelayedDefaultValueCloner(
- substitutionMap, superConstructor.function, function,
- libraryBuilder: classBuilder.libraryBuilder);
- if (!isConst) {
- // For constant constructors default values are computed and cloned part
- // of the outline expression and therefore passed to the
- // [SyntheticConstructorBuilder] below.
- //
- // For non-constant constructors default values are cloned as part of the
- // full compilation using [_delayedDefaultValueCloners].
- _delayedDefaultValueCloners.add(delayedDefaultValueCloner);
- }
Constructor constructor = new Constructor(function,
name: superConstructor.name,
initializers: <Initializer>[initializer],
@@ -1073,6 +1062,19 @@
//..fileOffset = cls.fileOffset
//..fileEndOffset = cls.fileOffset
..isNonNullableByDefault = cls.enclosingLibrary.isNonNullableByDefault;
+ DelayedDefaultValueCloner delayedDefaultValueCloner =
+ new DelayedDefaultValueCloner(
+ superConstructor, constructor, substitutionMap,
+ libraryBuilder: classBuilder.libraryBuilder);
+ if (!isConst) {
+ // For constant constructors default values are computed and cloned part
+ // of the outline expression and therefore passed to the
+ // [SyntheticConstructorBuilder] below.
+ //
+ // For non-constant constructors default values are cloned as part of the
+ // full compilation using [_delayedDefaultValueCloners].
+ registerDelayedDefaultValueCloner(delayedDefaultValueCloner);
+ }
TypeDependency? typeDependency;
if (hasTypeDependency) {
@@ -1109,11 +1111,30 @@
return constructorBuilder;
}
+ void registerDelayedDefaultValueCloner(DelayedDefaultValueCloner cloner) {
+ // TODO(johnniwinther): Avoid re-registration of cloners.
+ assert(
+ !_delayedDefaultValueCloners.containsKey(cloner.synthesized) ||
+ _delayedDefaultValueCloners[cloner.synthesized] == cloner,
+ "Default cloner already registered for ${cloner.synthesized}.");
+ _delayedDefaultValueCloners[cloner.synthesized] = cloner;
+ }
+
void finishSynthesizedParameters({bool forOutline = false}) {
+ void cloneDefaultValues(
+ DelayedDefaultValueCloner delayedDefaultValueCloner) {
+ DelayedDefaultValueCloner? originalCloner =
+ _delayedDefaultValueCloners[delayedDefaultValueCloner.original];
+ if (originalCloner != null) {
+ cloneDefaultValues(originalCloner);
+ }
+ delayedDefaultValueCloner.cloneDefaultValues(loader.typeEnvironment);
+ }
+
for (DelayedDefaultValueCloner delayedDefaultValueCloner
- in _delayedDefaultValueCloners) {
+ in _delayedDefaultValueCloners.values) {
if (!forOutline || delayedDefaultValueCloner.isOutlineNode) {
- delayedDefaultValueCloner.cloneDefaultValues(loader.typeEnvironment);
+ cloneDefaultValues(delayedDefaultValueCloner);
}
}
if (!forOutline) {
diff --git a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
index 7f77622..3aa7702 100644
--- a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
@@ -426,7 +426,7 @@
if (positionalSuperParameters != null || namedSuperParameters != null) {
delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
- substitution, superTarget.function, constructor.function,
+ superTarget, constructor, substitution,
positionalSuperParameters: positionalSuperParameters ?? const <int>[],
namedSuperParameters: namedSuperParameters ?? const <String>[],
isOutlineNode: true,
diff --git a/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart b/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
index b7ab94d..cef67f3 100644
--- a/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
@@ -503,7 +503,7 @@
(int index) => const DynamicType()));
}
delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
- substitutionMap, target!.function!, function,
+ target!, _procedure, substitutionMap,
libraryBuilder: libraryBuilder, identicalSignatures: false));
}
if (isConst && isPatch) {
diff --git a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
index f6fd8b7..720a1b4 100644
--- a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
@@ -251,10 +251,10 @@
_tearOffDependencies?.forEach((Procedure tearOff, Member target) {
InterfaceType targetType = typedef.type as InterfaceType;
delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
+ target,
+ tearOff,
new Map<TypeParameter, DartType>.fromIterables(
target.enclosingClass!.typeParameters, targetType.typeArguments),
- target.function!,
- tearOff.function,
libraryBuilder: libraryBuilder));
});
}
diff --git a/pkg/front_end/testcases/super_parameters/issue48708.dart.strong.expect b/pkg/front_end/testcases/super_parameters/issue48708.dart.strong.expect
index 05ade25..bbbaeed 100644
--- a/pkg/front_end/testcases/super_parameters/issue48708.dart.strong.expect
+++ b/pkg/front_end/testcases/super_parameters/issue48708.dart.strong.expect
@@ -19,7 +19,7 @@
;
}
abstract class _C&B&Mixin = self::B<self::A> with self::Mixin /*isAnonymousMixin*/ {
- synthetic constructor •({self::A field = #C1}) → self::_C&B&Mixin
+ synthetic constructor •({self::A field}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}
diff --git a/pkg/front_end/testcases/super_parameters/issue48708.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/issue48708.dart.strong.transformed.expect
index f71d862..1acdeb6 100644
--- a/pkg/front_end/testcases/super_parameters/issue48708.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/super_parameters/issue48708.dart.strong.transformed.expect
@@ -19,7 +19,7 @@
;
}
abstract class _C&B&Mixin extends self::B<self::A> implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/ {
- synthetic constructor •({self::A field = #C1}) → self::_C&B&Mixin
+ synthetic constructor •({self::A field}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}
diff --git a/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.expect b/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.expect
index 05ade25..bbbaeed 100644
--- a/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.expect
+++ b/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.expect
@@ -19,7 +19,7 @@
;
}
abstract class _C&B&Mixin = self::B<self::A> with self::Mixin /*isAnonymousMixin*/ {
- synthetic constructor •({self::A field = #C1}) → self::_C&B&Mixin
+ synthetic constructor •({self::A field}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}
diff --git a/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.modular.expect
index 05ade25..bbbaeed 100644
--- a/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.modular.expect
@@ -19,7 +19,7 @@
;
}
abstract class _C&B&Mixin = self::B<self::A> with self::Mixin /*isAnonymousMixin*/ {
- synthetic constructor •({self::A field = #C1}) → self::_C&B&Mixin
+ synthetic constructor •({self::A field}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}
diff --git a/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.transformed.expect
index f71d862..1acdeb6 100644
--- a/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/super_parameters/issue48708.dart.weak.transformed.expect
@@ -19,7 +19,7 @@
;
}
abstract class _C&B&Mixin extends self::B<self::A> implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/ {
- synthetic constructor •({self::A field = #C1}) → self::_C&B&Mixin
+ synthetic constructor •({self::A field}) → self::_C&B&Mixin
: super self::B::•(field: field)
;
}
diff --git a/pkg/front_end/testcases/super_parameters/issue48769.dart b/pkg/front_end/testcases/super_parameters/issue48769.dart
new file mode 100644
index 0000000..8ebe2e2
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48769.dart
@@ -0,0 +1,31 @@
+class NumProperty extends DiagnosticsProperty {
+ NumProperty({
+ super.showName,
+ });
+
+ NumProperty.lazy({
+ super.showName,
+ }) : super.lazy();
+}
+
+class DiagnosticsProperty extends DiagnosticsNode {
+ DiagnosticsProperty({
+ super.showName,
+ });
+
+ DiagnosticsProperty.lazy({
+ super.showName,
+ });
+}
+
+abstract class DiagnosticsNode {
+ DiagnosticsNode({
+ this.showName = true,
+ });
+
+ final bool showName;
+}
+
+void main() {
+ print('hello');
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48769.dart.strong.expect b/pkg/front_end/testcases/super_parameters/issue48769.dart.strong.expect
new file mode 100644
index 0000000..f151327
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48769.dart.strong.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class NumProperty extends self::DiagnosticsProperty {
+ constructor •({core::bool showName = #C1}) → self::NumProperty
+ : super self::DiagnosticsProperty::•(showName: showName)
+ ;
+ constructor lazy({core::bool showName = #C1}) → self::NumProperty
+ : super self::DiagnosticsProperty::lazy(showName: showName)
+ ;
+}
+class DiagnosticsProperty extends self::DiagnosticsNode {
+ constructor •({core::bool showName = #C1}) → self::DiagnosticsProperty
+ : super self::DiagnosticsNode::•(showName: showName)
+ ;
+ constructor lazy({core::bool showName = #C1}) → self::DiagnosticsProperty
+ : super self::DiagnosticsNode::•(showName: showName)
+ ;
+}
+abstract class DiagnosticsNode extends core::Object {
+ final field core::bool showName;
+ constructor •({core::bool showName = #C1}) → self::DiagnosticsNode
+ : self::DiagnosticsNode::showName = showName, super core::Object::•()
+ ;
+}
+static method main() → void {
+ core::print("hello");
+}
+
+constants {
+ #C1 = true
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48769.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/issue48769.dart.strong.transformed.expect
new file mode 100644
index 0000000..f151327
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48769.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class NumProperty extends self::DiagnosticsProperty {
+ constructor •({core::bool showName = #C1}) → self::NumProperty
+ : super self::DiagnosticsProperty::•(showName: showName)
+ ;
+ constructor lazy({core::bool showName = #C1}) → self::NumProperty
+ : super self::DiagnosticsProperty::lazy(showName: showName)
+ ;
+}
+class DiagnosticsProperty extends self::DiagnosticsNode {
+ constructor •({core::bool showName = #C1}) → self::DiagnosticsProperty
+ : super self::DiagnosticsNode::•(showName: showName)
+ ;
+ constructor lazy({core::bool showName = #C1}) → self::DiagnosticsProperty
+ : super self::DiagnosticsNode::•(showName: showName)
+ ;
+}
+abstract class DiagnosticsNode extends core::Object {
+ final field core::bool showName;
+ constructor •({core::bool showName = #C1}) → self::DiagnosticsNode
+ : self::DiagnosticsNode::showName = showName, super core::Object::•()
+ ;
+}
+static method main() → void {
+ core::print("hello");
+}
+
+constants {
+ #C1 = true
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48769.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/issue48769.dart.textual_outline.expect
new file mode 100644
index 0000000..3392cd2
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48769.dart.textual_outline.expect
@@ -0,0 +1,26 @@
+class NumProperty extends DiagnosticsProperty {
+ NumProperty({
+ super.showName,
+ });
+ NumProperty.lazy({
+ super.showName,
+ }) : super.lazy();
+}
+
+class DiagnosticsProperty extends DiagnosticsNode {
+ DiagnosticsProperty({
+ super.showName,
+ });
+ DiagnosticsProperty.lazy({
+ super.showName,
+ });
+}
+
+abstract class DiagnosticsNode {
+ DiagnosticsNode({
+ this.showName = true,
+ });
+ final bool showName;
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48769.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/super_parameters/issue48769.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0b4d826
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48769.dart.textual_outline_modelled.expect
@@ -0,0 +1,26 @@
+abstract class DiagnosticsNode {
+ DiagnosticsNode({
+ this.showName = true,
+ });
+ final bool showName;
+}
+
+class DiagnosticsProperty extends DiagnosticsNode {
+ DiagnosticsProperty({
+ super.showName,
+ });
+ DiagnosticsProperty.lazy({
+ super.showName,
+ });
+}
+
+class NumProperty extends DiagnosticsProperty {
+ NumProperty({
+ super.showName,
+ });
+ NumProperty.lazy({
+ super.showName,
+ }) : super.lazy();
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.expect b/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.expect
new file mode 100644
index 0000000..f151327
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class NumProperty extends self::DiagnosticsProperty {
+ constructor •({core::bool showName = #C1}) → self::NumProperty
+ : super self::DiagnosticsProperty::•(showName: showName)
+ ;
+ constructor lazy({core::bool showName = #C1}) → self::NumProperty
+ : super self::DiagnosticsProperty::lazy(showName: showName)
+ ;
+}
+class DiagnosticsProperty extends self::DiagnosticsNode {
+ constructor •({core::bool showName = #C1}) → self::DiagnosticsProperty
+ : super self::DiagnosticsNode::•(showName: showName)
+ ;
+ constructor lazy({core::bool showName = #C1}) → self::DiagnosticsProperty
+ : super self::DiagnosticsNode::•(showName: showName)
+ ;
+}
+abstract class DiagnosticsNode extends core::Object {
+ final field core::bool showName;
+ constructor •({core::bool showName = #C1}) → self::DiagnosticsNode
+ : self::DiagnosticsNode::showName = showName, super core::Object::•()
+ ;
+}
+static method main() → void {
+ core::print("hello");
+}
+
+constants {
+ #C1 = true
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.modular.expect
new file mode 100644
index 0000000..f151327
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.modular.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class NumProperty extends self::DiagnosticsProperty {
+ constructor •({core::bool showName = #C1}) → self::NumProperty
+ : super self::DiagnosticsProperty::•(showName: showName)
+ ;
+ constructor lazy({core::bool showName = #C1}) → self::NumProperty
+ : super self::DiagnosticsProperty::lazy(showName: showName)
+ ;
+}
+class DiagnosticsProperty extends self::DiagnosticsNode {
+ constructor •({core::bool showName = #C1}) → self::DiagnosticsProperty
+ : super self::DiagnosticsNode::•(showName: showName)
+ ;
+ constructor lazy({core::bool showName = #C1}) → self::DiagnosticsProperty
+ : super self::DiagnosticsNode::•(showName: showName)
+ ;
+}
+abstract class DiagnosticsNode extends core::Object {
+ final field core::bool showName;
+ constructor •({core::bool showName = #C1}) → self::DiagnosticsNode
+ : self::DiagnosticsNode::showName = showName, super core::Object::•()
+ ;
+}
+static method main() → void {
+ core::print("hello");
+}
+
+constants {
+ #C1 = true
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.outline.expect
new file mode 100644
index 0000000..f8249a7
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.outline.expect
@@ -0,0 +1,23 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class NumProperty extends self::DiagnosticsProperty {
+ constructor •({core::bool showName = true}) → self::NumProperty
+ ;
+ constructor lazy({core::bool showName = true}) → self::NumProperty
+ ;
+}
+class DiagnosticsProperty extends self::DiagnosticsNode {
+ constructor •({core::bool showName = true}) → self::DiagnosticsProperty
+ ;
+ constructor lazy({core::bool showName = true}) → self::DiagnosticsProperty
+ ;
+}
+abstract class DiagnosticsNode extends core::Object {
+ final field core::bool showName;
+ constructor •({core::bool showName = true}) → self::DiagnosticsNode
+ ;
+}
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.transformed.expect
new file mode 100644
index 0000000..f151327
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48769.dart.weak.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class NumProperty extends self::DiagnosticsProperty {
+ constructor •({core::bool showName = #C1}) → self::NumProperty
+ : super self::DiagnosticsProperty::•(showName: showName)
+ ;
+ constructor lazy({core::bool showName = #C1}) → self::NumProperty
+ : super self::DiagnosticsProperty::lazy(showName: showName)
+ ;
+}
+class DiagnosticsProperty extends self::DiagnosticsNode {
+ constructor •({core::bool showName = #C1}) → self::DiagnosticsProperty
+ : super self::DiagnosticsNode::•(showName: showName)
+ ;
+ constructor lazy({core::bool showName = #C1}) → self::DiagnosticsProperty
+ : super self::DiagnosticsNode::•(showName: showName)
+ ;
+}
+abstract class DiagnosticsNode extends core::Object {
+ final field core::bool showName;
+ constructor •({core::bool showName = #C1}) → self::DiagnosticsNode
+ : self::DiagnosticsNode::showName = showName, super core::Object::•()
+ ;
+}
+static method main() → void {
+ core::print("hello");
+}
+
+constants {
+ #C1 = true
+}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.expect
index 1d3e740..c1a5b49 100644
--- a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.expect
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.expect
@@ -161,7 +161,7 @@
;
}
class C9 = syn::A9 with self::B9 {
- synthetic constructor •([core::int? a = #C3]) → self::C9
+ synthetic constructor •([core::int? a]) → self::C9
: super syn::A9::•(a)
;
}
@@ -210,7 +210,7 @@
;
}
class C8 = syn::A8 with syn::B8 {
- synthetic constructor •({core::int? a = #C3}) → syn::C8
+ synthetic constructor •({core::int? a}) → syn::C8
: super syn::A8::•(a: a)
;
}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.transformed.expect
index 8995764..782b4ee 100644
--- a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.strong.transformed.expect
@@ -161,7 +161,7 @@
;
}
class C9 extends syn::A9 implements self::B9 /*isEliminatedMixin*/ {
- synthetic constructor •([core::int? a = #C3]) → self::C9
+ synthetic constructor •([core::int? a]) → self::C9
: super syn::A9::•(a)
;
}
@@ -210,7 +210,7 @@
;
}
class C8 extends syn::A8 implements syn::B8 /*isEliminatedMixin*/ {
- synthetic constructor •({core::int? a = #C3}) → syn::C8
+ synthetic constructor •({core::int? a}) → syn::C8
: super syn::A8::•(a: a)
;
}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.expect
index 1d3e740..c1a5b49 100644
--- a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.expect
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.expect
@@ -161,7 +161,7 @@
;
}
class C9 = syn::A9 with self::B9 {
- synthetic constructor •([core::int? a = #C3]) → self::C9
+ synthetic constructor •([core::int? a]) → self::C9
: super syn::A9::•(a)
;
}
@@ -210,7 +210,7 @@
;
}
class C8 = syn::A8 with syn::B8 {
- synthetic constructor •({core::int? a = #C3}) → syn::C8
+ synthetic constructor •({core::int? a}) → syn::C8
: super syn::A8::•(a: a)
;
}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.modular.expect
index 1d3e740..c1a5b49 100644
--- a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.modular.expect
@@ -161,7 +161,7 @@
;
}
class C9 = syn::A9 with self::B9 {
- synthetic constructor •([core::int? a = #C3]) → self::C9
+ synthetic constructor •([core::int? a]) → self::C9
: super syn::A9::•(a)
;
}
@@ -210,7 +210,7 @@
;
}
class C8 = syn::A8 with syn::B8 {
- synthetic constructor •({core::int? a = #C3}) → syn::C8
+ synthetic constructor •({core::int? a}) → syn::C8
: super syn::A8::•(a: a)
;
}
diff --git a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.transformed.expect
index 8995764..782b4ee 100644
--- a/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/super_parameters/synthesized_super_constructor_with_parameters.dart.weak.transformed.expect
@@ -161,7 +161,7 @@
;
}
class C9 extends syn::A9 implements self::B9 /*isEliminatedMixin*/ {
- synthetic constructor •([core::int? a = #C3]) → self::C9
+ synthetic constructor •([core::int? a]) → self::C9
: super syn::A9::•(a)
;
}
@@ -210,7 +210,7 @@
;
}
class C8 extends syn::A8 implements syn::B8 /*isEliminatedMixin*/ {
- synthetic constructor •({core::int? a = #C3}) → syn::C8
+ synthetic constructor •({core::int? a}) → syn::C8
: super syn::A8::•(a: a)
;
}
diff --git a/sdk/lib/js_util/js_util.dart b/sdk/lib/js_util/js_util.dart
index 5dca72d..9af9ea6 100644
--- a/sdk/lib/js_util/js_util.dart
+++ b/sdk/lib/js_util/js_util.dart
@@ -64,6 +64,9 @@
return _convert(data)!;
}
+@pragma('dart2js:tryInline')
+Object get globalThis => JS('', 'globalThis');
+
T newObject<T>() => JS('=Object', '{}');
bool hasProperty(Object o, Object name) => JS('bool', '# in #', name, o);
diff --git a/tests/language/inference_update_1/horizontal_inference_invocation_types_test.dart b/tests/language/inference_update_1/horizontal_inference_invocation_types_test.dart
new file mode 100644
index 0000000..c6a1b8b
--- /dev/null
+++ b/tests/language/inference_update_1/horizontal_inference_invocation_types_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests horizontal inference for a variety of types of invocations.
+
+// SharedOptions=--enable-experiment=inference-update-1
+
+import '../static_type_helper.dart';
+
+testFunctionExpressionInvocation() {
+ (<T>(T t, void Function(T) f) => t)(0, (x) {
+ x.expectStaticType<Exactly<int>>();
+ }).expectStaticType<Exactly<int>>();
+}
+
+testInstanceCreation() {
+ C(0, (x) {
+ x.expectStaticType<Exactly<int>>();
+ }).expectStaticType<Exactly<C<int>>>();
+}
+
+testInstanceMethodInvocation(B b) {
+ b.instanceMethod(0, (x) {
+ x.expectStaticType<Exactly<int>>();
+ }).expectStaticType<Exactly<int>>();
+}
+
+testStaticMethodInvocation() {
+ B.staticMethod(0, (x) {
+ x.expectStaticType<Exactly<int>>();
+ }).expectStaticType<Exactly<int>>();
+}
+
+testTopLevelFunctionInvocation() {
+ topLevelFunction(0, (x) {
+ x.expectStaticType<Exactly<int>>();
+ }).expectStaticType<Exactly<int>>();
+}
+
+testLocalFunctionInvocation() {
+ T localFunction<T>(T t, void Function(T) f) => throw '';
+ localFunction(0, (x) {
+ x.expectStaticType<Exactly<int>>();
+ }).expectStaticType<Exactly<int>>();
+}
+
+abstract class B {
+ T instanceMethod<T>(T t, void Function(T) f);
+ static T staticMethod<T>(T t, void Function(T) f) => throw '';
+}
+
+T topLevelFunction<T>(T t, void Function(T) f) => throw '';
+
+class C<T> {
+ C(T t, void Function(T) f);
+}
+
+main() {}
diff --git a/tests/lib/js/js_util/properties_test.dart b/tests/lib/js/js_util/properties_test.dart
index 84a09c8..5f718a6 100644
--- a/tests/lib/js/js_util/properties_test.dart
+++ b/tests/lib/js/js_util/properties_test.dart
@@ -189,8 +189,21 @@
function Five(a, b, c, d, e) {
this.count = 5;
}
+
+ globalThis.globalKey = 'foo';
""");
+ group('globalThis', () {
+ test('create', () {
+ expect(identical(js_util.globalThis, js_util.globalThis), isTrue);
+ });
+
+ test('isGlobalThis', () {
+ expect(js_util.hasProperty(js_util.globalThis, 'One'), isTrue);
+ expect(js_util.getProperty(js_util.globalThis, 'globalKey'), 'foo');
+ });
+ });
+
group('newObject', () {
test('create', () {
expect(identical(js_util.newObject(), js_util.newObject()), isFalse);
diff --git a/tests/lib_2/js/js_util/properties_test.dart b/tests/lib_2/js/js_util/properties_test.dart
index c19fe14..2b0af10 100644
--- a/tests/lib_2/js/js_util/properties_test.dart
+++ b/tests/lib_2/js/js_util/properties_test.dart
@@ -191,8 +191,21 @@
function Five(a, b, c, d, e) {
this.count = 5;
}
+
+ globalThis.globalKey = 'foo';
""");
+ group('globalThis', () {
+ test('create', () {
+ expect(identical(js_util.globalThis, js_util.globalThis), isTrue);
+ });
+
+ test('isGlobalThis', () {
+ expect(js_util.hasProperty(js_util.globalThis, 'One'), isTrue);
+ expect(js_util.getProperty(js_util.globalThis, 'globalKey'), 'foo');
+ });
+ });
+
group('newObject', () {
test('create', () {
expect(identical(js_util.newObject(), js_util.newObject()), isFalse);
diff --git a/tests/web/wasm/static_interop_test.dart b/tests/web/wasm/static_interop_test.dart
index 3df1c84..c1be1eb 100644
--- a/tests/web/wasm/static_interop_test.dart
+++ b/tests/web/wasm/static_interop_test.dart
@@ -104,8 +104,43 @@
Expect.equals(traveler, holder.foo);
}
+@JS()
+external String get foo;
+
+@JS('')
+external void set baz(String);
+
+@JS('boo.bar')
+external String get bam;
+
+@JS('bar')
+external String fooBar(String);
+
+void topLevelMethodsTest() {
+ eval(r'''
+ globalThis.foo = 'bar';
+ globalThis.baz = null;
+ globalThis.boo = {
+ 'bar': {
+ 'bam': 'jam'
+ }
+ }
+ globalThis.bar = {
+ 'fooBar': function(string) {
+ return string + ' ' + globalThis.baz;
+ }
+ }
+ ''');
+
+ Expect.equals(foo, 'bar');
+ Expect.equals(bam, 'jam');
+ baz = 'world!';
+ Expect.equals(fooBar('hello'), 'hello world!');
+}
+
void main() {
createClassTest();
setInteropPropertyTest();
setDartObjectPropertyTest();
+ topLevelMethodsTest();
}
diff --git a/tools/VERSION b/tools/VERSION
index 3a75f2e..822343f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 16
+PRERELEASE 17
PRERELEASE_PATCH 0
\ No newline at end of file