Version 2.11.0-160.0.dev
Merge commit '75ffae6a5c523810989c929f0c4ba4aece8590bc' into 'dev'
diff --git a/pkg/analysis_server/analysis_options.yaml b/pkg/analysis_server/analysis_options.yaml
index dd243d9..5995e86 100644
--- a/pkg/analysis_server/analysis_options.yaml
+++ b/pkg/analysis_server/analysis_options.yaml
@@ -15,6 +15,7 @@
linter:
rules:
+ - await_only_futures
- empty_statements
- unnecessary_brace_in_string_interps
#
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 95ed5c8..570c266 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -561,7 +561,7 @@
}
// Prepare the file information.
- var result = await server.getParsedUnit(file);
+ var result = server.getParsedUnit(file);
if (result == null) {
server.sendResponse(Response.fileNotAnalyzed(request, file));
return;
diff --git a/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart b/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart
index fff1df7..a4243a9 100644
--- a/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart
@@ -28,7 +28,7 @@
}
}
- void processPackage(Folder pkgFolder) async {
+ Future<void> processPackage(Folder pkgFolder) async {
for (var task in _codeTasks) {
await task.processPackage(pkgFolder);
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
index a8ec84f..93c14bd 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
@@ -44,7 +44,7 @@
}
}
- void _insertAt(ChangeBuilder builder, int offset) async {
+ Future<void> _insertAt(ChangeBuilder builder, int offset) async {
await builder.addDartFileEdit(file, (builder) {
builder.addSimpleInsertion(offset, 'late ');
});
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart
index 2025838..5bcc3fc 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart
@@ -60,7 +60,8 @@
if (newlineLoc == childArgSrc.length) {
newlineLoc -= 1;
}
- String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
+ String indentOld =
+ getLinePrefix(childArg.offset + eol.length + newlineLoc);
var indentNew = '$indentOld${getIndent(1)}';
// The separator includes 'child:' but that has no newlines.
String separator =
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart
index 6b0ac1a..5fcd235 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart
@@ -28,7 +28,7 @@
if (newlineIdx < 0 || newlineIdx == literalSrc.length - 1) {
return; // Lists need to be in multi-line format already.
}
- var indentOld = utils.getLinePrefix(node.offset + 1 + newlineIdx);
+ var indentOld = utils.getLinePrefix(node.offset + eol.length + newlineIdx);
var indentArg = '$indentOld${utils.getIndent(1)}';
var indentList = '$indentOld${utils.getIndent(2)}';
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_annotation.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_annotation.dart
index d40a8a5..6a6d159 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_annotation.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_annotation.dart
@@ -21,7 +21,7 @@
@override
Future<void> compute(ChangeBuilder builder) async {
- void addFix(Annotation node) async {
+ Future<void> addFix(Annotation node) async {
if (node == null) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart b/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart
index 32381fa..b176935 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart
@@ -87,7 +87,7 @@
return fixes;
}
- void _addFix_removeSetting() async {
+ Future<void> _addFix_removeSetting() async {
if (coveringNodePath[0] is YamlScalar) {
SourceRange deletionRange;
var index = 1;
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index 886804c..d626bd2 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -754,7 +754,7 @@
}
Future<void> _initializeReturnType() async {
- var typeProvider = await resolveResult.typeProvider;
+ var typeProvider = resolveResult.typeProvider;
if (_selectionFunctionExpression != null) {
variableType = '';
returnType = '';
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 540843b..bd39067 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -391,7 +391,7 @@
raw: true);
return;
}
- var file = await server.resourceProvider.getFile(filePath);
+ var file = server.resourceProvider.getFile(filePath);
if (!file.exists) {
p('The file <code>${escape(filePath)}</code> does not exist.', raw: true);
return;
diff --git a/pkg/analysis_server/lib/src/utilities/flutter.dart b/pkg/analysis_server/lib/src/utilities/flutter.dart
index d5a48c5..9243a189 100644
--- a/pkg/analysis_server/lib/src/utilities/flutter.dart
+++ b/pkg/analysis_server/lib/src/utilities/flutter.dart
@@ -95,7 +95,8 @@
if (newlineLoc == childArgSrc.length) {
newlineLoc -= 1;
}
- String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
+ String indentOld =
+ getLinePrefix(childArg.offset + eol.length + newlineLoc);
var indentNew = '$indentOld${getIndent(1)}';
// The separator includes 'child:' but that has no newlines.
String separator =
@@ -136,7 +137,8 @@
if (newlineLoc == childArgSrc.length) {
newlineLoc -= 1;
}
- String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
+ String indentOld =
+ getLinePrefix(childArg.offset + eol.length + newlineLoc);
var indentNew = '$indentOld${getIndent(1)}';
// The separator includes 'child:' but that has no newlines.
String separator =
diff --git a/pkg/analysis_server/test/analysis/notification_errors_test.dart b/pkg/analysis_server/test/analysis/notification_errors_test.dart
index 540323d..5a67754 100644
--- a/pkg/analysis_server/test/analysis/notification_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_errors_test.dart
@@ -203,7 +203,7 @@
// Add to priority files and give chance for the file to be analyzed (if
// it would).
- await setPriorityFiles([brokenFile]);
+ setPriorityFiles([brokenFile]);
await waitForTasksFinished();
await pumpEventQueue(times: 5000);
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 9bae3c4..c00d24e 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -866,12 +866,12 @@
extends AbstractCompletionDomainTest {
String testFileUri;
- void expectTokens(String content, List<TokenDetails> expectedTokens) async {
+ Future<void> expectTokens(String content, List<TokenDetails> expected) async {
newFile(testFile, content: content);
var request = CompletionListTokenDetailsParams(testFile).toRequest('0');
var response = await waitResponse(request);
List<Map<String, dynamic>> tokens = response.result['tokens'];
- _compareTokens(tokens, expectedTokens);
+ _compareTokens(tokens, expected);
}
@override
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 95e11f4..414c52d 100644
--- a/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
+++ b/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
@@ -65,7 +65,7 @@
join(workspaceFolder1Path, 'nested', 'deeply', 'in', 'folders');
final nestedFilePath = join(nestedFolderPath, 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
- await newFile(nestedFilePath);
+ newFile(nestedFilePath);
await initialize(allowEmptyRootUri: true);
await openFile(nestedFileUri, '');
@@ -98,7 +98,7 @@
join(workspaceFolder1Path, 'nested', 'deeply', 'in', 'folders');
final nestedFilePath = join(nestedFolderPath, 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
- await newFile(nestedFilePath);
+ newFile(nestedFilePath);
await initialize(allowEmptyRootUri: true);
await openFile(nestedFileUri, '');
@@ -132,7 +132,7 @@
join(workspaceFolder1Path, 'nested', 'deeply', 'in', 'folders');
final nestedFilePath = join(nestedFolderPath, 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
- await newFile(nestedFilePath);
+ newFile(nestedFilePath);
await initialize(workspaceFolders: [workspaceFolder1Uri]);
@@ -164,7 +164,7 @@
join(workspaceFolder1Path, 'nested', 'deeply', 'in', 'folders');
final nestedFilePath = join(nestedFolderPath, 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
- await newFile(nestedFilePath);
+ newFile(nestedFilePath);
await initialize(workspaceFolders: [workspaceFolder1Uri]);
@@ -201,10 +201,10 @@
// the pub cache folder being added as an analysis root, it should be analyzed
// by the existing project's driver.
final workspace1FilePath = join(workspaceFolder1Path, 'test.dart');
- await newFile(workspace1FilePath);
+ newFile(workspace1FilePath);
final workspace2FilePath = join(workspaceFolder2Path, 'test.dart');
final workspace2FileUri = Uri.file(workspace2FilePath);
- await newFile(workspace2FilePath);
+ newFile(workspace2FilePath);
await initialize(workspaceFolders: [workspaceFolder1Uri]);
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 0ed0c88..03def9f 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -29,7 +29,7 @@
Future f;
''';
- await newFile(mainFilePath, content: withoutMarkers(content));
+ newFile(mainFilePath, content: withoutMarkers(content));
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
@@ -70,7 +70,7 @@
Future f;
''';
- await newFile(mainFilePath, content: withoutMarkers(content));
+ newFile(mainFilePath, content: withoutMarkers(content));
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
@@ -97,7 +97,7 @@
}
Future<void> test_nonDartFile() async {
- await newFile(pubspecFilePath, content: simplePubspecContent);
+ newFile(pubspecFilePath, content: simplePubspecContent);
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
diff --git a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
index 0082910..c424137 100644
--- a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
@@ -31,7 +31,7 @@
Future foo;
''';
- await newFile(mainFilePath, content: withoutMarkers(content));
+ newFile(mainFilePath, content: withoutMarkers(content));
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -71,7 +71,7 @@
Future foo;
''';
- await newFile(mainFilePath, content: withoutMarkers(content));
+ newFile(mainFilePath, content: withoutMarkers(content));
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -100,7 +100,7 @@
var a = [Test, Test, Te[[]]st];
''';
- await newFile(mainFilePath, content: withoutMarkers(content));
+ newFile(mainFilePath, content: withoutMarkers(content));
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -120,7 +120,7 @@
var a = [Test, Test, Te[[]]st];
''';
- await newFile(mainFilePath, content: withoutMarkers(content));
+ newFile(mainFilePath, content: withoutMarkers(content));
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -137,7 +137,7 @@
}
Future<void> test_nonDartFile() async {
- await newFile(pubspecFilePath, content: simplePubspecContent);
+ newFile(pubspecFilePath, content: simplePubspecContent);
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -172,7 +172,7 @@
Completer a;
ProcessInfo b;
''';
- await newFile(mainFilePath, content: withoutMarkers(content));
+ newFile(mainFilePath, content: withoutMarkers(content));
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -199,7 +199,7 @@
Future<void> test_outsideRoot() async {
final otherFilePath = '/home/otherProject/foo.dart';
final otherFileUri = Uri.file(otherFilePath);
- await newFile(otherFilePath, content: 'bad code to create error');
+ newFile(otherFilePath, content: 'bad code to create error');
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index b733be9..2701b41 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -36,7 +36,7 @@
print('Test!');
}
''';
- await newFile(mainFilePath, content: withoutMarkers(content));
+ newFile(mainFilePath, content: withoutMarkers(content));
await initialize();
final codeActions = await getCodeActions(mainFileUri.toString(),
@@ -55,7 +55,7 @@
^
main() {}
''';
- await newFile(mainFilePath, content: content);
+ newFile(mainFilePath, content: content);
await initialize();
final codeActions = await getCodeActions(mainFileUri.toString());
@@ -136,7 +136,7 @@
}
}
''';
- await newFile(mainFilePath, content: withoutMarkers(content));
+ newFile(mainFilePath, content: withoutMarkers(content));
await initialize();
final codeActions = await getCodeActions(mainFileUri.toString(),
@@ -155,7 +155,7 @@
^
main() {}
''';
- await newFile(mainFilePath, content: content);
+ newFile(mainFilePath, content: content);
await initialize();
final codeActions = await getCodeActions(mainFileUri.toString());
diff --git a/pkg/analysis_server/test/lsp/code_actions_source_test.dart b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
index 8f4e841..12838ed 100644
--- a/pkg/analysis_server/test/lsp/code_actions_source_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
@@ -35,7 +35,7 @@
Completer foo;
int minified(int x, int y) => min(x, y);
''';
- await newFile(mainFilePath, content: content);
+ newFile(mainFilePath, content: content);
await initialize(
workspaceCapabilities: withApplyEditSupport(
withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));
@@ -64,7 +64,7 @@
Completer foo;
int minified(int x, int y) => min(x, y);
''';
- await newFile(mainFilePath, content: content);
+ newFile(mainFilePath, content: content);
await initialize(
workspaceCapabilities:
withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -77,7 +77,7 @@
}
Future<void> test_availableAsCodeActionLiteral() async {
- await newFile(mainFilePath);
+ newFile(mainFilePath);
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
@@ -93,7 +93,7 @@
}
Future<void> test_availableAsCommand() async {
- await newFile(mainFilePath);
+ newFile(mainFilePath);
await initialize(
workspaceCapabilities:
withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -108,7 +108,7 @@
Future<void> test_failsSilentlyIfFileHasErrors() async {
final content = 'invalid dart code';
- await newFile(mainFilePath, content: content);
+ newFile(mainFilePath, content: content);
await initialize(
workspaceCapabilities:
withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -136,7 +136,7 @@
Completer foo;
int minified(int x, int y) => min(x, y);
''';
- await newFile(mainFilePath, content: content);
+ newFile(mainFilePath, content: content);
await initialize(
workspaceCapabilities:
withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -158,7 +158,7 @@
}
Future<void> test_unavailableWhenNotRequested() async {
- await newFile(mainFilePath);
+ newFile(mainFilePath);
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
@@ -171,7 +171,7 @@
}
Future<void> test_unavailableWithoutApplyEditSupport() async {
- await newFile(mainFilePath);
+ newFile(mainFilePath);
await initialize();
final codeActions = await getCodeActions(mainFileUri.toString());
@@ -191,7 +191,7 @@
String a;
String b;
''';
- await newFile(mainFilePath, content: content);
+ newFile(mainFilePath, content: content);
await initialize(
workspaceCapabilities: withApplyEditSupport(
withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));
@@ -213,7 +213,7 @@
String a;
String b;
''';
- await newFile(mainFilePath, content: content);
+ newFile(mainFilePath, content: content);
await initialize(
workspaceCapabilities:
withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -226,7 +226,7 @@
}
Future<void> test_availableAsCodeActionLiteral() async {
- await newFile(mainFilePath);
+ newFile(mainFilePath);
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
@@ -242,7 +242,7 @@
}
Future<void> test_availableAsCommand() async {
- await newFile(mainFilePath);
+ newFile(mainFilePath);
await initialize(
workspaceCapabilities:
withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -260,7 +260,7 @@
String b;
String a;
''';
- await newFile(mainFilePath, content: content);
+ newFile(mainFilePath, content: content);
await initialize(
workspaceCapabilities:
withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -294,7 +294,7 @@
Future<void> test_failsIfFileHasErrors() async {
final content = 'invalid dart code';
- await newFile(mainFilePath, content: content);
+ newFile(mainFilePath, content: content);
await initialize(
workspaceCapabilities:
withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -315,7 +315,7 @@
}
Future<void> test_nonDartFile() async {
- await newFile(pubspecFilePath, content: simplePubspecContent);
+ newFile(pubspecFilePath, content: simplePubspecContent);
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
@@ -328,7 +328,7 @@
}
Future<void> test_unavailableWhenNotRequested() async {
- await newFile(mainFilePath);
+ newFile(mainFilePath);
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
@@ -341,7 +341,7 @@
}
Future<void> test_unavailableWithoutApplyEditSupport() async {
- await newFile(mainFilePath);
+ newFile(mainFilePath);
await initialize();
final codeActions = await getCodeActions(mainFileUri.toString());
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index 565fd21..f88804e 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -171,7 +171,7 @@
// Deleting the file should result in an update to remove the diagnostics.
final secondDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
- await deleteFile(mainFilePath);
+ deleteFile(mainFilePath);
final updatedDiagnostics = await secondDiagnosticsUpdate;
expect(updatedDiagnostics, hasLength(0));
}
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index 4bae1b9..43e9db8 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -262,12 +262,12 @@
Future<void> test_emptyAnalysisRoots_multipleOpenFiles() async {
final file1 = join(projectFolderPath, 'file1.dart');
final file1Uri = Uri.file(file1);
- await newFile(file1);
+ newFile(file1);
final file2 = join(projectFolderPath, 'file2.dart');
final file2Uri = Uri.file(file2);
- await newFile(file2);
+ newFile(file2);
final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
- await newFile(pubspecPath);
+ newFile(pubspecPath);
await initialize(allowEmptyRootUri: true);
@@ -290,7 +290,7 @@
final nestedFilePath = join(
projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
- await newFile(nestedFilePath);
+ newFile(nestedFilePath);
// The project folder shouldn't be added to start with.
await initialize(allowEmptyRootUri: true);
@@ -306,9 +306,9 @@
final nestedFilePath = join(
projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
- await newFile(nestedFilePath);
+ newFile(nestedFilePath);
final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
- await newFile(pubspecPath);
+ newFile(pubspecPath);
// The project folder shouldn't be added to start with.
await initialize(allowEmptyRootUri: true);
@@ -443,12 +443,12 @@
Future<void> test_onlyAnalyzeProjectsWithOpenFiles_multipleFiles() async {
final file1 = join(projectFolderPath, 'file1.dart');
final file1Uri = Uri.file(file1);
- await newFile(file1);
+ newFile(file1);
final file2 = join(projectFolderPath, 'file2.dart');
final file2Uri = Uri.file(file2);
- await newFile(file2);
+ newFile(file2);
final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
- await newFile(pubspecPath);
+ newFile(pubspecPath);
await initialize(
rootUri: projectFolderUri,
@@ -474,7 +474,7 @@
final nestedFilePath = join(
projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
- await newFile(nestedFilePath);
+ newFile(nestedFilePath);
// The project folder shouldn't be added to start with.
await initialize(
@@ -493,9 +493,9 @@
final nestedFilePath = join(
projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
final nestedFileUri = Uri.file(nestedFilePath);
- await newFile(nestedFilePath);
+ newFile(nestedFilePath);
final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
- await newFile(pubspecPath);
+ newFile(pubspecPath);
// The project folder shouldn't be added to start with.
await initialize(
diff --git a/pkg/analysis_server/test/lsp/rename_test.dart b/pkg/analysis_server/test/lsp/rename_test.dart
index 0896bf2..41469c8 100644
--- a/pkg/analysis_server/test/lsp/rename_test.dart
+++ b/pkg/analysis_server/test/lsp/rename_test.dart
@@ -290,7 +290,7 @@
final a = new [[Ob^ject]]();
''';
- await newFile(mainFilePath, content: withoutMarkers(content));
+ newFile(mainFilePath, content: withoutMarkers(content));
await initialize();
final request = makeRequest(
diff --git a/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart b/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart
index a119979..614fe4f 100644
--- a/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart
+++ b/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart
@@ -74,10 +74,10 @@
final payload = '{ json payload }';
final lspPacket =
makeLspPacket(payload, 'application/vscode-jsonrpc; charset=ascii');
- final outputStream = await Stream.fromIterable([lspPacket])
- .transform(LspPacketTransformer());
+ final outputStream =
+ Stream.fromIterable([lspPacket]).transform(LspPacketTransformer());
- expectLater(outputStream.toList(),
+ await expectLater(outputStream.toList(),
throwsA(const TypeMatcher<InvalidEncodingError>()));
});
});
diff --git a/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart b/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart
index 78926b0..d0d30dd 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart
@@ -50,7 +50,7 @@
var f = 0;
}
''');
- await await assertHasAssistAt('var ', '''
+ await assertHasAssistAt('var ', '''
class A {
int f = 0;
}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_children_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_children_test.dart
index f2db30e..b34b23d 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_children_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_children_test.dart
@@ -19,13 +19,6 @@
@override
AssistKind get kind => DartAssistKind.FLUTTER_CONVERT_TO_CHILDREN;
- @override
- void setUp() {
- super.setUp();
- // TODO(dantup): Get these tests passing with either line ending.
- useLineEndingsForPlatform = false;
- }
-
Future<void> test_childUnresolved() async {
addFlutterPackage();
verifyNoTestUnitErrors = false;
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart
index d53dda2..794cc11 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart
@@ -19,13 +19,6 @@
@override
AssistKind get kind => DartAssistKind.FLUTTER_WRAP_GENERIC;
- @override
- void setUp() {
- super.setUp();
- // TODO(dantup): Get these tests passing with either line ending.
- useLineEndingsForPlatform = false;
- }
-
Future<void> test_minimal() async {
addFlutterPackage();
await resolveTestUnit('''
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_flutter_child_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_flutter_child_test.dart
index c4268d2..3e17f59 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_flutter_child_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_flutter_child_test.dart
@@ -19,13 +19,6 @@
@override
FixKind get kind => DartFixKind.CONVERT_FLUTTER_CHILD;
- @override
- void setUp() {
- super.setUp();
- // TODO(dantup): Get these tests passing with either line ending.
- useLineEndingsForPlatform = false;
- }
-
Future<void> test_hasList() async {
addFlutterPackage();
await resolveTestUnit('''
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index a7fb58c..ca983e6 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -110,7 +110,7 @@
expect(resultCode, expected);
}
- void assertHasFixAllFix(ErrorCode errorCode, String expected,
+ Future<void> assertHasFixAllFix(ErrorCode errorCode, String expected,
{String target}) async {
if (useLineEndingsForPlatform) {
expected = normalizeNewlinesForPlatform(expected);
diff --git a/pkg/analysis_server/tool/completion_metrics/code_metrics.dart b/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
index 1ae1151..0876be9 100644
--- a/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
@@ -1356,7 +1356,7 @@
CodeShapeMetricsComputer();
/// Compute the metrics for the file(s) in the [rootPath].
- void compute(String rootPath) async {
+ Future<void> compute(String rootPath) async {
final collection = AnalysisContextCollection(
includedPaths: [rootPath],
resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1380,7 +1380,7 @@
/// separate context collection to prevent accumulating memory. The metrics
/// should be captured in the [collector]. Include additional details in the
/// output if [verbose] is `true`.
- void _computeInContext(
+ Future<void> _computeInContext(
ContextRoot root, CodeShapeDataCollector collector) async {
// Create a new collection to avoid consuming large quantities of memory.
final collection = AnalysisContextCollection(
diff --git a/pkg/analysis_server/tool/completion_metrics/flutter_metrics.dart b/pkg/analysis_server/tool/completion_metrics/flutter_metrics.dart
index 8ff6195..dee0616 100644
--- a/pkg/analysis_server/tool/completion_metrics/flutter_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/flutter_metrics.dart
@@ -172,7 +172,7 @@
FlutterMetricsComputer();
/// Compute the metrics for the file(s) in the [rootPath].
- void compute(String rootPath) async {
+ Future<void> compute(String rootPath) async {
final collection = AnalysisContextCollection(
includedPaths: [rootPath],
resourceProvider: PhysicalResourceProvider.INSTANCE,
diff --git a/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart b/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart
index 4b9b1c0..c788082 100644
--- a/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart
+++ b/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart
@@ -139,7 +139,7 @@
/// Compute the metrics for the file(s) in the [rootPath].
/// If [corpus] is true, treat rootPath as a container of packages, creating
/// a new context collection for each subdirectory.
- void compute(String rootPath, {@required bool verbose}) async {
+ Future<void> compute(String rootPath, {@required bool verbose}) async {
final collection = AnalysisContextCollection(
includedPaths: [rootPath],
resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -170,7 +170,8 @@
/// separate context collection to prevent accumulating memory. The metrics
/// should be captured in the [collector]. Include additional details in the
/// output if [verbose] is `true`.
- void _computeInContext(ContextRoot root, ImpliedTypeCollector collector,
+ Future<void> _computeInContext(
+ ContextRoot root, ImpliedTypeCollector collector,
{@required bool verbose}) async {
// Create a new collection to avoid consuming large quantities of memory.
final collection = AnalysisContextCollection(
diff --git a/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart b/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart
index e043511..2664da1 100644
--- a/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart
@@ -1869,7 +1869,7 @@
/// Compute the metrics for the file(s) in the [rootPath].
/// If [corpus] is true, treat rootPath as a container of packages, creating
/// a new context collection for each subdirectory.
- void compute(String rootPath, {@required bool verbose}) async {
+ Future<void> compute(String rootPath, {@required bool verbose}) async {
final collection = AnalysisContextCollection(
includedPaths: [rootPath],
resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1929,7 +1929,8 @@
/// separate context collection to prevent accumulating memory. The metrics
/// should be captured in the [collector]. Include additional details in the
/// output if [verbose] is `true`.
- void _computeInContext(ContextRoot root, RelevanceDataCollector collector,
+ Future<void> _computeInContext(
+ ContextRoot root, RelevanceDataCollector collector,
{@required bool verbose}) async {
// Create a new collection to avoid consuming large quantities of memory.
final collection = AnalysisContextCollection(
diff --git a/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart b/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
index 846e22d..b746fb6 100644
--- a/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
+++ b/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
@@ -1350,7 +1350,7 @@
/// Compute the metrics for the file(s) in the [rootPath].
/// If [corpus] is true, treat rootPath as a container of packages, creating
/// a new context collection for each subdirectory.
- void compute(String rootPath, {@required bool verbose}) async {
+ Future<void> compute(String rootPath, {@required bool verbose}) async {
final collection = AnalysisContextCollection(
includedPaths: [rootPath],
resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1365,7 +1365,8 @@
/// separate context collection to prevent accumulating memory. The metrics
/// should be captured in the [collector]. Include additional details in the
/// output if [verbose] is `true`.
- void _computeInContext(ContextRoot root, RelevanceDataCollector collector,
+ Future<void> _computeInContext(
+ ContextRoot root, RelevanceDataCollector collector,
{@required bool verbose}) async {
// Create a new collection to avoid consuming large quantities of memory.
final collection = AnalysisContextCollection(
diff --git a/pkg/analysis_server_client/analysis_options.yaml b/pkg/analysis_server_client/analysis_options.yaml
index fe1ff59..fd37fb4 100644
--- a/pkg/analysis_server_client/analysis_options.yaml
+++ b/pkg/analysis_server_client/analysis_options.yaml
@@ -4,6 +4,7 @@
linter:
rules:
+ - await_only_futures
- empty_statements
- unnecessary_brace_in_string_interps
#
diff --git a/pkg/analyzer/analysis_options.yaml b/pkg/analyzer/analysis_options.yaml
index b269720..3f9b8e3 100644
--- a/pkg/analyzer/analysis_options.yaml
+++ b/pkg/analyzer/analysis_options.yaml
@@ -27,6 +27,7 @@
linter:
rules:
- avoid_unused_constructor_parameters
+ - await_only_futures
- empty_statements
- iterable_contains_unrelated_type
- list_remove_unrelated_type
diff --git a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
new file mode 100644
index 0000000..c32b116
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
@@ -0,0 +1,336 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
+import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+class SimpleIdentifierResolver {
+ final ResolverVisitor _resolver;
+ final FlowAnalysisHelper _flowAnalysis;
+
+ SimpleIdentifierResolver(this._resolver, this._flowAnalysis);
+
+ ErrorReporter get _errorReporter => _resolver.errorReporter;
+
+ InvocationInferenceHelper get _inferenceHelper => _resolver.inferenceHelper;
+
+ TypeProviderImpl get _typeProvider => _resolver.typeProvider;
+
+ void resolve(SimpleIdentifier node) {
+ if (node.inDeclarationContext()) {
+ return;
+ }
+
+ _resolver.checkUnreachableNode(node);
+
+ _resolver.checkReadOfNotAssignedLocalVariable(node, node.staticElement);
+
+ _resolve1(node);
+ _resolve2(node);
+ }
+
+ /// Return the type that should be recorded for a node that resolved to the given accessor.
+ ///
+ /// @param accessor the accessor that the node resolved to
+ /// @return the type that should be recorded for a node that resolved to the given accessor
+ ///
+ /// TODO(scheglov) this is duplicate
+ DartType _getTypeOfProperty(PropertyAccessorElement accessor) {
+ FunctionType functionType = accessor.type;
+ if (functionType == null) {
+ // TODO(brianwilkerson) Report this internal error. This happens when we
+ // are analyzing a reference to a property before we have analyzed the
+ // declaration of the property or when the property does not have a
+ // defined type.
+ return DynamicTypeImpl.instance;
+ }
+ if (accessor.isSetter) {
+ List<DartType> parameterTypes = functionType.normalParameterTypes;
+ if (parameterTypes != null && parameterTypes.isNotEmpty) {
+ return parameterTypes[0];
+ }
+ PropertyAccessorElement getter = accessor.variable.getter;
+ if (getter != null) {
+ functionType = getter.type;
+ if (functionType != null) {
+ return functionType.returnType;
+ }
+ }
+ return DynamicTypeImpl.instance;
+ }
+ return functionType.returnType;
+ }
+
+ /// Return `true` if the given [node] is not a type literal.
+ ///
+ /// TODO(scheglov) this is duplicate
+ bool _isExpressionIdentifier(Identifier node) {
+ var parent = node.parent;
+ if (node is SimpleIdentifier && node.inDeclarationContext()) {
+ return false;
+ }
+ if (parent is ConstructorDeclaration) {
+ if (parent.name == node || parent.returnType == node) {
+ return false;
+ }
+ }
+ if (parent is ConstructorName ||
+ parent is MethodInvocation ||
+ parent is PrefixedIdentifier && parent.prefix == node ||
+ parent is PropertyAccess ||
+ parent is TypeName) {
+ return false;
+ }
+ return true;
+ }
+
+ /// Return `true` if the given [node] can validly be resolved to a prefix:
+ /// * it is the prefix in an import directive, or
+ /// * it is the prefix in a prefixed identifier.
+ bool _isValidAsPrefix(SimpleIdentifier node) {
+ AstNode parent = node.parent;
+ if (parent is ImportDirective) {
+ return identical(parent.prefix, node);
+ } else if (parent is PrefixedIdentifier) {
+ return true;
+ } else if (parent is MethodInvocation) {
+ return identical(parent.target, node) &&
+ parent.operator?.type == TokenType.PERIOD;
+ }
+ return false;
+ }
+
+ /// Record that the static type of the given node is the given type.
+ ///
+ /// @param expression the node whose type is to be recorded
+ /// @param type the static type of the node
+ ///
+ /// TODO(scheglov) this is duplicate
+ void _recordStaticType(Expression expression, DartType type) {
+ if (_resolver.migrationResolutionHooks != null) {
+ // TODO(scheglov) type cannot be null
+ type = _resolver.migrationResolutionHooks.modifyExpressionType(
+ expression,
+ type ?? DynamicTypeImpl.instance,
+ );
+ }
+
+ // TODO(scheglov) type cannot be null
+ if (type == null) {
+ expression.staticType = DynamicTypeImpl.instance;
+ } else {
+ expression.staticType = type;
+ if (_resolver.typeSystem.isBottom(type)) {
+ _flowAnalysis?.flow?.handleExit();
+ }
+ }
+ }
+
+ void _resolve1(SimpleIdentifier node) {
+ //
+ // Synthetic identifiers have been already reported during parsing.
+ //
+ if (node.isSynthetic) {
+ return;
+ }
+
+ //
+ // Ignore nodes that should have been resolved before getting here.
+ //
+ if (node.inDeclarationContext()) {
+ return;
+ }
+ if (node.staticElement is LocalVariableElement ||
+ node.staticElement is ParameterElement) {
+ return;
+ }
+ AstNode parent = node.parent;
+ if (parent is FieldFormalParameter) {
+ return;
+ } else if (parent is ConstructorFieldInitializer &&
+ parent.fieldName == node) {
+ return;
+ } else if (parent is Annotation && parent.constructorName == node) {
+ return;
+ }
+
+ //
+ // Otherwise, the node should be resolved.
+ //
+
+ // TODO(scheglov) Special-case resolution of ForStatement, don't use this.
+ var hasRead = true;
+ var hasWrite = false;
+ {
+ var parent = node.parent;
+ if (parent is ForEachPartsWithIdentifier && parent.identifier == node) {
+ hasRead = false;
+ hasWrite = true;
+ }
+ }
+
+ var resolver = PropertyElementResolver(_resolver);
+ var result = resolver.resolveSimpleIdentifier(
+ node: node,
+ hasRead: hasRead,
+ hasWrite: hasWrite,
+ );
+
+ // Element element = _resolver.elementResolver.resolveSimpleIdentifier(node);
+ Element element = hasRead ? result.readElement : result.writeElement;
+
+ ClassElement enclosingClass = _resolver.enclosingClass;
+ if (_isFactoryConstructorReturnType(node) &&
+ !identical(element, enclosingClass)) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS, node);
+ } else if (_isConstructorReturnType(node) &&
+ !identical(element, enclosingClass)) {
+ // This error is now reported by the parser.
+ element = null;
+ } else if (element == null ||
+ (element is PrefixElement && !_isValidAsPrefix(node))) {
+ // TODO(brianwilkerson) Recover from this error.
+ if (_isConstructorReturnType(node)) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
+ } else if (parent is Annotation) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_ANNOTATION, parent, [node.name]);
+ } else if (element != null) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+ node,
+ [element.name]);
+ } else if (node.name == "await" && _resolver.enclosingFunction != null) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT,
+ node,
+ );
+ } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+ node,
+ [node.name],
+ );
+ }
+ }
+ node.staticElement = element;
+ }
+
+ void _resolve2(SimpleIdentifier node) {
+ Element element = node.staticElement;
+
+ if (element is ExtensionElement) {
+ _setExtensionIdentifierType(node);
+ return;
+ }
+
+ DartType staticType = DynamicTypeImpl.instance;
+ if (element is ClassElement) {
+ if (_isExpressionIdentifier(node)) {
+ node.staticType = _typeProvider.typeType;
+ }
+ return;
+ } else if (element is FunctionTypeAliasElement) {
+ if (node.inDeclarationContext() || node.parent is TypeName) {
+ // no type
+ } else {
+ node.staticType = _typeProvider.typeType;
+ }
+ return;
+ } else if (element is MethodElement) {
+ staticType = element.type;
+ } else if (element is PropertyAccessorElement) {
+ staticType = _getTypeOfProperty(element);
+ } else if (element is ExecutableElement) {
+ staticType = element.type;
+ } else if (element is TypeParameterElement) {
+ staticType = _typeProvider.typeType;
+ } else if (element is VariableElement) {
+ staticType = _resolver.localVariableTypeProvider.getType(node);
+ } else if (element is PrefixElement) {
+ var parent = node.parent;
+ if (parent is PrefixedIdentifier && parent.prefix == node ||
+ parent is MethodInvocation && parent.target == node) {
+ return;
+ }
+ staticType = _typeProvider.dynamicType;
+ } else if (element is DynamicElementImpl) {
+ staticType = _typeProvider.typeType;
+ } else {
+ staticType = DynamicTypeImpl.instance;
+ }
+ staticType = _inferenceHelper.inferTearOff(node, node, staticType);
+ _recordStaticType(node, staticType);
+ }
+
+ /// TODO(scheglov) this is duplicate
+ void _setExtensionIdentifierType(Identifier node) {
+ if (node is SimpleIdentifier && node.inDeclarationContext()) {
+ return;
+ }
+
+ var parent = node.parent;
+
+ if (parent is PrefixedIdentifier && parent.identifier == node) {
+ node = parent;
+ parent = node.parent;
+ }
+
+ if (parent is CommentReference ||
+ parent is ExtensionOverride && parent.extensionName == node ||
+ parent is MethodInvocation && parent.target == node ||
+ parent is PrefixedIdentifier && parent.prefix == node ||
+ parent is PropertyAccess && parent.target == node) {
+ return;
+ }
+
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.EXTENSION_AS_EXPRESSION,
+ node,
+ [node.name],
+ );
+
+ if (node is PrefixedIdentifier) {
+ node.identifier.staticType = DynamicTypeImpl.instance;
+ node.staticType = DynamicTypeImpl.instance;
+ } else if (node is SimpleIdentifier) {
+ node.staticType = DynamicTypeImpl.instance;
+ }
+ }
+
+ /// Return `true` if the given [identifier] is the return type of a
+ /// constructor declaration.
+ static bool _isConstructorReturnType(SimpleIdentifier identifier) {
+ AstNode parent = identifier.parent;
+ if (parent is ConstructorDeclaration) {
+ return identical(parent.returnType, identifier);
+ }
+ return false;
+ }
+
+ /// Return `true` if the given [identifier] is the return type of a factory
+ /// constructor.
+ static bool _isFactoryConstructorReturnType(SimpleIdentifier identifier) {
+ AstNode parent = identifier.parent;
+ if (parent is ConstructorDeclaration) {
+ return identical(parent.returnType, identifier) &&
+ parent.factoryKeyword != null;
+ }
+ return false;
+ }
+}
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 20e0732..9939ed4 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -443,106 +442,6 @@
}
@override
- void visitSimpleIdentifier(SimpleIdentifier node) {
- //
- // Synthetic identifiers have been already reported during parsing.
- //
- if (node.isSynthetic) {
- return;
- }
- //
- // Ignore nodes that should have been resolved before getting here.
- //
- if (node.inDeclarationContext()) {
- return;
- }
- if (node.staticElement is LocalVariableElement ||
- node.staticElement is ParameterElement) {
- return;
- }
- AstNode parent = node.parent;
- if (parent is FieldFormalParameter) {
- return;
- } else if (parent is ConstructorFieldInitializer &&
- parent.fieldName == node) {
- return;
- } else if (parent is Annotation && parent.constructorName == node) {
- return;
- }
- //
- // Otherwise, the node should be resolved.
- //
- Element element = _resolveSimpleIdentifier(node);
- ClassElement enclosingClass = _resolver.enclosingClass;
- if (_isFactoryConstructorReturnType(node) &&
- !identical(element, enclosingClass)) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS, node);
- } else if (_isConstructorReturnType(node) &&
- !identical(element, enclosingClass)) {
- // This error is now reported by the parser.
- element = null;
- } else if (element == null ||
- (element is PrefixElement && !_isValidAsPrefix(node))) {
- // TODO(brianwilkerson) Recover from this error.
- if (_isConstructorReturnType(node)) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
- } else if (parent is Annotation) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.UNDEFINED_ANNOTATION, parent, [node.name]);
- } else if (element != null) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
- node,
- [element.name]);
- } else if (node.name == "await" && _resolver.enclosingFunction != null) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT,
- node,
- );
- } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
- node,
- [node.name],
- );
- }
- }
- node.staticElement = element;
-
- _resolver.setWriteElement(node, element);
-
- Element getter;
- var inGetterContext = node.inGetterContext();
- if (inGetterContext) {
- if (element is PropertyAccessorElement &&
- element.enclosingElement is CompilationUnitElement) {
- getter = element.variable.getter;
- }
- }
-
- if (node.inSetterContext() && inGetterContext && enclosingClass != null) {
- InterfaceType enclosingType = enclosingClass.thisType;
- var result = _typePropertyResolver.resolve(
- receiver: null,
- receiverType: enclosingType,
- name: node.name,
- receiverErrorNode: node,
- nameErrorEntity: node,
- );
- node.auxiliaryElements = AuxiliaryElements(
- result.getter,
- );
- getter ??= result.getter;
- }
-
- if (inGetterContext) {
- _resolver.setReadElement(node, getter);
- }
- }
-
- @override
void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
ClassElementImpl enclosingClass = _resolver.enclosingClass;
if (enclosingClass == null) {
@@ -630,22 +529,6 @@
_resolveAnnotations(node.metadata);
}
- /// Return `true` if the given [node] can validly be resolved to a prefix:
- /// * it is the prefix in an import directive, or
- /// * it is the prefix in a prefixed identifier.
- bool _isValidAsPrefix(SimpleIdentifier node) {
- AstNode parent = node.parent;
- if (parent is ImportDirective) {
- return identical(parent.prefix, node);
- } else if (parent is PrefixedIdentifier) {
- return true;
- } else if (parent is MethodInvocation) {
- return identical(parent.target, node) &&
- parent.operator?.type == TokenType.PERIOD;
- }
- return false;
- }
-
/// Return the target of a break or continue statement, and update the static
/// element of its label (if any). The [parentNode] is the AST node of the
/// break or continue statement. The [labelNode] is the label contained in
@@ -848,27 +731,6 @@
return null;
}
- /// Return `true` if the given [identifier] is the return type of a
- /// constructor declaration.
- static bool _isConstructorReturnType(SimpleIdentifier identifier) {
- AstNode parent = identifier.parent;
- if (parent is ConstructorDeclaration) {
- return identical(parent.returnType, identifier);
- }
- return false;
- }
-
- /// Return `true` if the given [identifier] is the return type of a factory
- /// constructor.
- static bool _isFactoryConstructorReturnType(SimpleIdentifier identifier) {
- AstNode parent = identifier.parent;
- if (parent is ConstructorDeclaration) {
- return identical(parent.returnType, identifier) &&
- parent.factoryKeyword != null;
- }
- return false;
- }
-
/// Resolve each of the annotations in the given list of [annotations].
static void _resolveAnnotations(NodeList<Annotation> annotations) {
for (Annotation annotation in annotations) {
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 3650e5b..f05f178 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -41,6 +41,7 @@
import 'package:analyzer/src/dart/resolver/prefixed_identifier_resolver.dart';
import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/dart/resolver/simple_identifier_resolver.dart';
import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart';
import 'package:analyzer/src/dart/resolver/variable_declaration_resolver.dart';
@@ -1832,13 +1833,7 @@
@override
void visitSimpleIdentifier(SimpleIdentifier node) {
- if (node.inDeclarationContext()) {
- return;
- }
-
- checkReadOfNotAssignedLocalVariable(node, node.staticElement);
-
- super.visitSimpleIdentifier(node);
+ SimpleIdentifierResolver(this, _flowAnalysis).resolve(node);
}
@override
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 610860c..ecee766 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -9,17 +9,13 @@
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
-import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
-import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/migration.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/variable_type_provider.dart';
import 'package:analyzer/src/task/strong/checker.dart'
show getExpressionType, getReadType;
@@ -48,9 +44,6 @@
/// The type representing the type 'dynamic'.
DartType _dynamicType;
- /// The object providing promoted or declared types of variables.
- LocalVariableTypeProvider _localVariableTypeProvider;
-
final FlowAnalysisHelper _flowAnalysis;
/// Initialize a newly created static type analyzer to analyze types for the
@@ -62,11 +55,8 @@
_typeProvider = _resolver.typeProvider;
_typeSystem = _resolver.typeSystem;
_dynamicType = _typeProvider.dynamicType;
- _localVariableTypeProvider = _resolver.localVariableTypeProvider;
}
- InvocationInferenceHelper get _inferenceHelper => _resolver.inferenceHelper;
-
/// Is `true` if the library being analyzed is non-nullable by default.
bool get _isNonNullableByDefault =>
_featureSet.isEnabled(Feature.non_nullable);
@@ -300,90 +290,6 @@
recordStaticType(node, _typeProvider.bottomType);
}
- /// The Dart Language Specification, 12.30: <blockquote>Evaluation of an identifier expression
- /// <i>e</i> of the form <i>id</i> proceeds as follows:
- ///
- /// Let <i>d</i> be the innermost declaration in the enclosing lexical scope whose name is
- /// <i>id</i>. If no such declaration exists in the lexical scope, let <i>d</i> be the declaration
- /// of the inherited member named <i>id</i> if it exists.
- /// * If <i>d</i> is a class or type alias <i>T</i>, the value of <i>e</i> is the unique instance
- /// of class `Type` reifying <i>T</i>.
- /// * If <i>d</i> is a type parameter <i>T</i>, then the value of <i>e</i> is the value of the
- /// actual type argument corresponding to <i>T</i> that was passed to the generative constructor
- /// that created the current binding of this. We are assured that this is well defined, because if
- /// we were in a static member the reference to <i>T</i> would be a compile-time error.
- /// * If <i>d</i> is a library variable then:
- /// * If <i>d</i> is of one of the forms <i>var v = e<sub>i</sub>;</i>, <i>T v =
- /// e<sub>i</sub>;</i>, <i>final v = e<sub>i</sub>;</i>, <i>final T v = e<sub>i</sub>;</i>, and no
- /// value has yet been stored into <i>v</i> then the initializer expression <i>e<sub>i</sub></i> is
- /// evaluated. If, during the evaluation of <i>e<sub>i</sub></i>, the getter for <i>v</i> is
- /// referenced, a CyclicInitializationError is thrown. If the evaluation succeeded yielding an
- /// object <i>o</i>, let <i>r = o</i>, otherwise let <i>r = null</i>. In any case, <i>r</i> is
- /// stored into <i>v</i>. The value of <i>e</i> is <i>r</i>.
- /// * If <i>d</i> is of one of the forms <i>const v = e;</i> or <i>const T v = e;</i> the result
- /// of the getter is the value of the compile time constant <i>e</i>. Otherwise
- /// * <i>e</i> evaluates to the current binding of <i>id</i>.
- /// * If <i>d</i> is a local variable or formal parameter then <i>e</i> evaluates to the current
- /// binding of <i>id</i>.
- /// * If <i>d</i> is a static method, top level function or local function then <i>e</i>
- /// evaluates to the function defined by <i>d</i>.
- /// * If <i>d</i> is the declaration of a static variable or static getter declared in class
- /// <i>C</i>, then <i>e</i> is equivalent to the getter invocation <i>C.id</i>.
- /// * If <i>d</i> is the declaration of a top level getter, then <i>e</i> is equivalent to the
- /// getter invocation <i>id</i>.
- /// * Otherwise, if <i>e</i> occurs inside a top level or static function (be it function,
- /// method, getter, or setter) or variable initializer, evaluation of e causes a NoSuchMethodError
- /// to be thrown.
- /// * Otherwise <i>e</i> is equivalent to the property extraction <i>this.id</i>.
- /// </blockquote>
- @override
- void visitSimpleIdentifier(SimpleIdentifier node) {
- Element element = node.staticElement;
-
- if (element is ExtensionElement) {
- _setExtensionIdentifierType(node);
- return;
- }
-
- DartType staticType = _dynamicType;
- if (element is ClassElement) {
- if (_isExpressionIdentifier(node)) {
- node.staticType = _nonNullable(_typeProvider.typeType);
- }
- return;
- } else if (element is FunctionTypeAliasElement) {
- if (node.inDeclarationContext() || node.parent is TypeName) {
- // no type
- } else {
- node.staticType = _nonNullable(_typeProvider.typeType);
- }
- return;
- } else if (element is MethodElement) {
- staticType = element.type;
- } else if (element is PropertyAccessorElement) {
- staticType = _getTypeOfProperty(element);
- } else if (element is ExecutableElement) {
- staticType = element.type;
- } else if (element is TypeParameterElement) {
- staticType = _nonNullable(_typeProvider.typeType);
- } else if (element is VariableElement) {
- staticType = _localVariableTypeProvider.getType(node);
- } else if (element is PrefixElement) {
- var parent = node.parent;
- if (parent is PrefixedIdentifier && parent.prefix == node ||
- parent is MethodInvocation && parent.target == node) {
- return;
- }
- staticType = _typeProvider.dynamicType;
- } else if (element is DynamicElementImpl) {
- staticType = _nonNullable(_typeProvider.typeType);
- } else {
- staticType = _dynamicType;
- }
- staticType = _inferenceHelper.inferTearOff(node, node, staticType);
- recordStaticType(node, staticType);
- }
-
/// The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
/// `String`.</blockquote>
@override
@@ -511,36 +417,6 @@
return type;
}
- /// Return the type that should be recorded for a node that resolved to the given accessor.
- ///
- /// @param accessor the accessor that the node resolved to
- /// @return the type that should be recorded for a node that resolved to the given accessor
- DartType _getTypeOfProperty(PropertyAccessorElement accessor) {
- FunctionType functionType = accessor.type;
- if (functionType == null) {
- // TODO(brianwilkerson) Report this internal error. This happens when we
- // are analyzing a reference to a property before we have analyzed the
- // declaration of the property or when the property does not have a
- // defined type.
- return _dynamicType;
- }
- if (accessor.isSetter) {
- List<DartType> parameterTypes = functionType.normalParameterTypes;
- if (parameterTypes != null && parameterTypes.isNotEmpty) {
- return parameterTypes[0];
- }
- PropertyAccessorElement getter = accessor.variable.getter;
- if (getter != null) {
- functionType = getter.type;
- if (functionType != null) {
- return functionType.returnType;
- }
- }
- return _dynamicType;
- }
- return functionType.returnType;
- }
-
/// Given an instance creation of a possibly generic type, infer the type
/// arguments using the current context type as well as the argument types.
void _inferInstanceCreationExpression(InstanceCreationExpression node) {
@@ -598,27 +474,6 @@
}
}
- /// Return `true` if the given [node] is not a type literal.
- bool _isExpressionIdentifier(Identifier node) {
- var parent = node.parent;
- if (node is SimpleIdentifier && node.inDeclarationContext()) {
- return false;
- }
- if (parent is ConstructorDeclaration) {
- if (parent.name == node || parent.returnType == node) {
- return false;
- }
- }
- if (parent is ConstructorName ||
- parent is MethodInvocation ||
- parent is PrefixedIdentifier && parent.prefix == node ||
- parent is PropertyAccess ||
- parent is TypeName) {
- return false;
- }
- return true;
- }
-
/// Return the non-nullable variant of the [type] if NNBD is enabled, otherwise
/// return the type itself.
DartType _nonNullable(DartType type) {
@@ -627,38 +482,4 @@
}
return type;
}
-
- void _setExtensionIdentifierType(Identifier node) {
- if (node is SimpleIdentifier && node.inDeclarationContext()) {
- return;
- }
-
- var parent = node.parent;
-
- if (parent is PrefixedIdentifier && parent.identifier == node) {
- node = parent;
- parent = node.parent;
- }
-
- if (parent is CommentReference ||
- parent is ExtensionOverride && parent.extensionName == node ||
- parent is MethodInvocation && parent.target == node ||
- parent is PrefixedIdentifier && parent.prefix == node ||
- parent is PropertyAccess && parent.target == node) {
- return;
- }
-
- _resolver.errorReporter.reportErrorForNode(
- CompileTimeErrorCode.EXTENSION_AS_EXPRESSION,
- node,
- [node.name],
- );
-
- if (node is PrefixedIdentifier) {
- node.identifier.staticType = _dynamicType;
- node.staticType = _dynamicType;
- } else if (node is SimpleIdentifier) {
- node.staticType = _dynamicType;
- }
- }
}
diff --git a/pkg/analyzer/lib/src/lint/project.dart b/pkg/analyzer/lib/src/lint/project.dart
index 18a944b..b3cc575 100644
--- a/pkg/analyzer/lib/src/lint/project.dart
+++ b/pkg/analyzer/lib/src/lint/project.dart
@@ -120,7 +120,7 @@
return false;
}
- void _calculate() async {
+ Future<void> _calculate() async {
if (sources == null || sources.isEmpty) {
return;
}
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index 35a067a..75588bf 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -664,40 +664,6 @@
_listener.assertNoErrors();
}
- test_visitSimpleIdentifier_classScope() async {
- InterfaceType doubleType = _typeProvider.doubleType;
- String fieldName = 'nan';
- SimpleIdentifier node = AstTestFactory.identifier3(fieldName);
- _resolveInClass(node, doubleType.element);
- expect(node.staticElement, doubleType.getGetter(fieldName));
- _listener.assertNoErrors();
- }
-
- test_visitSimpleIdentifier_lexicalScope() async {
- SimpleIdentifier node = AstTestFactory.identifier3("i");
- VariableElementImpl element = ElementFactory.localVariableElement(node);
- expect(_resolveIdentifier(node, [element]), same(element));
- _listener.assertNoErrors();
- }
-
- test_visitSimpleIdentifier_lexicalScope_field_setter() async {
- InterfaceType intType = _typeProvider.intType;
- ClassElementImpl classA = ElementFactory.classElement2("A");
- _encloseElement(classA);
- String fieldName = "a";
- FieldElement field =
- ElementFactory.fieldElement(fieldName, false, false, false, intType);
- classA.fields = <FieldElement>[field];
- classA.accessors = <PropertyAccessorElement>[field.getter, field.setter];
- SimpleIdentifier node = AstTestFactory.identifier3(fieldName);
- AstTestFactory.assignmentExpression(
- node, TokenType.EQ, AstTestFactory.integer(0));
- _resolveInClass(node, classA);
- PropertyAccessorElement element = node.staticElement;
- expect(element.isSetter, isTrue);
- _listener.assertNoErrors();
- }
-
test_visitSuperConstructorInvocation() async {
ClassElementImpl superclass = ElementFactory.classElement2("A");
_encloseElement(superclass);
@@ -811,18 +777,6 @@
/// has resolved the identifier.
///
/// @param node the expression to be resolved
- /// @param definedElements the elements that are to be defined in the scope in
- /// which the element is being resolved
- /// @return the element to which the expression was resolved
- Element _resolveIdentifier(Identifier node, [List<Element> definedElements]) {
- _resolveNode(node, definedElements);
- return node.staticElement;
- }
-
- /// Return the element associated with the given identifier after the resolver
- /// has resolved the identifier.
- ///
- /// @param node the expression to be resolved
/// @param enclosingClass the element representing the class enclosing the
/// identifier
/// @return the element to which the expression was resolved
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 8c827ee..3046a23 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -2870,7 +2870,7 @@
test_fuzz_38113() async {
// https://github.com/dart-lang/sdk/issues/38113
- await parseCompilationUnit(r'+t{{r?this}}', errors: [
+ parseCompilationUnit(r'+t{{r?this}}', errors: [
expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 1, 1),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index 5e5655f..ed80e60 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -124,7 +124,7 @@
var typeProvider = resolvedUnit.typeProvider;
var intClass = typeProvider.intType.element;
- var parsedLibrary = await session.getParsedLibrary(testPath);
+ var parsedLibrary = session.getParsedLibrary(testPath);
expect(() {
parsedLibrary.getElementDeclaration(intClass);
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_internal_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_internal_annotation_test.dart
index 2dee934..7de20a1 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_internal_annotation_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_internal_annotation_test.dart
@@ -22,14 +22,14 @@
void setUp() async {
super.setUp();
writeTestPackageConfigWithMeta();
- await newFile('$testPackageRootPath/pubspec.yaml', content: r'''
+ newFile('$testPackageRootPath/pubspec.yaml', content: r'''
name: test
version: 0.0.1
''');
}
void test_annotationInLib() async {
- await newFile('$testPackageLibPath/foo.dart', content: r'''
+ newFile('$testPackageLibPath/foo.dart', content: r'''
import 'package:meta/meta.dart';
@internal class One {}
''');
@@ -41,7 +41,7 @@
}
void test_annotationInLib_onLibrary() async {
- await newFile('$testPackageLibPath/foo.dart', content: r'''
+ newFile('$testPackageLibPath/foo.dart', content: r'''
@internal
library foo;
import 'package:meta/meta.dart';
@@ -54,7 +54,7 @@
}
void test_annotationInLibSrc() async {
- await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+ newFile('$testPackageLibPath/src/foo.dart', content: r'''
import 'package:meta/meta.dart';
@internal class One {}
''');
@@ -64,7 +64,7 @@
}
void test_annotationInLibSrcSubdirectory() async {
- await newFile('$testPackageLibPath/src/foo/foo.dart', content: r'''
+ newFile('$testPackageLibPath/src/foo/foo.dart', content: r'''
import 'package:meta/meta.dart';
@internal class One {}
''');
@@ -74,7 +74,7 @@
}
void test_annotationInLibSubdirectory() async {
- await newFile('$testPackageLibPath/foo/foo.dart', content: r'''
+ newFile('$testPackageLibPath/foo/foo.dart', content: r'''
import 'package:meta/meta.dart';
@internal class One {}
''');
@@ -86,7 +86,7 @@
}
void test_annotationInTest() async {
- await newFile('$testPackageRootPath/test/foo_test.dart', content: r'''
+ newFile('$testPackageRootPath/test/foo_test.dart', content: r'''
import 'package:meta/meta.dart';
@internal class One {}
''');
@@ -96,7 +96,7 @@
}
void test_privateClass() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
@internal class _One {}
''');
@@ -109,7 +109,7 @@
}
void test_privateClassConstructor_named() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
class _C {
@internal _C.named();
@@ -124,7 +124,7 @@
}
void test_privateClassConstructor_unnamed() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
class _C {
@internal _C();
@@ -139,7 +139,7 @@
}
void test_privateConstructor() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
class C {
@internal C._f();
@@ -153,7 +153,7 @@
}
void test_privateEnum() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
@internal enum _E {one}
''');
@@ -167,7 +167,7 @@
}
void test_privateEnumValue() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
enum E {@internal _one}
''');
@@ -180,7 +180,7 @@
}
void test_privateExtension() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
@internal extension _One on String {}
''');
@@ -192,7 +192,7 @@
}
void test_privateExtension_unnamed() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
@internal extension on String {}
''');
@@ -204,7 +204,7 @@
}
void test_privateField_instance() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
class C {
@internal int _i = 0;
@@ -219,7 +219,7 @@
}
void test_privateField_static() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
class C {
@internal static int _i = 0;
@@ -234,7 +234,7 @@
}
void test_privateGetter() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
class C {
@internal int get _i => 0;
@@ -249,7 +249,7 @@
}
void test_privateMethod_instance() async {
- await newFile(testPackageImplementationFilePath, content: r'''
+ newFile(testPackageImplementationFilePath, content: r'''
import 'package:meta/meta.dart';
class C {
@internal void _f() {}
@@ -264,7 +264,7 @@
}
void test_privateMethod_static() async {
- await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+ newFile('$testPackageLibPath/src/foo.dart', content: r'''
import 'package:meta/meta.dart';
class C {
@internal static void _f() {}
@@ -279,7 +279,7 @@
}
void test_privateMixin() async {
- await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+ newFile('$testPackageLibPath/src/foo.dart', content: r'''
import 'package:meta/meta.dart';
@internal mixin _One {}
''');
@@ -292,7 +292,7 @@
}
void test_privateTopLevelFunction() async {
- await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+ newFile('$testPackageLibPath/src/foo.dart', content: r'''
import 'package:meta/meta.dart';
@internal void _f() {}
''');
@@ -305,7 +305,7 @@
}
void test_privateTopLevelVariable() async {
- await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+ newFile('$testPackageLibPath/src/foo.dart', content: r'''
import 'package:meta/meta.dart';
@internal int _i = 1;
''');
@@ -318,7 +318,7 @@
}
void test_privateTypedef() async {
- await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+ newFile('$testPackageLibPath/src/foo.dart', content: r'''
import 'package:meta/meta.dart';
@internal typedef _T = void Function();
''');
@@ -331,7 +331,7 @@
}
void test_publicMethod_privateClass() async {
- await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+ newFile('$testPackageLibPath/src/foo.dart', content: r'''
import 'package:meta/meta.dart';
class _C {
@internal void f() {}
@@ -345,7 +345,7 @@
}
void test_publicMethod_privateClass_static() async {
- await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+ newFile('$testPackageLibPath/src/foo.dart', content: r'''
import 'package:meta/meta.dart';
class _C {
@internal static void f() {}
diff --git a/pkg/analyzer/test/src/diagnostics/subtype_of_sealed_class_test.dart b/pkg/analyzer/test/src/diagnostics/subtype_of_sealed_class_test.dart
index 3b2acfa..9322aa2 100644
--- a/pkg/analyzer/test/src/diagnostics/subtype_of_sealed_class_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/subtype_of_sealed_class_test.dart
@@ -28,7 +28,7 @@
meta: true,
);
- await newFile('$workspaceRootPath/foo/lib/foo.dart', content: r'''
+ newFile('$workspaceRootPath/foo/lib/foo.dart', content: r'''
import 'package:meta/meta.dart';
@sealed class Foo {}
''');
@@ -156,7 +156,7 @@
}
test_withinPackageLibDirectory_OK() async {
- await newFile('$testPackageLibPath/a.dart', content: r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
import 'package:meta/meta.dart';
@sealed class Foo {}
''');
@@ -172,7 +172,7 @@
}
test_withinPackageTestDirectory_OK() async {
- await newFile('$testPackageLibPath/a.dart', content: r'''
+ newFile('$testPackageLibPath/a.dart', content: r'''
import 'package:meta/meta.dart';
@sealed class Foo {}
''');
@@ -198,7 +198,7 @@
@sealed class Foo {}
''');
- await newFile(partPath, content: r'''
+ newFile(partPath, content: r'''
part of 'a.dart';
class Bar1 extends Foo {}
class Bar2 implements Foo {}
diff --git a/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart b/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
index 0c61468..4adaadd 100644
--- a/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
@@ -61,7 +61,7 @@
}
test_extensionOverride() async {
- await assertParseCodeAndPrintAst(this, '''
+ assertParseCodeAndPrintAst(this, '''
extension E on Object {
int f() => 0;
}
diff --git a/pkg/analyzer/test/verify_docs_test.dart b/pkg/analyzer/test/verify_docs_test.dart
index 6e5236c..975bbf2 100644
--- a/pkg/analyzer/test/verify_docs_test.dart
+++ b/pkg/analyzer/test/verify_docs_test.dart
@@ -44,11 +44,11 @@
snippetPath = provider.pathContext.join(snippetDirPath, 'snippet.dart');
}
- void verify() async {
+ Future<void> verify() async {
await verifyFolder(docFolder);
}
- void verifyFile(File file) async {
+ Future<void> verifyFile(File file) async {
String content = file.readAsStringSync();
List<String> lines = const LineSplitter().convert(content);
List<String> codeLines = [];
@@ -73,7 +73,7 @@
}
}
- void verifyFolder(Folder folder) async {
+ Future<void> verifyFolder(Folder folder) async {
for (Resource child in folder.getChildren()) {
if (child is File) {
if (child.shortName.endsWith('.md')) {
@@ -85,7 +85,7 @@
}
}
- void verifySnippet(File file, String snippet) async {
+ Future<void> verifySnippet(File file, String snippet) async {
// TODO(brianwilkerson) When the files outside of 'src' contain only public
// API, write code to compute the list of imports so that new public API
// will automatically be allowed.
diff --git a/pkg/analyzer_cli/analysis_options.yaml b/pkg/analyzer_cli/analysis_options.yaml
index a6ec312..ee6055a 100644
--- a/pkg/analyzer_cli/analysis_options.yaml
+++ b/pkg/analyzer_cli/analysis_options.yaml
@@ -14,6 +14,7 @@
rules:
- avoid_single_cascade_in_expression_statements
- avoid_unused_constructor_parameters
+ - await_only_futures
- empty_statements
- iterable_contains_unrelated_type
- list_remove_unrelated_type
diff --git a/pkg/analyzer_plugin/analysis_options.yaml b/pkg/analyzer_plugin/analysis_options.yaml
index 42406ef..ac616cb 100644
--- a/pkg/analyzer_plugin/analysis_options.yaml
+++ b/pkg/analyzer_plugin/analysis_options.yaml
@@ -3,6 +3,7 @@
implicit-casts: false
linter:
rules:
+ - await_only_futures
- empty_statements
- unnecessary_brace_in_string_interps
#
diff --git a/pkg/dartdev/pubspec.yaml b/pkg/dartdev/pubspec.yaml
index ecc93eb..511826b 100644
--- a/pkg/dartdev/pubspec.yaml
+++ b/pkg/dartdev/pubspec.yaml
@@ -26,5 +26,5 @@
usage: ^3.4.0
dev_dependencies:
- test: ^1.0.0
pedantic: ^1.9.0
+ test: ^1.0.0
diff --git a/pkg/dartfix/analysis_options.yaml b/pkg/dartfix/analysis_options.yaml
index bfb45bf..4be2194 100644
--- a/pkg/dartfix/analysis_options.yaml
+++ b/pkg/dartfix/analysis_options.yaml
@@ -16,6 +16,7 @@
linter:
rules:
+ - await_only_futures
- directives_ordering
- empty_statements
- unnecessary_brace_in_string_interps
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 53d5493..375ac5c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -1128,7 +1128,7 @@
if (loader.target.context.options
.isExperimentEnabledGlobally(ExperimentalFlag.valueClass)) {
valueClass.transformComponent(
- component, loader.coreTypes, loader.hierarchy);
+ component, loader.coreTypes, loader.hierarchy, environment);
ticker.logMs("Lowered value classes");
}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 6c237da..660c22a 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -257,4 +257,5 @@
set_literals/disambiguation_rule: RuntimeError
value_class/simple: RuntimeError # Expected
value_class/value_extends_non_value: RuntimeError # Expected
-value_class/value_implements_non_value: RuntimeError # Expected
\ No newline at end of file
+value_class/value_implements_non_value: RuntimeError # Expected
+value_class/copy_with_call_sites: RuntimeError # Expected
\ No newline at end of file
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 825cdf1..07eb30c 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -255,3 +255,4 @@
value_class/simple: RuntimeError # Expected
value_class/value_extends_non_value: RuntimeError # Expected
value_class/value_implements_non_value: RuntimeError # Expected
+value_class/copy_with_call_sites: RuntimeError # Expected
\ No newline at end of file
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart
new file mode 100644
index 0000000..031deb0
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'value_class_support_lib.dart';
+
+class Animal {
+ final int numberOfLegs;
+ Animal({required this.numberOfLegs});
+}
+
+@valueClass
+class Cat extends Animal {
+ final int numberOfWhiskers;
+}
+
+main() {
+ Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+ (cat as dynamic).copyWith(numberOfWhiskers: 4);
+}
+
+
+
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.outline.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.outline.expect
new file mode 100644
index 0000000..0e4993f
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.outline.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
+
+import "org-dartlang-testcase:///value_class_support_lib.dart";
+
+class Animal extends core::Object {
+ final field core::int numberOfLegs;
+ constructor •({required core::int numberOfLegs}) → self::Animal
+ ;
+}
+@val::valueClass
+class Cat extends self::Animal {
+ final field core::int numberOfWhiskers;
+ synthetic constructor •() → self::Cat
+ ;
+}
+static method main() → dynamic
+ ;
+
+library /*isNonNullableByDefault*/;
+import self as val;
+import "dart:core" as core;
+
+class JenkinsSmiHash extends core::Object {
+ synthetic constructor •() → val::JenkinsSmiHash
+ ;
+ static method combine(core::int hash, core::int value) → core::int
+ ;
+ static method finish(core::int hash) → core::int
+ ;
+}
+static const field core::String valueClass = "valueClass";
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.expect
new file mode 100644
index 0000000..dd3b9ec
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.expect
@@ -0,0 +1,72 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:18:20: Error: No named parameter with the name 'numberOfWhiskers'.
+// Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// class Cat extends Animal {
+// ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:14:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+// final int numberOfWhiskers;
+// ^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
+
+import "org-dartlang-testcase:///value_class_support_lib.dart";
+
+class Animal extends core::Object {
+ final field core::int numberOfLegs;
+ constructor •({required core::int numberOfLegs = #C1}) → self::Animal
+ : self::Animal::numberOfLegs = numberOfLegs, super core::Object::•()
+ ;
+}
+class Cat extends self::Animal {
+ final field core::int numberOfWhiskers = null;
+ synthetic constructor •({required core::int numberOfWhiskers, core::int numberOfLegs}) → self::Cat
+ : self::Cat::numberOfWhiskers = numberOfWhiskers, super self::Animal::•(numberOfLegs)
+ ;
+ operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+ return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+ get /*isNullableByDefault*/ hashCode() → core::int
+ return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///copy_with_call_sites.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+ method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+ return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
+}
+static method main() → dynamic {
+ self::Cat cat = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:18:20: Error: No named parameter with the name 'numberOfWhiskers'.
+ Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+ ^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
+ let final dynamic #t1 = cat as{ForNonNullableByDefault} dynamic in #t1.copyWith(numberOfWhiskers: 4, numberOfLegs: #t1.numberOfLegs);
+}
+
+library /*isNonNullableByDefault*/;
+import self as val;
+import "dart:core" as core;
+
+class JenkinsSmiHash extends core::Object {
+ synthetic constructor •() → val::JenkinsSmiHash
+ : super core::Object::•()
+ ;
+ static method combine(core::int hash, core::int value) → core::int {
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(value));
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(524287.{core::int::&}(hash).{core::int::<<}(10)));
+ return hash.{core::int::^}(hash.{core::int::>>}(6));
+ }
+ static method finish(core::int hash) → core::int {
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(67108863.{core::int::&}(hash).{core::int::<<}(3)));
+ hash = hash.{core::int::^}(hash.{core::int::>>}(11));
+ return 536870911.{core::int::&}(hash.{core::num::+}(16383.{core::int::&}(hash).{core::int::<<}(15)));
+ }
+}
+static const field core::String valueClass = #C2;
+
+constants {
+ #C1 = null
+ #C2 = "valueClass"
+}
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.transformed.expect
new file mode 100644
index 0000000..f361669
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.transformed.expect
@@ -0,0 +1,72 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:18:20: Error: No named parameter with the name 'numberOfWhiskers'.
+// Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// class Cat extends Animal {
+// ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:14:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+// final int numberOfWhiskers;
+// ^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
+
+import "org-dartlang-testcase:///value_class_support_lib.dart";
+
+class Animal extends core::Object {
+ final field core::int numberOfLegs;
+ constructor •({required core::int numberOfLegs = #C1}) → self::Animal
+ : self::Animal::numberOfLegs = numberOfLegs, super core::Object::•()
+ ;
+}
+class Cat extends self::Animal {
+ final field core::int numberOfWhiskers = null;
+ synthetic constructor •({required core::int numberOfWhiskers, core::int numberOfLegs}) → self::Cat
+ : self::Cat::numberOfWhiskers = numberOfWhiskers, super self::Animal::•(numberOfLegs)
+ ;
+ operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+ return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+ get /*isNullableByDefault*/ hashCode() → core::int
+ return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///copy_with_call_sites.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+ method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+ return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
+}
+static method main() → dynamic {
+ self::Cat cat = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:18:20: Error: No named parameter with the name 'numberOfWhiskers'.
+ Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+ ^^^^^^^^^^^^^^^^";
+ let final dynamic #t1 = cat as{ForNonNullableByDefault} dynamic in #t1.copyWith(numberOfWhiskers: 4, numberOfLegs: #t1.numberOfLegs);
+}
+
+library /*isNonNullableByDefault*/;
+import self as val;
+import "dart:core" as core;
+
+class JenkinsSmiHash extends core::Object {
+ synthetic constructor •() → val::JenkinsSmiHash
+ : super core::Object::•()
+ ;
+ static method combine(core::int hash, core::int value) → core::int {
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(value));
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(524287.{core::int::&}(hash).{core::int::<<}(10)));
+ return hash.{core::int::^}(hash.{core::int::>>}(6));
+ }
+ static method finish(core::int hash) → core::int {
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(67108863.{core::int::&}(hash).{core::int::<<}(3)));
+ hash = hash.{core::int::^}(hash.{core::int::>>}(11));
+ return 536870911.{core::int::&}(hash.{core::num::+}(16383.{core::int::&}(hash).{core::int::<<}(15)));
+ }
+}
+static const field core::String valueClass = #C2;
+
+constants {
+ #C1 = null
+ #C2 = "valueClass"
+}
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline.expect
new file mode 100644
index 0000000..93a182d
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline.expect
@@ -0,0 +1,13 @@
+import 'value_class_support_lib.dart';
+
+class Animal {
+ final int numberOfLegs;
+ Animal({required this.numberOfLegs});
+}
+
+@valueClass
+class Cat extends Animal {
+ final int numberOfWhiskers;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ce2b2e3
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+import 'value_class_support_lib.dart';
+
+class Animal {
+ Animal({required this.numberOfLegs});
+ final int numberOfLegs;
+}
+
+@valueClass
+class Cat extends Animal {
+ final int numberOfWhiskers;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.expect
new file mode 100644
index 0000000..dd3b9ec
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.expect
@@ -0,0 +1,72 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:18:20: Error: No named parameter with the name 'numberOfWhiskers'.
+// Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// class Cat extends Animal {
+// ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:14:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+// final int numberOfWhiskers;
+// ^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
+
+import "org-dartlang-testcase:///value_class_support_lib.dart";
+
+class Animal extends core::Object {
+ final field core::int numberOfLegs;
+ constructor •({required core::int numberOfLegs = #C1}) → self::Animal
+ : self::Animal::numberOfLegs = numberOfLegs, super core::Object::•()
+ ;
+}
+class Cat extends self::Animal {
+ final field core::int numberOfWhiskers = null;
+ synthetic constructor •({required core::int numberOfWhiskers, core::int numberOfLegs}) → self::Cat
+ : self::Cat::numberOfWhiskers = numberOfWhiskers, super self::Animal::•(numberOfLegs)
+ ;
+ operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+ return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+ get /*isNullableByDefault*/ hashCode() → core::int
+ return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///copy_with_call_sites.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+ method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+ return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
+}
+static method main() → dynamic {
+ self::Cat cat = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:18:20: Error: No named parameter with the name 'numberOfWhiskers'.
+ Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+ ^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
+ let final dynamic #t1 = cat as{ForNonNullableByDefault} dynamic in #t1.copyWith(numberOfWhiskers: 4, numberOfLegs: #t1.numberOfLegs);
+}
+
+library /*isNonNullableByDefault*/;
+import self as val;
+import "dart:core" as core;
+
+class JenkinsSmiHash extends core::Object {
+ synthetic constructor •() → val::JenkinsSmiHash
+ : super core::Object::•()
+ ;
+ static method combine(core::int hash, core::int value) → core::int {
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(value));
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(524287.{core::int::&}(hash).{core::int::<<}(10)));
+ return hash.{core::int::^}(hash.{core::int::>>}(6));
+ }
+ static method finish(core::int hash) → core::int {
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(67108863.{core::int::&}(hash).{core::int::<<}(3)));
+ hash = hash.{core::int::^}(hash.{core::int::>>}(11));
+ return 536870911.{core::int::&}(hash.{core::num::+}(16383.{core::int::&}(hash).{core::int::<<}(15)));
+ }
+}
+static const field core::String valueClass = #C2;
+
+constants {
+ #C1 = null
+ #C2 = "valueClass"
+}
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.transformed.expect
new file mode 100644
index 0000000..f361669
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.transformed.expect
@@ -0,0 +1,72 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:18:20: Error: No named parameter with the name 'numberOfWhiskers'.
+// Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// class Cat extends Animal {
+// ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:14:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+// final int numberOfWhiskers;
+// ^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
+
+import "org-dartlang-testcase:///value_class_support_lib.dart";
+
+class Animal extends core::Object {
+ final field core::int numberOfLegs;
+ constructor •({required core::int numberOfLegs = #C1}) → self::Animal
+ : self::Animal::numberOfLegs = numberOfLegs, super core::Object::•()
+ ;
+}
+class Cat extends self::Animal {
+ final field core::int numberOfWhiskers = null;
+ synthetic constructor •({required core::int numberOfWhiskers, core::int numberOfLegs}) → self::Cat
+ : self::Cat::numberOfWhiskers = numberOfWhiskers, super self::Animal::•(numberOfLegs)
+ ;
+ operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+ return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+ get /*isNullableByDefault*/ hashCode() → core::int
+ return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///copy_with_call_sites.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+ method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+ return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
+}
+static method main() → dynamic {
+ self::Cat cat = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:18:20: Error: No named parameter with the name 'numberOfWhiskers'.
+ Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+ ^^^^^^^^^^^^^^^^";
+ let final dynamic #t1 = cat as{ForNonNullableByDefault} dynamic in #t1.copyWith(numberOfWhiskers: 4, numberOfLegs: #t1.numberOfLegs);
+}
+
+library /*isNonNullableByDefault*/;
+import self as val;
+import "dart:core" as core;
+
+class JenkinsSmiHash extends core::Object {
+ synthetic constructor •() → val::JenkinsSmiHash
+ : super core::Object::•()
+ ;
+ static method combine(core::int hash, core::int value) → core::int {
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(value));
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(524287.{core::int::&}(hash).{core::int::<<}(10)));
+ return hash.{core::int::^}(hash.{core::int::>>}(6));
+ }
+ static method finish(core::int hash) → core::int {
+ hash = 536870911.{core::int::&}(hash.{core::num::+}(67108863.{core::int::&}(hash).{core::int::<<}(3)));
+ hash = hash.{core::int::^}(hash.{core::int::>>}(11));
+ return 536870911.{core::int::&}(hash.{core::num::+}(16383.{core::int::&}(hash).{core::int::<<}(15)));
+ }
+}
+static const field core::String valueClass = #C2;
+
+constants {
+ #C1 = null
+ #C2 = "valueClass"
+}
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index fee0310..eae95b4 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -75,4 +75,5 @@
nnbd_mixed/never_opt_out: TypeCheckError
value_class/simple: RuntimeError # Expected
value_class/value_extends_non_value: RuntimeError # Expected
-value_class/value_implements_non_value: RuntimeError # Expected
\ No newline at end of file
+value_class/value_implements_non_value: RuntimeError # Expected
+value_class/copy_with_call_sites: RuntimeError # Expected
\ No newline at end of file
diff --git a/pkg/kernel/lib/transformations/scanner.dart b/pkg/kernel/lib/transformations/scanner.dart
index 6d4a690..ce4b9fc 100644
--- a/pkg/kernel/lib/transformations/scanner.dart
+++ b/pkg/kernel/lib/transformations/scanner.dart
@@ -11,7 +11,7 @@
}
class ScanResult<X extends TreeNode, Y extends TreeNode> {
- Map<X, ScanResult<Y, TreeNode>> targets;
+ Map<X, ScanResult<Y, TreeNode>> targets = new Map();
Map<X, ScanError> errors;
}
@@ -26,11 +26,12 @@
ScanResult<Class, Y> scan(TreeNode node) {
ScanResult<Class, Y> result = new ScanResult();
- result.targets = new Map();
if (node is Class) {
if (predicate(node)) {
result.targets[node] = next?.scan(node);
+ // TODO(dmitryas): set result.errors when specification is landed,
+ // same with all other places where targets is set
}
} else if (node is Library) {
_scanLibrary(node, result);
@@ -65,12 +66,9 @@
ScanResult<Field, Y> scan(TreeNode node) {
ScanResult<Field, Y> result = new ScanResult();
- result.targets = new Map();
if (node is Field) {
- if (predicate(node)) {
- result.targets[node] = next?.scan(node);
- }
+ _scanField(node, result);
} else if (node is Class) {
_scanClass(node, result);
} else if (node is Library) {
@@ -82,11 +80,15 @@
return result;
}
+ void _scanField(Field field, ScanResult<Field, Y> result) {
+ if (predicate(field)) {
+ result.targets[field] = next?.scan(field);
+ }
+ }
+
void _scanClass(Class cls, ScanResult<Field, Y> result) {
for (Field field in cls.fields) {
- if (predicate(field)) {
- result.targets[field] = next?.scan(field);
- }
+ _scanField(field, result);
}
}
@@ -95,9 +97,7 @@
_scanClass(cls, result);
}
for (Field field in library.fields) {
- if (predicate(field)) {
- result.targets[field] = next?.scan(field);
- }
+ _scanField(field, result);
}
}
@@ -108,6 +108,57 @@
}
}
+abstract class MemberScanner<Y extends TreeNode> implements Scanner<Member, Y> {
+ final Scanner<Y, TreeNode> next;
+
+ MemberScanner(this.next);
+
+ bool predicate(Member node);
+
+ ScanResult<Member, Y> scan(TreeNode node) {
+ ScanResult<Member, Y> result = new ScanResult();
+
+ if (node is Member) {
+ _scanMember(node, result);
+ } else if (node is Class) {
+ _scanClass(node, result);
+ } else if (node is Library) {
+ _scanLibrary(node, result);
+ } else if (node is Component) {
+ _scanComponent(node, result);
+ }
+
+ return result;
+ }
+
+ void _scanMember(Member member, ScanResult<Member, Y> result) {
+ if (predicate(member)) {
+ result.targets[member] = next?.scan(member);
+ }
+ }
+
+ void _scanClass(Class cls, ScanResult<Member, Y> result) {
+ for (Member member in cls.members) {
+ _scanMember(member, result);
+ }
+ }
+
+ void _scanLibrary(Library library, ScanResult<Member, Y> result) {
+ for (Class cls in library.classes) {
+ _scanClass(cls, result);
+ }
+ for (Member member in library.members) {
+ _scanMember(member, result);
+ }
+ }
+
+ void _scanComponent(Component component, ScanResult<Member, Y> result) {
+ for (Library library in component.libraries) {
+ _scanLibrary(library, result);
+ }
+ }
+}
+
abstract class ProcedureScanner<Y extends TreeNode>
implements Scanner<Procedure, Y> {
final Scanner<Y, TreeNode> next;
@@ -118,12 +169,9 @@
ScanResult<Procedure, Y> scan(TreeNode node) {
ScanResult<Procedure, Y> result = new ScanResult();
- result.targets = new Map();
if (node is Procedure) {
- if (predicate(node)) {
- result.targets[node] = next?.scan(node);
- }
+ _scanProcedure(node, result);
} else if (node is Class) {
_scanClass(node, result);
} else if (node is Library) {
@@ -135,11 +183,15 @@
return result;
}
+ void _scanProcedure(Procedure procedure, ScanResult<Procedure, Y> result) {
+ if (predicate(procedure)) {
+ result.targets[procedure] = next?.scan(procedure);
+ }
+ }
+
void _scanClass(Class cls, ScanResult<Procedure, Y> result) {
for (Procedure procedure in cls.procedures) {
- if (predicate(procedure)) {
- result.targets[procedure] = next?.scan(procedure);
- }
+ _scanProcedure(procedure, result);
}
}
@@ -148,9 +200,7 @@
_scanClass(cls, result);
}
for (Procedure procedure in library.procedures) {
- if (predicate(procedure)) {
- result.targets[procedure] = next?.scan(procedure);
- }
+ _scanProcedure(procedure, result);
}
}
@@ -160,3 +210,51 @@
}
}
}
+
+abstract class ExpressionScanner<Y extends TreeNode>
+ extends RecursiveVisitor<void> implements Scanner<Expression, Y> {
+ final Scanner<Y, TreeNode> next;
+ ScanResult<Expression, Y> _result;
+
+ ExpressionScanner(this.next);
+
+ bool predicate(Expression node);
+
+ ScanResult<Expression, Y> scan(TreeNode node) {
+ ScanResult<Expression, Y> result = _result = new ScanResult();
+ node.accept(this);
+ _result = null;
+ return result;
+ }
+
+ void visitExpression(Expression node) {
+ if (predicate(node)) {
+ _result.targets[node] = next?.scan(node);
+ // TODO: Update result.errors.
+ }
+ }
+}
+
+abstract class MethodInvocationScanner<Y extends TreeNode>
+ extends RecursiveVisitor<void> implements Scanner<MethodInvocation, Y> {
+ final Scanner<Y, TreeNode> next;
+ ScanResult<MethodInvocation, Y> _result;
+
+ MethodInvocationScanner(this.next);
+
+ bool predicate(MethodInvocation node);
+
+ ScanResult<MethodInvocation, Y> scan(TreeNode node) {
+ ScanResult<MethodInvocation, Y> result = _result = new ScanResult();
+ node.accept(this);
+ _result = null;
+ return result;
+ }
+
+ void visitMethodInvocation(MethodInvocation node) {
+ if (predicate(node)) {
+ _result.targets[node] = next?.scan(node);
+ // TODO: Update result.errors.
+ }
+ }
+}
diff --git a/pkg/kernel/lib/transformations/value_class.dart b/pkg/kernel/lib/transformations/value_class.dart
index c760a89..c616cea 100644
--- a/pkg/kernel/lib/transformations/value_class.dart
+++ b/pkg/kernel/lib/transformations/value_class.dart
@@ -4,6 +4,8 @@
library kernel.transformations.value_class;
+import 'package:kernel/type_environment.dart';
+
import '../ast.dart';
import '../kernel.dart';
import '../core_types.dart' show CoreTypes;
@@ -13,18 +15,7 @@
class ValueClassScanner extends ClassScanner<Null> {
ValueClassScanner() : super(null);
- bool predicate(Class node) {
- for (Expression annotation in node.annotations) {
- if (annotation is ConstantExpression &&
- annotation.constant is StringConstant) {
- StringConstant constant = annotation.constant;
- if (constant.value == 'valueClass') {
- return true;
- }
- }
- }
- return false;
- }
+ bool predicate(Class node) => isValueClass(node);
}
class JenkinsClassScanner extends ClassScanner<Procedure> {
@@ -43,17 +34,48 @@
}
}
-void transformComponent(
- Component node, CoreTypes coreTypes, ClassHierarchy hierarchy) {
- ValueClassScanner scanner = new ValueClassScanner();
- ScanResult<Class, Null> valueClasses = scanner.scan(node);
- for (Class valueClass in valueClasses.targets.keys) {
- transformValueClass(valueClass, coreTypes, hierarchy);
+class AllMemberScanner extends MemberScanner<MethodInvocation> {
+ AllMemberScanner(Scanner<MethodInvocation, TreeNode> next) : super(next);
+
+ bool predicate(Member member) => true;
+}
+
+// Scans and matches all copyWith invocations were the reciever is _ as dynamic
+// It will filter out the results that are not value classes afterwards
+class ValueClassCopyWithScanner extends MethodInvocationScanner<Null> {
+ ValueClassCopyWithScanner() : super(null);
+
+ // The matching construct followed in unit-tests is:
+ // @valueClass V {}
+ // V v;
+ // (v as dynamic).copyWith() as V
+ bool predicate(MethodInvocation node) {
+ return node.name.name == "copyWith" &&
+ _isValueClassAsConstruct(node.receiver);
+ }
+
+ bool _isValueClassAsConstruct(Expression node) {
+ return node is AsExpression && node.type is DynamicType;
}
}
-void transformValueClass(
- Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy) {
+void transformComponent(Component node, CoreTypes coreTypes,
+ ClassHierarchy hierarchy, TypeEnvironment typeEnvironment) {
+ ValueClassScanner scanner = new ValueClassScanner();
+ ScanResult<Class, Null> valueClasses = scanner.scan(node);
+ for (Class valueClass in valueClasses.targets.keys) {
+ transformValueClass(valueClass, coreTypes, hierarchy, typeEnvironment);
+ }
+
+ treatCopyWithCallSites(node, coreTypes, typeEnvironment, hierarchy);
+
+ for (Class valueClass in valueClasses.targets.keys) {
+ removeValueClassAnnotation(valueClass);
+ }
+}
+
+void transformValueClass(Class cls, CoreTypes coreTypes,
+ ClassHierarchy hierarchy, TypeEnvironment typeEnvironment) {
List<VariableDeclaration> allVariables = queryAllInstanceVariables(cls);
Constructor syntheticConstructor = null;
for (Constructor constructor in cls.constructors) {
@@ -65,8 +87,8 @@
addConstructor(cls, coreTypes, syntheticConstructor);
addEqualsOperator(cls, coreTypes, hierarchy, allVariables.toList());
addHashCode(cls, coreTypes, hierarchy, allVariables.toList());
- addCopyWith(
- cls, coreTypes, hierarchy, allVariables.toList(), syntheticConstructor);
+ addCopyWith(cls, coreTypes, hierarchy, allVariables.toList(),
+ syntheticConstructor, typeEnvironment);
}
void addConstructor(
@@ -103,21 +125,6 @@
..addAll(ownFields.values)
..addAll(superParameters);
syntheticConstructor.initializers = initializersConstructor;
-
- int valueClassAnnotationIndex;
- for (int annotationIndex = 0;
- annotationIndex < cls.annotations.length;
- annotationIndex++) {
- Expression annotation = cls.annotations[annotationIndex];
- if (annotation is ConstantExpression &&
- annotation.constant is StringConstant) {
- StringConstant constant = annotation.constant;
- if (constant.value == 'valueClass') {
- valueClassAnnotationIndex = annotationIndex;
- }
- }
- }
- cls.annotations.removeAt(valueClassAnnotationIndex);
}
void addEqualsOperator(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
@@ -245,8 +252,13 @@
..fileOffset = cls.fileOffset);
}
-void addCopyWith(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
- List<VariableDeclaration> allVariables, Constructor syntheticConstructor) {
+void addCopyWith(
+ Class cls,
+ CoreTypes coreTypes,
+ ClassHierarchy hierarchy,
+ List<VariableDeclaration> allVariables,
+ Constructor syntheticConstructor,
+ TypeEnvironment typeEnvironment) {
Map<VariableDeclaration, Member> targetsEquals = new Map();
Map<VariableDeclaration, Member> targets = new Map();
for (VariableDeclaration variable in allVariables) {
@@ -291,3 +303,98 @@
..addAll(cls.fields.map<VariableDeclaration>(
(f) => VariableDeclaration(f.name.text, type: f.type)));
}
+
+void removeValueClassAnnotation(Class cls) {
+ int valueClassAnnotationIndex;
+ for (int annotationIndex = 0;
+ annotationIndex < cls.annotations.length;
+ annotationIndex++) {
+ Expression annotation = cls.annotations[annotationIndex];
+ if (annotation is ConstantExpression &&
+ annotation.constant is StringConstant) {
+ StringConstant constant = annotation.constant;
+ if (constant.value == 'valueClass') {
+ valueClassAnnotationIndex = annotationIndex;
+ }
+ }
+ }
+ cls.annotations.removeAt(valueClassAnnotationIndex);
+}
+
+void treatCopyWithCallSites(Component component, CoreTypes coreTypes,
+ TypeEnvironment typeEnvironment, ClassHierarchy hierarchy) {
+ ValueClassCopyWithScanner valueCopyWithScanner =
+ new ValueClassCopyWithScanner();
+ AllMemberScanner copyWithScanner = AllMemberScanner(valueCopyWithScanner);
+ ScanResult<Member, MethodInvocation> copyWithCallSites =
+ copyWithScanner.scan(component);
+ for (Member memberWithCopyWith in copyWithCallSites.targets.keys) {
+ if (copyWithCallSites.targets[memberWithCopyWith].targets != null) {
+ StaticTypeContext staticTypeContext =
+ StaticTypeContext(memberWithCopyWith, typeEnvironment);
+ for (MethodInvocation copyWithCall
+ in copyWithCallSites.targets[memberWithCopyWith].targets.keys) {
+ AsExpression receiver = copyWithCall.receiver as AsExpression;
+
+ Expression valueClassInstance = receiver.operand;
+ DartType valueClassType =
+ valueClassInstance.getStaticType(staticTypeContext);
+ if (valueClassType is InterfaceType) {
+ Class valueClass = valueClassType.classNode;
+ if (isValueClass(valueClass)) {
+ treatCopyWithCallSite(
+ valueClass, copyWithCall, coreTypes, hierarchy);
+ }
+ }
+ }
+ }
+ }
+}
+
+void treatCopyWithCallSite(Class valueClass, MethodInvocation copyWithCall,
+ CoreTypes coreTypes, ClassHierarchy hierarchy) {
+ Map<String, Expression> preTransformationArguments = new Map();
+ for (NamedExpression argument in copyWithCall.arguments.named) {
+ preTransformationArguments[argument.name] = argument.value;
+ }
+ Constructor syntheticConstructor;
+ for (Constructor constructor in valueClass.constructors) {
+ if (constructor.isSynthetic) {
+ syntheticConstructor = constructor;
+ }
+ }
+ List<VariableDeclaration> allArguments =
+ syntheticConstructor.function.namedParameters;
+
+ VariableDeclaration letVariable =
+ VariableDeclaration.forValue(copyWithCall.receiver);
+ Arguments postTransformationArguments = Arguments.empty();
+ for (VariableDeclaration argument in allArguments) {
+ if (preTransformationArguments.containsKey(argument.name)) {
+ postTransformationArguments.named.add(NamedExpression(
+ argument.name, preTransformationArguments[argument.name])
+ ..parent = postTransformationArguments);
+ } else {
+ postTransformationArguments.named.add(NamedExpression(argument.name,
+ PropertyGet(VariableGet(letVariable), Name(argument.name)))
+ ..parent = postTransformationArguments);
+ }
+ }
+ copyWithCall.replaceWith(Let(
+ letVariable,
+ MethodInvocation(VariableGet(letVariable), Name("copyWith"),
+ postTransformationArguments)));
+}
+
+bool isValueClass(Class node) {
+ for (Expression annotation in node.annotations) {
+ if (annotation is ConstantExpression &&
+ annotation.constant is StringConstant) {
+ StringConstant constant = annotation.constant;
+ if (constant.value == "valueClass") {
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/pkg/nnbd_migration/analysis_options.yaml b/pkg/nnbd_migration/analysis_options.yaml
index be53569..d38c130 100644
--- a/pkg/nnbd_migration/analysis_options.yaml
+++ b/pkg/nnbd_migration/analysis_options.yaml
@@ -16,6 +16,7 @@
linter:
rules:
+ - await_only_futures
- empty_constructor_bodies
- empty_statements
- unnecessary_brace_in_string_interps
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index a54bf55..34fd139 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -55,7 +55,7 @@
removeViaComments: removeViaComments,
warnOnWeakCode: warnOnWeakCode);
for (var path in input.keys) {
- if (!(await session.getFile(path)).isPart) {
+ if (!(session.getFile(path)).isPart) {
for (var unit in (await session.getResolvedLibrary(path)).units) {
migration.prepareInput(unit);
}
@@ -63,7 +63,7 @@
}
_betweenStages();
for (var path in input.keys) {
- if (!(await session.getFile(path)).isPart) {
+ if (!(session.getFile(path)).isPart) {
for (var unit in (await session.getResolvedLibrary(path)).units) {
migration.processInput(unit);
}
@@ -71,7 +71,7 @@
}
_betweenStages();
for (var path in input.keys) {
- if (!(await session.getFile(path)).isPart) {
+ if (!(session.getFile(path)).isPart) {
for (var unit in (await session.getResolvedLibrary(path)).units) {
migration.finalizeInput(unit);
}
diff --git a/pkg/nnbd_migration/test/migration_cli_test.dart b/pkg/nnbd_migration/test/migration_cli_test.dart
index 0d98a16..e9393df 100644
--- a/pkg/nnbd_migration/test/migration_cli_test.dart
+++ b/pkg/nnbd_migration/test/migration_cli_test.dart
@@ -444,7 +444,7 @@
'external bool operator ==(dynamic other)');
expect(newCoreLibText, isNot(oldCoreLibText));
coreLib.writeAsStringSync(newCoreLibText);
- var projectDir = await createProjectDir(simpleProject());
+ var projectDir = createProjectDir(simpleProject());
await assertRunFailure([projectDir], cli: cli);
var output = logger.stdoutBuffer.toString();
expect(output, contains(messages.sdkNnbdOff));
@@ -464,7 +464,7 @@
'external bool operator ==(dynamic other)');
expect(newCoreLibText, isNot(oldCoreLibText));
coreLib.writeAsStringSync(newCoreLibText);
- var projectDir = await createProjectDir(simpleProject());
+ var projectDir = createProjectDir(simpleProject());
await assertRunFailure([projectDir], cli: cli);
var output = logger.stdoutBuffer.toString();
expect(output, contains(messages.sdkNnbdOff));
@@ -564,7 +564,7 @@
test_lifecycle_apply_changes() async {
var projectContents = simpleProject();
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
var cliRunner = cli.decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
@@ -602,7 +602,7 @@
- empty_constructor_bodies
''';
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli()
.decodeCommandLineArgs(_parseArgs(['--no-web-preview', projectDir]));
await cliRunner.run();
@@ -615,7 +615,7 @@
test_lifecycle_contextdiscovery_handles_single() async {
var projectContents = simpleProject();
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli()
.decodeCommandLineArgs(_parseArgs(['--no-web-preview', projectDir]));
await cliRunner.run();
@@ -626,7 +626,7 @@
test_lifecycle_exception_handling() async {
var projectContents = simpleProject(sourceText: 'main() { print(0); }');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
injectArtificialException = true;
await assertRunFailure([projectDir]);
var errorOutput = logger.stderrBuffer.toString();
@@ -638,7 +638,7 @@
test_lifecycle_exception_handling_ignore() async {
var projectContents = simpleProject(sourceText: 'main() { print(0); }');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
injectArtificialException = true;
var cli = _createCli();
await runWithPreviewServer(cli, ['--ignore-exceptions', projectDir],
@@ -659,7 +659,7 @@
test_lifecycle_exception_handling_multiple() async {
var projectContents =
simpleProject(sourceText: 'main() { print(0); print(1); }');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
injectArtificialException = true;
await assertRunFailure([projectDir]);
var errorOutput = logger.stderrBuffer.toString();
@@ -673,7 +673,7 @@
test_lifecycle_exception_handling_with_error() async {
var projectContents =
simpleProject(sourceText: 'main() { print(0); unresolved; }');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
injectArtificialException = true;
await assertRunFailure(['--ignore-errors', projectDir]);
var errorOutput = logger.stderrBuffer.toString();
@@ -686,7 +686,7 @@
var projectContents = simpleProject(sourceText: '''
int f() => null
''');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
await assertRunFailure([projectDir]);
var output = logger.stdoutBuffer.toString();
expect(output, contains('1 analysis issue found'));
@@ -706,7 +706,7 @@
var projectContents = simpleProject(sourceText: '''
int? f() => null
''');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, ['--ignore-errors', projectDir],
(url) async {
@@ -722,7 +722,7 @@
test_lifecycle_no_preview() async {
var projectContents = simpleProject();
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli()
.decodeCommandLineArgs(_parseArgs(['--no-web-preview', projectDir]));
await cliRunner.run();
@@ -764,7 +764,7 @@
}
var projectContents = makeProject();
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var testPath =
resourceProvider.pathContext.join(projectDir, 'lib', 'test.dart');
var analyzeButDoNotMigratePath = resourceProvider.pathContext
@@ -789,7 +789,7 @@
test_lifecycle_preview() async {
var projectContents = simpleProject();
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
var localhostAddressText = Platform.environment.containsKey('FORCE_IPV6')
@@ -806,7 +806,7 @@
test_lifecycle_preview_add_hint() async {
var projectContents = simpleProject(sourceText: 'int x;');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
expect(
@@ -835,7 +835,7 @@
test_lifecycle_preview_apply_changes() async {
var projectContents = simpleProject();
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
bool applyHookCalled = false;
cli._onApplyHook = () {
@@ -861,7 +861,7 @@
}
test_lifecycle_preview_extra_forward_slash() async {
- var projectDir = await createProjectDir(simpleProject());
+ var projectDir = createProjectDir(simpleProject());
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
var uri = Uri.parse(url);
@@ -873,7 +873,7 @@
test_lifecycle_preview_navigation_links() async {
var projectContents = simpleProject(sourceText: 'int x;');
projectContents['lib/src/test.dart'] = 'import "../test.dart"; int y = x;';
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
expect(
@@ -907,7 +907,7 @@
test_lifecycle_preview_navigation_tree() async {
var projectContents = simpleProject(sourceText: 'int x;');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
expect(
@@ -940,7 +940,7 @@
test_lifecycle_preview_on_host_any() async {
var projectContents = simpleProject();
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli()
..decodeCommandLineArgs(_parseArgs(['--preview-hostname=any']));
await runWithPreviewServer(cli, [projectDir], (url) async {
@@ -953,7 +953,7 @@
test_lifecycle_preview_region_link() async {
var projectContents = simpleProject(sourceText: 'int x;');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
expect(
@@ -994,7 +994,7 @@
test_lifecycle_preview_region_table_path() async {
var projectContents = simpleProject(sourceText: 'int x;');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
expect(
@@ -1027,7 +1027,7 @@
test_lifecycle_preview_rerun() async {
var origSourceText = 'void f() {}';
var projectContents = simpleProject(sourceText: origSourceText);
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
await assertPreviewServerResponsive(url);
@@ -1049,7 +1049,7 @@
test_lifecycle_preview_rerun_added_file() async {
var projectContents = simpleProject();
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
await assertPreviewServerResponsive(url);
@@ -1072,7 +1072,7 @@
test_lifecycle_preview_rerun_deleted_file() async {
var projectContents = simpleProject();
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
// Note: we use the summary to verify that the deletion was noticed
var summaryPath = resourceProvider.convertPath('/summary.json');
@@ -1109,7 +1109,7 @@
test_lifecycle_preview_rerun_with_new_analysis_errors() async {
var origSourceText = 'void f(int i) {}';
var projectContents = simpleProject(sourceText: origSourceText);
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
await assertPreviewServerResponsive(url);
@@ -1143,9 +1143,9 @@
var crazyFunctionName = 'crazyFunctionNameThatHasNeverBeenSeenBefore';
var projectContents =
simpleProject(sourceText: 'void $crazyFunctionName() {}');
- var mainProjectDir = await createProjectDir(projectContents);
- var otherProjectDir = await createProjectDir(projectContents,
- posixPath: '/other_project_dir');
+ var mainProjectDir = createProjectDir(projectContents);
+ var otherProjectDir =
+ createProjectDir(projectContents, posixPath: '/other_project_dir');
var cli = _createCli();
await runWithPreviewServer(cli, [mainProjectDir], (url) async {
await assertPreviewServerResponsive(url);
@@ -1174,7 +1174,7 @@
test_lifecycle_preview_stack_hint_action() async {
var projectContents = simpleProject(sourceText: 'int x;');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
expect(
@@ -1209,7 +1209,7 @@
test_lifecycle_preview_stacktrace_link() async {
var projectContents = simpleProject(sourceText: 'int x;');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
await runWithPreviewServer(cli, [projectDir], (url) async {
expect(
@@ -1246,7 +1246,7 @@
var projectContents = simpleProject(sourceText: '''
int f() => null;
''');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
processManager._mockResult = ProcessResult(
123 /* pid */,
0 /* exitCode */,
@@ -1266,7 +1266,7 @@
var projectContents = simpleProject(sourceText: '''
int f() => null;
''');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
processManager._mockResult = ProcessResult(
123 /* pid */,
0 /* exitCode */,
@@ -1287,7 +1287,7 @@
test_lifecycle_summary() async {
var projectContents = simpleProject();
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var summaryPath = resourceProvider.convertPath('/summary.json');
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--summary', summaryPath, projectDir]));
@@ -1301,7 +1301,7 @@
test_lifecycle_summary_does_not_double_count_hint_removals() async {
var projectContents = simpleProject(sourceText: 'int/*?*/ x;');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var summaryPath = resourceProvider.convertPath('/summary.json');
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--summary', summaryPath, projectDir]));
@@ -1316,7 +1316,7 @@
test_lifecycle_summary_rewritten_upon_rerun() async {
var projectContents = simpleProject(sourceText: 'int f(int/*?*/ i) => i;');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cli = _createCli();
var summaryPath = resourceProvider.convertPath('/summary.json');
await runWithPreviewServer(cli, ['--summary', summaryPath, projectDir],
@@ -1351,7 +1351,7 @@
import 'package:does_not/exist.dart';
int f() => null;
''');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
await assertRunFailure([projectDir]);
var output = logger.stdoutBuffer.toString();
expect(output, contains('1 analysis issue found'));
@@ -1464,7 +1464,7 @@
test_package_config_does_not_exist() async {
var projectContents = simpleProject()
..remove('.dart_tool/package_config.json');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
await cliRunner.run();
@@ -1489,7 +1489,7 @@
}
''';
var projectContents = simpleProject(packageConfigText: packageConfigText);
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
await cliRunner.run();
@@ -1507,7 +1507,7 @@
}
''';
var projectContents = simpleProject(packageConfigText: packageConfigText);
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
await cliRunner.run();
@@ -1531,7 +1531,7 @@
}
''';
var projectContents = simpleProject(packageConfigText: packageConfigText);
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
await cliRunner.run();
@@ -1672,7 +1672,7 @@
var projectContents = simpleProject()
..remove('pubspec.yaml')
..remove('.dart_tool/package_config.json');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
await cliRunner.run();
@@ -1690,7 +1690,7 @@
environment:
foo: 1
''');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
await cliRunner.run();
@@ -1710,7 +1710,7 @@
environment: 1
''';
var projectContents = simpleProject(pubspecText: pubspecText);
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
await cliRunner.run();
@@ -1727,7 +1727,7 @@
''';
var projectContents = simpleProject(pubspecText: pubspecText)
..remove('.dart_tool/package_config.json');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
await cliRunner.run();
@@ -1742,7 +1742,7 @@
var projectContents = simpleProject(pubspecText: '''
name: test
''');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
await cliRunner.run();
@@ -1759,7 +1759,7 @@
test_pubspec_is_not_a_map() async {
var projectContents = simpleProject(pubspecText: 'not-a-map');
- var projectDir = await createProjectDir(projectContents);
+ var projectDir = createProjectDir(projectContents);
var cliRunner = _createCli().decodeCommandLineArgs(
_parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
expect(() async => await cliRunner.run(), throwsUnsupportedError);
@@ -1883,6 +1883,11 @@
}
@override
+ void trace(String message) {
+ throw UnimplementedError('TODO(paulberry)');
+ }
+
+ @override
void write(String message) {
stdoutBuffer.write(message);
}
@@ -1891,9 +1896,4 @@
void writeCharCode(int charCode) {
stdoutBuffer.writeCharCode(charCode);
}
-
- @override
- void trace(String message) {
- throw UnimplementedError('TODO(paulberry)');
- }
}
diff --git a/pkg/nnbd_migration/tool/codegen/generate_resources.dart b/pkg/nnbd_migration/tool/codegen/generate_resources.dart
index e1a9c86..43c9356 100644
--- a/pkg/nnbd_migration/tool/codegen/generate_resources.dart
+++ b/pkg/nnbd_migration/tool/codegen/generate_resources.dart
@@ -88,7 +88,7 @@
return lines.join('\n');
}
-void compileWebFrontEnd({bool devMode = false}) async {
+Future<void> compileWebFrontEnd({bool devMode = false}) async {
var sdkBinDir = path.dirname(Platform.resolvedExecutable);
var dart2jsBinary = Platform.isWindows ? 'dart2js.bat' : 'dart2js';
var dart2jsPath = path.join(sdkBinDir, dart2jsBinary);
diff --git a/runtime/bin/file_system_watcher_win.cc b/runtime/bin/file_system_watcher_win.cc
index 33654c4..b371363 100644
--- a/runtime/bin/file_system_watcher_win.cc
+++ b/runtime/bin/file_system_watcher_win.cc
@@ -80,6 +80,9 @@
const intptr_t kEventSize = sizeof(FILE_NOTIFY_INFORMATION);
DirectoryWatchHandle* dir = reinterpret_cast<DirectoryWatchHandle*>(path_id);
intptr_t available = dir->Available();
+ if (available <= 0) {
+ return Dart_NewList(0);
+ }
intptr_t max_count = available / kEventSize + 1;
Dart_Handle events = Dart_NewList(max_count);
uint8_t* buffer = Dart_ScopeAllocate(available);
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 5ec71e8..da31762 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -280,6 +280,9 @@
#endif
static constexpr int kWordSize = 1 << kWordSizeLog2;
static_assert(kWordSize == sizeof(word), "kWordSize should match sizeof(word)");
+// Our compiler code currently assumes this, so formally check it.
+static_assert(dart::kWordSize >= kWordSize,
+ "Host word size smaller than target word size");
static constexpr word kBitsPerWordLog2 = kWordSizeLog2 + kBitsPerByteLog2;
static constexpr word kBitsPerWord = 1 << kBitsPerWordLog2;
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index 39acb48..03fac70 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -332,7 +332,7 @@
class Raw<1, T> {
public:
static void Write(BaseWriteStream* st, T value) {
- st->WriteByte(bit_cast<int8_t>(value));
+ st->WriteByte(bit_cast<uint8_t>(value));
}
};
@@ -390,33 +390,25 @@
current_ += len;
}
- void WriteWord(uword value) {
- const intptr_t len = sizeof(uword);
- EnsureSpace(len);
- *reinterpret_cast<uword*>(current_) = value;
- current_ += len;
- }
+ void WriteWord(uword value) { WriteFixed(value); }
void WriteTargetWord(uword value) {
#if defined(IS_SIMARM_X64)
RELEASE_ASSERT(Utils::IsInt(32, static_cast<word>(value)));
- const intptr_t len = sizeof(uint32_t);
- EnsureSpace(len);
- *reinterpret_cast<uint32_t*>(current_) = static_cast<uint32_t>(value);
- current_ += len;
-#else // defined(IS_SIMARM_X64)
- WriteWord(value);
-#endif // defined(IS_SIMARM_X64)
+ WriteFixed(static_cast<uint32_t>(value));
+#else
+ WriteFixed(value);
+#endif
}
- void Print(const char* format, ...) {
+ void Printf(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) {
va_list args;
va_start(args, format);
- VPrint(format, args);
+ VPrintf(format, args);
va_end(args);
}
- void VPrint(const char* format, va_list args) {
+ void VPrintf(const char* format, va_list args) {
// Measure.
va_list measure_args;
va_copy(measure_args, args);
@@ -447,18 +439,17 @@
template <typename T>
void WriteFixed(T value) {
- const intptr_t len = sizeof(T);
- EnsureSpace(len);
- *reinterpret_cast<T*>(current_) = static_cast<T>(value);
- current_ += len;
+ WriteBytes(&value, sizeof(value));
}
- protected:
DART_FORCE_INLINE void WriteByte(uint8_t value) {
EnsureSpace(1);
*current_++ = value;
}
+ void WriteString(const char* cstr) { WriteBytes(cstr, strlen(cstr)); }
+
+ protected:
void EnsureSpace(intptr_t size_needed) {
if (Remaining() >= size_needed) return;
intptr_t increment_size = capacity_;
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index 9d08ce5..30c25bf 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -21,7 +21,7 @@
explicit ElfWriteStream(BaseWriteStream* stream)
: stream_(ASSERT_NOTNULL(stream)) {}
- intptr_t position() const { return stream_->Position(); }
+ intptr_t Position() const { return stream_->Position(); }
void Align(const intptr_t alignment) {
ASSERT(Utils::IsPowerOfTwo(alignment));
stream_->Align(alignment);
@@ -29,25 +29,13 @@
void WriteBytes(const uint8_t* b, intptr_t size) {
stream_->WriteBytes(b, size);
}
- void WriteByte(uint8_t value) {
- stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
- }
- void WriteHalf(uint16_t value) {
- stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
- }
- void WriteWord(uint32_t value) {
- stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
- }
- void WriteAddr(compiler::target::uword value) {
- stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
- }
- void WriteOff(compiler::target::uword value) {
- stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
- }
+ void WriteByte(uint8_t value) { stream_->WriteByte(value); }
+ void WriteHalf(uint16_t value) { stream_->WriteFixed(value); }
+ void WriteWord(uint32_t value) { stream_->WriteFixed(value); }
+ void WriteAddr(compiler::target::uword value) { stream_->WriteFixed(value); }
+ void WriteOff(compiler::target::uword value) { stream_->WriteFixed(value); }
#if defined(TARGET_ARCH_IS_64_BIT)
- void WriteXWord(uint64_t value) {
- stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
- }
+ void WriteXWord(uint64_t value) { stream_->WriteFixed(value); }
#endif
private:
@@ -602,7 +590,7 @@
cstr_(cstr) {}
void Write(ElfWriteStream* stream) const {
- const intptr_t start = stream->position();
+ const intptr_t start = stream->Position();
stream->WriteWord(name_index);
#if defined(TARGET_ARCH_IS_32_BIT)
stream->WriteAddr(offset);
@@ -617,7 +605,7 @@
stream->WriteAddr(offset);
stream->WriteXWord(size);
#endif
- ASSERT_EQUAL(stream->position() - start, sizeof(elf::Symbol));
+ ASSERT_EQUAL(stream->Position() - start, sizeof(elf::Symbol));
}
const intptr_t name_index;
@@ -655,9 +643,9 @@
void Write(ElfWriteStream* stream) {
for (intptr_t i = 0; i < Length(); i++) {
auto const symbol = At(i);
- const intptr_t start = stream->position();
+ const intptr_t start = stream->Position();
symbol->Write(stream);
- ASSERT_EQUAL(stream->position() - start, entry_size);
+ ASSERT_EQUAL(stream->Position() - start, entry_size);
}
}
@@ -777,7 +765,7 @@
Entry(elf::DynamicEntryType tag, intptr_t value) : tag(tag), value(value) {}
void Write(ElfWriteStream* stream) {
- const intptr_t start = stream->position();
+ const intptr_t start = stream->Position();
#if defined(TARGET_ARCH_IS_32_BIT)
stream->WriteWord(static_cast<uint32_t>(tag));
stream->WriteAddr(value);
@@ -785,7 +773,7 @@
stream->WriteXWord(static_cast<uint64_t>(tag));
stream->WriteAddr(value);
#endif
- ASSERT_EQUAL(stream->position() - start, sizeof(elf::DynamicEntry));
+ ASSERT_EQUAL(stream->Position() - start, sizeof(elf::DynamicEntry));
}
elf::DynamicEntryType tag;
@@ -1039,7 +1027,7 @@
} else {
part |= 0x80;
}
- stream_->WriteFixed(part);
+ stream_->WriteByte(part);
}
}
@@ -1053,35 +1041,32 @@
} else {
part |= 0x80;
}
- stream_->WriteFixed(part);
+ stream_->WriteByte(part);
}
}
- void u1(uint8_t value) { stream_->WriteFixed(value); }
- // Can't use WriteFixed for these, as we may not be at aligned positions.
- void u2(uint16_t value) { stream_->WriteBytes(&value, sizeof(value)); }
- void u4(uint32_t value) { stream_->WriteBytes(&value, sizeof(value)); }
- void u8(uint64_t value) { stream_->WriteBytes(&value, sizeof(value)); }
+ void u1(uint8_t value) { stream_->WriteByte(value); }
+ void u2(uint16_t value) { stream_->WriteFixed(value); }
+ void u4(uint32_t value) { stream_->WriteFixed(value); }
+ void u8(uint64_t value) { stream_->WriteFixed(value); }
void string(const char* cstr) { // NOLINT
- stream_->WriteBytes(reinterpret_cast<const uint8_t*>(cstr),
- strlen(cstr) + 1);
+ // Unlike stream_->WriteString(), we want the null terminator written.
+ stream_->WriteBytes(cstr, strlen(cstr) + 1);
}
- intptr_t position() { return stream_->Position(); }
intptr_t ReserveSize(const char* prefix, intptr_t* start) {
ASSERT(start != nullptr);
- intptr_t fixup = position();
+ intptr_t fixup = stream_->Position();
// We assume DWARF v2, so all sizes are 32-bit.
u4(0);
// All sizes for DWARF sections measure the size of the section data _after_
// the size value.
- *start = position();
+ *start = stream_->Position();
return fixup;
}
void SetSize(intptr_t fixup, const char* prefix, intptr_t start) {
- const intptr_t old_position = position();
+ const intptr_t old_position = stream_->Position();
stream_->SetPosition(fixup);
- const uint32_t value = old_position - start;
- stream_->WriteBytes(&value, sizeof(value));
+ stream_->WriteFixed(static_cast<uint32_t>(old_position - start));
stream_->SetPosition(old_position);
}
void OffsetFromSymbol(const char* symbol, intptr_t offset) {
@@ -1108,7 +1093,7 @@
void RegisterAbstractOrigin(intptr_t index) {
ASSERT(abstract_origins_ != nullptr);
ASSERT(index < abstract_origins_size_);
- abstract_origins_[index] = position();
+ abstract_origins_[index] = stream_->Position();
}
void AbstractOrigin(intptr_t index) { u4(abstract_origins_[index]); }
@@ -1532,12 +1517,12 @@
stream->WriteHalf(sections_.length());
stream->WriteHalf(shstrtab_->index());
- ASSERT_EQUAL(stream->position(), sizeof(elf::ElfHeader));
+ ASSERT_EQUAL(stream->Position(), sizeof(elf::ElfHeader));
}
void Elf::WriteProgramTable(ElfWriteStream* stream) {
ASSERT(program_table_file_size_ >= 0); // Check for finalization.
- ASSERT(stream->position() == program_table_file_offset_);
+ ASSERT(stream->Position() == program_table_file_offset_);
#if defined(DEBUG)
// Here, we count the number of times that a PT_LOAD writable segment is
// followed by a non-writable segment. We initialize last_writable to true so
@@ -1554,9 +1539,9 @@
last_writable = segment->IsWritable();
}
#endif
- const intptr_t start = stream->position();
+ const intptr_t start = stream->Position();
segment->WriteProgramHeader(stream);
- const intptr_t end = stream->position();
+ const intptr_t end = stream->Position();
ASSERT_EQUAL(end - start, sizeof(elf::ProgramHeader));
}
#if defined(DEBUG)
@@ -1570,12 +1555,12 @@
void Elf::WriteSectionTable(ElfWriteStream* stream) {
ASSERT(section_table_file_size_ >= 0); // Check for finalization.
stream->Align(kElfSectionTableAlignment);
- ASSERT_EQUAL(stream->position(), section_table_file_offset_);
+ ASSERT_EQUAL(stream->Position(), section_table_file_offset_);
for (auto const section : sections_) {
- const intptr_t start = stream->position();
+ const intptr_t start = stream->Position();
section->WriteSectionHeader(stream);
- const intptr_t end = stream->position();
+ const intptr_t end = stream->Position();
ASSERT_EQUAL(end - start, sizeof(elf::SectionHeader));
}
}
@@ -1598,9 +1583,9 @@
stream->Align(load_align);
current_segment = section->load_segment;
}
- ASSERT_EQUAL(stream->position(), section->file_offset());
+ ASSERT_EQUAL(stream->Position(), section->file_offset());
section->Write(stream);
- ASSERT_EQUAL(stream->position(),
+ ASSERT_EQUAL(stream->Position(),
section->file_offset() + section->FileSize());
}
}
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 8ed1d98..ae8efbe 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -622,27 +622,30 @@
explicit DwarfAssemblyStream(BaseWriteStream* stream)
: stream_(ASSERT_NOTNULL(stream)) {}
- void sleb128(intptr_t value) { Print(".sleb128 %" Pd "\n", value); }
- void uleb128(uintptr_t value) { Print(".uleb128 %" Pd "\n", value); }
- void u1(uint8_t value) { Print(".byte %u\n", value); }
- void u2(uint16_t value) { Print(".2byte %u\n", value); }
- void u4(uint32_t value) { Print(".4byte %" Pu32 "\n", value); }
- void u8(uint64_t value) { Print(".8byte %" Pu64 "\n", value); }
+ void sleb128(intptr_t value) { stream_->Printf(".sleb128 %" Pd "\n", value); }
+ void uleb128(uintptr_t value) {
+ stream_->Printf(".uleb128 %" Pd "\n", value);
+ }
+ void u1(uint8_t value) { stream_->Printf(".byte %u\n", value); }
+ void u2(uint16_t value) { stream_->Printf(".2byte %u\n", value); }
+ void u4(uint32_t value) { stream_->Printf(".4byte %" Pu32 "\n", value); }
+ void u8(uint64_t value) { stream_->Printf(".8byte %" Pu64 "\n", value); }
void string(const char* cstr) { // NOLINT
- Print(".string \"%s\"\n", cstr); // NOLINT
+ stream_->Printf(".string \"%s\"\n", cstr); // NOLINT
}
// Uses labels, so doesn't output to start or return a useful fixup position.
intptr_t ReserveSize(const char* prefix, intptr_t* start) {
// Assignment to temp works around buggy Mac assembler.
- Print("L%s_size = .L%s_end - .L%s_start\n", prefix, prefix, prefix);
- Print(".4byte L%s_size\n", prefix);
- Print(".L%s_start:\n", prefix);
+ stream_->Printf("L%s_size = .L%s_end - .L%s_start\n", prefix, prefix,
+ prefix);
+ stream_->Printf(".4byte L%s_size\n", prefix);
+ stream_->Printf(".L%s_start:\n", prefix);
return -1;
}
// Just need to label the end so the assembler can calculate the size, so
// start and the fixup position is unused.
void SetSize(intptr_t fixup, const char* prefix, intptr_t start) {
- Print(".L%s_end:\n", prefix);
+ stream_->Printf(".L%s_end:\n", prefix);
}
void OffsetFromSymbol(const char* symbol, intptr_t offset) {
if (offset == 0) {
@@ -655,51 +658,53 @@
intptr_t offset1,
const char* symbol2,
intptr_t offset2) {
- Print(".uleb128 %s - %s + %" Pd "\n", symbol1, symbol2, offset1 - offset2);
+ stream_->Printf(".uleb128 %s - %s + %" Pd "\n", symbol1, symbol2,
+ offset1 - offset2);
}
// No-op, we'll be using labels.
void InitializeAbstractOrigins(intptr_t size) {}
void RegisterAbstractOrigin(intptr_t index) {
// Label for DW_AT_abstract_origin references
- Print(".Lfunc%" Pd ":\n", index);
+ stream_->Printf(".Lfunc%" Pd ":\n", index);
}
void AbstractOrigin(intptr_t index) {
// Assignment to temp works around buggy Mac assembler.
- Print("Ltemp%" Pd " = .Lfunc%" Pd " - %s\n", temp_, index, kDebugInfoLabel);
- Print(".4byte Ltemp%" Pd "\n", temp_);
+ stream_->Printf("Ltemp%" Pd " = .Lfunc%" Pd " - %s\n", temp_, index,
+ kDebugInfoLabel);
+ stream_->Printf(".4byte Ltemp%" Pd "\n", temp_);
temp_++;
}
// Methods for writing the assembly prologues for various DWARF sections.
void AbbreviationsPrologue() {
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
- Print(".section __DWARF,__debug_abbrev,regular,debug\n");
+ stream_->WriteString(".section __DWARF,__debug_abbrev,regular,debug\n");
#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
defined(TARGET_OS_FUCHSIA)
- Print(".section .debug_abbrev,\"\"\n");
+ stream_->WriteString(".section .debug_abbrev,\"\"\n");
#else
UNIMPLEMENTED();
#endif
}
void DebugInfoPrologue() {
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
- Print(".section __DWARF,__debug_info,regular,debug\n");
+ stream_->WriteString(".section __DWARF,__debug_info,regular,debug\n");
#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
defined(TARGET_OS_FUCHSIA)
- Print(".section .debug_info,\"\"\n");
+ stream_->WriteString(".section .debug_info,\"\"\n");
#else
UNIMPLEMENTED();
#endif
// Used to calculate abstract origin values.
- Print("%s:\n", kDebugInfoLabel);
+ stream_->Printf("%s:\n", kDebugInfoLabel);
}
void LineNumberProgramPrologue() {
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
- Print(".section __DWARF,__debug_line,regular,debug\n");
+ stream_->WriteString(".section __DWARF,__debug_line,regular,debug\n");
#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
defined(TARGET_OS_FUCHSIA)
- Print(".section .debug_line,\"\"\n");
+ stream_->WriteString(".section .debug_line,\"\"\n");
#else
UNIMPLEMENTED();
#endif
@@ -708,22 +713,17 @@
private:
static constexpr const char* kDebugInfoLabel = ".Ldebug_info";
- void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) {
- va_list args;
- va_start(args, format);
- stream_->VPrint(format, args);
- va_end(args);
- }
-
#if defined(TARGET_ARCH_IS_32_BIT)
#define FORM_ADDR ".4byte"
#elif defined(TARGET_ARCH_IS_64_BIT)
#define FORM_ADDR ".8byte"
#endif
- void PrintNamedAddress(const char* name) { Print(FORM_ADDR " %s\n", name); }
+ void PrintNamedAddress(const char* name) {
+ stream_->Printf(FORM_ADDR " %s\n", name);
+ }
void PrintNamedAddressWithOffset(const char* name, intptr_t offset) {
- Print(FORM_ADDR " %s + %" Pd "\n", name, offset);
+ stream_->Printf(FORM_ADDR " %s + %" Pd "\n", name, offset);
}
#undef FORM_ADDR
@@ -840,10 +840,10 @@
#if defined(DART_PRECOMPILER)
auto const bss_symbol =
vm ? kVmSnapshotBssAsmSymbol : kIsolateSnapshotBssAsmSymbol;
- assembly_stream_->Print(".bss\n");
+ assembly_stream_->WriteString(".bss\n");
// Align the BSS contents as expected by the Image class.
Align(ImageWriter::kBssAlignment);
- assembly_stream_->Print("%s:\n", bss_symbol);
+ assembly_stream_->Printf("%s:\n", bss_symbol);
auto const entry_count = vm ? BSS::kVmEntryCount : BSS::kIsolateEntryCount;
for (intptr_t i = 0; i < entry_count; i++) {
@@ -860,18 +860,18 @@
#else
#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
defined(TARGET_OS_FUCHSIA)
- assembly_stream_->Print(".section .rodata\n");
+ assembly_stream_->WriteString(".section .rodata\n");
#elif defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
- assembly_stream_->Print(".const\n");
+ assembly_stream_->WriteString(".const\n");
#else
UNIMPLEMENTED();
#endif
const char* data_symbol =
vm ? kVmSnapshotDataAsmSymbol : kIsolateSnapshotDataAsmSymbol;
- assembly_stream_->Print(".globl %s\n", data_symbol);
+ assembly_stream_->Printf(".globl %s\n", data_symbol);
Align(ImageWriter::kRODataAlignment);
- assembly_stream_->Print("%s:\n", data_symbol);
+ assembly_stream_->Printf("%s:\n", data_symbol);
const uword buffer = reinterpret_cast<uword>(clustered_stream->buffer());
const intptr_t length = clustered_stream->bytes_written();
WriteByteSequence(buffer, buffer + length);
@@ -895,13 +895,13 @@
const char* instructions_symbol = vm ? kVmSnapshotInstructionsAsmSymbol
: kIsolateSnapshotInstructionsAsmSymbol;
- assembly_stream_->Print(".text\n");
- assembly_stream_->Print(".globl %s\n", instructions_symbol);
+ assembly_stream_->WriteString(".text\n");
+ assembly_stream_->Printf(".globl %s\n", instructions_symbol);
// Start snapshot at page boundary.
ASSERT(ImageWriter::kTextAlignment >= VirtualMemory::PageSize());
Align(ImageWriter::kTextAlignment);
- assembly_stream_->Print("%s:\n", instructions_symbol);
+ assembly_stream_->Printf("%s:\n", instructions_symbol);
#if defined(DART_PRECOMPILER)
auto const bss_symbol =
@@ -976,8 +976,8 @@
// An ImageHeader has four fields:
// 1) The BSS offset from this section.
- assembly_stream_->Print("%s %s - %s\n", kLiteralPrefix, bss_symbol,
- instructions_symbol);
+ assembly_stream_->Printf("%s %s - %s\n", kLiteralPrefix, bss_symbol,
+ instructions_symbol);
text_offset += compiler::target::kWordSize;
// 2) The relocated address of the instructions.
//
@@ -1133,7 +1133,7 @@
#endif
// 2. Write a label at the entry point.
// Linux's perf uses these labels.
- assembly_stream_->Print("%s:\n", object_name);
+ assembly_stream_->Printf("%s:\n", object_name);
{
// 3. Write from the payload start to payload end. For AOT snapshots
@@ -1160,11 +1160,10 @@
Utils::RoundDown(payload_end, sizeof(compiler::target::uword));
for (uword cursor = payload_start; cursor < possible_relocations_end;
cursor += sizeof(compiler::target::uword)) {
- compiler::target::uword data =
- *reinterpret_cast<compiler::target::uword*>(cursor);
+ uword data = *reinterpret_cast<compiler::target::uword*>(cursor);
if ((cursor - payload_start) == next_reloc_offset) {
- assembly_stream_->Print("%s %s - (.) + %" Pd "\n", kLiteralPrefix,
- bss_symbol, /*addend=*/data);
+ assembly_stream_->Printf("%s %s - (.) + %" Pu "\n", kLiteralPrefix,
+ bss_symbol, /*addend=*/data);
text_offset += compiler::target::kWordSize;
next_reloc_offset = iterator.MoveNext() ? iterator.PcOffset() : -1;
} else {
@@ -1243,12 +1242,14 @@
// Creates DWARF's .debug_frame
// CFI = Call frame information
// CFA = Canonical frame address
- assembly_stream_->Print(".cfi_startproc\n");
+ assembly_stream_->WriteString(".cfi_startproc\n");
#if defined(TARGET_ARCH_X64)
- assembly_stream_->Print(".cfi_def_cfa rbp, 0\n"); // CFA is fp+0
- assembly_stream_->Print(".cfi_offset rbp, 0\n"); // saved fp is *(CFA+0)
- assembly_stream_->Print(".cfi_offset rip, 8\n"); // saved pc is *(CFA+8)
+ assembly_stream_->WriteString(".cfi_def_cfa rbp, 0\n"); // CFA is fp+0
+ assembly_stream_->WriteString(
+ ".cfi_offset rbp, 0\n"); // saved fp is *(CFA+0)
+ assembly_stream_->WriteString(
+ ".cfi_offset rip, 8\n"); // saved pc is *(CFA+8)
// saved sp is CFA+16
// Should be ".cfi_value_offset rsp, 16", but requires gcc newer than late
// 2016 and not supported by Android's libunwind.
@@ -1257,14 +1258,16 @@
// uleb128 size of operation 2
// DW_OP_plus_uconst 0x23
// uleb128 addend 16
- assembly_stream_->Print(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
+ assembly_stream_->WriteString(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
#elif defined(TARGET_ARCH_ARM64)
COMPILE_ASSERT(FP == R29);
COMPILE_ASSERT(LR == R30);
- assembly_stream_->Print(".cfi_def_cfa x29, 0\n"); // CFA is fp+0
- assembly_stream_->Print(".cfi_offset x29, 0\n"); // saved fp is *(CFA+0)
- assembly_stream_->Print(".cfi_offset x30, 8\n"); // saved pc is *(CFA+8)
+ assembly_stream_->WriteString(".cfi_def_cfa x29, 0\n"); // CFA is fp+0
+ assembly_stream_->WriteString(
+ ".cfi_offset x29, 0\n"); // saved fp is *(CFA+0)
+ assembly_stream_->WriteString(
+ ".cfi_offset x30, 8\n"); // saved pc is *(CFA+8)
// saved sp is CFA+16
// Should be ".cfi_value_offset sp, 16", but requires gcc newer than late
// 2016 and not supported by Android's libunwind.
@@ -1273,19 +1276,20 @@
// uleb128 size of operation 2
// DW_OP_plus_uconst 0x23
// uleb128 addend 16
- assembly_stream_->Print(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
+ assembly_stream_->WriteString(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
#elif defined(TARGET_ARCH_ARM)
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
COMPILE_ASSERT(FP == R7);
- assembly_stream_->Print(".cfi_def_cfa r7, 0\n"); // CFA is fp+j0
- assembly_stream_->Print(".cfi_offset r7, 0\n"); // saved fp is *(CFA+0)
+ assembly_stream_->WriteString(".cfi_def_cfa r7, 0\n"); // CFA is fp+j0
+ assembly_stream_->WriteString(".cfi_offset r7, 0\n"); // saved fp is *(CFA+0)
#else
COMPILE_ASSERT(FP == R11);
- assembly_stream_->Print(".cfi_def_cfa r11, 0\n"); // CFA is fp+0
- assembly_stream_->Print(".cfi_offset r11, 0\n"); // saved fp is *(CFA+0)
+ assembly_stream_->WriteString(".cfi_def_cfa r11, 0\n"); // CFA is fp+0
+ assembly_stream_->WriteString(
+ ".cfi_offset r11, 0\n"); // saved fp is *(CFA+0)
#endif
- assembly_stream_->Print(".cfi_offset lr, 4\n"); // saved pc is *(CFA+4)
+ assembly_stream_->WriteString(".cfi_offset lr, 4\n"); // saved pc is *(CFA+4)
// saved sp is CFA+8
// Should be ".cfi_value_offset sp, 8", but requires gcc newer than late
// 2016 and not supported by Android's libunwind.
@@ -1294,14 +1298,14 @@
// uleb128 size of operation 2
// DW_OP_plus_uconst 0x23
// uleb128 addend 8
- assembly_stream_->Print(".cfi_escape 0x10, 13, 2, 0x23, 8\n");
+ assembly_stream_->WriteString(".cfi_escape 0x10, 13, 2, 0x23, 8\n");
// libunwind on ARM may use .ARM.exidx instead of .debug_frame
#if !defined(TARGET_OS_MACOS) && !defined(TARGET_OS_MACOS_IOS)
COMPILE_ASSERT(FP == R11);
- assembly_stream_->Print(".fnstart\n");
- assembly_stream_->Print(".save {r11, lr}\n");
- assembly_stream_->Print(".setfp r11, sp, #0\n");
+ assembly_stream_->WriteString(".fnstart\n");
+ assembly_stream_->WriteString(".save {r11, lr}\n");
+ assembly_stream_->WriteString(".setfp r11, sp, #0\n");
#endif
#endif
@@ -1310,10 +1314,10 @@
void AssemblyImageWriter::FrameUnwindEpilogue() {
#if defined(TARGET_ARCH_ARM)
#if !defined(TARGET_OS_MACOS) && !defined(TARGET_OS_MACOS_IOS)
- assembly_stream_->Print(".fnend\n");
+ assembly_stream_->WriteString(".fnend\n");
#endif
#endif
- assembly_stream_->Print(".cfi_endproc\n");
+ assembly_stream_->WriteString(".cfi_endproc\n");
}
intptr_t AssemblyImageWriter::WriteByteSequence(uword start, uword end) {
@@ -1327,20 +1331,22 @@
}
if (end != end_of_words) {
auto start_of_rest = reinterpret_cast<const uint8_t*>(end_of_words);
- assembly_stream_->Print(".byte ");
+ assembly_stream_->WriteString(".byte ");
for (auto cursor = start_of_rest;
cursor < reinterpret_cast<const uint8_t*>(end); cursor++) {
- if (cursor != start_of_rest) assembly_stream_->Print(", ");
- assembly_stream_->Print("0x%0.2" Px "", *cursor);
+ if (cursor != start_of_rest) {
+ assembly_stream_->WriteString(", ");
+ }
+ assembly_stream_->Printf("0x%0.2x", *cursor);
}
- assembly_stream_->Print("\n");
+ assembly_stream_->WriteString("\n");
}
return end - start;
}
intptr_t AssemblyImageWriter::Align(intptr_t alignment, uword position) {
const uword next_position = Utils::RoundUp(position, alignment);
- assembly_stream_->Print(".balign %" Pd ", 0\n", alignment);
+ assembly_stream_->Printf(".balign %" Pd ", 0\n", alignment);
return next_position - position;
}
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index a75871b..44673a3 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -484,12 +484,15 @@
const char* kLiteralPrefix = ".long";
#endif
- intptr_t WriteWordLiteralText(compiler::target::uword value) {
+ intptr_t WriteWordLiteralText(uword value) {
+#if defined(IS_SIMARM_X64)
+ ASSERT(value <= kMaxUint32);
+#endif
// Padding is helpful for comparing the .S with --disassemble.
#if defined(TARGET_ARCH_IS_64_BIT)
- assembly_stream_->Print(".quad 0x%0.16" Px "\n", value);
+ assembly_stream_->Printf(".quad 0x%0.16" Px "\n", value);
#else
- assembly_stream_->Print(".long 0x%0.8" Px "\n", value);
+ assembly_stream_->Printf(".long 0x%0.8" Px "\n", value);
#endif
return compiler::target::kWordSize;
}
diff --git a/tools/VERSION b/tools/VERSION
index 452c461..77e4c0e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 159
+PRERELEASE 160
PRERELEASE_PATCH 0
\ No newline at end of file