Version 2.17.0-201.0.dev
Merge commit '4b0706aec7b69a18f4c30d69d30e461a0c778923' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index 01bfc12..5292a02 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -7048,11 +7048,17 @@
// to determine if this is part of a conditional expression
//
Listener originalListener = listener;
- listener = new ForwardingListener();
- // TODO(danrubel): consider using TokenStreamGhostWriter here
+ TokenStreamRewriter? originalRewriter = cachedRewriter;
+ listener = new NullListener();
+ UndoableTokenStreamRewriter undoableTokenStreamRewriter =
+ new UndoableTokenStreamRewriter();
+ cachedRewriter = undoableTokenStreamRewriter;
Token afterExpression =
parseExpressionWithoutCascade(afterIdentifier).next!;
+ // Undo all changes and reset.
+ undoableTokenStreamRewriter.undo();
listener = originalListener;
+ cachedRewriter = originalRewriter;
if (optional(':', afterExpression)) {
// Looks like part of a conditional expression.
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index a1e8437..6ae02e1 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -169,12 +169,13 @@
/// version of each document being modified so it's important to call this
/// immediately after computing edits to ensure the document is not modified
/// before the version number is read.
- CodeAction _createAssistAction(SourceChange change) {
+ CodeAction _createAssistAction(SourceChange change, ResolvedUnitResult unit) {
return CodeAction(
title: change.message,
kind: toCodeActionKind(change.id, CodeActionKind.Refactor),
diagnostics: const [],
- edit: createWorkspaceEdit(server, change),
+ edit: createWorkspaceEdit(server, change,
+ allowSnippets: true, filePath: unit.path, lineInfo: unit.lineInfo),
);
}
@@ -182,12 +183,14 @@
/// version of each document being modified so it's important to call this
/// immediately after computing edits to ensure the document is not modified
/// before the version number is read.
- CodeAction _createFixAction(SourceChange change, Diagnostic diagnostic) {
+ CodeAction _createFixAction(
+ SourceChange change, Diagnostic diagnostic, ResolvedUnitResult unit) {
return CodeAction(
title: change.message,
kind: toCodeActionKind(change.id, CodeActionKind.QuickFix),
diagnostics: [diagnostic],
- edit: createWorkspaceEdit(server, change),
+ edit: createWorkspaceEdit(server, change,
+ allowSnippets: true, filePath: unit.path, lineInfo: unit.lineInfo),
);
}
@@ -269,12 +272,12 @@
final codeActions = <CodeAction>[];
codeActions.addAll(assists.map((assist) {
- final action = _createAssistAction(assist.change);
+ final action = _createAssistAction(assist.change, unit);
codeActionPriorities[action] = assist.kind.priority;
return action;
}));
codeActions.addAll(pluginChanges.map((change) {
- final action = _createAssistAction(change.change);
+ final action = _createAssistAction(change.change, unit);
codeActionPriorities[action] = change.priority;
return action;
}));
@@ -361,7 +364,7 @@
);
codeActions.addAll(
fixes.map((fix) {
- final action = _createFixAction(fix.change, diagnostic);
+ final action = _createFixAction(fix.change, diagnostic, unit);
codeActionPriorities[action] = fix.kind.priority;
return action;
}),
@@ -382,7 +385,7 @@
final pluginFixActions = pluginFixes.expand(
(fix) => fix.fixes.map((fixChange) {
final action = _createFixAction(
- fixChange.change, pluginErrorToDiagnostic(fix.error));
+ fixChange.change, pluginErrorToDiagnostic(fix.error), unit);
codeActionPriorities[action] = fixChange.priority;
return action;
}),
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 9026e05..8125d9a 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -119,51 +119,74 @@
return edit;
}
-/// Creates a [lsp.WorkspaceEdit] from a [server.SourceChange] that can include
-/// experimental [server.SnippetTextEdit]s if the client has indicated support
-/// for these in the experimental section of their client capabilities.
+/// Creates a [lsp.WorkspaceEdit] from a [server.SourceChange].
+///
+/// Can return experimental [server.SnippetTextEdit]s if the following are true:
+/// - the client has indicated support for in the experimental section of their
+/// client capabilities, and
+/// - [allowSnippets] is true, and
+/// - [change] contains only a single edit to the single file [filePath]
+/// - [lineInfo] is provided (which should be for the single edited file)
///
/// Note: This code will fetch the version of each document being modified so
/// it's important to call this immediately after computing edits to ensure
/// the document is not modified before the version number is read.
lsp.WorkspaceEdit createWorkspaceEdit(
- lsp.LspAnalysisServer server, server.SourceChange change) {
+ lsp.LspAnalysisServer server,
+ server.SourceChange change, {
+ // The caller must specify whether snippets are valid here for where they're
+ // sending this edit. Right now, support is limited to CodeActions.
+ bool allowSnippets = false,
+ String? filePath,
+ LineInfo? lineInfo,
+}) {
// In order to return snippets, we must ensure we are only modifying a single
- // existing file with a single edit and that there is a linked edit group with
- // only one position and no suggestions.
- if (!server.clientCapabilities!.experimentalSnippetTextEdit ||
+ // existing file with a single edit and that there is either a selection or a
+ // linked edit group (otherwise there's no value in snippets).
+ if (!allowSnippets ||
+ !server.clientCapabilities!.experimentalSnippetTextEdit ||
+ !server.clientCapabilities!.documentChanges ||
+ filePath == null ||
+ lineInfo == null ||
change.edits.length != 1 ||
- change.edits.first.fileStamp == -1 || // new file
- change.edits.first.edits.length != 1 ||
- change.linkedEditGroups.isEmpty ||
- change.linkedEditGroups.first.positions.length != 1 ||
- change.linkedEditGroups.first.suggestions.isNotEmpty) {
+ change.edits.single.fileStamp == -1 || // new file
+ change.edits.single.file != filePath ||
+ change.edits.single.edits.length != 1 ||
+ (change.selection == null && change.linkedEditGroups.isEmpty)) {
return createPlainWorkspaceEdit(server, change.edits);
}
- // Additionally, the selection must fall within the edit offset.
- final edit = change.edits.first.edits.first;
- final selectionOffset = change.linkedEditGroups.first.positions.first.offset;
- final selectionLength = change.linkedEditGroups.first.length;
+ final fileEdit = change.edits.single;
+ final snippetEdits = toSnippetTextEdits(
+ fileEdit.file,
+ fileEdit,
+ change.linkedEditGroups,
+ lineInfo,
+ selectionOffset: change.selection?.offset,
+ );
- if (selectionOffset < edit.offset ||
- selectionOffset + selectionLength > edit.offset + edit.length) {
- return createPlainWorkspaceEdit(server, change.edits);
- }
+ // Compile the edits into a TextDocumentEdit for this file.
+ final textDocumentEdit = lsp.TextDocumentEdit(
+ textDocument: server.getVersionedDocumentIdentifier(fileEdit.file),
+ edits: snippetEdits
+ .map((e) => Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit,
+ lsp.TextEdit>.t1(e))
+ .toList(),
+ );
- return toWorkspaceEdit(
- server.clientCapabilities!,
- change.edits
- .map((e) => FileEditInformation(
- server.getVersionedDocumentIdentifier(e.file),
- // We should never produce edits for a file with no LineInfo.
- server.getLineInfo(e.file)!,
- e.edits,
- selectionOffsetRelative: selectionOffset - edit.offset,
- selectionLength: selectionLength,
- newFile: e.fileStamp == -1,
- ))
- .toList());
+ // Convert to the union that documentChanges require.
+ final textDocumentEditsAsUnion = Either4<lsp.TextDocumentEdit, lsp.CreateFile,
+ lsp.RenameFile, lsp.DeleteFile>.t1(textDocumentEdit);
+
+ // Convert to the union that documentChanges is.
+ final documentChanges = Either2<
+ List<lsp.TextDocumentEdit>,
+ List<
+ Either4<lsp.TextDocumentEdit, lsp.CreateFile, lsp.RenameFile,
+ lsp.DeleteFile>>>.t2([textDocumentEditsAsUnion]);
+
+ /// Add the textDocumentEdit to a WorkspaceEdit.
+ return lsp.WorkspaceEdit(documentChanges: documentChanges);
}
lsp.CompletionItemKind? declarationKindToCompletionItemKind(
diff --git a/pkg/analysis_server/lib/src/lsp/snippets.dart b/pkg/analysis_server/lib/src/lsp/snippets.dart
index e88dcaa..0c9d5c6 100644
--- a/pkg/analysis_server/lib/src/lsp/snippets.dart
+++ b/pkg/analysis_server/lib/src/lsp/snippets.dart
@@ -85,6 +85,11 @@
// Use the index as an ID to keep all related positions together (so
// the remain "linked").
linkedGroupId: index,
+ // If there is no selection, no tabstops, and only a single edit group
+ // allow it to be the final tabstop.
+ isFinal: selectionOffset == null &&
+ (tabStopOffsetLengthPairs?.isEmpty ?? false) &&
+ editGroups?.length == 1,
),
);
}
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_locator.dart b/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
index 4453aea..f5e1247 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
@@ -14,9 +14,6 @@
/// directory.
static const String defaultPluginFolderName = 'analyzer_plugin';
- /// The name of the `pubspec.yaml` file.
- static const String pubspecFileName = 'pubspec.yaml';
-
/// The name of the `tools` directory, in which the default plugin directory
/// is located.
static const String toolsFolderName = 'tools';
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
index fa6eee9..7e1578b 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
@@ -14,6 +14,7 @@
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/glob.dart';
import 'package:analyzer/src/workspace/bazel.dart';
import 'package:analyzer/src/workspace/gn.dart';
@@ -418,7 +419,7 @@
@visibleForTesting
List<String> pathsFor(String pluginPath) {
var pluginFolder = resourceProvider.getFolder(pluginPath);
- var pubspecFile = pluginFolder.getChildAssumingFile('pubspec.yaml');
+ var pubspecFile = pluginFolder.getChildAssumingFile(file_paths.pubspecYaml);
if (!pubspecFile.exists) {
// If there's no pubspec file, then we don't need to copy the package
// because we won't be running pub.
@@ -689,7 +690,8 @@
var stateName = _uniqueDirectoryName(pluginPath) + '.packages';
var packagesFile = stateFolder.getChildAssumingFile(stateName);
if (!packagesFile.exists) {
- var pluginPubspec = pluginFolder.getChildAssumingFile('pubspec.yaml');
+ var pluginPubspec =
+ pluginFolder.getChildAssumingFile(file_paths.pubspecYaml);
if (!pluginPubspec.exists) {
return null;
}
@@ -710,8 +712,8 @@
if (packageSource != null) {
var libDirPath = context.dirname(packageSource.fullName);
visitedPackages[packageName] = libDirPath;
- var pubspecPath =
- context.join(context.dirname(libDirPath), 'pubspec.yaml');
+ var pubspecPath = context.join(
+ context.dirname(libDirPath), file_paths.pubspecYaml);
pubspecFiles.add(resourceProvider.getFile(pubspecPath));
}
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart b/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart
index 16a3c80..68e682f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart
@@ -7,6 +7,7 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/hint/sdk_constraint_extractor.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
@@ -72,7 +73,7 @@
File? _findPubspecFile() {
var file = resourceProvider.getFile(this.file);
for (var folder in file.parent.withAncestors) {
- var pubspecFile = folder.getChildAssumingFile('pubspec.yaml');
+ var pubspecFile = folder.getChildAssumingFile(file_paths.pubspecYaml);
if (pubspecFile.exists) {
return pubspecFile;
}
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index b7f2f61..68863ac 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -30,6 +30,7 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/source/package_map_resolver.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:collection/collection.dart';
import 'package:path/path.dart' as path;
@@ -501,8 +502,8 @@
buf.writeln('<p>');
buf.writeln(
writeOption('Has .packages file', folder.getChild('.packages').exists));
- buf.writeln(writeOption(
- 'Has pubspec.yaml file', folder.getChild('pubspec.yaml').exists));
+ buf.writeln(writeOption('Has pubspec.yaml file',
+ folder.getChild(file_paths.pubspecYaml).exists));
buf.writeln('</p>');
buf.writeln('</div>');
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index 58804ac..2d8b06f 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -50,6 +50,7 @@
/// class, an empty list if there are no experiments that should be enabled.
List<String> get experiments => [
EnableString.enhanced_enums,
+ EnableString.macros,
EnableString.named_arguments_anywhere,
EnableString.super_parameters,
];
diff --git a/pkg/analysis_server/test/analysis/notification_errors_test.dart b/pkg/analysis_server/test/analysis/notification_errors_test.dart
index 491d5b9..a85cfaefb 100644
--- a/pkg/analysis_server/test/analysis/notification_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_errors_test.dart
@@ -474,8 +474,7 @@
}
Future<void> test_pubspecFile() async {
- var filePath = join(projectPath, 'pubspec.yaml');
- var pubspecFile = newFile(filePath, content: '''
+ var pubspecFile = newPubspecYamlFile(projectPath, '''
version: 1.3.2
''').path;
@@ -488,7 +487,7 @@
var errors = filesErrors[pubspecFile]!;
expect(errors, hasLength(1));
var error = errors[0];
- expect(error.location.file, filePath);
+ expect(error.location.file, pubspecFile);
expect(error.severity, AnalysisErrorSeverity.WARNING);
expect(error.type, AnalysisErrorType.STATIC_WARNING);
//
@@ -512,8 +511,7 @@
- sort_pub_dependencies
''');
- var filePath = join(projectPath, 'pubspec.yaml');
- var pubspecFile = newFile(filePath, content: '''
+ var pubspecFile = newPubspecYamlFile(projectPath, '''
name: sample
dependencies:
@@ -530,7 +528,7 @@
var errors = filesErrors[pubspecFile]!;
expect(errors, hasLength(1));
var error = errors[0];
- expect(error.location.file, filePath);
+ expect(error.location.file, pubspecFile);
expect(error.severity, AnalysisErrorSeverity.INFO);
expect(error.type, AnalysisErrorType.LINT);
//
diff --git a/pkg/analysis_server/test/client/completion_driver_test.dart b/pkg/analysis_server/test/client/completion_driver_test.dart
index 47c6443..6316a24 100644
--- a/pkg/analysis_server/test/client/completion_driver_test.dart
+++ b/pkg/analysis_server/test/client/completion_driver_test.dart
@@ -27,6 +27,10 @@
late CompletionDriver driver;
late List<CompletionSuggestion> suggestions;
+ bool get isProtocolVersion1 {
+ return protocol == TestingCompletionProtocol.version1;
+ }
+
bool get isProtocolVersion2 {
return protocol == TestingCompletionProtocol.version2;
}
@@ -35,22 +39,6 @@
AnalysisServerOptions get serverOptions => AnalysisServerOptions();
- bool get _isProtocolVersion1 {
- return protocol == TestingCompletionProtocol.version1;
- }
-
- Future<void> addProjectFile(String relativePath, String content) async {
- newFile('$testPackageRootPath/$relativePath', content: content);
- // todo (pq): handle more than lib
- expect(relativePath, startsWith('lib/'));
- var packageRelativePath = relativePath.substring(4);
- var uriStr = 'package:test/$packageRelativePath';
-
- if (_isProtocolVersion1) {
- await driver.waitForSetWithUri(uriStr);
- }
- }
-
Future<List<CompletionSuggestion>> addTestFile(String content,
{int? offset}) async {
driver.addTestFile(content, offset: offset);
@@ -110,9 +98,9 @@
}
Future<List<CompletionSuggestion>> getSuggestions() async {
- if (_isProtocolVersion1) {
- await driver.waitForSetWithUri('dart:core');
- await driver.waitForSetWithUri('dart:async');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('dart:core');
+ await waitForSetWithUri('dart:async');
}
switch (protocol) {
@@ -159,7 +147,7 @@
''');
driver = CompletionDriver(
- supportsAvailableSuggestions: _isProtocolVersion1,
+ supportsAvailableSuggestions: isProtocolVersion1,
server: this,
);
await driver.createProject();
@@ -211,6 +199,10 @@
return matches.first;
}
+ Future<void> waitForSetWithUri(String uri) {
+ return driver.waitForSetWithUri(uri);
+ }
+
void _assertNoErrorsInProjectFiles() {
var errors = <AnalysisError>[];
driver.filesErrors.forEach((file, fileErrors) {
@@ -304,14 +296,19 @@
mixin CompletionWithSuggestionsTestCases on AbstractCompletionDriverTest {
Future<void> test_project_filterImports_defaultConstructor() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {}
''');
- await addProjectFile('lib/b.dart', r'''
+ newFile('$testPackageLibPath/b.dart', content: r'''
export 'a.dart';
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ await waitForSetWithUri('package:test/b.dart');
+ }
+
await addTestFile('''
import 'a.dart';
void f() {
@@ -327,16 +324,21 @@
/// See: https://github.com/dart-lang/sdk/issues/40620
Future<void> test_project_filterImports_enumValues() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
enum E {
e,
}
''');
- await addProjectFile('lib/b.dart', r'''
+ newFile('$testPackageLibPath/b.dart', content: r'''
export 'a.dart';
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ await waitForSetWithUri('package:test/b.dart');
+ }
+
await addTestFile('''
import 'a.dart';
void f() {
@@ -351,16 +353,21 @@
/// See: https://github.com/dart-lang/sdk/issues/40620
Future<void> test_project_filterImports_namedConstructors() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {
A.a();
}
''');
- await addProjectFile('lib/b.dart', r'''
+ newFile('$testPackageLibPath/b.dart', content: r'''
export 'a.dart';
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ await waitForSetWithUri('package:test/b.dart');
+ }
+
await addTestFile('''
import 'a.dart';
void f() {
@@ -375,14 +382,19 @@
}
Future<void> test_project_filterMultipleImports() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {}
''');
- await addProjectFile('lib/b.dart', r'''
+ newFile('$testPackageLibPath/b.dart', content: r'''
export 'a.dart';
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ await waitForSetWithUri('package:test/b.dart');
+ }
+
await addTestFile('''
import 'a.dart';
import 'b.dart';
@@ -398,7 +410,7 @@
}
Future<void> test_project_lib() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {}
enum E {
e,
@@ -410,6 +422,10 @@
var v = 0;
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -451,12 +467,16 @@
}
Future<void> test_project_lib_fields_class() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {
int f = 0;
}
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void m() {
^
@@ -467,12 +487,16 @@
}
Future<void> test_project_lib_fields_static() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {
static int f = 0;
}
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -486,12 +510,16 @@
}
Future<void> test_project_lib_getters_class() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {
int get g => 0;
}
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -502,12 +530,16 @@
}
Future<void> test_project_lib_getters_static() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {
static int get g => 0;
}
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -522,10 +554,14 @@
/// See: https://github.com/dart-lang/sdk/issues/40626
Future<void> test_project_lib_getters_topLevel() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
int get g => 0;
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -539,12 +575,16 @@
}
Future<void> test_project_lib_methods_class() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {
void foo() => 0;
}
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -555,12 +595,16 @@
}
Future<void> test_project_lib_methods_static() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {
static void foo() => 0;
}
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -571,14 +615,19 @@
}
Future<void> test_project_lib_multipleExports() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {}
''');
- await addProjectFile('lib/b.dart', r'''
+ newFile('$testPackageLibPath/b.dart', content: r'''
export 'a.dart';
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ await waitForSetWithUri('package:test/b.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -593,12 +642,16 @@
}
Future<void> test_project_lib_setters_class() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {
set s(int s) {}
}
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -609,12 +662,16 @@
}
Future<void> test_project_lib_setters_static() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A {
static set g(int g) {}
}
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -626,10 +683,14 @@
/// See: https://github.com/dart-lang/sdk/issues/40626
Future<void> test_project_lib_setters_topLevel() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
set s(int s) {}
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
void f() {
^
@@ -645,7 +706,7 @@
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38739')
Future<void>
test_project_suggestionRelevance_constructorParameterType() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
import 'b.dart';
class A {
@@ -653,10 +714,15 @@
}
''');
- await addProjectFile('lib/b.dart', r'''
+ newFile('$testPackageLibPath/b.dart', content: r'''
class O { }
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ await waitForSetWithUri('package:test/b.dart');
+ }
+
await addTestFile('''
import 'a.dart';
@@ -679,10 +745,14 @@
}
Future<void> test_project_suggestionRelevance_constructorsAndTypes() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
class A { }
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
import 'a.dart';
@@ -707,11 +777,15 @@
/// See: https://github.com/dart-lang/sdk/issues/35529
Future<void> test_project_suggestMixins() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
mixin M { }
class A { }
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
await addTestFile('''
class C extends Object with ^
''');
diff --git a/pkg/analysis_server/test/client/impl/completion_driver.dart b/pkg/analysis_server/test/client/impl/completion_driver.dart
index 095db29..c57c328 100644
--- a/pkg/analysis_server/test/client/impl/completion_driver.dart
+++ b/pkg/analysis_server/test/client/impl/completion_driver.dart
@@ -279,16 +279,12 @@
} else if (notification.event == SERVER_NOTIFICATION_CONNECTED) {
// Ignored.
} else {
- print('Unhandled notififcation: ${notification.event}');
+ print('Unhandled notification: ${notification.event}');
}
}
- Future<AvailableSuggestionSet> waitForSetWithUri(String uri) async {
- while (true) {
- var result = uriToSetMap[uri];
- if (result != null) {
- return result;
- }
+ Future<void> waitForSetWithUri(String uri) async {
+ while (uriToSetMap[uri] == null) {
await Future.delayed(const Duration(milliseconds: 1));
}
}
diff --git a/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart b/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart
index 38428ff..f07d1ac 100644
--- a/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -17,7 +18,7 @@
class SdkVersionAsyncExportedFromCoreIntegrationTest
extends AbstractAnalysisServerIntegrationTest {
Future<void> test_update_pubspec() async {
- var pubspecPath = sourcePath('pubspec.yaml');
+ var pubspecPath = sourcePath(file_paths.pubspecYaml);
writeFile(pubspecPath, r'''
name: test
environment:
diff --git a/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart b/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
index 98ad357..14ae4a4 100644
--- a/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
+++ b/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -32,9 +33,9 @@
workspaceFolder2Uri = Uri.file(workspaceFolder2Path);
workspaceFolder3Uri = Uri.file(workspaceFolder3Path);
- newFile(join(workspaceFolder1Path, 'pubspec.yaml'));
- newFile(join(workspaceFolder2Path, 'pubspec.yaml'));
- newFile(join(workspaceFolder3Path, 'pubspec.yaml'));
+ newPubspecYamlFile(workspaceFolder1Path, '');
+ newPubspecYamlFile(workspaceFolder2Path, '');
+ newPubspecYamlFile(workspaceFolder3Path, '');
}
Future<void> test_changeWorkspaceFolders_add() async {
@@ -220,8 +221,14 @@
final nestedFilePath = join(nestedFolderPath, 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
newFile(nestedFilePath);
- deleteFile(join(
- workspaceFolder1Path, 'pubspec.yaml')); // Ensure no pubspecs in tree.
+
+ // Ensure no pubspecs in tree.
+ deleteFile(
+ join(
+ workspaceFolder1Path,
+ file_paths.pubspecYaml,
+ ),
+ );
await initialize(allowEmptyRootUri: true);
await openFile(nestedFileUri, '');
diff --git a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
index cf67637f..68652df 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -249,7 +249,70 @@
);
}
- Future<void> test_snippetTextEdits_supported() async {
+ Future<void> test_snippetTextEdits_multiEditGroup() async {
+ // As test_snippetTextEdits_singleEditGroup, but uses an assist that
+ // produces multiple linked edit groups.
+
+ const content = '''
+ import 'package:flutter/widgets.dart';
+ build() {
+ return Container(
+ child: Ro^w(
+ children: [
+ Text('111'),
+ Text('222'),
+ Container(),
+ ],
+ ),
+ );
+ }
+ ''';
+
+ const expectedContent = r'''
+ import 'package:flutter/widgets.dart';
+ build() {
+ return Container(
+ child: ${1:widget}(
+ ${2:child}: Row(
+ children: [
+ Text('111'),
+ Text('222'),
+ Container(),
+ ],
+ ),
+ ),
+ );
+ }
+ ''';
+
+ newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+ workspaceCapabilities:
+ withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+ experimentalCapabilities: {
+ 'snippetTextEdit': true,
+ },
+ );
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ position: positionFromMarker(content));
+ final assist = findEditAction(
+ codeActions,
+ CodeActionKind('refactor.flutter.wrap.generic'),
+ 'Wrap with widget...')!;
+
+ // Ensure applying the changes will give us the expected content.
+ final edit = assist.edit!;
+ final contents = {
+ mainFilePath: withoutMarkers(content),
+ };
+ applyDocumentChanges(contents, edit.documentChanges!);
+ expect(contents[mainFilePath], equals(expectedContent));
+ }
+
+ Future<void> test_snippetTextEdits_singleEditGroup() async {
// This tests experimental support for including Snippets in TextEdits.
// https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
//
@@ -273,8 +336,8 @@
''';
// For testing, the snippet will be inserted literally into the text, as
- // this requires some magic on the client. The expected text should therefore
- // contain the snippets in the standard format.
+ // this requires some magic on the client. The expected text should
+ // therefore contain the snippets in the standard format.
const expectedContent = r'''
import 'package:flutter/widgets.dart';
build() {
@@ -426,6 +489,63 @@
);
}
+ Future<void> test_surround_editGroupsAndSelection() async {
+ const content = '''
+void f() {
+ [[print(0);]]
+}
+''';
+
+ const expectedContent = r'''
+void f() {
+ if (${1:condition}) {
+ print(0);
+ }$0
+}
+''';
+
+ newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+ workspaceCapabilities:
+ withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+ experimentalCapabilities: {
+ 'snippetTextEdit': true,
+ },
+ );
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ range: rangeFromMarkers(content));
+ final assist = findEditAction(codeActions,
+ CodeActionKind('refactor.surround.if'), "Surround with 'if'")!;
+
+ // Ensure the edit came back, and using documentChanges.
+ final edit = assist.edit!;
+ expect(edit.documentChanges, isNotNull);
+ expect(edit.changes, isNull);
+
+ // Ensure applying the changes will give us the expected content.
+ final contents = {
+ mainFilePath: withoutMarkers(content),
+ };
+ applyDocumentChanges(contents, edit.documentChanges!);
+ expect(contents[mainFilePath], equals(expectedContent));
+
+ // Also ensure there was a single edit that was correctly marked
+ // as a SnippetTextEdit.
+ final textEdits = _extractTextDocumentEdits(edit.documentChanges!)
+ .expand((tde) => tde.edits)
+ .map((edit) => edit.map(
+ (e) => e,
+ (e) => throw 'Expected SnippetTextEdit, got AnnotatedTextEdit',
+ (e) => throw 'Expected SnippetTextEdit, got TextEdit',
+ ))
+ .toList();
+ expect(textEdits, hasLength(1));
+ expect(textEdits.first.insertTextFormat, equals(InsertTextFormat.Snippet));
+ }
+
List<TextDocumentEdit> _extractTextDocumentEdits(
Either2<
List<TextDocumentEdit>,
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index 5cf681a..6b43de8 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -502,8 +502,7 @@
final file2 = join(projectFolderPath, 'file2.dart');
final file2Uri = Uri.file(file2);
newFile(file2);
- final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
- newFile(pubspecPath);
+ newPubspecYamlFile(projectFolderPath, '');
await initialize(allowEmptyRootUri: true);
@@ -549,8 +548,7 @@
projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
newFile(nestedFilePath);
- final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
- newFile(pubspecPath);
+ newPubspecYamlFile(projectFolderPath, '');
// The project folder shouldn't be added to start with.
await initialize(allowEmptyRootUri: true);
@@ -716,8 +714,7 @@
}
Future<void> test_nonFileScheme_workspaceFolders() async {
- final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
- newFile(pubspecPath);
+ newPubspecYamlFile(projectFolderPath, '');
final rootUri = Uri.parse('vsls://');
final fileUri = rootUri.replace(path: '/file1.dart');
@@ -788,8 +785,7 @@
final file2 = join(projectFolderPath, 'file2.dart');
final file2Uri = Uri.file(file2);
newFile(file2);
- final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
- newFile(pubspecPath);
+ newPubspecYamlFile(projectFolderPath, '');
await initialize(
rootUri: projectFolderUri,
@@ -842,8 +838,7 @@
projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
newFile(nestedFilePath);
- final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
- newFile(pubspecPath);
+ newPubspecYamlFile(projectFolderPath, '');
// The project folder shouldn't be added to start with.
await initialize(
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index f9f3c7d..4d5a6c4 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -22,6 +22,7 @@
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
import 'package:collection/collection.dart';
@@ -212,7 +213,7 @@
newFile(join(projectFolderPath, 'lib', 'file.dart'));
mainFilePath = join(projectFolderPath, 'lib', 'main.dart');
mainFileUri = Uri.file(mainFilePath);
- pubspecFilePath = join(projectFolderPath, 'pubspec.yaml');
+ pubspecFilePath = join(projectFolderPath, file_paths.pubspecYaml);
pubspecFileUri = Uri.file(pubspecFilePath);
analysisOptionsPath = join(projectFolderPath, 'analysis_options.yaml');
analysisOptionsUri = Uri.file(analysisOptionsPath);
diff --git a/pkg/analysis_server/test/lsp/snippets_test.dart b/pkg/analysis_server/test/lsp/snippets_test.dart
index a126c9b..48cefb0 100644
--- a/pkg/analysis_server/test/lsp/snippets_test.dart
+++ b/pkg/analysis_server/test/lsp/snippets_test.dart
@@ -155,7 +155,7 @@
],
);
expect(result, equals(r'''
-var ${1|a,aaa,bbb\${\}\,\|,ccc|} = 1;
+var ${0|a,aaa,bbb\${\}\,\|,ccc|} = 1;
'''));
}
@@ -180,8 +180,8 @@
],
);
expect(result, equals(r'''
-class $1 {
- $1();
+class $0 {
+ $0();
}
'''));
}
@@ -208,8 +208,8 @@
],
);
expect(result, equals(r'''
-class ${1:A} {
- ${1:A}();
+class ${0:A} {
+ ${0:A}();
}
'''));
}
@@ -235,8 +235,8 @@
],
);
expect(result, equals(r'''
-class ${1:A} {
- ${1:A}();
+class ${0:A} {
+ ${0:A}();
}
'''));
}
@@ -264,8 +264,8 @@
],
);
expect(result, equals(r'''
-class ${1:A} {
- ${1:A}();
+class ${0:A} {
+ ${0:A}();
}
'''));
}
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
index d154a6e..66a1a19 100644
--- a/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
@@ -59,10 +59,14 @@
}
Future<void> test_enumConstantName_imported_withPrefix() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
enum MyEnum { foo01 }
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
var response = await getTestCodeSuggestions('''
import 'a.dart' as prefix;
@@ -115,10 +119,14 @@
}
Future<void> test_enumName_imported_withPrefix() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
enum MyEnum { foo01 }
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
var response = await getTestCodeSuggestions('''
import 'a.dart' as prefix;
@@ -147,10 +155,14 @@
@FailingTest(reason: 'element.kind is LIBRARY')
Future<void> test_importPrefix() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
enum MyEnum { v }
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
var response = await getTestCodeSuggestions('''
import 'a.dart' as prefix01;
@@ -177,10 +189,14 @@
}
Future<void> test_importPrefix_dot() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
enum MyEnum { v }
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
var response = await getTestCodeSuggestions('''
import 'a.dart' as prefix;
@@ -230,10 +246,14 @@
}
Future<void> test_nothing_imported_withPrefix() async {
- await addProjectFile('lib/a.dart', r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
enum MyEnum { v }
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
+
var response = await getTestCodeSuggestions('''
import 'a.dart' as prefix;
@@ -284,9 +304,12 @@
// imported
{
- await addProjectFile('lib/a.dart', '''
+ newFile('$testPackageLibPath/a.dart', content: '''
$declaration
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
var response = await getTestCodeSuggestions('''
import 'a.dart';
void f() {
@@ -298,9 +321,12 @@
// not imported
{
- await addProjectFile('lib/a.dart', '''
+ newFile('$testPackageLibPath/a.dart', content: '''
$declaration
''');
+ if (isProtocolVersion1) {
+ await waitForSetWithUri('package:test/a.dart');
+ }
var response = await getTestCodeSuggestions('''
void f() {
$codeAtCompletion
diff --git a/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart b/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart
index cf45244..4156e12 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart
@@ -69,9 +69,7 @@
}
void _createPubspec(String content) {
- pubspecPath =
- newFile('/package/${PluginLocator.pubspecFileName}', content: content)
- .path;
+ pubspecPath = newPubspecYamlFile('/package', content).path;
}
String _createPubspecWithKey() {
diff --git a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
index ffb6492..d2644f7 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
@@ -10,6 +10,7 @@
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/dart/analysis/context_root.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/workspace/basic.dart';
import 'package:analyzer_plugin/channel/channel.dart';
import 'package:analyzer_plugin/protocol/protocol.dart';
@@ -760,7 +761,7 @@
//
// Create a pubspec.yaml file.
//
- var pubspecFile = io.File(path.join(pluginPath, 'pubspec.yaml'));
+ var pubspecFile = io.File(path.join(pluginPath, file_paths.pubspecYaml));
pubspecFile.writeAsStringSync(_getPubspecFileContent());
//
// Create the 'bin' directory.
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
index 051c4eb..1104ef2 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
@@ -7,6 +7,7 @@
import 'package:analysis_server/src/services/pub/pub_command.dart';
import 'package:analysis_server/src/services/pub/pub_package_service.dart';
import 'package:analyzer/instrumentation/service.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:http/http.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -28,7 +29,7 @@
late PubPackageService pubPackageService;
@override
- String get fileName => 'pubspec.yaml';
+ String get fileName => file_paths.pubspecYaml;
@override
PubspecGenerator get generator =>
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index 7de5c96..2cbad2f 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -13,6 +13,7 @@
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/glob.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:args/args.dart';
@@ -48,9 +49,6 @@
/// interaction to use when making `analysis.updateContent` requests.
static String OVERLAY_STYLE_OPTION_NAME = 'overlay-style';
- /// The name of the pubspec file.
- static const String PUBSPEC_FILE_NAME = 'pubspec.yaml';
-
/// The name of the branch used to clean-up after making temporary changes.
static const String TEMP_BRANCH_NAME = 'temp';
@@ -203,7 +201,7 @@
var children = directory.listSync(recursive: true, followLinks: false);
for (var child in children) {
var filePath = child.path;
- if (path.basename(filePath) == PUBSPEC_FILE_NAME) {
+ if (path.basename(filePath) == file_paths.pubspecYaml) {
pubspecFiles.add(filePath);
}
}
@@ -353,7 +351,7 @@
statistics.commitsWithChangeInRootCount++;
await _replayDiff(commitDelta);
}
- changedPubspecs = commitDelta.filesMatching(PUBSPEC_FILE_NAME);
+ changedPubspecs = commitDelta.filesMatching(file_paths.pubspecYaml);
}
} finally {
// Ensure that the repository is left at the most recent commit.
diff --git a/pkg/analysis_server/tool/code_completion/corpus.dart b/pkg/analysis_server/tool/code_completion/corpus.dart
index d7f02f2..26cae4f 100644
--- a/pkg/analysis_server/tool/code_completion/corpus.dart
+++ b/pkg/analysis_server/tool/code_completion/corpus.dart
@@ -5,6 +5,7 @@
import 'dart:convert';
import 'dart:io';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:html/parser.dart' show parse;
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as path;
@@ -96,7 +97,8 @@
headers: const {'User-Agent': 'dart.pkg.completion_metrics'});
bool _hasPubspec(FileSystemEntity f) =>
- f is Directory && File(path.join(f.path, 'pubspec.yaml')).existsSync();
+ f is Directory &&
+ File(path.join(f.path, file_paths.pubspecYaml)).existsSync();
Future<ProcessResult> _runPub(String dir) async =>
await Process.run('flutter', ['pub', 'get'], workingDirectory: dir);
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index d3a04fe..0aa945a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -27,6 +27,7 @@
import 'package:analyzer/src/summary/summary_sdk.dart';
import 'package:analyzer/src/summary2/package_bundle_format.dart';
import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer/src/workspace/workspace.dart';
@@ -198,7 +199,7 @@
/// TODO(scheglov) Get it from [Workspace]?
File? _findPubspecFile(ContextRoot contextRoot) {
for (var current in contextRoot.root.withAncestors) {
- var file = current.getChildAssumingFile('pubspec.yaml');
+ var file = current.getChildAssumingFile(file_paths.pubspecYaml);
if (file.exists) {
return file;
}
diff --git a/pkg/analyzer/lib/src/workspace/package_build.dart b/pkg/analyzer/lib/src/workspace/package_build.dart
index c30333e..5a10e9a 100644
--- a/pkg/analyzer/lib/src/workspace/package_build.dart
+++ b/pkg/analyzer/lib/src/workspace/package_build.dart
@@ -10,6 +10,7 @@
import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer/src/summary/api_signature.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/uri.dart';
import 'package:analyzer/src/workspace/pub.dart';
import 'package:analyzer/src/workspace/workspace.dart';
@@ -136,10 +137,6 @@
'generated'
];
- /// We use pubspec.yaml to get the package name to be consistent with how
- /// package:build does it.
- static const String _pubspecName = 'pubspec.yaml';
-
/// The associated pubspec file.
final File _pubspecFile;
@@ -298,7 +295,7 @@
Map<String, List<Folder>> packageMap, String filePath) {
var startFolder = provider.getFolder(filePath);
for (var folder in startFolder.withAncestors) {
- final File pubspec = folder.getChildAssumingFile(_pubspecName);
+ final File pubspec = folder.getChildAssumingFile(file_paths.pubspecYaml);
final Folder dartToolDir =
folder.getChildAssumingFolder(_dartToolRootName);
final Folder dartToolBuildDir =
diff --git a/pkg/analyzer/lib/src/workspace/pub.dart b/pkg/analyzer/lib/src/workspace/pub.dart
index 1d83253..a6e66ce 100644
--- a/pkg/analyzer/lib/src/workspace/pub.dart
+++ b/pkg/analyzer/lib/src/workspace/pub.dart
@@ -7,15 +7,13 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/lint/pub.dart';
import 'package:analyzer/src/summary/api_signature.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/workspace/simple.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:meta/meta.dart';
/// Information about a Pub workspace.
class PubWorkspace extends SimpleWorkspace {
- /// The name of the file that identifies the root of the workspace.
- static const String _pubspecName = 'pubspec.yaml';
-
/// The singular package in this workspace.
///
/// Each Pub workspace is itself one package.
@@ -68,7 +66,7 @@
) {
var start = provider.getFolder(filePath);
for (var current in start.withAncestors) {
- var pubspec = current.getChildAssumingFile(_pubspecName);
+ var pubspec = current.getChildAssumingFile(file_paths.pubspecYaml);
if (pubspec.exists) {
var root = current.path;
return PubWorkspace._(provider, packageMap, root, pubspec);
diff --git a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
index 77954c0..26937b0 100644
--- a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
@@ -4,7 +4,6 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -366,15 +365,44 @@
}
''');
- var creation = findNode.instanceCreation('A<int, String>(0);');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int, String>',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int', 'U': 'String'},
- );
- _assertArgumentList(creation.argumentList, ['0']);
+ var node = findNode.instanceCreation('A<int, String>(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ NamedType
+ name: SimpleIdentifier
+ token: String
+ staticElement: dart:core::@class::String
+ staticType: null
+ type: String
+ rightBracket: >
+ type: A<int, String>
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::•
+ substitution: {T: int, U: String}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int, String>
+''');
}
test_targetNull_extension() async {
@@ -408,10 +436,42 @@
}
''');
- var invocation = findNode.methodInvocation('A<int, String>(0);');
- assertElement(invocation, findElement.topFunction('A'));
- assertInvokeType(invocation, 'void Function(int)');
- _assertArgumentList(invocation.argumentList, ['0']);
+ var node = findNode.methodInvocation('A<int, String>(0);');
+ assertResolvedNodeText(node, r'''
+MethodInvocation
+ methodName: SimpleIdentifier
+ token: A
+ staticElement: self::@function::A
+ staticType: void Function<T, U>(int)
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ NamedType
+ name: SimpleIdentifier
+ token: String
+ staticElement: dart:core::@class::String
+ staticType: null
+ type: String
+ rightBracket: >
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticInvokeType: void Function(int)
+ staticType: void
+ typeArgumentTypes
+ int
+ String
+''');
}
test_targetNull_typeAlias_interfaceType() async {
@@ -427,16 +487,44 @@
}
''');
- var creation = findNode.instanceCreation('X<int, String>(0);');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int, String>',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int', 'U': 'String'},
- expectedTypeNameElement: findElement.typeAlias('X'),
- );
- _assertArgumentList(creation.argumentList, ['0']);
+ var node = findNode.instanceCreation('X<int, String>(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: X
+ staticElement: self::@typeAlias::X
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ NamedType
+ name: SimpleIdentifier
+ token: String
+ staticElement: dart:core::@class::String
+ staticType: null
+ type: String
+ rightBracket: >
+ type: A<int, String>
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::•
+ substitution: {T: int, U: String}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int, String>
+''');
}
test_targetNull_typeAlias_Never() async {
@@ -469,19 +557,43 @@
}
''');
- var importFind = findElement.importFind('package:test/a.dart');
-
- var creation = findNode.instanceCreation('A.named(0);');
- assertInstanceCreation(
- creation,
- importFind.class_('A'),
- 'A<int>',
- constructorName: 'named',
- expectedPrefix: importFind.prefix,
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- );
- _assertArgumentList(creation.argumentList, ['0']);
+ var node = findNode.instanceCreation('A.named(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: prefix
+ staticElement: self::@prefix::prefix
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: A
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ type: A<int>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::A::@constructor::named
+ substitution: {T: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::A::@constructor::named
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int>
+''');
}
test_targetPrefixedIdentifier_prefix_class_constructor_typeArguments() async {
@@ -503,24 +615,53 @@
messageContains: ["The constructor 'prefix.A.named'"]),
]);
- var importFind = findElement.importFind('package:test/a.dart');
-
- var creation = findNode.instanceCreation('named<int>(0);');
- assertInstanceCreation(
- creation,
- importFind.class_('A'),
- 'A<int>',
- constructorName: 'named',
- expectedPrefix: importFind.prefix,
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- );
- _assertTypeArgumentList(
- creation.constructorName.type.typeArguments,
- ['int'],
- );
- expect((creation as InstanceCreationExpressionImpl).typeArguments, isNull);
- _assertArgumentList(creation.argumentList, ['0']);
+ var node = findNode.instanceCreation('named<int>(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: prefix
+ staticElement: self::@prefix::prefix
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: A
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ type: A<int>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::A::@constructor::named
+ substitution: {T: int}
+ staticType: null
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::A::@constructor::named
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int>
+''');
}
test_targetPrefixedIdentifier_prefix_class_constructor_typeArguments_new() async {
@@ -542,23 +683,53 @@
messageContains: ["The constructor 'prefix.A.new'"]),
]);
- var importFind = findElement.importFind('package:test/a.dart');
-
- var creation = findNode.instanceCreation('new<int>(0);');
- assertInstanceCreation(
- creation,
- importFind.class_('A'),
- 'A<int>',
- expectedPrefix: importFind.prefix,
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- );
- _assertTypeArgumentList(
- creation.constructorName.type.typeArguments,
- ['int'],
- );
- expect((creation as InstanceCreationExpressionImpl).typeArguments, isNull);
- _assertArgumentList(creation.argumentList, ['0']);
+ var node = findNode.instanceCreation('new<int>(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: prefix
+ staticElement: self::@prefix::prefix
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: A
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ type: A<int>
+ period: .
+ name: SimpleIdentifier
+ token: new
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::A::@constructor::•
+ substitution: {T: int}
+ staticType: null
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::A::@constructor::•
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int>
+''');
}
test_targetPrefixedIdentifier_prefix_getter_method() async {
@@ -578,12 +749,36 @@
}
''');
- var importFind = findElement.importFind('package:test/a.dart');
-
- var invocation = findNode.methodInvocation('bar(0);');
- assertElement(invocation, importFind.class_('A').getMethod('bar'));
- assertInvokeType(invocation, 'void Function(int)');
- _assertArgumentList(invocation.argumentList, ['0']);
+ var node = findNode.methodInvocation('bar(0);');
+ assertResolvedNodeText(node, r'''
+MethodInvocation
+ target: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: prefix
+ staticElement: self::@prefix::prefix
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: foo
+ staticElement: package:test/a.dart::@getter::foo
+ staticType: A
+ staticElement: package:test/a.dart::@getter::foo
+ staticType: A
+ operator: .
+ methodName: SimpleIdentifier
+ token: bar
+ staticElement: package:test/a.dart::@class::A::@method::bar
+ staticType: void Function(int)
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticInvokeType: void Function(int)
+ staticType: void
+''');
}
test_targetPrefixedIdentifier_typeAlias_interfaceType_constructor() async {
@@ -603,20 +798,43 @@
}
''');
- var importFind = findElement.importFind('package:test/a.dart');
-
- var creation = findNode.instanceCreation('X.named(0);');
- assertInstanceCreation(
- creation,
- importFind.class_('A'),
- 'A<int>',
- constructorName: 'named',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- expectedPrefix: findElement.prefix('prefix'),
- expectedTypeNameElement: importFind.typeAlias('X'),
- );
- _assertArgumentList(creation.argumentList, ['0']);
+ var node = findNode.instanceCreation('X.named(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: prefix
+ staticElement: self::@prefix::prefix
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: X
+ staticElement: package:test/a.dart::@typeAlias::X
+ staticType: null
+ staticElement: package:test/a.dart::@typeAlias::X
+ staticType: null
+ type: A<int>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::A::@constructor::named
+ substitution: {T: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::A::@constructor::named
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int>
+''');
}
test_targetSimpleIdentifier_class_constructor() async {
@@ -630,16 +848,35 @@
}
''');
- var creation = findNode.instanceCreation('A.named(0);');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int>',
- constructorName: 'named',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- );
- _assertArgumentList(creation.argumentList, ['0']);
+ var node = findNode.instanceCreation('A.named(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A<int>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int>
+''');
}
test_targetSimpleIdentifier_class_constructor_typeArguments() async {
@@ -657,27 +894,52 @@
messageContains: ["The constructor 'A.named'"]),
]);
- var creation = findNode.instanceCreation('named<int, String>(0);');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- // TODO(scheglov) Move type arguments
- 'A<dynamic, dynamic>',
-// 'A<int, String>',
- constructorName: 'named',
- expectedConstructorMember: true,
- // TODO(scheglov) Move type arguments
- expectedSubstitution: {'T': 'dynamic', 'U': 'dynamic'},
-// expectedSubstitution: {'T': 'int', 'U': 'String'},
- );
// TODO(scheglov) Move type arguments
-// _assertTypeArgumentList(
-// creation.constructorName.type.typeArguments,
-// ['int', 'String'],
-// );
- // TODO(scheglov) Fix and uncomment.
-// expect((creation as InstanceCreationExpressionImpl).typeArguments, isNull);
- _assertArgumentList(creation.argumentList, ['0']);
+ var node = findNode.instanceCreation('named<int, String>(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A<dynamic, dynamic>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: dynamic, U: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: dynamic, U: dynamic}
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ NamedType
+ name: SimpleIdentifier
+ token: String
+ staticElement: dart:core::@class::String
+ staticType: null
+ type: String
+ rightBracket: >
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<dynamic, dynamic>
+''');
}
test_targetSimpleIdentifier_class_constructor_typeArguments_new() async {
@@ -695,26 +957,52 @@
messageContains: ["The constructor 'A.new'"]),
]);
- var creation = findNode.instanceCreation('new<int, String>(0);');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- // TODO(scheglov) Move type arguments
- 'A<dynamic, dynamic>',
-// 'A<int, String>',
- expectedConstructorMember: true,
- // TODO(scheglov) Move type arguments
- expectedSubstitution: {'T': 'dynamic', 'U': 'dynamic'},
-// expectedSubstitution: {'T': 'int', 'U': 'String'},
- );
// TODO(scheglov) Move type arguments
-// _assertTypeArgumentList(
-// creation.constructorName.type.typeArguments,
-// ['int', 'String'],
-// );
- // TODO(scheglov) Fix and uncomment.
-// expect((creation as InstanceCreationExpressionImpl).typeArguments, isNull);
- _assertArgumentList(creation.argumentList, ['0']);
+ var node = findNode.instanceCreation('new<int, String>(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A<dynamic, dynamic>
+ period: .
+ name: SimpleIdentifier
+ token: new
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::•
+ substitution: {T: dynamic, U: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::•
+ substitution: {T: dynamic, U: dynamic}
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ NamedType
+ name: SimpleIdentifier
+ token: String
+ staticElement: dart:core::@class::String
+ staticType: null
+ type: String
+ rightBracket: >
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<dynamic, dynamic>
+''');
}
test_targetSimpleIdentifier_class_staticMethod() async {
@@ -747,18 +1035,52 @@
}
''');
- var importFind = findElement.importFind('package:test/a.dart');
-
- var creation = findNode.instanceCreation('A<int, String>(0);');
- assertInstanceCreation(
- creation,
- importFind.class_('A'),
- 'A<int, String>',
- expectedPrefix: importFind.prefix,
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int', 'U': 'String'},
- );
- _assertArgumentList(creation.argumentList, ['0']);
+ var node = findNode.instanceCreation('A<int, String>(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: prefix
+ staticElement: self::@prefix::prefix
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: A
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ NamedType
+ name: SimpleIdentifier
+ token: String
+ staticElement: dart:core::@class::String
+ staticType: null
+ type: String
+ rightBracket: >
+ type: A<int, String>
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::A::@constructor::•
+ substitution: {T: int, U: String}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int, String>
+''');
}
test_targetSimpleIdentifier_prefix_extension() async {
@@ -803,12 +1125,47 @@
}
''');
- var importFind = findElement.importFind('package:test/a.dart');
-
- var invocation = findNode.methodInvocation('A<int, String>(0);');
- assertElement(invocation, importFind.topFunction('A'));
- assertInvokeType(invocation, 'void Function(int)');
- _assertArgumentList(invocation.argumentList, ['0']);
+ var node = findNode.methodInvocation('A<int, String>(0);');
+ assertResolvedNodeText(node, r'''
+MethodInvocation
+ target: SimpleIdentifier
+ token: prefix
+ staticElement: self::@prefix::prefix
+ staticType: null
+ operator: .
+ methodName: SimpleIdentifier
+ token: A
+ staticElement: package:test/a.dart::@function::A
+ staticType: void Function<T, U>(int)
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ NamedType
+ name: SimpleIdentifier
+ token: String
+ staticElement: dart:core::@class::String
+ staticType: null
+ type: String
+ rightBracket: >
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticInvokeType: void Function(int)
+ staticType: void
+ typeArgumentTypes
+ int
+ String
+''');
}
test_targetSimpleIdentifier_typeAlias_interfaceType_constructor() async {
@@ -824,27 +1181,35 @@
}
''');
- var creation = findNode.instanceCreation('X.named(0);');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int>',
- constructorName: 'named',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- expectedTypeNameElement: findElement.typeAlias('X'),
- );
- _assertArgumentList(creation.argumentList, ['0']);
- }
-
- void _assertArgumentList(
- ArgumentList argumentList,
- List<String> expectedArguments,
- ) {
- var argumentStrings = argumentList.arguments
- .map((e) => result.content.substring(e.offset, e.end))
- .toList();
- expect(argumentStrings, expectedArguments);
+ var node = findNode.instanceCreation('X.named(0);');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: X
+ staticElement: self::@typeAlias::X
+ staticType: null
+ type: A<int>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int>
+''');
}
void _assertExtensionOverride(
@@ -864,20 +1229,6 @@
);
assertType(override.extendedType, expectedExtendedType);
}
-
- void _assertTypeArgumentList(
- TypeArgumentList? argumentList,
- List<String> expectedArguments,
- ) {
- if (argumentList == null) {
- fail('Expected TypeArgumentList, actually null.');
- }
-
- var argumentStrings = argumentList.arguments
- .map((e) => result.content.substring(e.offset, e.end))
- .toList();
- expect(argumentStrings, expectedArguments);
- }
}
@reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 7d4c7a1..bd15dd4 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -262,8 +262,8 @@
List<String> get collectionIncludedPaths => [workspaceRootPath];
List<String> get experiments => [
- EnableString.constructor_tearoffs,
EnableString.enhanced_enums,
+ EnableString.macros,
EnableString.named_arguments_anywhere,
EnableString.super_parameters,
];
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
index 5175800..1508e0f 100644
--- a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
@@ -32,15 +32,35 @@
''');
- var creation = findNode.instanceCreation('A.named(0)');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int>',
- constructorName: 'named',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- );
+ var node = findNode.instanceCreation('A.named(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A<int>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int>
+''');
}
test_class_generic_named_withTypeArguments() async {
@@ -55,15 +75,41 @@
''');
- var creation = findNode.instanceCreation('A<int>');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int>',
- constructorName: 'named',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- );
+ var node = findNode.instanceCreation('A<int>');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ type: A<int>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: int}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: A<int>
+''');
assertNamedType(findNode.namedType('int>'), intElement, 'int');
}
@@ -79,14 +125,28 @@
''');
- var creation = findNode.instanceCreation('A(0)');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int>',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- );
+ var node = findNode.instanceCreation('A(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A<int>
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::•
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int>
+''');
}
test_class_generic_unnamed_withTypeArguments() async {
@@ -99,14 +159,34 @@
''');
- var creation = findNode.instanceCreation('A<int>');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int>',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- );
+ var node = findNode.instanceCreation('A<int>');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ type: A<int>
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::•
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: A<int>
+''');
assertNamedType(findNode.namedType('int>'), intElement, 'int');
}
@@ -122,8 +202,26 @@
''');
- var creation = findNode.instanceCreation('A(0)');
- assertInstanceCreation(creation, findElement.class_('A'), 'A');
+ var node = findNode.instanceCreation('A(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A
+ staticElement: self::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A
+''');
}
test_demoteType() async {
@@ -140,10 +238,29 @@
''');
- assertType(
- findNode.instanceCreation('A(s)'),
- 'A<S>',
- );
+ var node = findNode.instanceCreation('A(s)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A<S>
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::•
+ substitution: {T: S}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ SimpleIdentifier
+ token: s
+ staticElement: s@38
+ staticType: S & int
+ rightParenthesis: )
+ staticType: A<S>
+''');
}
test_error_newWithInvalidTypeParameters_implicitNew_inference_top() async {
@@ -153,14 +270,34 @@
error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 12, 8),
]);
- var creation = findNode.instanceCreation('Map<int>');
- assertInstanceCreation(
- creation,
- mapElement,
- 'Map<dynamic, dynamic>',
- expectedConstructorMember: true,
- expectedSubstitution: {'K': 'dynamic', 'V': 'dynamic'},
- );
+ var node = findNode.instanceCreation('Map<int>');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: Map
+ staticElement: dart:core::@class::Map
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ type: Map<dynamic, dynamic>
+ staticElement: ConstructorMember
+ base: dart:core::@class::Map::@constructor::•
+ substitution: {K: dynamic, V: dynamic}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: Map<dynamic, dynamic>
+''');
}
test_error_wrongNumberOfTypeArgumentsConstructor_explicitNew() async {
@@ -178,15 +315,42 @@
messageContains: ["The constructor 'Foo.bar'"]),
]);
- var creation = findNode.instanceCreation('Foo.bar<int>');
- assertInstanceCreation(
- creation,
- findElement.class_('Foo'),
- 'Foo<dynamic>',
- constructorName: 'bar',
- expectedConstructorMember: true,
- expectedSubstitution: {'X': 'dynamic'},
- );
+ var node = findNode.instanceCreation('Foo.bar<int>');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ keyword: new
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: Foo
+ staticElement: self::@class::Foo
+ staticType: null
+ type: Foo<dynamic>
+ period: .
+ name: SimpleIdentifier
+ token: bar
+ staticElement: ConstructorMember
+ base: self::@class::Foo::@constructor::bar
+ substitution: {X: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::Foo::@constructor::bar
+ substitution: {X: dynamic}
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: Foo<dynamic>
+''');
}
test_error_wrongNumberOfTypeArgumentsConstructor_explicitNew_new() async {
@@ -204,14 +368,42 @@
messageContains: ["The constructor 'Foo.new'"]),
]);
- var creation = findNode.instanceCreation('Foo.new<int>');
- assertInstanceCreation(
- creation,
- findElement.class_('Foo'),
- 'Foo<dynamic>',
- expectedConstructorMember: true,
- expectedSubstitution: {'X': 'dynamic'},
- );
+ var node = findNode.instanceCreation('Foo.new<int>');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ keyword: new
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: Foo
+ staticElement: self::@class::Foo
+ staticType: null
+ type: Foo<dynamic>
+ period: .
+ name: SimpleIdentifier
+ token: new
+ staticElement: ConstructorMember
+ base: self::@class::Foo::@constructor::•
+ substitution: {X: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::Foo::@constructor::•
+ substitution: {X: dynamic}
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: Foo<dynamic>
+''');
}
test_error_wrongNumberOfTypeArgumentsConstructor_explicitNew_prefix() async {
@@ -232,15 +424,50 @@
// TODO(brianwilkerson) Test this more carefully after we can re-write the
// AST to reflect the expected structure.
-// var creation = findNode.instanceCreation('Foo.bar<int>');
-// var import = findElement.import('package:test/a.dart');
-// assertInstanceCreation(
-// creation,
-// import.importedLibrary.getType('Foo'),
-// 'Foo',
-// constructorName: 'bar',
-// expectedPrefix: import.prefix,
-// );
+ var node = findNode.instanceCreation('Foo.bar<int>');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ keyword: new
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: self::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: Foo
+ staticElement: package:test/a.dart::@class::Foo
+ staticType: null
+ staticElement: package:test/a.dart::@class::Foo
+ staticType: null
+ type: Foo<dynamic>
+ period: .
+ name: SimpleIdentifier
+ token: bar
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::Foo::@constructor::bar
+ substitution: {X: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::Foo::@constructor::bar
+ substitution: {X: dynamic}
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: Foo<dynamic>
+''');
}
test_error_wrongNumberOfTypeArgumentsConstructor_implicitNew() async {
@@ -257,19 +484,41 @@
5),
]);
- var creation = findNode.instanceCreation('Foo.bar<int>');
- assertInstanceCreation(
- creation,
- findElement.class_('Foo'),
- // TODO(scheglov) Move type arguments
- 'Foo<dynamic>',
-// 'Foo<int>',
- constructorName: 'bar',
- expectedConstructorMember: true,
- // TODO(scheglov) Move type arguments
- expectedSubstitution: {'X': 'dynamic'},
-// expectedSubstitution: {'X': 'int'},
- );
+ var node = findNode.instanceCreation('Foo.bar<int>');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: Foo
+ staticElement: self::@class::Foo
+ staticType: null
+ type: Foo<dynamic>
+ period: .
+ name: SimpleIdentifier
+ token: bar
+ staticElement: ConstructorMember
+ base: self::@class::Foo::@constructor::bar
+ substitution: {X: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::Foo::@constructor::bar
+ substitution: {X: dynamic}
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: Foo<dynamic>
+''');
}
test_error_wrongNumberOfTypeArgumentsConstructor_implicitNew_prefix() async {
@@ -289,18 +538,49 @@
5),
]);
- var import = findElement.import('package:test/a.dart');
-
- var creation = findNode.instanceCreation('Foo.bar<int>');
- assertInstanceCreation(
- creation,
- import.importedLibrary!.getType('Foo')!,
- 'Foo<int>',
- constructorName: 'bar',
- expectedConstructorMember: true,
- expectedPrefix: import.prefix,
- expectedSubstitution: {'X': 'int'},
- );
+ var node = findNode.instanceCreation('Foo.bar<int>');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: self::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: Foo
+ staticElement: package:test/a.dart::@class::Foo
+ staticType: null
+ staticElement: package:test/a.dart::@class::Foo
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ type: Foo<int>
+ period: .
+ name: SimpleIdentifier
+ token: bar
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::Foo::@constructor::bar
+ substitution: {X: int}
+ staticType: null
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::Foo::@constructor::bar
+ substitution: {X: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: Foo<int>
+''');
}
test_namedArgument_anywhere() async {
@@ -324,11 +604,85 @@
}
''');
- assertInstanceCreation(
- findNode.instanceCreation('X(g'),
- findElement.class_('X'),
- 'X',
- );
+ var node = findNode.instanceCreation('X(g');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: X
+ staticElement: self::@class::X
+ staticType: null
+ type: X
+ staticElement: self::@class::X::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ MethodInvocation
+ methodName: SimpleIdentifier
+ token: g1
+ staticElement: self::@function::g1
+ staticType: T Function<T>()
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticInvokeType: A Function()
+ staticType: A
+ typeArgumentTypes
+ A
+ NamedExpression
+ name: Label
+ label: SimpleIdentifier
+ token: c
+ staticElement: self::@class::X::@constructor::•::@parameter::c
+ staticType: null
+ colon: :
+ expression: MethodInvocation
+ methodName: SimpleIdentifier
+ token: g3
+ staticElement: self::@function::g3
+ staticType: T Function<T>()
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticInvokeType: C? Function()
+ staticType: C?
+ typeArgumentTypes
+ C?
+ MethodInvocation
+ methodName: SimpleIdentifier
+ token: g2
+ staticElement: self::@function::g2
+ staticType: T Function<T>()
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticInvokeType: B Function()
+ staticType: B
+ typeArgumentTypes
+ B
+ NamedExpression
+ name: Label
+ label: SimpleIdentifier
+ token: d
+ staticElement: self::@class::X::@constructor::•::@parameter::d
+ staticType: null
+ colon: :
+ expression: MethodInvocation
+ methodName: SimpleIdentifier
+ token: g4
+ staticElement: self::@function::g4
+ staticType: T Function<T>()
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticInvokeType: D? Function()
+ staticType: D?
+ typeArgumentTypes
+ D?
+ rightParenthesis: )
+ staticType: X
+''');
var g1 = findNode.methodInvocation('g1()');
assertType(g1, 'A');
@@ -362,16 +716,35 @@
}
''');
- var creation = findNode.instanceCreation('B.named(0)');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int>',
- constructorName: 'named',
- expectedTypeNameElement: findElement.typeAlias('B'),
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- );
+ var node = findNode.instanceCreation('B.named(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: B
+ staticElement: self::@typeAlias::B
+ staticType: null
+ type: A<int>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: dynamic}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int>
+''');
}
test_typeAlias_generic_class_generic_named_infer_partial() async {
@@ -387,16 +760,37 @@
}
''');
- var creation = findNode.instanceCreation('B.named(0, ');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int, String>',
- constructorName: 'named',
- expectedTypeNameElement: findElement.typeAlias('B'),
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int', 'U': 'String'},
- );
+ var node = findNode.instanceCreation('B.named(0, ');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: B
+ staticElement: self::@typeAlias::B
+ staticType: null
+ type: A<int, String>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: dynamic, U: String}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: int, U: String}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ SimpleStringLiteral
+ literal: ''
+ rightParenthesis: )
+ staticType: A<int, String>
+''');
}
test_typeAlias_generic_class_generic_unnamed_infer_all() async {
@@ -412,15 +806,28 @@
}
''');
- var creation = findNode.instanceCreation('B(0)');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int>',
- expectedTypeNameElement: findElement.typeAlias('B'),
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int'},
- );
+ var node = findNode.instanceCreation('B(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: B
+ staticElement: self::@typeAlias::B
+ staticType: null
+ type: A<int>
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::•
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<int>
+''');
}
test_typeAlias_generic_class_generic_unnamed_infer_partial() async {
@@ -436,15 +843,30 @@
}
''');
- var creation = findNode.instanceCreation('B(0, ');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<int, String>',
- expectedTypeNameElement: findElement.typeAlias('B'),
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'int', 'U': 'String'},
- );
+ var node = findNode.instanceCreation('B(0, ');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: B
+ staticElement: self::@typeAlias::B
+ staticType: null
+ type: A<int, String>
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::•
+ substitution: {T: int, U: String}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ SimpleStringLiteral
+ literal: ''
+ rightParenthesis: )
+ staticType: A<int, String>
+''');
}
test_typeAlias_notGeneric_class_generic_named_argumentTypeMismatch() async {
@@ -462,16 +884,35 @@
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 77, 1),
]);
- var creation = findNode.instanceCreation('B.named(0)');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<String>',
- constructorName: 'named',
- expectedTypeNameElement: findElement.typeAlias('B'),
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'String'},
- );
+ var node = findNode.instanceCreation('B.named(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: B
+ staticElement: self::@typeAlias::B
+ staticType: null
+ type: A<String>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: String}
+ staticType: null
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::named
+ substitution: {T: String}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<String>
+''');
}
test_typeAlias_notGeneric_class_generic_unnamed_argumentTypeMismatch() async {
@@ -489,15 +930,28 @@
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 65, 1),
]);
- var creation = findNode.instanceCreation('B(0)');
- assertInstanceCreation(
- creation,
- findElement.class_('A'),
- 'A<String>',
- expectedTypeNameElement: findElement.typeAlias('B'),
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'String'},
- );
+ var node = findNode.instanceCreation('B(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: B
+ staticElement: self::@typeAlias::B
+ staticType: null
+ type: A<String>
+ staticElement: ConstructorMember
+ base: self::@class::A::@constructor::•
+ substitution: {T: String}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A<String>
+''');
}
test_unnamed_declaredNew() async {
@@ -512,8 +966,26 @@
''');
- var creation = findNode.instanceCreation('A(0)');
- assertInstanceCreation(creation, findElement.class_('A'), 'A');
+ var node = findNode.instanceCreation('A(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A
+ staticElement: self::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A
+''');
}
test_unnamedViaNew_declaredNew() async {
@@ -528,8 +1000,31 @@
''');
- var creation = findNode.instanceCreation('A.new(0)');
- assertInstanceCreation(creation, findElement.class_('A'), 'A');
+ var node = findNode.instanceCreation('A.new(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A
+ period: .
+ name: SimpleIdentifier
+ token: new
+ staticElement: self::@class::A::@constructor::•
+ staticType: null
+ staticElement: self::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A
+''');
}
test_unnamedViaNew_declaredUnnamed() async {
@@ -544,8 +1039,31 @@
''');
- var creation = findNode.instanceCreation('A.new(0)');
- assertInstanceCreation(creation, findElement.class_('A'), 'A');
+ var node = findNode.instanceCreation('A.new(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A
+ period: .
+ name: SimpleIdentifier
+ token: new
+ staticElement: self::@class::A::@constructor::•
+ staticType: null
+ staticElement: self::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A
+''');
}
}
@@ -567,7 +1085,30 @@
]);
// Resolution should continue even though the experiment is not enabled.
- var creation = findNode.instanceCreation('A.new(0)');
- assertInstanceCreation(creation, findElement.class_('A'), 'A');
+ var node = findNode.instanceCreation('A.new(0)');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A
+ period: .
+ name: SimpleIdentifier
+ token: new
+ staticElement: self::@class::A::@constructor::•
+ staticType: null
+ staticElement: self::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: A
+''');
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
index daa949c..a425545 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -17,98 +17,220 @@
@reflectiveTest
class OptionalConstDriverResolutionTest extends PubPackageResolutionTest {
- Map<String, LibraryElement> libraries = {};
-
- LibraryElement get libraryA => libraries['package:test/a.dart']!;
-
test_instantiateToBounds_notPrefixed_named() async {
- var creation = await _resolveImplicitConst('B.named()');
- assertInstanceCreation(
- creation,
- libraryA.getType('B')!,
- 'B<num>',
- constructorName: 'named',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'num'},
- );
+ var node = await _resolveImplicitConst('B.named()');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: B
+ staticElement: package:test/a.dart::@class::B
+ staticType: null
+ type: B<num>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::B::@constructor::named
+ substitution: {T: num}
+ staticType: null
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::B::@constructor::named
+ substitution: {T: num}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: B<num>
+''');
}
test_instantiateToBounds_notPrefixed_unnamed() async {
- var creation = await _resolveImplicitConst('B()');
- assertInstanceCreation(
- creation,
- libraryA.getType('B')!,
- 'B<num>',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'num'},
- );
+ var node = await _resolveImplicitConst('B()');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: B
+ staticElement: package:test/a.dart::@class::B
+ staticType: null
+ type: B<num>
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::B::@constructor::•
+ substitution: {T: num}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: B<num>
+''');
}
test_instantiateToBounds_prefixed_named() async {
- var creation = await _resolveImplicitConst('p.B.named()', prefix: 'p');
- assertInstanceCreation(
- creation,
- libraryA.getType('B')!,
- 'B<num>',
- constructorName: 'named',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'num'},
- expectedPrefix: _importOfA().prefix,
- );
+ var node = await _resolveImplicitConst('p.B.named()', prefix: 'p');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: package:test/b.dart::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: B
+ staticElement: package:test/a.dart::@class::B
+ staticType: null
+ staticElement: package:test/a.dart::@class::B
+ staticType: null
+ type: B<num>
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::B::@constructor::named
+ substitution: {T: num}
+ staticType: null
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::B::@constructor::named
+ substitution: {T: num}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: B<num>
+''');
}
test_instantiateToBounds_prefixed_unnamed() async {
- var creation = await _resolveImplicitConst('p.B()', prefix: 'p');
- assertInstanceCreation(
- creation,
- libraryA.getType('B')!,
- 'B<num>',
- expectedConstructorMember: true,
- expectedSubstitution: {'T': 'num'},
- expectedPrefix: _importOfA().prefix,
- );
+ var node = await _resolveImplicitConst('p.B()', prefix: 'p');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: package:test/b.dart::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: B
+ staticElement: package:test/a.dart::@class::B
+ staticType: null
+ staticElement: package:test/a.dart::@class::B
+ staticType: null
+ type: B<num>
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::B::@constructor::•
+ substitution: {T: num}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: B<num>
+''');
}
test_notPrefixed_named() async {
- var creation = await _resolveImplicitConst('A.named()');
- assertInstanceCreation(
- creation,
- libraryA.getType('A')!,
- 'A',
- constructorName: 'named',
- );
+ var node = await _resolveImplicitConst('A.named()');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ type: A
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: package:test/a.dart::@class::A::@constructor::named
+ staticType: null
+ staticElement: package:test/a.dart::@class::A::@constructor::named
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: A
+''');
}
test_notPrefixed_unnamed() async {
- var creation = await _resolveImplicitConst('A()');
- assertInstanceCreation(
- creation,
- libraryA.getType('A')!,
- 'A',
- );
+ var node = await _resolveImplicitConst('A()');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ type: A
+ staticElement: package:test/a.dart::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: A
+''');
}
test_prefixed_named() async {
- var creation = await _resolveImplicitConst('p.A.named()', prefix: 'p');
- // Note, that we don't resynthesize the import prefix.
- assertInstanceCreation(
- creation,
- libraryA.getType('A')!,
- 'A',
- constructorName: 'named',
- expectedPrefix: _importOfA().prefix,
- );
+ var node = await _resolveImplicitConst('p.A.named()', prefix: 'p');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: package:test/b.dart::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: A
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ type: A
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: package:test/a.dart::@class::A::@constructor::named
+ staticType: null
+ staticElement: package:test/a.dart::@class::A::@constructor::named
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: A
+''');
}
test_prefixed_unnamed() async {
- var creation = await _resolveImplicitConst('p.A()', prefix: 'p');
- // Note, that we don't resynthesize the import prefix.
- assertInstanceCreation(
- creation,
- libraryA.getType('A')!,
- 'A',
- expectedPrefix: _importOfA().prefix,
- );
+ var node = await _resolveImplicitConst('p.A()', prefix: 'p');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: package:test/b.dart::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: A
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ staticElement: package:test/a.dart::@class::A
+ staticType: null
+ type: A
+ staticElement: package:test/a.dart::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: A
+''');
}
test_prefixed_unnamed_generic() async {
@@ -117,52 +239,49 @@
const C();
}
''');
+
await assertNoErrorsInCode(r'''
import 'a.dart' as p;
const x = p.C<int>();
''');
- _fillLibraries();
- var element_C = libraryA.getType('C');
- var element_p = findElement.prefix('p');
-
- var creation = findNode.instanceCreation('p.C<int>()');
- assertType(creation, 'C<int>');
-
- var constructorName = creation.constructorName;
-
- var typeName = constructorName.type;
- assertType(typeName, 'C<int>');
-
- var pC = typeName.name as PrefixedIdentifier;
- assertElement(pC, element_C);
- // TODO(scheglov) enforce
-// assertTypeNull(pC);
-
- var ref_p = pC.prefix;
- assertElement(ref_p, element_p);
- assertTypeNull(ref_p);
-
- var ref_C = pC.identifier;
- assertElement(ref_C, element_C);
- assertTypeNull(ref_C);
-
- assertType(typeName.typeArguments!.arguments[0], 'int');
- }
-
- void _fillLibraries([LibraryElement? library]) {
- library ??= result.unit.declaredElement!.library;
- var uriStr = library.source.uri.toString();
- if (!libraries.containsKey(uriStr)) {
- libraries[uriStr] = library;
- library.importedLibraries.forEach(_fillLibraries);
- }
- }
-
- ImportElement _importOfA() {
- var importOfB = findElement.import('package:test/b.dart');
- return importOfB.importedLibrary!.imports[0];
+ var node = findNode.instanceCreation('p.C<int>()');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: self::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: C
+ staticElement: package:test/a.dart::@class::C
+ staticType: null
+ staticElement: package:test/a.dart::@class::C
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ type: C<int>
+ staticElement: ConstructorMember
+ base: package:test/a.dart::@class::C::@constructor::•
+ substitution: {T: int}
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: C<int>
+''');
}
Future<InstanceCreationExpression> _resolveImplicitConst(String expr,
@@ -194,7 +313,6 @@
import 'b.dart';
var v = a;
''');
- _fillLibraries();
var vg = findNode.simple('a;').staticElement as PropertyAccessorElement;
var v = vg.variable as ConstVariableElement;
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 8744443..002686b 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -384,54 +384,6 @@
assertTypeNull(identifier);
}
- /// TODO(srawlins): Refactor to accept an `Object? expectedConstructor` which
- /// can accept `elementMatcher` for generics, and simplify, similar to
- /// `assertConstructorReference`.
- void assertInstanceCreation(
- InstanceCreationExpression creation,
- ClassElement expectedClassElement,
- String expectedType, {
- String? constructorName,
- bool expectedConstructorMember = false,
- Map<String, String>? expectedSubstitution,
- PrefixElement? expectedPrefix,
- Element? expectedTypeNameElement,
- }) {
- var expectedConstructorElement =
- _getConstructorElement(expectedClassElement, constructorName);
-
- var actualConstructorElement =
- getNodeElement(creation) as ConstructorElement?;
- var constructorName2 = creation.constructorName.name;
- if (constructorName2 != null) {
- // TODO(brianwilkerson) This used to enforce that the two elements were
- // the same object, but the changes to the AstRewriteVisitor broke that.
- // We should explore re-establishing this restriction for performance.
- assertConstructorElement(
- constructorName2.staticElement as ConstructorElement?,
- actualConstructorElement,
- );
- }
-
- if (expectedConstructorMember) {
- expect(actualConstructorElement, const TypeMatcher<Member>());
- assertMember(
- creation,
- expectedConstructorElement,
- expectedSubstitution!,
- );
- } else {
- assertElement(creation, expectedConstructorElement);
- }
-
- assertType(creation, expectedType);
-
- var namedType = creation.constructorName.type;
- expectedTypeNameElement ??= expectedClassElement;
- assertNamedType(namedType, expectedTypeNameElement, expectedType,
- expectedPrefix: expectedPrefix);
- }
-
/// Resolve the [code], and ensure that it can be resolved without a crash,
/// and is invalid, i.e. produces a diagnostic.
Future<void> assertInvalidTestCode(String code) async {
@@ -566,8 +518,15 @@
assertType(node.staticType, type);
}
- void assertResolvedNodeText(AstNode node, String expected) {
- var actual = _resolvedNodeText(node);
+ void assertResolvedNodeText(
+ AstNode node,
+ String expected, {
+ bool skipArgumentList = false,
+ }) {
+ var actual = _resolvedNodeText(
+ node,
+ skipArgumentList: skipArgumentList,
+ );
if (actual != expected) {
print(actual);
NodeTextExpectationsCollector.add(actual);
@@ -935,23 +894,17 @@
fail('Expected SimpleIdentifier: (${node.runtimeType}) $node');
}
- ConstructorElement _getConstructorElement(
- ClassElement classElement, String? constructorName) {
- var constructorElement = constructorName == null
- ? classElement.unnamedConstructor
- : classElement.getNamedConstructor(constructorName);
- return constructorElement ??
- fail("No constructor '${constructorName ?? '<unnamed>'}' in class "
- "'${classElement.name}'.");
- }
-
- String _resolvedNodeText(AstNode node) {
+ String _resolvedNodeText(
+ AstNode node, {
+ bool skipArgumentList = false,
+ }) {
var buffer = StringBuffer();
node.accept(
ResolvedAstPrinter(
selfUriStr: result.uri.toString(),
sink: buffer,
indent: '',
+ skipArgumentList: skipArgumentList,
),
);
return buffer.toString();
diff --git a/pkg/analyzer/test/src/dart/resolution/variance_test.dart b/pkg/analyzer/test/src/dart/resolution/variance_test.dart
index 34067a8..96e40ac 100644
--- a/pkg/analyzer/test/src/dart/resolution/variance_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/variance_test.dart
@@ -2,7 +2,6 @@
// 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:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -39,9 +38,22 @@
inferContraContra(Contravariant<Upper>(), Contravariant<Middle>());
}
''');
- assertType(
- findNode.methodInvocation('inferContraContra(').typeArgumentTypes![0],
- 'Middle');
+
+ var node = findNode.methodInvocation('inferContraContra(');
+ assertResolvedNodeText(
+ node,
+ r'''
+MethodInvocation
+ methodName: SimpleIdentifier
+ token: inferContraContra
+ staticElement: self::@function::inferContraContra
+ staticType: Exactly<T> Function<T>(Contravariant<T>, Contravariant<T>)
+ staticInvokeType: Exactly<Middle> Function(Contravariant<Middle>, Contravariant<Middle>)
+ staticType: Exactly<Middle>
+ typeArgumentTypes
+ Middle
+''',
+ skipArgumentList: true);
}
test_inference_in_parameter_downwards() async {
@@ -52,15 +64,30 @@
}
main() {
- B<int> b = new B(<num>[])..x=2.2;
+ B<int> b = B(<num>[])..x=2.2;
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 76, 1),
]);
- assertType(
- (findNode.instanceCreation('new B').staticType as InterfaceType)
- .typeArguments[0],
- 'num');
+
+ var node = findNode.instanceCreation('B(<num>');
+ assertResolvedNodeText(
+ node,
+ r'''
+InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: B
+ staticElement: self::@class::B
+ staticType: null
+ type: B<num>
+ staticElement: ConstructorMember
+ base: self::@class::B::@constructor::•
+ substitution: {T: num}
+ staticType: B<num>
+''',
+ skipArgumentList: true);
}
test_inference_inout_parameter() async {
@@ -79,6 +106,22 @@
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 159, 19),
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 180, 16),
]);
+
+ var node = findNode.methodInvocation('inferInvInv(');
+ assertResolvedNodeText(
+ node,
+ r'''
+MethodInvocation
+ methodName: SimpleIdentifier
+ token: inferInvInv
+ staticElement: self::@function::inferInvInv
+ staticType: Exactly<T> Function<T>(Invariant<T>, Invariant<T>)
+ staticInvokeType: Exactly<Object> Function(Invariant<Object>, Invariant<Object>)
+ staticType: Exactly<Object>
+ typeArgumentTypes
+ Object
+''',
+ skipArgumentList: true);
}
test_inference_out_parameter() async {
@@ -96,7 +139,21 @@
inferCovCov(Covariant<Upper>(), Covariant<Middle>());
}
''');
- assertType(findNode.methodInvocation('inferCovCov(').typeArgumentTypes![0],
- 'Upper');
+
+ var node = findNode.methodInvocation('inferCovCov(');
+ assertResolvedNodeText(
+ node,
+ r'''
+MethodInvocation
+ methodName: SimpleIdentifier
+ token: inferCovCov
+ staticElement: self::@function::inferCovCov
+ staticType: Exactly<T> Function<T>(Covariant<T>, Covariant<T>)
+ staticInvokeType: Exactly<Upper> Function(Covariant<Upper>, Covariant<Upper>)
+ staticType: Exactly<Upper>
+ typeArgumentTypes
+ Upper
+''',
+ skipArgumentList: true);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_instantiate_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_instantiate_test.dart
index 8dd5c55..7bcc0e2 100644
--- a/pkg/analyzer/test/src/diagnostics/mixin_instantiate_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/mixin_instantiate_test.dart
@@ -30,9 +30,28 @@
error(CompileTimeErrorCode.MIXIN_INSTANTIATE, 43, 1),
]);
- var creation = findNode.instanceCreation('M.named();');
- var m = findElement.mixin('M');
- assertInstanceCreation(creation, m, 'M', constructorName: 'named');
+ var node = findNode.instanceCreation('M.named();');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ keyword: new
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: M
+ staticElement: self::@mixin::M
+ staticType: null
+ type: M
+ period: .
+ name: SimpleIdentifier
+ token: named
+ staticElement: self::@mixin::M::@constructor::named
+ staticType: null
+ staticElement: self::@mixin::M::@constructor::named
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: M
+''');
}
test_namedConstructor_undefined() async {
@@ -62,8 +81,22 @@
error(CompileTimeErrorCode.MIXIN_INSTANTIATE, 27, 1),
]);
- var creation = findNode.instanceCreation('M();');
- var m = findElement.mixin('M');
- assertInstanceCreation(creation, m, 'M');
+ var node = findNode.instanceCreation('M();');
+ assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+ keyword: new
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: M
+ staticElement: self::@mixin::M
+ staticType: null
+ type: M
+ staticElement: self::@mixin::M::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: M
+''');
}
}
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index e0617b5..f8a4382c 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -15,15 +15,6 @@
import 'package:analyzer/src/summary2/reference.dart';
import 'package:test/test.dart';
-/// Used in [ResolvedAstPrinter] to print lines of code that corresponding
-/// to a subtree of AST. This help to make the bulky presentation of AST a
-/// bit more understandable.
-abstract class CodeLinesProvider {
- /// If the [offset] corresponds to a new, never requested before line,
- /// return this line, otherwise return `null`.
- String nextLine(int offset);
-}
-
/// Prints AST as a tree, with properties and children.
class ResolvedAstPrinter extends ThrowingAstVisitor<void> {
/// The URI of the library that contains the AST being printed.
@@ -32,8 +23,7 @@
/// The target sink to print AST.
final StringSink _sink;
- /// The optional provider for code lines, might be `null`.
- final CodeLinesProvider? _codeLinesProvider;
+ final bool skipArgumentList;
/// If `true`, linking of [EnumConstantDeclaration] will be checked
/// TODO(scheglov) Remove after https://github.com/dart-lang/sdk/issues/48380
@@ -51,20 +41,18 @@
required String? selfUriStr,
required StringSink sink,
required String indent,
- CodeLinesProvider? codeLinesProvider,
+ this.skipArgumentList = false,
this.withCheckingLinking = false,
bool withOffsets = false,
bool withResolution = true,
}) : _selfUriStr = selfUriStr,
_sink = sink,
- _codeLinesProvider = codeLinesProvider,
_withOffsets = withOffsets,
_withResolution = withResolution,
_indent = indent;
@override
void visitAdjacentStrings(AdjacentStrings node) {
- _writeNextCodeLine(node);
_writeln('AdjacentStrings');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -75,7 +63,6 @@
@override
void visitAnnotation(Annotation node) {
- _writeNextCodeLine(node);
_writeln('Annotation');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -85,7 +72,6 @@
@override
void visitArgumentList(ArgumentList node) {
- _writeNextCodeLine(node);
_writeln('ArgumentList');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -94,7 +80,6 @@
@override
void visitAsExpression(AsExpression node) {
- _writeNextCodeLine(node);
_writeln('AsExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -104,7 +89,6 @@
@override
void visitAssertInitializer(AssertInitializer node) {
- _writeNextCodeLine(node);
_writeln('AssertInitializer');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -113,7 +97,6 @@
@override
void visitAssertStatement(AssertStatement node) {
- _writeNextCodeLine(node);
_writeln('AssertStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -122,7 +105,6 @@
@override
void visitAssignmentExpression(AssignmentExpression node) {
- _writeNextCodeLine(node);
_writeln('AssignmentExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -137,7 +119,6 @@
@override
void visitAwaitExpression(AwaitExpression node) {
- _writeNextCodeLine(node);
_writeln('AwaitExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -147,7 +128,6 @@
@override
void visitBinaryExpression(BinaryExpression node) {
- _writeNextCodeLine(node);
_writeln('BinaryExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -159,7 +139,6 @@
@override
void visitBlock(Block node) {
- _writeNextCodeLine(node);
_writeln('Block');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -168,7 +147,6 @@
@override
void visitBlockFunctionBody(BlockFunctionBody node) {
- _writeNextCodeLine(node);
_writeln('BlockFunctionBody');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -177,7 +155,6 @@
@override
void visitBooleanLiteral(BooleanLiteral node) {
- _writeNextCodeLine(node);
_writeln('BooleanLiteral');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -187,7 +164,6 @@
@override
void visitBreakStatement(BreakStatement node) {
- _writeNextCodeLine(node);
_writeln('BreakStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -196,7 +172,6 @@
@override
void visitCascadeExpression(CascadeExpression node) {
- _writeNextCodeLine(node);
_writeln('CascadeExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -206,7 +181,6 @@
@override
void visitCatchClause(CatchClause node) {
- _writeNextCodeLine(node);
_writeln('CatchClause');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -215,7 +189,6 @@
@override
void visitClassDeclaration(ClassDeclaration node) {
- _writeNextCodeLine(node);
_writeln('ClassDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -227,7 +200,6 @@
@override
void visitComment(Comment node) {
- _writeNextCodeLine(node);
_writeln('Comment');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -236,7 +208,6 @@
@override
void visitCompilationUnit(CompilationUnit node) {
- _writeNextCodeLine(node);
_writeln('CompilationUnit');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -245,7 +216,6 @@
@override
void visitConditionalExpression(ConditionalExpression node) {
- _writeNextCodeLine(node);
_writeln('ConditionalExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -255,7 +225,6 @@
@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
- _writeNextCodeLine(node);
_writeln('ConstructorDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -267,7 +236,6 @@
@override
void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
- _writeNextCodeLine(node);
_writeln('ConstructorFieldInitializer');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -276,7 +244,6 @@
@override
void visitConstructorName(ConstructorName node) {
- _writeNextCodeLine(node);
_writeln('ConstructorName');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -304,7 +271,6 @@
@override
void visitContinueStatement(ContinueStatement node) {
- _writeNextCodeLine(node);
_writeln('ContinueStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -313,7 +279,6 @@
@override
void visitDeclaredIdentifier(DeclaredIdentifier node) {
- _writeNextCodeLine(node);
_writeln('DeclaredIdentifier');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -325,7 +290,6 @@
@override
void visitDefaultFormalParameter(DefaultFormalParameter node) {
- _writeNextCodeLine(node);
_writeln('DefaultFormalParameter');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -338,7 +302,6 @@
@override
void visitDoStatement(DoStatement node) {
- _writeNextCodeLine(node);
_writeln('DoStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -347,7 +310,6 @@
@override
void visitDoubleLiteral(DoubleLiteral node) {
- _writeNextCodeLine(node);
_writeln('DoubleLiteral');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -357,7 +319,6 @@
@override
void visitEmptyFunctionBody(EmptyFunctionBody node) {
- _writeNextCodeLine(node);
_writeln('EmptyFunctionBody');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -378,7 +339,6 @@
@override
void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
_checkChildrenEntitiesLinking(node);
- _writeNextCodeLine(node);
_writeln('EnumConstantDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -390,7 +350,6 @@
@override
void visitEnumDeclaration(EnumDeclaration node) {
- _writeNextCodeLine(node);
_writeln('EnumDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -402,7 +361,6 @@
@override
void visitExportDirective(ExportDirective node) {
- _writeNextCodeLine(node);
_writeln('ExportDirective');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -417,7 +375,6 @@
@override
void visitExpressionFunctionBody(ExpressionFunctionBody node) {
- _writeNextCodeLine(node);
_writeln('ExpressionFunctionBody');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -426,7 +383,6 @@
@override
void visitExpressionStatement(ExpressionStatement node) {
- _writeNextCodeLine(node);
_writeln('ExpressionStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -435,7 +391,6 @@
@override
void visitExtendsClause(ExtendsClause node) {
- _writeNextCodeLine(node);
_writeln('ExtendsClause');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -444,7 +399,6 @@
@override
void visitExtensionOverride(ExtensionOverride node) {
- _writeNextCodeLine(node);
_writeln('ExtensionOverride');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -456,7 +410,6 @@
@override
void visitFieldDeclaration(FieldDeclaration node) {
- _writeNextCodeLine(node);
_writeln('FieldDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -468,7 +421,6 @@
@override
void visitFieldFormalParameter(FieldFormalParameter node) {
- _writeNextCodeLine(node);
_writeln('FieldFormalParameter');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -481,7 +433,6 @@
@override
void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
- _writeNextCodeLine(node);
_writeln('ForEachPartsWithDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -490,7 +441,6 @@
@override
void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
- _writeNextCodeLine(node);
_writeln('ForEachPartsWithIdentifier');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -499,7 +449,6 @@
@override
void visitFormalParameterList(FormalParameterList node) {
- _writeNextCodeLine(node);
_writeln('FormalParameterList');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -508,7 +457,6 @@
@override
void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
- _writeNextCodeLine(node);
_writeln('ForPartsWithDeclarations');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -517,7 +465,6 @@
@override
void visitForPartsWithExpression(ForPartsWithExpression node) {
- _writeNextCodeLine(node);
_writeln('ForPartsWithExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -526,7 +473,6 @@
@override
void visitForStatement(ForStatement node) {
- _writeNextCodeLine(node);
_writeln('ForStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -535,7 +481,6 @@
@override
void visitFunctionDeclaration(FunctionDeclaration node) {
- _writeNextCodeLine(node);
_writeln('FunctionDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -548,7 +493,6 @@
@override
void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
- _writeNextCodeLine(node);
_writeln('FunctionDeclarationStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -557,7 +501,6 @@
@override
void visitFunctionExpression(FunctionExpression node) {
- _writeNextCodeLine(node);
_writeln('FunctionExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -570,7 +513,6 @@
@override
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
- _writeNextCodeLine(node);
_writeln('FunctionExpressionInvocation');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -593,7 +535,6 @@
@override
void visitFunctionTypeAlias(FunctionTypeAlias node) {
- _writeNextCodeLine(node);
_writeln('FunctionTypeAlias');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -605,7 +546,6 @@
@override
void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
- _writeNextCodeLine(node);
_writeln('FunctionTypedFormalParameter');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -618,7 +558,6 @@
@override
void visitGenericFunctionType(covariant GenericFunctionTypeImpl node) {
- _writeNextCodeLine(node);
_writeln('GenericFunctionType');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -634,7 +573,6 @@
@override
void visitGenericTypeAlias(GenericTypeAlias node) {
- _writeNextCodeLine(node);
_writeln('GenericTypeAlias');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -646,7 +584,6 @@
@override
void visitHideCombinator(HideCombinator node) {
- _writeNextCodeLine(node);
_writeln('HideCombinator');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -663,7 +600,6 @@
@override
void visitIfStatement(IfStatement node) {
- _writeNextCodeLine(node);
_writeln('IfStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -672,7 +608,6 @@
@override
void visitImplementsClause(ImplementsClause node) {
- _writeNextCodeLine(node);
_writeln('ImplementsClause');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -692,7 +627,6 @@
@override
void visitImportDirective(ImportDirective node) {
- _writeNextCodeLine(node);
_writeln('ImportDirective');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -707,7 +641,6 @@
@override
void visitIndexExpression(IndexExpression node) {
- _writeNextCodeLine(node);
_writeln('IndexExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -718,7 +651,6 @@
@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
- _writeNextCodeLine(node);
_writeln('InstanceCreationExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -728,7 +660,6 @@
@override
void visitIntegerLiteral(IntegerLiteral node) {
- _writeNextCodeLine(node);
_writeln('IntegerLiteral');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -738,7 +669,6 @@
@override
void visitInterpolationExpression(InterpolationExpression node) {
- _writeNextCodeLine(node);
_writeln('InterpolationExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -747,7 +677,6 @@
@override
void visitInterpolationString(InterpolationString node) {
- _writeNextCodeLine(node);
_writeln('InterpolationString');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -756,7 +685,6 @@
@override
void visitIsExpression(IsExpression node) {
- _writeNextCodeLine(node);
_writeln('IsExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -766,7 +694,6 @@
@override
void visitLabel(Label node) {
- _writeNextCodeLine(node);
_writeln('Label');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -775,7 +702,6 @@
@override
void visitLibraryDirective(LibraryDirective node) {
- _writeNextCodeLine(node);
_writeln('LibraryDirective');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -785,7 +711,6 @@
@override
void visitLibraryIdentifier(LibraryIdentifier node) {
- _writeNextCodeLine(node);
_writeln('LibraryIdentifier');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -796,7 +721,6 @@
@override
void visitListLiteral(ListLiteral node) {
- _writeNextCodeLine(node);
_writeln('ListLiteral');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -806,7 +730,6 @@
@override
void visitMapLiteralEntry(MapLiteralEntry node) {
- _writeNextCodeLine(node);
_writeln('SetOrMapLiteral');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -815,7 +738,6 @@
@override
void visitMethodDeclaration(MethodDeclaration node) {
- _writeNextCodeLine(node);
_writeln('MethodDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -828,7 +750,6 @@
@override
void visitMethodInvocation(MethodInvocation node) {
- _writeNextCodeLine(node);
_writeln('MethodInvocation');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -840,7 +761,6 @@
@override
void visitMixinDeclaration(MixinDeclaration node) {
- _writeNextCodeLine(node);
_writeln('MixinDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -852,7 +772,6 @@
@override
void visitNamedExpression(NamedExpression node) {
- _writeNextCodeLine(node);
_writeln('NamedExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -861,7 +780,6 @@
@override
void visitNamedType(NamedType node) {
- _writeNextCodeLine(node);
_writeln('NamedType');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -871,7 +789,6 @@
@override
void visitNullLiteral(NullLiteral node) {
- _writeNextCodeLine(node);
_writeln('NullLiteral');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -881,7 +798,6 @@
@override
void visitOnClause(OnClause node) {
- _writeNextCodeLine(node);
_writeln('OnClause');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -890,7 +806,6 @@
@override
void visitParenthesizedExpression(ParenthesizedExpression node) {
- _writeNextCodeLine(node);
_writeln('ParenthesizedExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -900,7 +815,6 @@
@override
void visitPartDirective(PartDirective node) {
- _writeNextCodeLine(node);
_writeln('PartDirective');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -913,7 +827,6 @@
@override
void visitPartOfDirective(PartOfDirective node) {
- _writeNextCodeLine(node);
_writeln('PartOfDirective');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -923,7 +836,6 @@
@override
void visitPostfixExpression(PostfixExpression node) {
- _writeNextCodeLine(node);
_writeln('PostfixExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -940,7 +852,6 @@
@override
void visitPrefixedIdentifier(PrefixedIdentifier node) {
- _writeNextCodeLine(node);
_writeln('PrefixedIdentifier');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -951,7 +862,6 @@
@override
void visitPrefixExpression(PrefixExpression node) {
- _writeNextCodeLine(node);
_writeln('PrefixExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -968,7 +878,6 @@
@override
void visitPropertyAccess(PropertyAccess node) {
- _writeNextCodeLine(node);
_writeln('PropertyAccess');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -980,7 +889,6 @@
void visitRedirectingConstructorInvocation(
RedirectingConstructorInvocation node,
) {
- _writeNextCodeLine(node);
_writeln('RedirectingConstructorInvocation');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -990,7 +898,6 @@
@override
void visitReturnStatement(ReturnStatement node) {
- _writeNextCodeLine(node);
_writeln('ReturnStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -999,7 +906,6 @@
@override
void visitSetOrMapLiteral(SetOrMapLiteral node) {
- _writeNextCodeLine(node);
_writeln('SetOrMapLiteral');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1010,7 +916,6 @@
@override
void visitShowCombinator(ShowCombinator node) {
- _writeNextCodeLine(node);
_writeln('ShowCombinator');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1019,7 +924,6 @@
@override
void visitSimpleFormalParameter(SimpleFormalParameter node) {
- _writeNextCodeLine(node);
_writeln('SimpleFormalParameter');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1032,7 +936,6 @@
@override
void visitSimpleIdentifier(SimpleIdentifier node) {
- _writeNextCodeLine(node);
_writeln('SimpleIdentifier');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1047,7 +950,6 @@
@override
void visitSimpleStringLiteral(SimpleStringLiteral node) {
- _writeNextCodeLine(node);
_writeln('SimpleStringLiteral');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1064,7 +966,6 @@
@override
void visitStringInterpolation(StringInterpolation node) {
- _writeNextCodeLine(node);
_writeln('StringInterpolation');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1075,7 +976,6 @@
@override
void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
- _writeNextCodeLine(node);
_writeln('SuperConstructorInvocation');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1085,7 +985,6 @@
@override
void visitSuperExpression(SuperExpression node) {
- _writeNextCodeLine(node);
_writeln('SuperExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1098,7 +997,6 @@
if (withCheckingLinking) {
_checkChildrenEntitiesLinking(node);
}
- _writeNextCodeLine(node);
_writeln('SuperFormalParameter');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1111,7 +1009,6 @@
@override
void visitSwitchCase(SwitchCase node) {
- _writeNextCodeLine(node);
_writeln('SwitchCase');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1120,7 +1017,6 @@
@override
void visitSwitchDefault(SwitchDefault node) {
- _writeNextCodeLine(node);
_writeln('SwitchDefault');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1129,7 +1025,6 @@
@override
void visitSwitchStatement(SwitchStatement node) {
- _writeNextCodeLine(node);
_writeln('SwitchStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1146,7 +1041,6 @@
@override
void visitThisExpression(ThisExpression node) {
- _writeNextCodeLine(node);
_writeln('ThisExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1156,7 +1050,6 @@
@override
void visitThrowExpression(ThrowExpression node) {
- _writeNextCodeLine(node);
_writeln('ThrowExpression');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1166,7 +1059,6 @@
@override
void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- _writeNextCodeLine(node);
_writeln('TopLevelVariableDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1178,7 +1070,6 @@
@override
void visitTryStatement(TryStatement node) {
- _writeNextCodeLine(node);
_writeln('TryStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1187,7 +1078,6 @@
@override
void visitTypeArgumentList(TypeArgumentList node) {
- _writeNextCodeLine(node);
_writeln('TypeArgumentList');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1205,7 +1095,6 @@
@override
void visitTypeParameter(TypeParameter node) {
- _writeNextCodeLine(node);
_writeln('TypeParameter');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1217,7 +1106,6 @@
@override
void visitTypeParameterList(TypeParameterList node) {
- _writeNextCodeLine(node);
_writeln('TypeParameterList');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1226,7 +1114,6 @@
@override
void visitVariableDeclaration(VariableDeclaration node) {
- _writeNextCodeLine(node);
_writeln('VariableDeclaration');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1238,7 +1125,6 @@
@override
void visitVariableDeclarationList(VariableDeclarationList node) {
- _writeNextCodeLine(node);
_writeln('VariableDeclarationList');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1247,7 +1133,6 @@
@override
void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
- _writeNextCodeLine(node);
_writeln('VariableDeclarationStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1256,7 +1141,6 @@
@override
void visitWhileStatement(WhileStatement node) {
- _writeNextCodeLine(node);
_writeln('WhileStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1265,7 +1149,6 @@
@override
void visitWithClause(WithClause node) {
- _writeNextCodeLine(node);
_writeln('WithClause');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1274,7 +1157,6 @@
@override
void visitYieldStatement(YieldStatement node) {
- _writeNextCodeLine(node);
_writeln('YieldStatement');
_withIndent(() {
_writeNamedChildEntities(node);
@@ -1452,7 +1334,10 @@
if (value is Token) {
_writeToken(entity.name, value);
} else if (value is AstNode) {
- _writeNode(entity.name, value);
+ if (value is ArgumentList && skipArgumentList) {
+ } else {
+ _writeNode(entity.name, value);
+ }
} else if (value is List<Token>) {
_writeTokenList(entity.name, value);
} else if (value is List<AstNode>) {
@@ -1463,15 +1348,6 @@
}
}
- void _writeNextCodeLine(AstNode node) {
- var nextCodeLine = _codeLinesProvider?.nextLine(node.offset);
- if (nextCodeLine != null) {
- nextCodeLine = nextCodeLine.trim();
- _sink.writeln('// $nextCodeLine');
- _sink.write(_indent);
- }
- }
-
void _writeNode(String name, AstNode? node) {
if (node != null) {
_sink.write(_indent);
diff --git a/pkg/analyzer/test/util/feature_sets.dart b/pkg/analyzer/test/util/feature_sets.dart
index 85a4cd9..53627ba 100644
--- a/pkg/analyzer/test/util/feature_sets.dart
+++ b/pkg/analyzer/test/util/feature_sets.dart
@@ -37,8 +37,9 @@
static final FeatureSet latestWithExperiments = FeatureSet.fromEnableFlags2(
sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: [
- EnableString.constructor_tearoffs,
EnableString.enhanced_enums,
+ EnableString.macros,
+ EnableString.named_arguments_anywhere,
EnableString.super_parameters,
],
);
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 295bc86..9b497f6 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -112,6 +112,12 @@
allowed: verbosityOption.allowed,
allowedHelp: verbosityOption.allowedHelp,
)
+ ..addOption(
+ packagesOption.flag,
+ abbr: packagesOption.abbr,
+ valueHelp: packagesOption.valueHelp,
+ help: packagesOption.help,
+ )
..addMultiOption(
defineOption.flag,
help: defineOption.help,
@@ -158,12 +164,18 @@
final enabledExperiments = args.enabledExperiments;
final environmentVars = args['define'] ?? <String, String>{};
+
// Build arguments.
- List<String> buildArgs = [];
+ final buildArgs = <String>[];
buildArgs.add('--snapshot-kind=$formatName');
buildArgs.add('--snapshot=${path.canonicalize(outputFile)}');
- String? verbosity = args[verbosityOption.flag];
+ final String? packages = args[packagesOption.flag];
+ if (packages != null) {
+ buildArgs.add('--packages=$packages');
+ }
+
+ final String? verbosity = args[verbosityOption.flag];
buildArgs.add('--verbosity=$verbosity');
if (enabledExperiments.isNotEmpty) {
@@ -226,13 +238,12 @@
)
..addFlag('enable-asserts',
negatable: false, help: 'Enable assert statements.')
- ..addOption('packages',
- abbr: 'p',
- valueHelp: 'path',
- help:
- '''Get package locations from the specified file instead of .packages.
-<path> can be relative or absolute.
-For example: dart compile $commandName --packages=/tmp/pkgs main.dart''')
+ ..addOption(
+ packagesOption.flag,
+ abbr: packagesOption.abbr,
+ valueHelp: packagesOption.valueHelp,
+ help: packagesOption.help,
+ )
..addFlag('sound-null-safety',
help: 'Respect the nullability of types at runtime.',
defaultsTo: null)
@@ -319,7 +330,9 @@
allowed: Verbosity.allowedValues,
allowedHelp: Verbosity.allowedValuesHelp,
);
+
late final Option defineOption;
+ late final Option packagesOption;
CompileSubcommandCommand(String name, String description, bool verbose,
{bool hidden = false})
@@ -331,6 +344,14 @@
Define an environment declaration. To specify multiple declarations, use multiple options or use commas to separate key-value pairs.
For example: dart compile $name -Da=1,b=2 main.dart''',
),
+ packagesOption = Option(
+ flag: 'packages',
+ abbr: 'p',
+ valueHelp: 'path',
+ help:
+ '''Get package locations from the specified file instead of .packages.
+<path> can be relative or absolute.
+For example: dart compile $name --packages=/tmp/pkgs main.dart'''),
super(name, description, verbose, hidden: hidden);
}
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_47020.dart b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart
new file mode 100644
index 0000000..2a6f3cb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart
@@ -0,0 +1,6 @@
+void main() {
+ Function? f = () {
+ print(1)
+ };
+ f();
+}
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.expect
new file mode 100644
index 0000000..3bc47da
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.expect
@@ -0,0 +1,56 @@
+Problems reported:
+
+parser/nnbd/issue_47020:3:12: Expected ';' after this.
+ print(1)
+ ^
+
+beginCompilationUnit(void)
+ beginMetadataStar(void)
+ endMetadataStar(0)
+ beginTopLevelMember(void)
+ beginTopLevelMethod(, null, null)
+ handleVoidKeyword(void)
+ handleIdentifier(main, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ beginMetadataStar(Function)
+ endMetadataStar(0)
+ handleIdentifier(Function, typeReference)
+ handleNoTypeArguments(?)
+ handleType(Function, ?)
+ beginVariablesDeclaration(f, null, null)
+ handleIdentifier(f, localVariableDeclaration)
+ beginInitializedIdentifier(f)
+ beginVariableInitializer(=)
+ handleNoTypeVariables(()
+ beginFunctionExpression(()
+ beginFormalParameters((, MemberKind.Local)
+ endFormalParameters(0, (, ), MemberKind.Local)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(print, expression)
+ handleNoTypeArguments(()
+ beginArguments(()
+ handleLiteralInt(1)
+ endArguments(1, (, ))
+ handleSend(print, })
+ handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endFunctionExpression((, ;)
+ endVariableInitializer(=)
+ endInitializedIdentifier(f)
+ endVariablesDeclaration(1, ;)
+ handleIdentifier(f, expression)
+ handleNoTypeArguments(()
+ beginArguments(()
+ endArguments(0, (, ))
+ handleSend(f, ;)
+ handleExpressionStatement(;)
+ endBlockFunctionBody(2, {, })
+ endTopLevelMethod(void, null, })
+ endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.intertwined.expect
new file mode 100644
index 0000000..06f70a8
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.intertwined.expect
@@ -0,0 +1,175 @@
+parseUnit(void)
+ skipErrorTokens(void)
+ listener: beginCompilationUnit(void)
+ syntheticPreviousToken(void)
+ parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+ parseMetadataStar()
+ listener: beginMetadataStar(void)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl()
+ listener: beginTopLevelMember(void)
+ parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, main, false)
+ listener: beginTopLevelMethod(, null, null)
+ listener: handleVoidKeyword(void)
+ ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+ listener: handleIdentifier(main, topLevelFunctionDeclaration)
+ parseMethodTypeVar(main)
+ listener: handleNoTypeVariables(()
+ parseGetterOrFormalParameters(main, main, false, MemberKind.TopLevelMethod)
+ parseFormalParameters(main, MemberKind.TopLevelMethod)
+ parseFormalParametersRest((, MemberKind.TopLevelMethod)
+ listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+ listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ parseFunctionBody(), false, false)
+ listener: beginBlockFunctionBody({)
+ notEofOrValue(}, Function)
+ parseStatement({)
+ parseStatementX({)
+ parseExpressionStatementOrDeclaration({, false)
+ parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+ looksLikeLocalFunction(f)
+ parseExpressionWithoutCascade(=)
+ parsePrecedenceExpression(=, 1, false)
+ parseUnaryExpression(=, false)
+ parsePrimary(=, expression)
+ parseParenthesizedExpressionOrFunctionLiteral(=)
+ parseFunctionExpression(=)
+ parseFormalParametersRequiredOpt(=, MemberKind.Local)
+ parseFormalParametersRest((, MemberKind.Local)
+ parseAsyncOptBody(), true, false)
+ parseAsyncModifierOpt())
+ inPlainSync()
+ parseFunctionBody(), true, false)
+ notEofOrValue(}, print)
+ parseStatement({)
+ parseStatementX({)
+ parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+ looksLikeLocalFunction(print)
+ parseExpressionStatement({)
+ parseExpression({)
+ parsePrecedenceExpression({, 1, true)
+ parseUnaryExpression({, true)
+ parsePrimary({, expression)
+ parseSendOrFunctionLiteral({, expression)
+ looksLikeFunctionBody(})
+ parseSend({, expression)
+ isNextIdentifier({)
+ ensureIdentifier({, expression)
+ parseArgumentsOpt(print)
+ parseArguments(print)
+ parseArgumentsRest(()
+ parseExpression(()
+ parsePrecedenceExpression((, 1, true)
+ parseUnaryExpression((, true)
+ parsePrimary((, expression)
+ parseLiteralInt(()
+ ensureSemicolon())
+ reportRecoverableError(), Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ rewriter()
+ notEofOrValue(}, })
+ listener: beginMetadataStar(Function)
+ listener: endMetadataStar(0)
+ listener: handleIdentifier(Function, typeReference)
+ listener: handleNoTypeArguments(?)
+ listener: handleType(Function, ?)
+ listener: beginVariablesDeclaration(f, null, null)
+ parseVariablesDeclarationRest(?, true)
+ parseOptionallyInitializedIdentifier(?)
+ ensureIdentifier(?, localVariableDeclaration)
+ listener: handleIdentifier(f, localVariableDeclaration)
+ listener: beginInitializedIdentifier(f)
+ parseVariableInitializerOpt(f)
+ listener: beginVariableInitializer(=)
+ parseExpression(=)
+ parsePrecedenceExpression(=, 1, true)
+ parseUnaryExpression(=, true)
+ parsePrimary(=, expression)
+ parseParenthesizedExpressionOrFunctionLiteral(=)
+ listener: handleNoTypeVariables(()
+ parseFunctionExpression(=)
+ listener: beginFunctionExpression(()
+ parseFormalParametersRequiredOpt(=, MemberKind.Local)
+ parseFormalParametersRest((, MemberKind.Local)
+ listener: beginFormalParameters((, MemberKind.Local)
+ listener: endFormalParameters(0, (, ), MemberKind.Local)
+ parseAsyncOptBody(), true, false)
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ parseFunctionBody(), true, false)
+ listener: beginBlockFunctionBody({)
+ notEofOrValue(}, print)
+ parseStatement({)
+ parseStatementX({)
+ parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+ looksLikeLocalFunction(print)
+ parseExpressionStatement({)
+ parseExpression({)
+ parsePrecedenceExpression({, 1, true)
+ parseUnaryExpression({, true)
+ parsePrimary({, expression)
+ parseSendOrFunctionLiteral({, expression)
+ looksLikeFunctionBody(})
+ parseSend({, expression)
+ isNextIdentifier({)
+ ensureIdentifier({, expression)
+ listener: handleIdentifier(print, expression)
+ listener: handleNoTypeArguments(()
+ parseArgumentsOpt(print)
+ parseArguments(print)
+ parseArgumentsRest(()
+ listener: beginArguments(()
+ parseExpression(()
+ parsePrecedenceExpression((, 1, true)
+ parseUnaryExpression((, true)
+ parsePrimary((, expression)
+ parseLiteralInt(()
+ listener: handleLiteralInt(1)
+ listener: endArguments(1, (, ))
+ listener: handleSend(print, })
+ ensureSemicolon())
+ reportRecoverableError(), Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
+ rewriter()
+ listener: handleExpressionStatement(;)
+ notEofOrValue(}, })
+ listener: endBlockFunctionBody(1, {, })
+ listener: endFunctionExpression((, ;)
+ listener: endVariableInitializer(=)
+ listener: endInitializedIdentifier(f)
+ ensureSemicolon(})
+ listener: endVariablesDeclaration(1, ;)
+ notEofOrValue(}, f)
+ parseStatement(;)
+ parseStatementX(;)
+ parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+ looksLikeLocalFunction(f)
+ parseExpressionStatement(;)
+ parseExpression(;)
+ parsePrecedenceExpression(;, 1, true)
+ parseUnaryExpression(;, true)
+ parsePrimary(;, expression)
+ parseSendOrFunctionLiteral(;, expression)
+ looksLikeFunctionBody(;)
+ parseSend(;, expression)
+ isNextIdentifier(;)
+ ensureIdentifier(;, expression)
+ listener: handleIdentifier(f, expression)
+ listener: handleNoTypeArguments(()
+ parseArgumentsOpt(f)
+ parseArguments(f)
+ parseArgumentsRest(()
+ listener: beginArguments(()
+ listener: endArguments(0, (, ))
+ listener: handleSend(f, ;)
+ ensureSemicolon())
+ listener: handleExpressionStatement(;)
+ notEofOrValue(}, })
+ listener: endBlockFunctionBody(2, {, })
+ listener: endTopLevelMethod(void, null, })
+ listener: endTopLevelDeclaration()
+ reportAllErrorTokens(void)
+ listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.parser.expect
new file mode 100644
index 0000000..f31ed62
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.parser.expect
@@ -0,0 +1,17 @@
+NOTICE: Stream was rewritten by parser!
+
+void main() {
+Function? f = () {
+print(1)
+;};
+f();
+}
+
+
+void[KeywordToken] main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+Function[KeywordToken]?[SimpleToken] f[StringToken] =[SimpleToken] ([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]1[StringToken])[SimpleToken]
+;[SyntheticToken]}[SimpleToken];[SimpleToken]
+f[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.scanner.expect
new file mode 100644
index 0000000..0bec4b0
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.scanner.expect
@@ -0,0 +1,15 @@
+void main() {
+Function? f = () {
+print(1)
+};
+f();
+}
+
+
+void[KeywordToken] main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+Function[KeywordToken]?[SimpleToken] f[StringToken] =[SimpleToken] ([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]1[StringToken])[SimpleToken]
+}[SimpleToken];[SimpleToken]
+f[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/runtime/vm/heap/weak_code.cc b/runtime/vm/heap/weak_code.cc
index 44730a3..5e59703 100644
--- a/runtime/vm/heap/weak_code.cc
+++ b/runtime/vm/heap/weak_code.cc
@@ -58,7 +58,7 @@
return false;
}
-void WeakCodeReferences::DisableCode() {
+void WeakCodeReferences::DisableCode(bool are_mutators_stopped) {
Thread* thread = Thread::Current();
const Array& code_objects = Array::Handle(thread->zone(), array_.ptr());
#if defined(DART_PRECOMPILED_RUNTIME)
@@ -74,8 +74,7 @@
}
auto isolate_group = IsolateGroup::Current();
- // Deoptimize stacks and disable code with mutators stopped.
- isolate_group->RunWithStoppedMutators([&]() {
+ auto disable_code_fun = [&]() {
Code& code = Code::Handle();
isolate_group->ForEachIsolate(
[&](Isolate* isolate) {
@@ -140,7 +139,15 @@
}
UpdateArrayTo(Object::null_array());
- });
+ };
+
+ // Deoptimize stacks and disable code (with mutators stopped if they are not
+ // stopped yet).
+ if (are_mutators_stopped) {
+ disable_code_fun();
+ } else {
+ isolate_group->RunWithStoppedMutators(disable_code_fun);
+ }
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
diff --git a/runtime/vm/heap/weak_code.h b/runtime/vm/heap/weak_code.h
index 74b4389..e87ac5c 100644
--- a/runtime/vm/heap/weak_code.h
+++ b/runtime/vm/heap/weak_code.h
@@ -28,7 +28,7 @@
static bool IsOptimizedCode(const Array& dependent_code, const Code& code);
- void DisableCode();
+ void DisableCode(bool are_mutators_stopped);
bool HasCodes() const;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 00807b5..241097c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4083,7 +4083,7 @@
THR_Print("Deopt for CHA (new subclass %s)\n", subclass.ToCString());
}
}
- a.DisableCode();
+ a.DisableCode(/*are_mutators_stopped=*/false);
}
void Class::DisableAllCHAOptimizedCode() {
@@ -10949,7 +10949,7 @@
a.Register(code);
}
-void Field::DeoptimizeDependentCode() const {
+void Field::DeoptimizeDependentCode(bool are_mutators_stopped) const {
DEBUG_ASSERT(
IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
ASSERT(IsOriginal());
@@ -10957,7 +10957,7 @@
if (FLAG_trace_deoptimization && a.HasCodes()) {
THR_Print("Deopt for field guard (field %s)\n", ToCString());
}
- a.DisableCode();
+ a.DisableCode(are_mutators_stopped);
}
bool Field::IsConsistentWith(const Field& other) const {
@@ -11231,45 +11231,102 @@
}
}
-bool Field::UpdateGuardedCidAndLength(const Object& value) const {
- ASSERT(IsOriginal());
- const intptr_t cid = value.GetClassId();
+class FieldGuardUpdater {
+ public:
+ FieldGuardUpdater(const Field* field, const Object& value);
+
+ bool IsUpdateNeeded() {
+ return does_guarded_cid_need_update_ ||
+ does_is_nullable_need_update_ ||
+ does_list_length_and_offset_need_update_ ||
+ does_static_type_exactness_state_need_update_;
+ }
+ void DoUpdate();
+
+ private:
+ void ReviewExactnessState();
+ void ReviewGuards();
+
+ intptr_t guarded_cid() { return guarded_cid_; }
+ void set_guarded_cid(intptr_t guarded_cid) {
+ guarded_cid_ = guarded_cid;
+ does_guarded_cid_need_update_ = true;
+ }
+
+ bool is_nullable() { return is_nullable_; }
+ void set_is_nullable(bool is_nullable) {
+ is_nullable_ = is_nullable;
+ does_is_nullable_need_update_ = true;
+ }
+
+ intptr_t guarded_list_length() { return list_length_; }
+ void set_guarded_list_length_and_offset(intptr_t list_length,
+ intptr_t list_length_in_object_offset) {
+ list_length_ = list_length;
+ list_length_in_object_offset_ = list_length_in_object_offset;
+ does_list_length_and_offset_need_update_ = true;
+ }
+
+ StaticTypeExactnessState static_type_exactness_state() {
+ return static_type_exactness_state_;
+ }
+ void set_static_type_exactness_state(StaticTypeExactnessState state) {
+ static_type_exactness_state_ = state;
+ does_static_type_exactness_state_need_update_ = true;
+ }
+
+ const Field* field_;
+ const Object& value_;
+
+ intptr_t guarded_cid_;
+ bool is_nullable_;
+ intptr_t list_length_;
+ intptr_t list_length_in_object_offset_;
+ StaticTypeExactnessState static_type_exactness_state_;
+
+ bool does_guarded_cid_need_update_ = false;
+ bool does_is_nullable_need_update_ = false;
+ bool does_list_length_and_offset_need_update_ = false;
+ bool does_static_type_exactness_state_need_update_ = false;
+};
+
+void FieldGuardUpdater::ReviewGuards() {
+ ASSERT(field_->IsOriginal());
+ const intptr_t cid = value_.GetClassId();
if (guarded_cid() == kIllegalCid) {
- // Field is assigned first time.
set_guarded_cid(cid);
set_is_nullable(cid == kNullCid);
// Start tracking length if needed.
ASSERT((guarded_list_length() == Field::kUnknownFixedLength) ||
(guarded_list_length() == Field::kNoFixedLength));
- if (needs_length_check()) {
+ if (field_->needs_length_check()) {
ASSERT(guarded_list_length() == Field::kUnknownFixedLength);
- set_guarded_list_length(GetListLength(value));
- InitializeGuardedListLengthInObjectOffset();
+ set_guarded_list_length_and_offset(GetListLength(value_),
+ GetListLengthOffset(cid));
}
if (FLAG_trace_field_guards) {
- THR_Print(" => %s\n", GuardedPropertiesAsCString());
+ THR_Print(" => %s\n", field_->GuardedPropertiesAsCString());
}
-
- return false;
+ return;
}
if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) {
// Class id of the assigned value matches expected class id and nullability.
// If we are tracking length check if it has matches.
- if (needs_length_check() &&
- (guarded_list_length() != GetListLength(value))) {
+ if (field_->needs_length_check() &&
+ (guarded_list_length() != GetListLength(value_))) {
ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
- set_guarded_list_length(Field::kNoFixedLength);
- set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
- return true;
+ set_guarded_list_length_and_offset(Field::kNoFixedLength,
+ Field::kUnknownLengthOffset);
+ return;
}
// Everything matches.
- return false;
+ return;
}
if ((cid == kNullCid) && !is_nullable()) {
@@ -11288,14 +11345,11 @@
}
// If we were tracking length drop collected feedback.
- if (needs_length_check()) {
+ if (field_->needs_length_check()) {
ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
- set_guarded_list_length(Field::kNoFixedLength);
- set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
+ set_guarded_list_length_and_offset(Field::kNoFixedLength,
+ Field::kUnknownLengthOffset);
}
-
- // Expected class id or nullability of the field changed.
- return true;
}
bool Class::FindInstantiationOf(Zone* zone,
@@ -11555,10 +11609,10 @@
}
}
-bool Field::UpdateGuardedExactnessState(const Object& value) const {
+void FieldGuardUpdater::ReviewExactnessState() {
if (!static_type_exactness_state().IsExactOrUninitialized()) {
// Nothing to update.
- return false;
+ return;
}
if (guarded_cid() == kDynamicCid) {
@@ -11568,14 +11622,14 @@
"dynamic\n");
}
set_static_type_exactness_state(StaticTypeExactnessState::NotExact());
- return true; // Invalidate.
+ return;
}
// If we are storing null into a field or we have an exact super type
// then there is nothing to do.
- if (value.IsNull() || static_type_exactness_state().IsHasExactSuperType() ||
+ if (value_.IsNull() || static_type_exactness_state().IsHasExactSuperType() ||
static_type_exactness_state().IsHasExactSuperClass()) {
- return false;
+ return;
}
// If we are storing a non-null value into a field that is considered
@@ -11583,16 +11637,16 @@
// type.
ASSERT(guarded_cid() != kNullCid);
- const Type& field_type = Type::Cast(AbstractType::Handle(type()));
+ const Type& field_type = Type::Cast(AbstractType::Handle(field_->type()));
const TypeArguments& field_type_args =
TypeArguments::Handle(field_type.arguments());
- const Instance& instance = Instance::Cast(value);
+ const Instance& instance = Instance::Cast(value_);
TypeArguments& args = TypeArguments::Handle();
if (static_type_exactness_state().IsTriviallyExact()) {
args = instance.GetTypeArguments();
if (args.ptr() == field_type_args.ptr()) {
- return false;
+ return;
}
if (FLAG_trace_field_guards) {
@@ -11601,13 +11655,43 @@
}
set_static_type_exactness_state(StaticTypeExactnessState::NotExact());
- return true;
+ return;
}
ASSERT(static_type_exactness_state().IsUninitialized());
set_static_type_exactness_state(StaticTypeExactnessState::Compute(
field_type, instance, FLAG_trace_field_guards));
- return true;
+ return;
+}
+
+FieldGuardUpdater::FieldGuardUpdater(const Field* field, const Object& value):
+ field_(field),
+ value_(value),
+ guarded_cid_(field->guarded_cid()),
+ is_nullable_(field->is_nullable()),
+ list_length_(field->guarded_list_length()),
+ list_length_in_object_offset_(
+ field->guarded_list_length_in_object_offset()),
+ static_type_exactness_state_(field->static_type_exactness_state()) {
+ ReviewGuards();
+ ReviewExactnessState();
+}
+
+void FieldGuardUpdater::DoUpdate() {
+ if (does_guarded_cid_need_update_) {
+ field_->set_guarded_cid(guarded_cid_);
+ }
+ if (does_is_nullable_need_update_) {
+ field_->set_is_nullable(is_nullable_);
+ }
+ if (does_list_length_and_offset_need_update_) {
+ field_->set_guarded_list_length(list_length_);
+ field_->set_guarded_list_length_in_object_offset(
+ list_length_in_object_offset_);
+ }
+ if (does_static_type_exactness_state_need_update_) {
+ field_->set_static_type_exactness_state(static_type_exactness_state_);
+ }
}
void Field::RecordStore(const Object& value) const {
@@ -11633,20 +11717,19 @@
value.ToCString());
}
- bool invalidate = false;
- if (UpdateGuardedCidAndLength(value)) {
- invalidate = true;
- }
- if (UpdateGuardedExactnessState(value)) {
- invalidate = true;
- }
-
- if (invalidate) {
+ FieldGuardUpdater updater(this, value);
+ if (updater.IsUpdateNeeded()) {
if (FLAG_trace_field_guards) {
THR_Print(" => %s\n", GuardedPropertiesAsCString());
}
-
- DeoptimizeDependentCode();
+ // Nobody else could have updated guard state since we are holding write
+ // program lock. But we need to ensure we stop mutators as we update
+ // guard state as we can't have optimized code running with updated fields.
+ auto isolate_group = IsolateGroup::Current();
+ isolate_group->RunWithStoppedMutators([&]() {
+ updater.DoUpdate();
+ DeoptimizeDependentCode(/*are_mutators_stopped=*/true);
+ });
}
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 25d7a8e..668b201 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4390,7 +4390,7 @@
void RegisterDependentCode(const Code& code) const;
// Deoptimize all dependent code objects.
- void DeoptimizeDependentCode() const;
+ void DeoptimizeDependentCode(bool are_mutators_stopped = false) const;
// Used by background compiler to check consistency of field copy with its
// original.
@@ -4509,15 +4509,6 @@
class IsNonNullableIntBit
: public BitField<uint16_t, bool, kIsNonNullableIntBit, 1> {};
- // Update guarded cid and guarded length for this field. Returns true, if
- // deoptimization of dependent code is required.
- bool UpdateGuardedCidAndLength(const Object& value) const;
-
- // Update guarded exactness state for this field. Returns true, if
- // deoptimization of dependent code is required.
- // Assumes that guarded cid was already updated.
- bool UpdateGuardedExactnessState(const Object& value) const;
-
// Force this field's guard to be dynamic and deoptimize dependent code.
void ForceDynamicGuardedCidAndLength() const;
diff --git a/tests/language/vm/lazy_deopt_with_exception_concurrent_test.dart b/tests/language/vm/lazy_deopt_with_exception_concurrent_test.dart
new file mode 100644
index 0000000..5aa5637
--- /dev/null
+++ b/tests/language/vm/lazy_deopt_with_exception_concurrent_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2016, 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.
+// Test deoptimization on an optimistically hoisted smi check.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+// Test that lazy deoptimization works if the program returns to a function
+// that is scheduled for lazy deoptimization via an exception, even under
+// heavy concurrent load.
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+class C {
+ dynamic x = 42;
+}
+
+@pragma('vm:never-inline')
+AA(C c, bool b) {
+ if (b) {
+ c.x = 2.5;
+ throw 123;
+ }
+}
+
+@pragma('vm:never-inline')
+T1(C c, bool b) {
+ try {
+ AA(c, b);
+ } on dynamic {}
+ return c.x + 1;
+}
+
+@pragma('vm:never-inline')
+T2(C c, bool b) {
+ try {
+ AA(c, b);
+ } on String {
+ Expect.isTrue(false);
+ } on int catch (e) {
+ Expect.equals(e, 123);
+ Expect.equals(b, true);
+ Expect.equals(c.x, 2.5);
+ }
+ return c.x + 1;
+}
+
+main() async {
+ const count = 10;
+
+ final rp = ReceivePort();
+ for (int i = 0; i < count; ++i) {
+ Isolate.spawn(entry, i, onExit: rp.sendPort);
+ }
+ final si = StreamIterator(rp);
+ int j = 0;
+ while (await si.moveNext()) {
+ j++;
+ if (j == count) break;
+ }
+ print('done');
+
+ if (j != count) throw 'a';
+ si.cancel();
+ rp.close();
+ print('done');
+}
+
+void entry(_) {
+ var c = new C();
+ for (var i = 0; i < 100000; ++i) {
+ T1(c, false);
+ T2(c, false);
+ }
+ Expect.equals(43, T1(c, false));
+ Expect.equals(43, T2(c, false));
+ Expect.equals(3.5, T1(c, true));
+ Expect.equals(3.5, T2(c, true));
+}
diff --git a/tests/language_2/vm/lazy_deopt_with_exception_concurrent_test.dart b/tests/language_2/vm/lazy_deopt_with_exception_concurrent_test.dart
new file mode 100644
index 0000000..3e07cbb
--- /dev/null
+++ b/tests/language_2/vm/lazy_deopt_with_exception_concurrent_test.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2016, 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.
+// Test deoptimization on an optimistically hoisted smi check.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+// @dart = 2.9
+
+// Test that lazy deoptimization works if the program returns to a function
+// that is scheduled for lazy deoptimization via an exception.
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+class C {
+ dynamic x = 42;
+}
+
+@pragma('vm:never-inline')
+AA(C c, bool b) {
+ if (b) {
+ c.x = 2.5;
+ throw 123;
+ }
+}
+
+@pragma('vm:never-inline')
+T1(C c, bool b) {
+ try {
+ AA(c, b);
+ } on dynamic {}
+ return c.x + 1;
+}
+
+@pragma('vm:never-inline')
+T2(C c, bool b) {
+ try {
+ AA(c, b);
+ } on String {
+ Expect.isTrue(false);
+ } on int catch (e) {
+ Expect.equals(e, 123);
+ Expect.equals(b, true);
+ Expect.equals(c.x, 2.5);
+ }
+ return c.x + 1;
+}
+
+main() async {
+ const count = 10;
+
+ final rp = ReceivePort();
+ for (int i = 0; i < count; ++i) {
+ Isolate.spawn(entry, i, onExit: rp.sendPort);
+ }
+ final si = StreamIterator(rp);
+ int j = 0;
+ while (await si.moveNext()) {
+ j++;
+ if (j == count) break;
+ }
+ print('done');
+
+ if (j != count) throw 'a';
+ si.cancel();
+ rp.close();
+ print('done');
+}
+
+void entry(_) {
+ var c = new C();
+ for (var i = 0; i < 100000; ++i) {
+ T1(c, false);
+ T2(c, false);
+ }
+ Expect.equals(43, T1(c, false));
+ Expect.equals(43, T2(c, false));
+ Expect.equals(3.5, T1(c, true));
+ Expect.equals(3.5, T2(c, true));
+}
diff --git a/tools/VERSION b/tools/VERSION
index 911a64f..79f9a08 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 200
+PRERELEASE 201
PRERELEASE_PATCH 0
\ No newline at end of file