Version 2.6.0-dev.4.0
Merge commit '942af5bd62496330ab24720333cab08a2e8e5e07' into dev
diff --git a/BUILD.gn b/BUILD.gn
index 1aff52e..60d07ff 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -3,7 +3,6 @@
# BSD-style license that can be found in the LICENSE file.
import("build/config/gclient_args.gni")
-import("build/dart/dart_host_sdk_toolchain.gni")
targetting_fuchsia = target_os == "fuchsia"
@@ -17,9 +16,7 @@
":runtime",
]
if (defined(checkout_llvm) && checkout_llvm) {
- deps += [
- ":llvm_codegen"
- ]
+ deps += [ ":llvm_codegen" ]
}
}
@@ -51,13 +48,13 @@
}
deps = [
"runtime/bin:dart",
+ "runtime/bin:entrypoints_verification_test_extension",
+ "runtime/bin:ffi_test_dynamic_library",
+ "runtime/bin:ffi_test_functions",
"runtime/bin:process_test",
"runtime/bin:run_vm_tests",
"runtime/bin:sample_extension",
"runtime/bin:test_extension",
- "runtime/bin:entrypoints_verification_test_extension",
- "runtime/bin:ffi_test_dynamic_library",
- "runtime/bin:ffi_test_functions",
"runtime/vm:kernel_platform_files($host_toolchain)",
"utils/kernel-service:kernel-service",
]
@@ -92,15 +89,6 @@
]
}
-if (defined(dart_host_sdk_toolchain) &&
- dart_host_sdk_toolchain != host_toolchain) {
- group("create_host_sdk") {
- deps = [
- "sdk:create_sdk($dart_host_sdk_toolchain)",
- ]
- }
-}
-
group("dart2js") {
deps = [
"utils/compiler:dart2js",
@@ -142,8 +130,8 @@
group("llvm_codegen") {
if (defined(checkout_llvm) && checkout_llvm) {
deps = [
- "runtime/llvm_codegen/codegen",
"runtime/llvm_codegen/bit",
+ "runtime/llvm_codegen/codegen",
]
}
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ee267aa..ec7b523 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,7 +33,7 @@
The Linter was updated to `0.1.98`, which includes:
-* fixed null raw expression accesses in use_to_and_as_if_applicable
+* fixed null raw expression accesses in `use_to_and_as_if_applicable`
* internal migration to using analyzer `InheritanceManager3`
* internal migration away from using analyzer `resolutionMap`
* various fixes and improvements to anticipate support for extension-methods
diff --git a/DEPS b/DEPS
index 7d7529e..60b6900 100644
--- a/DEPS
+++ b/DEPS
@@ -82,9 +82,9 @@
# and land the review.
#
# For more details, see https://github.com/dart-lang/sdk/issues/30164
- "dart_style_tag": "1.3.0", # Please see the note above before updating.
+ "dart_style_tag": "1.3.1", # Please see the note above before updating.
- "dartdoc_rev" : "6934accd88c29a73cae26d0c4def3323efc2119c",
+ "dartdoc_tag" : "v0.28.6",
"fixnum_tag": "0.10.9",
"glob_tag": "1.1.7",
"html_tag" : "0.14.0+1",
@@ -102,7 +102,7 @@
"linter_tag": "0.1.98",
"logging_tag": "0.11.3+2",
"markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
- "markdown_tag": "2.0.3",
+ "markdown_tag": "2.1.1",
"matcher_tag": "0.12.3",
"mime_tag": "0.9.6+2",
"mockito_tag": "d39ac507483b9891165e422ec98d9fb480037c8b",
@@ -174,7 +174,7 @@
Var("dart_root") + "/tools/sdks": {
"packages": [{
"package": "dart/dart-sdk/${{platform}}",
- "version": "version:2.5.0",
+ "version": "version:2.6.0-dev.3.0",
}],
"dep_type": "cipd",
},
@@ -276,7 +276,7 @@
Var("dart_root") + "/third_party/pkg/dart2js_info":
Var("dart_git") + "dart2js_info.git" + "@" + Var("dart2js_info_tag"),
Var("dart_root") + "/third_party/pkg/dartdoc":
- Var("dart_git") + "dartdoc.git" + "@" + Var("dartdoc_rev"),
+ Var("dart_git") + "dartdoc.git" + "@" + Var("dartdoc_tag"),
Var("dart_root") + "/third_party/pkg/fixnum":
Var("dart_git") + "fixnum.git" + "@" + Var("fixnum_tag"),
Var("dart_root") + "/third_party/pkg/glob":
diff --git a/build/dart/dart_action.gni b/build/dart/dart_action.gni
index e3d36f6..8fa5e57 100644
--- a/build/dart/dart_action.gni
+++ b/build/dart/dart_action.gni
@@ -3,7 +3,6 @@
# BSD-style license that can be found in the LICENSE file.
import("../executable_suffix.gni")
-import("dart_host_sdk_toolchain.gni")
import("prebuilt_dart_sdk.gni")
_is_fuchsia = defined(is_fuchsia_tree) && is_fuchsia_tree
@@ -62,7 +61,7 @@
outputs = invoker.outputs
# Construct the host toolchain version of the tool.
- host_tool = invoker.tool + "($dart_host_toolchain)"
+ host_tool = invoker.tool + "($host_toolchain)"
# Get the path to the executable. Currently, this assumes that the tool
# does not specify output_name so that the target name is the name to use.
diff --git a/build/dart/dart_host_sdk_toolchain.gni b/build/dart/dart_host_sdk_toolchain.gni
deleted file mode 100644
index f61d287..0000000
--- a/build/dart/dart_host_sdk_toolchain.gni
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2017, 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.
-
-# dart_host_toolchain should be used in the Dart tree instead of host_toolchain.
-# It will ensure that we are selecting the correct host toolchain.
-dart_host_toolchain = host_toolchain
-
-# Config variable: dart_host_sdk_toolchain
-# In a cross-build, this should be set to the toolchain to use to build a Dart
-# SDK to run on the host that targets the host. This is distinct from
-# 'host_toolchain', which in a cross-build builds artifacts to run on the host
-# that target the target architecture.
-if (defined(dart_host_sdk_toolchain) && current_toolchain == dart_host_sdk_toolchain) {
- dart_host_toolchain = dart_host_sdk_toolchain
-}
diff --git a/pkg/analysis_server/analysis_options.yaml b/pkg/analysis_server/analysis_options.yaml
index ed8c3c5..589be1c 100644
--- a/pkg/analysis_server/analysis_options.yaml
+++ b/pkg/analysis_server/analysis_options.yaml
@@ -1,4 +1,5 @@
include: package:pedantic/analysis_options.1.8.0.yaml
+
analyzer:
# This currently finds ~1,200 implicit-casts issues when enabled.
# strong-mode:
@@ -6,6 +7,8 @@
exclude:
- test/mock_packages/**
errors:
+ # Increase the severity of the unused_import hint.
+ unused_import: warning
# Ignoring "style" lint rules from pedantic for now. There are pre-existing
# violations that need to be cleaned up. Each one can be cleaned up and
# enabled according to the value provided.
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
index b1173da..ef4751b 100644
--- a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -9,6 +9,8 @@
import 'package:analysis_server/src/edit/nnbd_migration/info_builder.dart';
import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_listener.dart';
import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_renderer.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/highlight_js.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/highlight_css.dart';
import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
@@ -214,22 +216,36 @@
/// Generate output into the given [folder].
void _generateOutput(OverlayResourceProvider provider, Folder folder) async {
- List<LibraryInfo> libraryInfos = await InfoBuilder(listener.server)
- .explainMigration(instrumentationListener.data, listener);
- listener.addDetail('libraryInfos has ${libraryInfos.length} libs');
+ List<LibraryInfo> libraryInfos =
+ await InfoBuilder(instrumentationListener.data, listener)
+ .explainMigration();
+ var pathContext = provider.pathContext;
+ MigrationInfo migrationInfo =
+ MigrationInfo(libraryInfos, pathContext, includedRoot);
for (LibraryInfo info in libraryInfos) {
- var pathContext = provider.pathContext;
- var libraryPath =
+ assert(info.units.isNotEmpty);
+ String libraryPath =
pathContext.setExtension(info.units.first.path, '.html');
- // TODO(srawlins): Choose a better scheme than the double underscores,
- // likely with actual directories, which need to be individually created.
- var relativePath = pathContext
- .relative(libraryPath, from: includedRoot)
- .replaceAll('/', '__');
- File output = folder.getChildAssumingFile(relativePath);
- String rendered = InstrumentationRenderer(info).render();
+ String relativePath =
+ pathContext.relative(libraryPath, from: includedRoot);
+ List<String> directories =
+ pathContext.split(pathContext.dirname(relativePath));
+ for (int i = 0; i < directories.length; i++) {
+ String directory = pathContext.joinAll(directories.sublist(0, i + 1));
+ folder.getChildAssumingFolder(directory).create();
+ }
+ File output =
+ provider.getFile(pathContext.join(folder.path, relativePath));
+ String rendered = InstrumentationRenderer(info, migrationInfo).render();
output.writeAsStringSync(rendered);
}
+ // Generate resource files:
+ File highlightJsOutput =
+ provider.getFile(pathContext.join(folder.path, 'highlight.pack.js'));
+ highlightJsOutput.writeAsStringSync(decodeHighlightJs());
+ File highlightCssOutput =
+ provider.getFile(pathContext.join(folder.path, 'androidstudio.css'));
+ highlightCssOutput.writeAsStringSync(decodeHighlightCss());
}
static void task(DartFixRegistrar registrar, DartFixListener listener,
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/highlight_css.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/highlight_css.dart
new file mode 100644
index 0000000..1dbdb96
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/highlight_css.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, 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.
+
+/* To regenerate this file:
+
+1. Build and download highlight.zip for Dart [1].
+2. Extract highlight.zip, and find styles/androidstudio.css.
+3. Run:
+
+ sed -i -e '/^const _highlightCss =/{
+ r'<(echo 'const _highlightCss = "'"$(base64 < styles/androidstudio.css)"'";')'
+ d
+ }' highlight_css.dart
+
+[1] https://highlightjs.org/download/
+*/
+
+import 'dart:convert';
+
+const _highlightCss =
+ "LyoKRGF0ZTogMjQgRmV2IDIwMTUKQXV0aG9yOiBQZWRybyBPbGl2ZWlyYSA8a2FueXR1QGdtYWlsIC4gY29tPgoqLwoKLmhsanMgewogIGNvbG9yOiAjYTliN2M2OwogIGJhY2tncm91bmQ6ICMyODJiMmU7CiAgZGlzcGxheTogYmxvY2s7CiAgb3ZlcmZsb3cteDogYXV0bzsKICBwYWRkaW5nOiAwLjVlbTsKfQoKLmhsanMtbnVtYmVyLAouaGxqcy1saXRlcmFsLAouaGxqcy1zeW1ib2wsCi5obGpzLWJ1bGxldCB7CiAgY29sb3I6ICM2ODk3QkI7Cn0KCi5obGpzLWtleXdvcmQsCi5obGpzLXNlbGVjdG9yLXRhZywKLmhsanMtZGVsZXRpb24gewogIGNvbG9yOiAjY2M3ODMyOwp9CgouaGxqcy12YXJpYWJsZSwKLmhsanMtdGVtcGxhdGUtdmFyaWFibGUsCi5obGpzLWxpbmsgewogIGNvbG9yOiAjNjI5NzU1Owp9CgouaGxqcy1jb21tZW50LAouaGxqcy1xdW90ZSB7CiAgY29sb3I6ICM4MDgwODA7Cn0KCi5obGpzLW1ldGEgewogIGNvbG9yOiAjYmJiNTI5Owp9CgouaGxqcy1zdHJpbmcsCi5obGpzLWF0dHJpYnV0ZSwKLmhsanMtYWRkaXRpb24gewogIGNvbG9yOiAjNkE4NzU5Owp9CgouaGxqcy1zZWN0aW9uLAouaGxqcy10aXRsZSwKLmhsanMtdHlwZSB7CiAgY29sb3I6ICNmZmM2NmQ7Cn0KCi5obGpzLW5hbWUsCi5obGpzLXNlbGVjdG9yLWlkLAouaGxqcy1zZWxlY3Rvci1jbGFzcyB7CiAgY29sb3I6ICNlOGJmNmE7Cn0KCi5obGpzLWVtcGhhc2lzIHsKICBmb250LXN0eWxlOiBpdGFsaWM7Cn0KCi5obGpzLXN0cm9uZyB7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7Cn0K";
+
+String decodeHighlightCss() =>
+ String.fromCharCodes(base64Decode(_highlightCss));
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/highlight_js.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/highlight_js.dart
new file mode 100644
index 0000000..fdec128
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/highlight_js.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, 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.
+
+/* To regenerate this file:
+
+1. Build and download highlight.zip for Dart [1].
+2. Extract highlight.zip, and find highlight.pack.js.
+3. Run:
+
+ sed -i -e '/^const _highlightJs =/{
+ r'<(echo 'const _highlightJs = "'"$(base64 < highlight.pack.js)"'";')'
+ d
+ }' highlightjs.dart
+
+[1] https://highlightjs.org/download/
+*/
+
+import 'dart:convert';
+
+const _highlightJs =
+ "LyohIGhpZ2hsaWdodC5qcyB2OS4xNS4xMCB8IEJTRDMgTGljZW5zZSB8IGdpdC5pby9obGpzbGljZW5zZSAqLwohZnVuY3Rpb24oZSl7dmFyIG49Im9iamVjdCI9PXR5cGVvZiB3aW5kb3cmJndpbmRvd3x8Im9iamVjdCI9PXR5cGVvZiBzZWxmJiZzZWxmOyJ1bmRlZmluZWQiPT10eXBlb2YgZXhwb3J0c3x8ZXhwb3J0cy5ub2RlVHlwZT9uJiYobi5obGpzPWUoe30pLCJmdW5jdGlvbiI9PXR5cGVvZiBkZWZpbmUmJmRlZmluZS5hbWQmJmRlZmluZShbXSxmdW5jdGlvbigpe3JldHVybiBuLmhsanN9KSk6ZShleHBvcnRzKX0oZnVuY3Rpb24oYSl7dmFyIGY9W10sdT1PYmplY3Qua2V5cyxOPXt9LGM9e30sbj0vXihuby0/aGlnaGxpZ2h0fHBsYWlufHRleHQpJC9pLHM9L1xibGFuZyg/OnVhZ2UpPy0oW1x3LV0rKVxiL2ksdD0vKCheKDxbXj5dKz58XHR8KSt8KD86XG4pKSkvZ20scj17Y2FzZV9pbnNlbnNpdGl2ZToiY0kiLGxleGVtZXM6ImwiLGNvbnRhaW5zOiJjIixrZXl3b3JkczoiayIsc3ViTGFuZ3VhZ2U6InNMIixjbGFzc05hbWU6ImNOIixiZWdpbjoiYiIsYmVnaW5LZXl3b3JkczoiYksiLGVuZDoiZSIsZW5kc1dpdGhQYXJlbnQ6ImVXIixpbGxlZ2FsOiJpIixleGNsdWRlQmVnaW46ImVCIixleGNsdWRlRW5kOiJlRSIscmV0dXJuQmVnaW46InJCIixyZXR1cm5FbmQ6InJFIixyZWxldmFuY2U6InIiLHZhcmlhbnRzOiJ2IixJREVOVF9SRToiSVIiLFVOREVSU0NPUkVfSURFTlRfUkU6IlVJUiIsTlVNQkVSX1JFOiJOUiIsQ19OVU1CRVJfUkU6IkNOUiIsQklOQVJZX05VTUJFUl9SRToiQk5SIixSRV9TVEFSVEVSU19SRToiUlNSIixCQUNLU0xBU0hfRVNDQVBFOiJCRSIsQVBPU19TVFJJTkdfTU9ERToiQVNNIixRVU9URV9TVFJJTkdfTU9ERToiUVNNIixQSFJBU0FMX1dPUkRTX01PREU6IlBXTSIsQ19MSU5FX0NPTU1FTlRfTU9ERToiQ0xDTSIsQ19CTE9DS19DT01NRU5UX01PREU6IkNCQ00iLEhBU0hfQ09NTUVOVF9NT0RFOiJIQ00iLE5VTUJFUl9NT0RFOiJOTSIsQ19OVU1CRVJfTU9ERToiQ05NIixCSU5BUllfTlVNQkVSX01PREU6IkJOTSIsQ1NTX05VTUJFUl9NT0RFOiJDU1NOTSIsUkVHRVhQX01PREU6IlJNIixUSVRMRV9NT0RFOiJUTSIsVU5ERVJTQ09SRV9USVRMRV9NT0RFOiJVVE0iLENPTU1FTlQ6IkMiLGJlZ2luUmU6ImJSIixlbmRSZToiZVIiLGlsbGVnYWxSZToiaVIiLGxleGVtZXNSZToibFIiLHRlcm1pbmF0b3JzOiJ0Iix0ZXJtaW5hdG9yX2VuZDoidEUifSxiPSI8L3NwYW4+IixoPXtjbGFzc1ByZWZpeDoiaGxqcy0iLHRhYlJlcGxhY2U6bnVsbCx1c2VCUjohMSxsYW5ndWFnZXM6dm9pZCAwfTtmdW5jdGlvbiBfKGUpe3JldHVybiBlLnJlcGxhY2UoLyYvZywiJmFtcDsiKS5yZXBsYWNlKC88L2csIiZsdDsiKS5yZXBsYWNlKC8+L2csIiZndDsiKX1mdW5jdGlvbiBFKGUpe3JldHVybiBlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCl9ZnVuY3Rpb24gdihlLG4pe3ZhciB0PWUmJmUuZXhlYyhuKTtyZXR1cm4gdCYmMD09PXQuaW5kZXh9ZnVuY3Rpb24gbChlKXtyZXR1cm4gbi50ZXN0KGUpfWZ1bmN0aW9uIGcoZSl7dmFyIG4sdD17fSxyPUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywxKTtmb3IobiBpbiBlKXRbbl09ZVtuXTtyZXR1cm4gci5mb3JFYWNoKGZ1bmN0aW9uKGUpe2ZvcihuIGluIGUpdFtuXT1lW25dfSksdH1mdW5jdGlvbiBSKGUpe3ZhciBhPVtdO3JldHVybiBmdW5jdGlvbiBlKG4sdCl7Zm9yKHZhciByPW4uZmlyc3RDaGlsZDtyO3I9ci5uZXh0U2libGluZykzPT09ci5ub2RlVHlwZT90Kz1yLm5vZGVWYWx1ZS5sZW5ndGg6MT09PXIubm9kZVR5cGUmJihhLnB1c2goe2V2ZW50OiJzdGFydCIsb2Zmc2V0OnQsbm9kZTpyfSksdD1lKHIsdCksRShyKS5tYXRjaCgvYnJ8aHJ8aW1nfGlucHV0Lyl8fGEucHVzaCh7ZXZlbnQ6InN0b3AiLG9mZnNldDp0LG5vZGU6cn0pKTtyZXR1cm4gdH0oZSwwKSxhfWZ1bmN0aW9uIGkoZSl7aWYociYmIWUubGFuZ0FwaVJlc3RvcmVkKXtmb3IodmFyIG4gaW4gZS5sYW5nQXBpUmVzdG9yZWQ9ITAscillW25dJiYoZVtyW25dXT1lW25dKTsoZS5jfHxbXSkuY29uY2F0KGUudnx8W10pLmZvckVhY2goaSl9fWZ1bmN0aW9uIG0obyl7ZnVuY3Rpb24gcyhlKXtyZXR1cm4gZSYmZS5zb3VyY2V8fGV9ZnVuY3Rpb24gYyhlLG4pe3JldHVybiBuZXcgUmVnRXhwKHMoZSksIm0iKyhvLmNJPyJpIjoiIikrKG4/ImciOiIiKSl9IWZ1bmN0aW9uIG4odCxlKXtpZighdC5jb21waWxlZCl7aWYodC5jb21waWxlZD0hMCx0Lms9dC5rfHx0LmJLLHQuayl7ZnVuY3Rpb24gcih0LGUpe28uY0kmJihlPWUudG9Mb3dlckNhc2UoKSksZS5zcGxpdCgiICIpLmZvckVhY2goZnVuY3Rpb24oZSl7dmFyIG49ZS5zcGxpdCgifCIpO2FbblswXV09W3QsblsxXT9OdW1iZXIoblsxXSk6MV19KX12YXIgYT17fTsic3RyaW5nIj09dHlwZW9mIHQuaz9yKCJrZXl3b3JkIix0LmspOnUodC5rKS5mb3JFYWNoKGZ1bmN0aW9uKGUpe3IoZSx0LmtbZV0pfSksdC5rPWF9dC5sUj1jKHQubHx8L1x3Ky8sITApLGUmJih0LmJLJiYodC5iPSJcXGIoIit0LmJLLnNwbGl0KCIgIikuam9pbigifCIpKyIpXFxiIiksdC5ifHwodC5iPS9cQnxcYi8pLHQuYlI9Yyh0LmIpLHQuZW5kU2FtZUFzQmVnaW4mJih0LmU9dC5iKSx0LmV8fHQuZVd8fCh0LmU9L1xCfFxiLyksdC5lJiYodC5lUj1jKHQuZSkpLHQudEU9cyh0LmUpfHwiIix0LmVXJiZlLnRFJiYodC50RSs9KHQuZT8ifCI6IiIpK2UudEUpKSx0LmkmJih0LmlSPWModC5pKSksbnVsbD09dC5yJiYodC5yPTEpLHQuY3x8KHQuYz1bXSksdC5jPUFycmF5LnByb3RvdHlwZS5jb25jYXQuYXBwbHkoW10sdC5jLm1hcChmdW5jdGlvbihlKXtyZXR1cm4gZnVuY3Rpb24obil7cmV0dXJuIG4udiYmIW4uY2FjaGVkX3ZhcmlhbnRzJiYobi5jYWNoZWRfdmFyaWFudHM9bi52Lm1hcChmdW5jdGlvbihlKXtyZXR1cm4gZyhuLHt2Om51bGx9LGUpfSkpLG4uY2FjaGVkX3ZhcmlhbnRzfHxuLmVXJiZbZyhuKV18fFtuXX0oInNlbGYiPT09ZT90OmUpfSkpLHQuYy5mb3JFYWNoKGZ1bmN0aW9uKGUpe24oZSx0KX0pLHQuc3RhcnRzJiZuKHQuc3RhcnRzLGUpO3ZhciBpPXQuYy5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIGUuYks/IlxcLj8oPzoiK2UuYisiKVxcLj8iOmUuYn0pLmNvbmNhdChbdC50RSx0LmldKS5tYXAocykuZmlsdGVyKEJvb2xlYW4pO3QudD1pLmxlbmd0aD9jKGZ1bmN0aW9uKGUsbil7Zm9yKHZhciB0PS9cWyg/OlteXFxcXV18XFwuKSpcXXxcKFw/P3xcXChbMS05XVswLTldKil8XFwuLyxyPTAsYT0iIixpPTA7aTxlLmxlbmd0aDtpKyspe3ZhciBvPXIsYz1zKGVbaV0pO2ZvcigwPGkmJihhKz1uKTswPGMubGVuZ3RoOyl7dmFyIHU9dC5leGVjKGMpO2lmKG51bGw9PXUpe2ErPWM7YnJlYWt9YSs9Yy5zdWJzdHJpbmcoMCx1LmluZGV4KSxjPWMuc3Vic3RyaW5nKHUuaW5kZXgrdVswXS5sZW5ndGgpLCJcXCI9PXVbMF1bMF0mJnVbMV0/YSs9IlxcIitTdHJpbmcoTnVtYmVyKHVbMV0pK28pOihhKz11WzBdLCIoIj09dVswXSYmcisrKX19cmV0dXJuIGF9KGksInwiKSwhMCk6e2V4ZWM6ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH19fX0obyl9ZnVuY3Rpb24gQyhlLG4saSx0KXtmdW5jdGlvbiBjKGUsbix0LHIpe3ZhciBhPSc8c3BhbiBjbGFzcz0iJysocj8iIjpoLmNsYXNzUHJlZml4KTtyZXR1cm4gZT8oYSs9ZSsnIj4nKStuKyh0PyIiOmIpOm59ZnVuY3Rpb24gbygpe0UrPW51bGwhPWwuc0w/ZnVuY3Rpb24oKXt2YXIgZT0ic3RyaW5nIj09dHlwZW9mIGwuc0w7aWYoZSYmIU5bbC5zTF0pcmV0dXJuIF8oZyk7dmFyIG49ZT9DKGwuc0wsZywhMCxmW2wuc0xdKTpPKGcsbC5zTC5sZW5ndGg/bC5zTDp2b2lkIDApO3JldHVybiAwPGwuciYmKFIrPW4uciksZSYmKGZbbC5zTF09bi50b3ApLGMobi5sYW5ndWFnZSxuLnZhbHVlLCExLCEwKX0oKTpmdW5jdGlvbigpe3ZhciBlLG4sdCxyLGEsaSxvO2lmKCFsLmspcmV0dXJuIF8oZyk7Zm9yKHI9IiIsbj0wLGwubFIubGFzdEluZGV4PTAsdD1sLmxSLmV4ZWMoZyk7dDspcis9XyhnLnN1YnN0cmluZyhuLHQuaW5kZXgpKSxhPWwsaT10LHZvaWQgMCxvPXMuY0k/aVswXS50b0xvd2VyQ2FzZSgpOmlbMF0sKGU9YS5rLmhhc093blByb3BlcnR5KG8pJiZhLmtbb10pPyhSKz1lWzFdLHIrPWMoZVswXSxfKHRbMF0pKSk6cis9Xyh0WzBdKSxuPWwubFIubGFzdEluZGV4LHQ9bC5sUi5leGVjKGcpO3JldHVybiByK18oZy5zdWJzdHIobikpfSgpLGc9IiJ9ZnVuY3Rpb24gdShlKXtFKz1lLmNOP2MoZS5jTiwiIiwhMCk6IiIsbD1PYmplY3QuY3JlYXRlKGUse3BhcmVudDp7dmFsdWU6bH19KX1mdW5jdGlvbiByKGUsbil7aWYoZys9ZSxudWxsPT1uKXJldHVybiBvKCksMDt2YXIgdD1mdW5jdGlvbihlLG4pe3ZhciB0LHIsYTtmb3IodD0wLHI9bi5jLmxlbmd0aDt0PHI7dCsrKWlmKHYobi5jW3RdLmJSLGUpKXJldHVybiBuLmNbdF0uZW5kU2FtZUFzQmVnaW4mJihuLmNbdF0uZVI9KGE9bi5jW3RdLmJSLmV4ZWMoZSlbMF0sbmV3IFJlZ0V4cChhLnJlcGxhY2UoL1stXC9cXF4kKis/LigpfFtcXXt9XS9nLCJcXCQmIiksIm0iKSkpLG4uY1t0XX0obixsKTtpZih0KXJldHVybiB0LnNraXA/Zys9bjoodC5lQiYmKGcrPW4pLG8oKSx0LnJCfHx0LmVCfHwoZz1uKSksdSh0KSx0LnJCPzA6bi5sZW5ndGg7dmFyIHI9ZnVuY3Rpb24gZShuLHQpe2lmKHYobi5lUix0KSl7Zm9yKDtuLmVuZHNQYXJlbnQmJm4ucGFyZW50OyluPW4ucGFyZW50O3JldHVybiBufWlmKG4uZVcpcmV0dXJuIGUobi5wYXJlbnQsdCl9KGwsbik7aWYocil7dmFyIGE9bDtmb3IoYS5za2lwP2crPW46KGEuckV8fGEuZUV8fChnKz1uKSxvKCksYS5lRSYmKGc9bikpO2wuY04mJihFKz1iKSxsLnNraXB8fGwuc0x8fChSKz1sLnIpLChsPWwucGFyZW50KSE9PXIucGFyZW50Oyk7cmV0dXJuIHIuc3RhcnRzJiYoci5lbmRTYW1lQXNCZWdpbiYmKHIuc3RhcnRzLmVSPXIuZVIpLHUoci5zdGFydHMpKSxhLnJFPzA6bi5sZW5ndGh9aWYoZnVuY3Rpb24oZSxuKXtyZXR1cm4haSYmdihuLmlSLGUpfShuLGwpKXRocm93IG5ldyBFcnJvcignSWxsZWdhbCBsZXhlbWUgIicrbisnIiBmb3IgbW9kZSAiJysobC5jTnx8Ijx1bm5hbWVkPiIpKyciJyk7cmV0dXJuIGcrPW4sbi5sZW5ndGh8fDF9dmFyIHM9QihlKTtpZighcyl0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gbGFuZ3VhZ2U6ICInK2UrJyInKTttKHMpO3ZhciBhLGw9dHx8cyxmPXt9LEU9IiI7Zm9yKGE9bDthIT09czthPWEucGFyZW50KWEuY04mJihFPWMoYS5jTiwiIiwhMCkrRSk7dmFyIGc9IiIsUj0wO3RyeXtmb3IodmFyIGQscCxNPTA7bC50Lmxhc3RJbmRleD1NLGQ9bC50LmV4ZWMobik7KXA9cihuLnN1YnN0cmluZyhNLGQuaW5kZXgpLGRbMF0pLE09ZC5pbmRleCtwO2ZvcihyKG4uc3Vic3RyKE0pKSxhPWw7YS5wYXJlbnQ7YT1hLnBhcmVudClhLmNOJiYoRSs9Yik7cmV0dXJue3I6Uix2YWx1ZTpFLGxhbmd1YWdlOmUsdG9wOmx9fWNhdGNoKGUpe2lmKGUubWVzc2FnZSYmLTEhPT1lLm1lc3NhZ2UuaW5kZXhPZigiSWxsZWdhbCIpKXJldHVybntyOjAsdmFsdWU6XyhuKX07dGhyb3cgZX19ZnVuY3Rpb24gTyh0LGUpe2U9ZXx8aC5sYW5ndWFnZXN8fHUoTik7dmFyIHI9e3I6MCx2YWx1ZTpfKHQpfSxhPXI7cmV0dXJuIGUuZmlsdGVyKEIpLmZpbHRlcihNKS5mb3JFYWNoKGZ1bmN0aW9uKGUpe3ZhciBuPUMoZSx0LCExKTtuLmxhbmd1YWdlPWUsbi5yPmEuciYmKGE9biksbi5yPnIuciYmKGE9cixyPW4pfSksYS5sYW5ndWFnZSYmKHIuc2Vjb25kX2Jlc3Q9YSkscn1mdW5jdGlvbiBkKGUpe3JldHVybiBoLnRhYlJlcGxhY2V8fGgudXNlQlI/ZS5yZXBsYWNlKHQsZnVuY3Rpb24oZSxuKXtyZXR1cm4gaC51c2VCUiYmIlxuIj09PWU/Ijxicj4iOmgudGFiUmVwbGFjZT9uLnJlcGxhY2UoL1x0L2csaC50YWJSZXBsYWNlKToiIn0pOmV9ZnVuY3Rpb24gbyhlKXt2YXIgbix0LHIsYSxpLG89ZnVuY3Rpb24oZSl7dmFyIG4sdCxyLGEsaT1lLmNsYXNzTmFtZSsiICI7aWYoaSs9ZS5wYXJlbnROb2RlP2UucGFyZW50Tm9kZS5jbGFzc05hbWU6IiIsdD1zLmV4ZWMoaSkpcmV0dXJuIEIodFsxXSk/dFsxXToibm8taGlnaGxpZ2h0Ijtmb3Iobj0wLHI9KGk9aS5zcGxpdCgvXHMrLykpLmxlbmd0aDtuPHI7bisrKWlmKGwoYT1pW25dKXx8QihhKSlyZXR1cm4gYX0oZSk7bChvKXx8KGgudXNlQlI/KG49ZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiwiZGl2IikpLmlubmVySFRNTD1lLmlubmVySFRNTC5yZXBsYWNlKC9cbi9nLCIiKS5yZXBsYWNlKC88YnJbIFwvXSo+L2csIlxuIik6bj1lLGk9bi50ZXh0Q29udGVudCxyPW8/QyhvLGksITApOk8oaSksKHQ9UihuKSkubGVuZ3RoJiYoKGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiwiZGl2IikpLmlubmVySFRNTD1yLnZhbHVlLHIudmFsdWU9ZnVuY3Rpb24oZSxuLHQpe3ZhciByPTAsYT0iIixpPVtdO2Z1bmN0aW9uIG8oKXtyZXR1cm4gZS5sZW5ndGgmJm4ubGVuZ3RoP2VbMF0ub2Zmc2V0IT09blswXS5vZmZzZXQ/ZVswXS5vZmZzZXQ8blswXS5vZmZzZXQ/ZTpuOiJzdGFydCI9PT1uWzBdLmV2ZW50P2U6bjplLmxlbmd0aD9lOm59ZnVuY3Rpb24gYyhlKXthKz0iPCIrRShlKStmLm1hcC5jYWxsKGUuYXR0cmlidXRlcyxmdW5jdGlvbihlKXtyZXR1cm4iICIrZS5ub2RlTmFtZSsnPSInK18oZS52YWx1ZSkucmVwbGFjZSgnIicsIiZxdW90OyIpKyciJ30pLmpvaW4oIiIpKyI+In1mdW5jdGlvbiB1KGUpe2ErPSI8LyIrRShlKSsiPiJ9ZnVuY3Rpb24gcyhlKXsoInN0YXJ0Ij09PWUuZXZlbnQ/Yzp1KShlLm5vZGUpfWZvcig7ZS5sZW5ndGh8fG4ubGVuZ3RoOyl7dmFyIGw9bygpO2lmKGErPV8odC5zdWJzdHJpbmcocixsWzBdLm9mZnNldCkpLHI9bFswXS5vZmZzZXQsbD09PWUpe2ZvcihpLnJldmVyc2UoKS5mb3JFYWNoKHUpO3MobC5zcGxpY2UoMCwxKVswXSksKGw9bygpKT09PWUmJmwubGVuZ3RoJiZsWzBdLm9mZnNldD09PXI7KTtpLnJldmVyc2UoKS5mb3JFYWNoKGMpfWVsc2Uic3RhcnQiPT09bFswXS5ldmVudD9pLnB1c2gobFswXS5ub2RlKTppLnBvcCgpLHMobC5zcGxpY2UoMCwxKVswXSl9cmV0dXJuIGErXyh0LnN1YnN0cihyKSl9KHQsUihhKSxpKSksci52YWx1ZT1kKHIudmFsdWUpLGUuaW5uZXJIVE1MPXIudmFsdWUsZS5jbGFzc05hbWU9ZnVuY3Rpb24oZSxuLHQpe3ZhciByPW4/Y1tuXTp0LGE9W2UudHJpbSgpXTtyZXR1cm4gZS5tYXRjaCgvXGJobGpzXGIvKXx8YS5wdXNoKCJobGpzIiksLTE9PT1lLmluZGV4T2YocikmJmEucHVzaChyKSxhLmpvaW4oIiAiKS50cmltKCl9KGUuY2xhc3NOYW1lLG8sci5sYW5ndWFnZSksZS5yZXN1bHQ9e2xhbmd1YWdlOnIubGFuZ3VhZ2UscmU6ci5yfSxyLnNlY29uZF9iZXN0JiYoZS5zZWNvbmRfYmVzdD17bGFuZ3VhZ2U6ci5zZWNvbmRfYmVzdC5sYW5ndWFnZSxyZTpyLnNlY29uZF9iZXN0LnJ9KSl9ZnVuY3Rpb24gcCgpe2lmKCFwLmNhbGxlZCl7cC5jYWxsZWQ9ITA7dmFyIGU9ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgicHJlIGNvZGUiKTtmLmZvckVhY2guY2FsbChlLG8pfX1mdW5jdGlvbiBCKGUpe3JldHVybiBlPShlfHwiIikudG9Mb3dlckNhc2UoKSxOW2VdfHxOW2NbZV1dfWZ1bmN0aW9uIE0oZSl7dmFyIG49QihlKTtyZXR1cm4gbiYmIW4uZGlzYWJsZUF1dG9kZXRlY3R9cmV0dXJuIGEuaGlnaGxpZ2h0PUMsYS5oaWdobGlnaHRBdXRvPU8sYS5maXhNYXJrdXA9ZCxhLmhpZ2hsaWdodEJsb2NrPW8sYS5jb25maWd1cmU9ZnVuY3Rpb24oZSl7aD1nKGgsZSl9LGEuaW5pdEhpZ2hsaWdodGluZz1wLGEuaW5pdEhpZ2hsaWdodGluZ09uTG9hZD1mdW5jdGlvbigpe2FkZEV2ZW50TGlzdGVuZXIoIkRPTUNvbnRlbnRMb2FkZWQiLHAsITEpLGFkZEV2ZW50TGlzdGVuZXIoImxvYWQiLHAsITEpfSxhLnJlZ2lzdGVyTGFuZ3VhZ2U9ZnVuY3Rpb24obixlKXt2YXIgdD1OW25dPWUoYSk7aSh0KSx0LmFsaWFzZXMmJnQuYWxpYXNlcy5mb3JFYWNoKGZ1bmN0aW9uKGUpe2NbZV09bn0pfSxhLmxpc3RMYW5ndWFnZXM9ZnVuY3Rpb24oKXtyZXR1cm4gdShOKX0sYS5nZXRMYW5ndWFnZT1CLGEuYXV0b0RldGVjdGlvbj1NLGEuaW5oZXJpdD1nLGEuSVI9YS5JREVOVF9SRT0iW2EtekEtWl1cXHcqIixhLlVJUj1hLlVOREVSU0NPUkVfSURFTlRfUkU9IlthLXpBLVpfXVxcdyoiLGEuTlI9YS5OVU1CRVJfUkU9IlxcYlxcZCsoXFwuXFxkKyk/IixhLkNOUj1hLkNfTlVNQkVSX1JFPSIoLT8pKFxcYjBbeFhdW2EtZkEtRjAtOV0rfChcXGJcXGQrKFxcLlxcZCopP3xcXC5cXGQrKShbZUVdWy0rXT9cXGQrKT8pIixhLkJOUj1hLkJJTkFSWV9OVU1CRVJfUkU9IlxcYigwYlswMV0rKSIsYS5SU1I9YS5SRV9TVEFSVEVSU19SRT0iIXwhPXwhPT18JXwlPXwmfCYmfCY9fFxcKnxcXCo9fFxcK3xcXCs9fCx8LXwtPXwvPXwvfDp8O3w8PHw8PD18PD18PHw9PT18PT18PXw+Pj49fD4+PXw+PXw+Pj58Pj58PnxcXD98XFxbfFxce3xcXCh8XFxefFxcXj18XFx8fFxcfD18XFx8XFx8fH4iLGEuQkU9YS5CQUNLU0xBU0hfRVNDQVBFPXtiOiJcXFxcW1xcc1xcU10iLHI6MH0sYS5BU009YS5BUE9TX1NUUklOR19NT0RFPXtjTjoic3RyaW5nIixiOiInIixlOiInIixpOiJcXG4iLGM6W2EuQkVdfSxhLlFTTT1hLlFVT1RFX1NUUklOR19NT0RFPXtjTjoic3RyaW5nIixiOiciJyxlOiciJyxpOiJcXG4iLGM6W2EuQkVdfSxhLlBXTT1hLlBIUkFTQUxfV09SRFNfTU9ERT17YjovXGIoYXxhbnx0aGV8YXJlfEknbXxpc24ndHxkb24ndHxkb2Vzbid0fHdvbid0fGJ1dHxqdXN0fHNob3VsZHxwcmV0dHl8c2ltcGx5fGVub3VnaHxnb25uYXxnb2luZ3x3dGZ8c298c3VjaHx3aWxsfHlvdXx5b3VyfHRoZXl8bGlrZXxtb3JlKVxiL30sYS5DPWEuQ09NTUVOVD1mdW5jdGlvbihlLG4sdCl7dmFyIHI9YS5pbmhlcml0KHtjTjoiY29tbWVudCIsYjplLGU6bixjOltdfSx0fHx7fSk7cmV0dXJuIHIuYy5wdXNoKGEuUFdNKSxyLmMucHVzaCh7Y046ImRvY3RhZyIsYjoiKD86VE9ET3xGSVhNRXxOT1RFfEJVR3xYWFgpOiIscjowfSkscn0sYS5DTENNPWEuQ19MSU5FX0NPTU1FTlRfTU9ERT1hLkMoIi8vIiwiJCIpLGEuQ0JDTT1hLkNfQkxPQ0tfQ09NTUVOVF9NT0RFPWEuQygiL1xcKiIsIlxcKi8iKSxhLkhDTT1hLkhBU0hfQ09NTUVOVF9NT0RFPWEuQygiIyIsIiQiKSxhLk5NPWEuTlVNQkVSX01PREU9e2NOOiJudW1iZXIiLGI6YS5OUixyOjB9LGEuQ05NPWEuQ19OVU1CRVJfTU9ERT17Y046Im51bWJlciIsYjphLkNOUixyOjB9LGEuQk5NPWEuQklOQVJZX05VTUJFUl9NT0RFPXtjTjoibnVtYmVyIixiOmEuQk5SLHI6MH0sYS5DU1NOTT1hLkNTU19OVU1CRVJfTU9ERT17Y046Im51bWJlciIsYjphLk5SKyIoJXxlbXxleHxjaHxyZW18dnd8dmh8dm1pbnx2bWF4fGNtfG1tfGlufHB0fHBjfHB4fGRlZ3xncmFkfHJhZHx0dXJufHN8bXN8SHp8a0h6fGRwaXxkcGNtfGRwcHgpPyIscjowfSxhLlJNPWEuUkVHRVhQX01PREU9e2NOOiJyZWdleHAiLGI6L1wvLyxlOi9cL1tnaW11eV0qLyxpOi9cbi8sYzpbYS5CRSx7YjovXFsvLGU6L1xdLyxyOjAsYzpbYS5CRV19XX0sYS5UTT1hLlRJVExFX01PREU9e2NOOiJ0aXRsZSIsYjphLklSLHI6MH0sYS5VVE09YS5VTkRFUlNDT1JFX1RJVExFX01PREU9e2NOOiJ0aXRsZSIsYjphLlVJUixyOjB9LGEuTUVUSE9EX0dVQVJEPXtiOiJcXC5cXHMqIithLlVJUixyOjB9LGF9KTtobGpzLnJlZ2lzdGVyTGFuZ3VhZ2UoInhtbCIsZnVuY3Rpb24ocyl7dmFyIGU9e2VXOiEwLGk6LzwvLHI6MCxjOlt7Y046ImF0dHIiLGI6IltBLVphLXowLTlcXC5fOi1dKyIscjowfSx7YjovPVxzKi8scjowLGM6W3tjTjoic3RyaW5nIixlbmRzUGFyZW50OiEwLHY6W3tiOi8iLyxlOi8iL30se2I6LycvLGU6LycvfSx7YjovW15ccyInPTw+YF0rL31dfV19XX07cmV0dXJue2FsaWFzZXM6WyJodG1sIiwieGh0bWwiLCJyc3MiLCJhdG9tIiwieGpiIiwieHNkIiwieHNsIiwicGxpc3QiLCJ3c2YiXSxjSTohMCxjOlt7Y046Im1ldGEiLGI6IjwhRE9DVFlQRSIsZToiPiIscjoxMCxjOlt7YjoiXFxbIixlOiJcXF0ifV19LHMuQygiXHgzYyEtLSIsIi0tXHgzZSIse3I6MTB9KSx7YjoiPFxcIVxcW0NEQVRBXFxbIixlOiJcXF1cXF0+IixyOjEwfSx7Y046Im1ldGEiLGI6LzxcP3htbC8sZTovXD8+LyxyOjEwfSx7YjovPFw/KHBocCk/LyxlOi9cPz4vLHNMOiJwaHAiLGM6W3tiOiIvXFwqIixlOiJcXCovIixza2lwOiEwfSx7YjonYiInLGU6JyInLHNraXA6ITB9LHtiOiJiJyIsZToiJyIsc2tpcDohMH0scy5pbmhlcml0KHMuQVNNLHtpOm51bGwsY046bnVsbCxjOm51bGwsc2tpcDohMH0pLHMuaW5oZXJpdChzLlFTTSx7aTpudWxsLGNOOm51bGwsYzpudWxsLHNraXA6ITB9KV19LHtjTjoidGFnIixiOiI8c3R5bGUoPz1cXHN8PnwkKSIsZToiPiIsazp7bmFtZToic3R5bGUifSxjOltlXSxzdGFydHM6e2U6Ijwvc3R5bGU+IixyRTohMCxzTDpbImNzcyIsInhtbCJdfX0se2NOOiJ0YWciLGI6IjxzY3JpcHQoPz1cXHN8PnwkKSIsZToiPiIsazp7bmFtZToic2NyaXB0In0sYzpbZV0sc3RhcnRzOntlOiI8XC9zY3JpcHQ+IixyRTohMCxzTDpbImFjdGlvbnNjcmlwdCIsImphdmFzY3JpcHQiLCJoYW5kbGViYXJzIiwieG1sIiwidmJzY3JpcHQiXX19LHtjTjoidGFnIixiOiI8Lz8iLGU6Ii8/PiIsYzpbe2NOOiJuYW1lIixiOi9bXlwvPjxcc10rLyxyOjB9LGVdfV19fSk7aGxqcy5yZWdpc3Rlckxhbmd1YWdlKCJtYXJrZG93biIsZnVuY3Rpb24oZSl7cmV0dXJue2FsaWFzZXM6WyJtZCIsIm1rZG93biIsIm1rZCJdLGM6W3tjTjoic2VjdGlvbiIsdjpbe2I6Il4jezEsNn0iLGU6IiQifSx7YjoiXi4rP1xcbls9LV17Mix9JCJ9XX0se2I6IjwiLGU6Ij4iLHNMOiJ4bWwiLHI6MH0se2NOOiJidWxsZXQiLGI6Il5cXHMqKFsqKy1dfChcXGQrXFwuKSlcXHMrIn0se2NOOiJzdHJvbmciLGI6IlsqX117Mn0uKz9bKl9dezJ9In0se2NOOiJlbXBoYXNpcyIsdjpbe2I6IlxcKi4rP1xcKiJ9LHtiOiJfLis/XyIscjowfV19LHtjTjoicXVvdGUiLGI6Il4+XFxzKyIsZToiJCJ9LHtjTjoiY29kZSIsdjpbe2I6Il5gYGB3KnMqJCIsZToiXmBgYHMqJCJ9LHtiOiJgLis/YCJ9LHtiOiJeKCB7NH18XHQpIixlOiIkIixyOjB9XX0se2I6Il5bLVxcKl17Myx9IixlOiIkIn0se2I6IlxcWy4rP1xcXVtcXChcXFtdLio/W1xcKVxcXV0iLHJCOiEwLGM6W3tjTjoic3RyaW5nIixiOiJcXFsiLGU6IlxcXSIsZUI6ITAsckU6ITAscjowfSx7Y046ImxpbmsiLGI6IlxcXVxcKCIsZToiXFwpIixlQjohMCxlRTohMH0se2NOOiJzeW1ib2wiLGI6IlxcXVxcWyIsZToiXFxdIixlQjohMCxlRTohMH1dLHI6MTB9LHtiOi9eXFtbXlxuXStcXTovLHJCOiEwLGM6W3tjTjoic3ltYm9sIixiOi9cWy8sZTovXF0vLGVCOiEwLGVFOiEwfSx7Y046ImxpbmsiLGI6LzpccyovLGU6LyQvLGVCOiEwfV19XX19KTtobGpzLnJlZ2lzdGVyTGFuZ3VhZ2UoImRhcnQiLGZ1bmN0aW9uKGUpe3ZhciB0PXtjTjoic3Vic3QiLHY6W3tiOiJcXCRbQS1aYS16MC05X10rIn1dfSxyPXtjTjoic3Vic3QiLHY6W3tiOiJcXCR7IixlOiJ9In1dLGs6InRydWUgZmFsc2UgbnVsbCB0aGlzIGlzIG5ldyBzdXBlciJ9LG49e2NOOiJzdHJpbmciLHY6W3tiOiJyJycnIixlOiInJycifSx7YjonciIiIicsZTonIiIiJ30se2I6InInIixlOiInIixpOiJcXG4ifSx7YjonciInLGU6JyInLGk6IlxcbiJ9LHtiOiInJyciLGU6IicnJyIsYzpbZS5CRSx0LHJdfSx7YjonIiIiJyxlOiciIiInLGM6W2UuQkUsdCxyXX0se2I6IiciLGU6IiciLGk6IlxcbiIsYzpbZS5CRSx0LHJdfSx7YjonIicsZTonIicsaToiXFxuIixjOltlLkJFLHQscl19XX07ci5jPVtlLkNOTSxuXTtyZXR1cm57azp7a2V5d29yZDoiYXNzZXJ0IGFzeW5jIGF3YWl0IGJyZWFrIGNhc2UgY2F0Y2ggY2xhc3MgY29uc3QgY29udGludWUgZGVmYXVsdCBkbyBlbHNlIGVudW0gZXh0ZW5kcyBmYWxzZSBmaW5hbCBmaW5hbGx5IGZvciBpZiBpbiBpcyBuZXcgbnVsbCByZXRocm93IHJldHVybiBzdXBlciBzd2l0Y2ggc3luYyB0aGlzIHRocm93IHRydWUgdHJ5IHZhciB2b2lkIHdoaWxlIHdpdGggeWllbGQgYWJzdHJhY3QgYXMgZHluYW1pYyBleHBvcnQgZXh0ZXJuYWwgZmFjdG9yeSBnZXQgaW1wbGVtZW50cyBpbXBvcnQgbGlicmFyeSBvcGVyYXRvciBwYXJ0IHNldCBzdGF0aWMgdHlwZWRlZiIsYnVpbHRfaW46InByaW50IENvbXBhcmFibGUgRGF0ZVRpbWUgRHVyYXRpb24gRnVuY3Rpb24gSXRlcmFibGUgSXRlcmF0b3IgTGlzdCBNYXAgTWF0Y2ggTnVsbCBPYmplY3QgUGF0dGVybiBSZWdFeHAgU2V0IFN0b3B3YXRjaCBTdHJpbmcgU3RyaW5nQnVmZmVyIFN0cmluZ1NpbmsgU3ltYm9sIFR5cGUgVXJpIGJvb2wgZG91YmxlIGludCBudW0gZG9jdW1lbnQgd2luZG93IHF1ZXJ5U2VsZWN0b3IgcXVlcnlTZWxlY3RvckFsbCBFbGVtZW50IEVsZW1lbnRMaXN0In0sYzpbbixlLkMoIi9cXCpcXCoiLCJcXCovIix7c0w6Im1hcmtkb3duIn0pLGUuQygiLy8vIiwiJCIse3NMOiJtYXJrZG93biJ9KSxlLkNMQ00sZS5DQkNNLHtjTjoiY2xhc3MiLGJLOiJjbGFzcyBpbnRlcmZhY2UiLGU6InsiLGVFOiEwLGM6W3tiSzoiZXh0ZW5kcyBpbXBsZW1lbnRzIn0sZS5VVE1dfSxlLkNOTSx7Y046Im1ldGEiLGI6IkBbQS1aYS16XSsifSx7YjoiPT4ifV19fSk7";
+
+String decodeHighlightJs() => String.fromCharCodes(base64Decode(_highlightJs));
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
index acd9c24..694a210 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
@@ -6,23 +6,49 @@
import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_information.dart';
import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/offset_mapper.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart'
+ show Location, SourceEdit, SourceFileEdit;
+import 'package:nnbd_migration/instrumentation.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+
+class FixInfo {
+ /// The fix being described.
+ SingleNullabilityFix fix;
+
+ /// The reasons why the fix was made.
+ List<FixReasonInfo> reasons;
+
+ /// Initialize information about a fix from the given map [entry].
+ FixInfo(this.fix, this.reasons);
+}
/// A builder used to build the migration information for a library.
class InfoBuilder {
- /// The analysis session used to get information about libraries.
- AnalysisServer server;
+ /// The instrumentation information gathered while the migration engine was
+ /// running.
+ final InstrumentationInformation info;
+
+ /// The listener used to gather the changes to be applied.
+ final DartFixListener listener;
+
+ /// A map from the path of a compilation unit to the information about that
+ /// unit.
+ final Map<String, UnitInfo> unitMap = {};
/// Initialize a newly created builder.
- InfoBuilder(this.server);
+ InfoBuilder(this.info, this.listener);
+
+ /// The analysis server used to get information about libraries.
+ AnalysisServer get server => listener.server;
/// Return the migration information for all of the libraries that were
/// migrated.
- Future<List<LibraryInfo>> explainMigration(
- InstrumentationInformation info, DartFixListener listener) async {
+ Future<List<LibraryInfo>> explainMigration() async {
Map<Source, SourceInformation> sourceInfo = info.sourceInformation;
List<LibraryInfo> libraries = [];
for (Source source in sourceInfo.keys) {
@@ -38,6 +64,42 @@
return libraries;
}
+ /// Compute the details for the fix with the given [fixInfo].
+ List<RegionDetail> _computeDetails(FixInfo fixInfo) {
+ List<RegionDetail> details = [];
+ for (FixReasonInfo reason in fixInfo.reasons) {
+ if (reason is NullabilityNodeInfo) {
+ for (EdgeInfo edge in reason.upstreamEdges) {
+ EdgeOriginInfo origin = info.edgeOrigin[edge];
+ if (origin != null) {
+ AstNode node = origin.node;
+ if (node.parent is ArgumentList) {
+ if (node is NullLiteral) {
+ details.add(RegionDetail(
+ 'null is explicitly passed as an argument.',
+ _targetFor(origin)));
+ } else {
+ details.add(RegionDetail(
+ 'A nullable value is explicitly passed as an argument.',
+ _targetFor(origin)));
+ }
+ } else {
+ details.add(RegionDetail(
+ 'A nullable value is assigned.', _targetFor(origin)));
+ }
+ }
+ }
+ } else if (reason is EdgeInfo) {
+ // TODO(brianwilkerson) Implement this after finding an example whose
+ // reason is an edge.
+ } else {
+ throw UnimplementedError(
+ 'Unexpected class of reason: ${reason.runtimeType}');
+ }
+ }
+ return details;
+ }
+
/// Return the migration information for the given library.
LibraryInfo _explainLibrary(
ParsedLibraryResult result,
@@ -47,50 +109,76 @@
List<UnitInfo> units = [];
for (ParsedUnitResult unit in result.units) {
SourceFileEdit edit = listener.sourceChange.getFileEdit(unit.path);
- units.add(_explainUnit(unit, edit));
+ units.add(_explainUnit(sourceInfo, unit, edit));
}
return LibraryInfo(units);
}
/// Return the migration information for the given unit.
- UnitInfo _explainUnit(ParsedUnitResult result, SourceFileEdit fileEdit) {
- List<RegionInfo> regions = [];
+ UnitInfo _explainUnit(SourceInformation sourceInfo, ParsedUnitResult result,
+ SourceFileEdit fileEdit) {
+ UnitInfo unitInfo = _unitForPath(result.path);
String content = result.content;
// [fileEdit] is null when a file has no edits.
- if (fileEdit == null) {
- return UnitInfo(result.path, content, regions);
- }
- List<SourceEdit> edits = fileEdit.edits;
- edits.sort((first, second) => first.offset.compareTo(second.offset));
- // Compute the deltas for the regions that will be computed as we apply the
- // edits. We need the deltas because the offsets to the regions are relative
- // to the edited source, but the edits are being applied in reverse order so
- // the offset in the pre-edited source will not match the offset in the
- // post-edited source. The deltas compensate for that difference.
- List<int> deltas = [];
- int previousDelta = 0;
- for (SourceEdit edit in edits) {
- deltas.add(previousDelta);
- previousDelta += (edit.replacement.length - edit.length);
- }
- // Apply edits in reverse order and build the regions.
- int index = edits.length - 1;
- for (SourceEdit edit in edits.reversed) {
- int offset = edit.offset;
- int length = edit.length;
- String replacement = edit.replacement;
- int end = offset + length;
- int delta = deltas[index--];
- // Insert the replacement text without deleting the replaced text.
- content = content.replaceRange(end, end, replacement);
- if (length > 0) {
- // TODO(brianwilkerson) Create a sensible explanation.
- regions.add(RegionInfo(offset + delta, length, 'removed'));
+ if (fileEdit != null) {
+ List<RegionInfo> regions = unitInfo.regions;
+ List<SourceEdit> edits = fileEdit.edits;
+ edits.sort((first, second) => first.offset.compareTo(second.offset));
+ OffsetMapper mapper = OffsetMapper.forEdits(edits);
+ // Apply edits in reverse order and build the regions.
+ for (SourceEdit edit in edits.reversed) {
+ int offset = edit.offset;
+ int length = edit.length;
+ String replacement = edit.replacement;
+ int end = offset + length;
+ // Insert the replacement text without deleting the replaced text.
+ content = content.replaceRange(end, end, replacement);
+ FixInfo fixInfo = _findFixInfo(sourceInfo, offset);
+ if (fixInfo != null) {
+ String explanation = '${fixInfo.fix.description.appliedMessage}.';
+ List<RegionDetail> details = _computeDetails(fixInfo);
+ if (length > 0) {
+ regions.add(
+ RegionInfo(mapper.map(offset), length, explanation, details));
+ }
+ regions.add(RegionInfo(
+ mapper.map(end), replacement.length, explanation, details));
+ }
}
- // TODO(brianwilkerson) Create a sensible explanation.
- regions.add(RegionInfo(end + delta, replacement.length, 'added'));
+ regions.sort((first, second) => first.offset.compareTo(second.offset));
+ unitInfo.offsetMapper = mapper;
}
- regions.sort((first, second) => first.offset.compareTo(second.offset));
- return UnitInfo(result.path, content, regions);
+ unitInfo.content = content;
+ return unitInfo;
+ }
+
+ /// Return information about the fix that was applied at the given [offset],
+ /// or `null` if the information could not be found. The information is
+ /// extracted from the [sourceInfo].
+ FixInfo _findFixInfo(SourceInformation sourceInfo, int offset) {
+ for (MapEntry<SingleNullabilityFix, List<FixReasonInfo>> entry
+ in sourceInfo.fixes.entries) {
+ Location location = entry.key.location;
+ if (location.offset == offset) {
+ return FixInfo(entry.key, entry.value);
+ }
+ }
+ return null;
+ }
+
+ /// Return the navigation target corresponding to the given [origin].
+ NavigationTarget _targetFor(EdgeOriginInfo origin) {
+ AstNode node = origin.node;
+ String filePath = origin.source.fullName;
+ UnitInfo unitInfo = _unitForPath(filePath);
+ NavigationTarget target =
+ NavigationTarget(filePath, node.offset, node.length);
+ unitInfo.targets.add(target);
+ return target;
+ }
+
+ /// Return the unit info for the file at the given [path].
+ UnitInfo _unitForPath(String path) {
+ return unitMap.putIfAbsent(path, () => UnitInfo(path));
}
}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
index bb3f1d0..b51c370 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
@@ -31,7 +31,8 @@
@override
void fix(SingleNullabilityFix fix, Iterable<FixReasonInfo> reasons) {
- _sourceInfo(fix.source).fixes[fix] = reasons.toList();
+ _sourceInfo(fix.source).fixes[fix] =
+ reasons.where((reason) => reason != null).toList();
}
@override
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
index 5b14508..6735746 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
@@ -1,19 +1,31 @@
import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:meta/meta.dart';
import 'package:mustache/mustache.dart' as mustache;
+import 'package:path/path.dart' as path;
-/// Instrumentation display output for a library that was migrated to use non-nullable types.
+/// Instrumentation display output for a library that was migrated to use
+/// non-nullable types.
class InstrumentationRenderer {
/// Display information for a library.
- final LibraryInfo info;
+ final LibraryInfo libraryInfo;
+
+ /// Information for a whole migration, so that libraries can reference each
+ /// other.
+ final MigrationInfo migrationInfo;
/// Creates an output object for the given library info.
- InstrumentationRenderer(this.info);
+ InstrumentationRenderer(this.libraryInfo, this.migrationInfo);
- /// Builds an HTML view of the instrumentation information in [info].
+ /// Builds an HTML view of the instrumentation information in [libraryInfo].
String render() {
int previousIndex = 0;
- Map<String, dynamic> mustacheContext = {'units': <Map<String, dynamic>>[]};
- for (var compilationUnit in info.units) {
+ Map<String, dynamic> mustacheContext = {
+ 'units': <Map<String, dynamic>>[],
+ 'links': migrationInfo.libraryLinks(libraryInfo),
+ 'highlightJsPath': migrationInfo.highlightJsPath(libraryInfo),
+ 'highlightStylePath': migrationInfo.highlightStylePath(libraryInfo),
+ };
+ for (var compilationUnit in libraryInfo.units) {
// List of Mustache context for both unmodified and modified regions:
//
// * 'modified': Whether this region represents modified source, or
@@ -55,13 +67,70 @@
}
}
+/// A class storing rendering information for an entire migration report.
+///
+/// This generally provides one [InstrumentationRenderer] (for one library)
+/// with information about the rest of the libraries represented in the
+/// instrumentation output.
+class MigrationInfo {
+ /// The information about the libraries that are are migrated.
+ final List<LibraryInfo> libraries;
+
+ /// The resource provider's path context.
+ final path.Context pathContext;
+
+ /// The filesystem root used to create relative paths for each unit.
+ final String includedRoot;
+
+ MigrationInfo(this.libraries, this.pathContext, this.includedRoot);
+
+ /// Generate mustache context for library links, for navigation in the
+ /// instrumentation document for [thisLibrary].
+ List<Map<String, Object>> libraryLinks(LibraryInfo thisLibrary) {
+ return [
+ for (var library in libraries)
+ {
+ 'name': _computeName(library),
+ 'isLink': library != thisLibrary,
+ if (library != thisLibrary)
+ 'href': _pathTo(library, source: thisLibrary)
+ }
+ ];
+ }
+
+ /// Return the path to [library] from [includedRoot], to be used as a display
+ /// name for a library.
+ String _computeName(LibraryInfo library) =>
+ pathContext.relative(library.units.first.path, from: includedRoot);
+
+ /// The path to [target], relative to [from].
+ String _pathTo(LibraryInfo target, {@required LibraryInfo source}) {
+ assert(target.units.isNotEmpty);
+ assert(source.units.isNotEmpty);
+ String targetPath =
+ pathContext.setExtension(target.units.first.path, '.html');
+ String sourceDir = pathContext.dirname(source.units.first.path);
+ return pathContext.relative(targetPath, from: sourceDir);
+ }
+
+ /// The path to the highlight.js script, relative to [libraryInfo].
+ String highlightJsPath(LibraryInfo libraryInfo) =>
+ pathContext.relative(pathContext.join(includedRoot, 'highlight.pack.js'),
+ from: pathContext.dirname(libraryInfo.units.first.path));
+
+ /// The path to the highlight.js stylesheet, relative to [libraryInfo].
+ String highlightStylePath(LibraryInfo libraryInfo) =>
+ pathContext.relative(pathContext.join(includedRoot, 'androidstudio.css'),
+ from: pathContext.dirname(libraryInfo.units.first.path));
+}
+
/// A mustache template for one library's instrumentation output.
mustache.Template _template = mustache.Template(r'''
<html>
<head>
<title>Non-nullable fix instrumentation report</title>
- <script src="highlight.pack.js"></script>
- <link rel="stylesheet" href="styles/androidstudio.css">
+ <script src="{{ highlightJsPath }}"></script>
+ <link rel="stylesheet" href="{{ highlightStylePath }}">
<style>
body {
font-family: sans-serif;
@@ -75,15 +144,13 @@
.content {
font-family: monospace;
- white-space: pre;
-}
-
-.content.highlighting {
position: relative;
+ white-space: pre;
}
.regions {
position: absolute;
+ left: 0.5em;
top: 0.5em;
/* The content of the regions is not visible; the user instead will see the
* highlighted copy of the content. */
@@ -105,12 +172,15 @@
border: solid 2px #999;
color: #333;
cursor: auto;
- left: 50%;
- margin-left: -100px;
+ font-family: sans-serif;
+ font-size: 0.8em;
+ left: 0;
+ margin-left: 0;
padding: 1px;
position: absolute;
top: 100%;
visibility: hidden;
+ white-space: normal;
width: 200px;
z-index: 1;
}
@@ -122,16 +192,25 @@
</head>
<body>
<h1>Non-nullable fix instrumentation report</h1>
- <p><em>Well-written introduction to this report.</em></p>'''
- ' {{# units }}'
- ' <h2>{{{ path }}}</h2>'
- ' <div class="content highlighting">'
+ <p><em>Well-written introduction to this report.</em></p>
+ <div class="navigation">
+ {{# links }}
+ {{# isLink }}<a href="{{ href }}">{{ name }}</a>{{/ isLink }}
+ {{^ isLink }}{{ name }}{{/ isLink }}
+ <br />
+ {{/ links }}
+ </div>
+ {{# units }}'''
+ '<h2>{{{ path }}}</h2>'
+ '<div class="content">'
+ '<div class="highlighting">'
'{{! These regions are written out, unmodified, as they need to be found }}'
'{{! in one simple text string for highlight.js to hightlight them. }}'
'{{# regions }}'
'{{ content }}'
'{{/ regions }}'
- ' <div class="regions">'
+ '</div>'
+ '<div class="regions">'
'{{! The regions are then printed again, overlaying the first copy of the }}'
'{{! content, to provide tooltips for modified regions. }}'
'{{# regions }}'
@@ -140,13 +219,14 @@
'<span class="tooltip">{{explanation}}</span></span>{{/ modified }}'
'{{/ regions }}'
'</div></div>'
- ' {{/ units }}'
- ' <script lang="javascript">'
- 'document.addEventListener("DOMContentLoaded", (event) => {'
- ' document.querySelectorAll(".highlighting").forEach((block) => {'
- ' hljs.highlightBlock(block);'
- ' });'
- '});'
- ' </script>'
- ' </body>'
- '</html>');
+ r'''
+ {{/ units }}
+ <script lang="javascript">
+document.addEventListener("DOMContentLoaded", (event) => {
+ document.querySelectorAll(".highlighting").forEach((block) => {
+ hljs.highlightBlock(block);
+ });
+});
+ </script>
+ </body>
+</html>''');
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
index 2f872624..7a66011 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
@@ -2,6 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:analysis_server/src/edit/nnbd_migration/offset_mapper.dart';
+import 'package:analyzer/src/generated/utilities_general.dart';
+
/// The migration information associated with a single library.
class LibraryInfo {
/// The information about the units in the library. The information about the
@@ -12,6 +15,45 @@
LibraryInfo(this.units);
}
+/// A location to which a user might want to navigate.
+class NavigationTarget {
+ /// The file containing the anchor.
+ final String filePath;
+
+ /// The offset of the anchor.
+ final int offset;
+
+ /// The length of the anchor.
+ final int length;
+
+ /// Initialize a newly created anchor.
+ NavigationTarget(this.filePath, this.offset, this.length);
+
+ @override
+ int get hashCode => JenkinsSmiHash.hash3(filePath.hashCode, offset, length);
+
+ @override
+ bool operator ==(other) {
+ return other is NavigationTarget &&
+ other.filePath == filePath &&
+ other.offset == offset &&
+ other.length == length;
+ }
+}
+
+/// An additional detail related to a region.
+class RegionDetail {
+ /// A textual description of the detail.
+ final String description;
+
+ /// The location associated with the detail, such as the location of an
+ /// argument that's assigned to a parameter.
+ final NavigationTarget target;
+
+ /// Initialize a newly created detail.
+ RegionDetail(this.description, this.target);
+}
+
/// A description of an explanation associated with a region of code that was
/// modified.
class RegionInfo {
@@ -24,8 +66,11 @@
/// The explanation to be displayed for the region.
final String explanation;
+ /// Details that further explain why a change was made.
+ final List<RegionDetail> details;
+
/// Initialize a newly created region.
- RegionInfo(this.offset, this.length, this.explanation);
+ RegionInfo(this.offset, this.length, this.explanation, this.details);
}
/// The migration information associated with a single compilation unit.
@@ -34,12 +79,20 @@
final String path;
/// The content of unit.
- final String content;
+ String content;
/// The information about the regions that have an explanation associated with
- /// them.
- final List<RegionInfo> regions;
+ /// them. The offsets in these regions are offsets into the post-edit content.
+ final List<RegionInfo> regions = [];
+
+ /// The navigation targets that are located in this file. The offsets in these
+ /// targets are offsets into the pre-edit content.
+ final Set<NavigationTarget> targets = {};
+
+ /// The object used to map the pre-edit offsets in the navigation targets to
+ /// the post-edit offsets in the [content].
+ OffsetMapper offsetMapper = OffsetMapper.identity;
/// Initialize a newly created unit.
- UnitInfo(this.path, this.content, this.regions);
+ UnitInfo(this.path);
}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/offset_mapper.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/offset_mapper.dart
new file mode 100644
index 0000000..24d2c3e
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/offset_mapper.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2019, 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_plugin/protocol/protocol_common.dart';
+
+/// An object that can map the offsets before a sequence of edits to the offsets
+/// after applying the edits.
+abstract class OffsetMapper {
+ /// A mapper used for files that were not modified.
+ static OffsetMapper identity = _IdentityMapper();
+
+ /// Return a mapper representing the file modified by the given [edits].
+ factory OffsetMapper.forEdits(List<SourceEdit> edits) => _EditMapper(edits);
+
+ /// Return the post-edit offset that corresponds to the given pre-edit
+ /// [offset].
+ int map(int offset);
+}
+
+/// A mapper used for files that were modified by a set of edits.
+class _EditMapper implements OffsetMapper {
+ /// A list whose elements are the highest pre-edit offset for which the
+ /// corresponding element of [_deltas] should be applied.
+ List<int> _offsets = [];
+
+ /// A list whose elements are the deltas to be applied for all pre-edit
+ /// offsets that are less than or equal to the corresponding element of
+ /// [_offsets].
+ List<int> _deltas = [];
+
+ /// Initialize a newly created mapper based on the given set of [edits].
+ _EditMapper(List<SourceEdit> edits) {
+ _initializeDeltas(edits);
+ }
+
+ @override
+ int map(int offset) => offset + _deltaFor(offset);
+
+ /// Return the delta to be added to the pre-edit [offset] to produce the
+ /// post-edit offset.
+ int _deltaFor(int offset) {
+ for (int i = 0; i < _offsets.length; i++) {
+ int currentOffset = _offsets[i];
+ if (currentOffset >= offset || currentOffset < 0) {
+ return _deltas[i];
+ }
+ }
+ // We should never get here because [_initializeDeltas] always adds an
+ // offset/delta pair at the end of the list whose offset is less than zero.
+ return 0;
+ }
+
+ /// Initialize the list of old offsets and deltas used by [_deltaFor].
+ void _initializeDeltas(List<SourceEdit> edits) {
+ int previousDelta = 0;
+ for (SourceEdit edit in edits) {
+ int offset = edit.offset;
+ int length = edit.length;
+ _offsets.add(offset);
+ _deltas.add(previousDelta);
+ previousDelta += (edit.replacement.length - length);
+ }
+ _offsets.add(-1);
+ _deltas.add(previousDelta);
+ }
+}
+
+/// A mapper used for files that were not modified.
+class _IdentityMapper implements OffsetMapper {
+ @override
+ int map(int offset) => offset;
+}
diff --git a/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart b/pkg/analysis_server/test/analysis/notification_analyzed_files_test.dart
similarity index 100%
rename from pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart
rename to pkg/analysis_server/test/analysis/notification_analyzed_files_test.dart
diff --git a/pkg/analysis_server/test/analysis/notification_closingLabels_test.dart b/pkg/analysis_server/test/analysis/notification_closing_labels_test.dart
similarity index 100%
rename from pkg/analysis_server/test/analysis/notification_closingLabels_test.dart
rename to pkg/analysis_server/test/analysis/notification_closing_labels_test.dart
diff --git a/pkg/analysis_server/test/analysis/test_all.dart b/pkg/analysis_server/test/analysis/test_all.dart
index 5b8b7e9..bd8d396 100644
--- a/pkg/analysis_server/test/analysis/test_all.dart
+++ b/pkg/analysis_server/test/analysis/test_all.dart
@@ -4,52 +4,47 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'get_errors_test.dart' as get_errors_test;
-import 'get_hover_test.dart' as get_hover_test;
-import 'get_navigation_test.dart' as get_navigation_test;
-import 'get_signature_test.dart' as get_signature_information_test;
+import 'get_errors_test.dart' as get_errors;
+import 'get_hover_test.dart' as get_hover;
+import 'get_navigation_test.dart' as get_navigation;
+import 'get_signature_test.dart' as get_signature_information;
import 'notification_analysis_options_test.dart'
- as notification_analysis_options_test;
-import 'notification_analyzedFiles_test.dart'
- as notification_analyzedFiles_test;
-import 'notification_closingLabels_test.dart'
- as notification_closingLabels_test;
-import 'notification_errors_test.dart' as notification_errors_test;
-import 'notification_folding_test.dart' as notification_folding_test;
-import 'notification_highlights2_test.dart' as notification_highlights2_test;
-import 'notification_highlights_test.dart' as notification_highlights_test;
-import 'notification_implemented_test.dart' as notification_implemented_test;
-import 'notification_navigation_test.dart' as notification_navigation_test;
-import 'notification_occurrences_test.dart' as notification_occurrences_test;
-import 'notification_outline_test.dart' as notification_outline_test;
-import 'notification_overrides_test.dart' as notification_overrides_test;
-import 'reanalyze_test.dart' as reanalyze_test;
-import 'set_priority_files_test.dart' as set_priority_files_test;
-import 'update_content_test.dart' as update_content_test;
+ as notification_analysis_options;
+import 'notification_analyzed_files_test.dart' as notification_analyzed_files;
+import 'notification_closing_labels_test.dart' as notification_closing_labels;
+import 'notification_errors_test.dart' as notification_errors;
+import 'notification_folding_test.dart' as notification_folding;
+import 'notification_highlights2_test.dart' as notification_highlights2;
+import 'notification_highlights_test.dart' as notification_highlights;
+import 'notification_implemented_test.dart' as notification_implemented;
+import 'notification_navigation_test.dart' as notification_navigation;
+import 'notification_occurrences_test.dart' as notification_occurrences;
+import 'notification_outline_test.dart' as notification_outline;
+import 'notification_overrides_test.dart' as notification_overrides;
+import 'reanalyze_test.dart' as reanalyze;
+import 'set_priority_files_test.dart' as set_priority_files;
+import 'update_content_test.dart' as update_content;
-/**
- * Utility for manually running all tests.
- */
main() {
defineReflectiveSuite(() {
- get_errors_test.main();
- get_hover_test.main();
- get_navigation_test.main();
- get_signature_information_test.main();
- notification_analysis_options_test.main();
- notification_analyzedFiles_test.main();
- notification_closingLabels_test.main();
- notification_folding_test.main();
- notification_errors_test.main();
- notification_highlights2_test.main();
- notification_highlights_test.main();
- notification_implemented_test.main();
- notification_navigation_test.main();
- notification_occurrences_test.main();
- notification_outline_test.main();
- notification_overrides_test.main();
- reanalyze_test.main();
- set_priority_files_test.main();
- update_content_test.main();
+ get_errors.main();
+ get_hover.main();
+ get_navigation.main();
+ get_signature_information.main();
+ notification_analysis_options.main();
+ notification_analyzed_files.main();
+ notification_closing_labels.main();
+ notification_folding.main();
+ notification_errors.main();
+ notification_highlights2.main();
+ notification_highlights.main();
+ notification_implemented.main();
+ notification_navigation.main();
+ notification_occurrences.main();
+ notification_outline.main();
+ notification_overrides.main();
+ reanalyze.main();
+ set_priority_files.main();
+ update_content.main();
}, name: 'analysis');
}
diff --git a/pkg/analysis_server/test/domain_edit_dartfix_test.dart b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
index 261ada4..c3fa84f 100644
--- a/pkg/analysis_server/test/domain_edit_dartfix_test.dart
+++ b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
@@ -7,7 +7,6 @@
import 'package:analysis_server/src/edit/edit_dartfix.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:linter/src/rules.dart';
-import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -300,10 +299,7 @@
await performFix(
includedFixes: ['non-nullable'], outputDir: outputDir.path);
expect(outputDir.exists, true);
- // TODO(https://github.com/dart-lang/sdk/issues/38574): Fix Windows.
- if (path.style != path.Style.windows) {
- expect(outputDir.getChildren(), isNotEmpty);
- }
+ expect(outputDir.getChildren(), isNotEmpty);
}
test_dartfix_partFile() async {
diff --git a/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
index 30e390f..7865f34 100644
--- a/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
+++ b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
@@ -17,16 +17,26 @@
@reflectiveTest
class InstrumentationRendererTest extends AbstractAnalysisTest {
+ /// Render [libraryInfo], using a [MigrationInfo] which knows only about this
+ /// library.
+ // TODO(srawlins): Add tests for navigation links, which use multiple
+ // libraries.
+ String renderLibrary(LibraryInfo libraryInfo) {
+ MigrationInfo migrationInfo =
+ MigrationInfo([libraryInfo], resourceProvider.pathContext, '/project');
+ return InstrumentationRenderer(libraryInfo, migrationInfo).render();
+ }
+
test_outputContainsEachPath() async {
LibraryInfo info = LibraryInfo([
- UnitInfo('/lib/a.dart', 'int? a = null;',
- [RegionInfo(3, 1, 'null was assigned')]),
- UnitInfo('/lib/part1.dart', 'int? b = null;',
- [RegionInfo(3, 1, 'null was assigned')]),
- UnitInfo('/lib/part2.dart', 'int? c = null;',
- [RegionInfo(3, 1, 'null was assigned')]),
+ unit('/lib/a.dart', 'int? a = null;',
+ regions: [RegionInfo(3, 1, 'null was assigned', [])]),
+ unit('/lib/part1.dart', 'int? b = null;',
+ regions: [RegionInfo(3, 1, 'null was assigned', [])]),
+ unit('/lib/part2.dart', 'int? c = null;',
+ regions: [RegionInfo(3, 1, 'null was assigned', [])]),
]);
- String output = InstrumentationRenderer(info).render();
+ String output = renderLibrary(info);
expect(output, contains('<h2>/lib/a.dart</h2>'));
expect(output, contains('<h2>/lib/part1.dart</h2>'));
expect(output, contains('<h2>/lib/part2.dart</h2>'));
@@ -34,10 +44,10 @@
test_outputContainsEscapedHtml() async {
LibraryInfo info = LibraryInfo([
- UnitInfo('/lib/a.dart', 'List<String>? a = null;',
- [RegionInfo(12, 1, 'null was assigned')]),
+ unit('/lib/a.dart', 'List<String>? a = null;',
+ regions: [RegionInfo(12, 1, 'null was assigned', [])]),
]);
- String output = InstrumentationRenderer(info).render();
+ String output = renderLibrary(info);
expect(
output,
contains('List<String><span class="region">?'
@@ -46,21 +56,27 @@
test_outputContainsEscapedHtml_ampersand() async {
LibraryInfo info = LibraryInfo([
- UnitInfo('/lib/a.dart', 'bool a = true && false;', []),
+ unit('/lib/a.dart', 'bool a = true && false;', regions: []),
]);
- String output = InstrumentationRenderer(info).render();
+ String output = renderLibrary(info);
expect(output, contains('bool a = true && false;'));
}
test_outputContainsModifiedAndUnmodifiedRegions() async {
LibraryInfo info = LibraryInfo([
- UnitInfo('/lib/a.dart', 'int? a = null;',
- [RegionInfo(3, 1, 'null was assigned')]),
+ unit('/lib/a.dart', 'int? a = null;',
+ regions: [RegionInfo(3, 1, 'null was assigned', [])]),
]);
- String output = InstrumentationRenderer(info).render();
+ String output = renderLibrary(info);
expect(
output,
contains('int<span class="region">?'
'<span class="tooltip">null was assigned</span></span> a = null;'));
}
+
+ UnitInfo unit(String path, String content, {List<RegionInfo> regions}) {
+ return UnitInfo(path)
+ ..content = content
+ ..regions.addAll(regions);
+ }
}
diff --git a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart b/pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart
similarity index 100%
rename from pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
rename to pkg/analysis_server/test/integration/analysis/get_errors_non_standard_sdk_test.dart
diff --git a/pkg/analysis_server/test/integration/analysis/test_all.dart b/pkg/analysis_server/test/integration/analysis/test_all.dart
index a0cdc52..ea09692 100644
--- a/pkg/analysis_server/test/integration/analysis/test_all.dart
+++ b/pkg/analysis_server/test/integration/analysis/test_all.dart
@@ -6,7 +6,7 @@
import 'analysis_options_test.dart' as analysis_options_test;
import 'error_test.dart' as error_test;
-import 'get_errors_nonStandard_sdk_test.dart' as get_errors_nonStandard_sdk;
+import 'get_errors_non_standard_sdk_test.dart' as get_errors_non_standard_sdk;
import 'get_errors_test.dart' as get_errors_test;
import 'get_hover_test.dart' as get_hover_test;
import 'get_imported_elements_test.dart' as get_imported_elements_test;
@@ -41,7 +41,7 @@
analysis_options_test.main();
error_test.main();
get_errors_test.main();
- get_errors_nonStandard_sdk.main();
+ get_errors_non_standard_sdk.main();
get_library_dependencies_test.main();
get_hover_test.main();
get_imported_elements_test.main();
diff --git a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
index aac6231..e1eeec2 100644
--- a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
@@ -57,8 +57,8 @@
@override
Future<ResponseMessage> sendRequestToServer(RequestMessage request) {
final completer = new Completer<ResponseMessage>();
- final id = request.id.map(
- (num) => num, (string) => throw 'String IDs not supported in tests');
+ final id = request.id.map((number) => number,
+ (string) => throw 'String IDs not supported in tests');
_completers[id] = completer;
client.channel.sendRequest(request);
@@ -87,7 +87,7 @@
await client.start();
client.serverToClient.listen((message) {
if (message is ResponseMessage) {
- final id = message.id.map((num) => num,
+ final id = message.id.map((number) => number,
(string) => throw 'String IDs not supported in tests');
final completer = _completers[id];
diff --git a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
index 8cccc13..1773c51 100644
--- a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
+++ b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
@@ -4,7 +4,6 @@
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -12,9 +11,7 @@
main() {
defineReflectiveSuite(() {
- if (!AnalysisDriver.useSummary2) {
- defineReflectiveTests(WorkspaceSymbolsTest);
- }
+ defineReflectiveTests(WorkspaceSymbolsTest);
});
}
diff --git a/pkg/analysis_server/test/search/declarations_test.dart b/pkg/analysis_server/test/search/declarations_test.dart
index 3d505be..000ba70 100644
--- a/pkg/analysis_server/test/search/declarations_test.dart
+++ b/pkg/analysis_server/test/search/declarations_test.dart
@@ -6,7 +6,6 @@
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -15,9 +14,7 @@
main() {
defineReflectiveSuite(() {
- if (!AnalysisDriver.useSummary2) {
- defineReflectiveTests(DeclarationsTest);
- }
+ defineReflectiveTests(DeclarationsTest);
});
}
diff --git a/pkg/analysis_server/test/services/correction/change_test.dart b/pkg/analysis_server/test/services/correction/change_test.dart
index 1a74aa1..3568037 100644
--- a/pkg/analysis_server/test/services/correction/change_test.dart
+++ b/pkg/analysis_server/test/services/correction/change_test.dart
@@ -142,6 +142,7 @@
SourceEdit a = new SourceEdit(1, 2, 'aaa');
expect(a == a, isTrue);
expect(a == new SourceEdit(1, 2, 'aaa'), isTrue);
+ // ignore: unrelated_type_equality_checks
expect(a == this, isFalse);
expect(a == new SourceEdit(1, 2, 'bbb'), isFalse);
expect(a == new SourceEdit(10, 2, 'aaa'), isFalse);
@@ -259,6 +260,7 @@
var c = new LinkedEditSuggestion('c', LinkedEditSuggestionKind.METHOD);
expect(a == a, isTrue);
expect(a == a2, isTrue);
+ // ignore: unrelated_type_equality_checks
expect(a == this, isFalse);
expect(a == b, isFalse);
expect(a == c, isFalse);
@@ -274,6 +276,7 @@
expect(a == a, isTrue);
expect(a == a2, isTrue);
expect(a == b, isFalse);
+ // ignore: unrelated_type_equality_checks
expect(a == this, isFalse);
}
diff --git a/pkg/analysis_server/test/src/computer/closingLabels_computer_test.dart b/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
similarity index 100%
rename from pkg/analysis_server/test/src/computer/closingLabels_computer_test.dart
rename to pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
diff --git a/pkg/analysis_server/test/src/computer/test_all.dart b/pkg/analysis_server/test/src/computer/test_all.dart
index def1a36..fa0c1a9 100644
--- a/pkg/analysis_server/test/src/computer/test_all.dart
+++ b/pkg/analysis_server/test/src/computer/test_all.dart
@@ -4,23 +4,22 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'closingLabels_computer_test.dart' as closingLabels_computer_test;
-import 'folding_computer_test.dart' as folding_computer_test;
+import 'closing_labels_computer_test.dart' as closing_labels_computer;
+import 'folding_computer_test.dart' as folding_computer;
import 'highlights2_computer_test.dart' as highlights2_computer;
import 'highlights_computer_test.dart' as highlights_computer;
-import 'import_elements_computer_test.dart' as import_elements_computer_test;
-import 'imported_elements_computer_test.dart'
- as imported_elements_computer_test;
-import 'outline_computer_test.dart' as outline_computer_test;
+import 'import_elements_computer_test.dart' as import_elements_computer;
+import 'imported_elements_computer_test.dart' as imported_elements_computer;
+import 'outline_computer_test.dart' as outline_computer;
main() {
defineReflectiveSuite(() {
- closingLabels_computer_test.main();
- folding_computer_test.main();
+ closing_labels_computer.main();
+ folding_computer.main();
highlights2_computer.main();
highlights_computer.main();
- import_elements_computer_test.main();
- imported_elements_computer_test.main();
- outline_computer_test.main();
+ import_elements_computer.main();
+ imported_elements_computer.main();
+ outline_computer.main();
});
}
diff --git a/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart b/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart
index 8f6487f..408a7a7 100644
--- a/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart
+++ b/pkg/analysis_server/test/src/edit/fix/non_nullable_fix_test.dart
@@ -136,12 +136,11 @@
Folder outputDir = getFolder('/outputDir');
await performFix(included: [projectPath], outputDir: outputDir.path);
expect(outputDir.exists, true);
- expect(outputDir.getChildAssumingFile('bin__bin.html').exists, isTrue);
- expect(outputDir.getChildAssumingFile('lib__lib1.html').exists, isTrue);
- expect(outputDir.getChildAssumingFile('lib__lib2.html').exists, isTrue);
- expect(
- outputDir.getChildAssumingFile('lib__src__lib3.html').exists, isTrue);
- expect(outputDir.getChildAssumingFile('test__test.html').exists, isTrue);
+ expect(getFile('/outputDir/bin/bin.html').exists, isTrue);
+ expect(getFile('/outputDir/lib/lib1.html').exists, isTrue);
+ expect(getFile('/outputDir/lib/lib2.html').exists, isTrue);
+ expect(getFile('/outputDir/lib/src/lib3.html').exists, isTrue);
+ expect(getFile('/outputDir/test/test.html').exists, isTrue);
}
test_outputDirContainsFilesRootedInASubdirectory() async {
@@ -151,9 +150,9 @@
included: [context.join(projectPath, 'lib')],
outputDir: outputDir.path);
expect(outputDir.exists, true);
- expect(outputDir.getChildAssumingFile('lib1.html').exists, isTrue);
- expect(outputDir.getChildAssumingFile('lib2.html').exists, isTrue);
- expect(outputDir.getChildAssumingFile('src__lib3.html').exists, isTrue);
+ expect(getFile('/outputDir/lib1.html').exists, isTrue);
+ expect(getFile('/outputDir/lib2.html').exists, isTrue);
+ expect(getFile('/outputDir/src/lib3.html').exists, isTrue);
}
test_outputDirContainsFilesRootedInParentOfSingleFile() async {
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
index f300740..ca0162f 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2019, 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.
@@ -48,9 +48,9 @@
migration.processInput(result);
migration.finish();
// Build the migration info.
- InfoBuilder builder = InfoBuilder(server);
InstrumentationInformation info = instrumentationListener.data;
- infos = await builder.explainMigration(info, listener);
+ InfoBuilder builder = InfoBuilder(info, listener);
+ infos = await builder.explainMigration();
}
test_parameter_nullableFromInvocation() async {
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/offset_mapper_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/offset_mapper_test.dart
new file mode 100644
index 0000000..4697e18
--- /dev/null
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/offset_mapper_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/edit/nnbd_migration/offset_mapper.dart';
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../analysis_abstract.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(OffsetMapperTest);
+ });
+}
+
+@reflectiveTest
+class OffsetMapperTest extends AbstractAnalysisTest {
+ test_identity() {
+ OffsetMapper mapper = OffsetMapper.identity;
+ expect(mapper.map(0), 0);
+ expect(mapper.map(20), 20);
+ expect(mapper.map(0xFFFFFF), 0xFFFFFF);
+ }
+
+ test_multipleEdits() {
+ OffsetMapper mapper = OffsetMapper.forEdits([
+ SourceEdit(13, 0, '?'),
+ SourceEdit(21, 0, '!'),
+ SourceEdit(32, 0, '?'),
+ ]);
+ expect(mapper.map(0), 0);
+ expect(mapper.map(13), 13);
+ expect(mapper.map(14), 15);
+ expect(mapper.map(21), 22);
+ expect(mapper.map(22), 24);
+ expect(mapper.map(32), 34);
+ expect(mapper.map(33), 36);
+ expect(mapper.map(55), 58);
+ }
+
+ test_singleEdit() {
+ OffsetMapper mapper = OffsetMapper.forEdits([
+ SourceEdit(13, 0, '?'),
+ ]);
+ expect(mapper.map(0), 0);
+ expect(mapper.map(13), 13);
+ expect(mapper.map(14), 15);
+ }
+}
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/test_all.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/test_all.dart
index b7ddf83..6dd7cab 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/test_all.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/test_all.dart
@@ -5,9 +5,11 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'info_builder_test.dart' as info_builder;
+import 'offset_mapper_test.dart' as offset_mapper;
main() {
defineReflectiveSuite(() {
info_builder.main();
+ offset_mapper.main();
}, name: 'nnbd_migration');
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart
index e240531..7656709 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart
@@ -4,7 +4,6 @@
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver;
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -79,8 +78,7 @@
class B extends A {
}
''');
- if (AnalysisDriver.useSummary2) {
- await assertHasFix('''
+ await assertHasFix('''
abstract class A {
void forEach(int f(double p1, String p2));
}
@@ -92,20 +90,6 @@
}
}
''');
- } else {
- await assertHasFix('''
-abstract class A {
- void forEach(int f(double p1, String p2));
-}
-
-class B extends A {
- @override
- void forEach(int Function(double p1, String p2) f) {
- // TODO: implement forEach
- }
-}
-''');
- }
}
test_generics_typeArguments() async {
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart
index e29ce89..692041f 100644
--- a/pkg/analysis_server/test/stress/completion/completion_runner.dart
+++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -257,7 +257,7 @@
*/
bool _isNamedExpressionName(SimpleIdentifier identifier) {
AstNode parent = identifier.parent;
- return parent is NamedExpression && parent.name == identifier;
+ return parent is NamedExpression && parent.name.label == identifier;
}
/**
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
index 3b06fd1..3c7e5ed 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
@@ -539,7 +539,7 @@
if (_match([TokenType.LESS])) {
while (true) {
typeArgs.add(_type(containerName, fieldName));
- if (_peek() != TokenType.COMMA) {
+ if (_peek().type != TokenType.COMMA) {
_consume(TokenType.GREATER, 'Expected >');
break;
}
diff --git a/pkg/analysis_server/tool/spec/to_html.dart b/pkg/analysis_server/tool/spec/to_html.dart
index f8b74ac..1a29203 100644
--- a/pkg/analysis_server/tool/spec/to_html.dart
+++ b/pkg/analysis_server/tool/spec/to_html.dart
@@ -286,7 +286,7 @@
h3(() => write('Domains'));
for (var domain in api.domains) {
if (domain.experimental ||
- (domain.requests.isEmpty && domain.notifications == 0)) {
+ (domain.requests.isEmpty && domain.notifications.isEmpty)) {
continue;
}
generateDomainIndex(domain);
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 274f08e..427a827 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.38.5-dev
+* Added the interface `PromotableElement`, which representing
+ variables that can be type promoted (local variables and parameters,
+ but not fields).
+
## 0.38.4
* Bug fixes: #33300, #38484, #38505.
diff --git a/pkg/analyzer/analysis_options.yaml b/pkg/analyzer/analysis_options.yaml
index 46298e7..3fa0592 100644
--- a/pkg/analyzer/analysis_options.yaml
+++ b/pkg/analyzer/analysis_options.yaml
@@ -1,9 +1,12 @@
include: package:pedantic/analysis_options.1.8.0.yaml
+
analyzer:
# This currently finds ~4,500 implicit-casts issues when enabled.
# strong-mode:
# implicit-casts: false
errors:
+ # Increase the severity of the unused_import hint.
+ unused_import: warning
# Ignoring "style" lint rules from pedantic for now. There are pre-existing
# violations that need to be cleaned up. Each one can be cleaned up and
# enabled according to the value provided.
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 8ae0ba1..5637045 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1423,7 +1423,7 @@
/// A local variable.
///
/// Clients may not extend, implement or mix-in this class.
-abstract class LocalVariableElement implements LocalElement, VariableElement {}
+abstract class LocalVariableElement implements PromotableElement {}
/// An element that represents a method defined within a class.
///
@@ -1472,7 +1472,7 @@
///
/// Clients may not extend, implement or mix-in this class.
abstract class ParameterElement
- implements LocalElement, VariableElement, ConstantEvaluationTarget {
+ implements PromotableElement, ConstantEvaluationTarget {
/// Return the Dart code of the default value, or `null` if no default value.
String get defaultValueCode;
@@ -1570,6 +1570,12 @@
List<LibraryElement> get importedLibraries;
}
+/// A variable that might be subject to type promotion. This might be a local
+/// variable or a parameter.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class PromotableElement implements LocalElement, VariableElement {}
+
/// A getter or a setter. Note that explicitly defined property accessors
/// implicitly define a synthetic field. Symmetrically, synthetic accessors are
/// implicitly created for explicitly defined fields. The following rules apply:
diff --git a/pkg/analyzer/lib/src/dart/analysis/ddc.dart b/pkg/analyzer/lib/src/dart/analysis/ddc.dart
index f526171..c86790c 100644
--- a/pkg/analyzer/lib/src/dart/analysis/ddc.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/ddc.dart
@@ -6,7 +6,6 @@
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
@@ -14,12 +13,8 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/link.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/resynthesize.dart';
-import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'package:analyzer/src/summary2/informative_data.dart';
import 'package:analyzer/src/summary2/link.dart' as summary2;
@@ -44,7 +39,6 @@
List<int> summaryBytes;
RestrictedAnalysisContext context;
- SummaryResynthesizer resynthesizer;
summary2.LinkedElementFactory elementFactory;
DevCompilerResynthesizerBuilder({
@@ -77,7 +71,8 @@
);
_fileCrawler.crawl();
- _buildPackageBundleBytes();
+ _computeLinkedLibraries2();
+ summaryBytes = _assembler.assemble().toBuffer();
var bundle = PackageBundle.fromBuffer(summaryBytes);
// Create an analysis context to contain the state for this build unit.
@@ -87,46 +82,7 @@
);
context = RestrictedAnalysisContext(synchronousSession, _sourceFactory);
- if (AnalysisDriver.useSummary2) {
- _createElementFactory(bundle);
- } else {
- resynthesizer = StoreBasedSummaryResynthesizer(
- context,
- null,
- context.sourceFactory,
- /*strongMode*/ true,
- SummaryDataStore([])
- ..addStore(_summaryData)
- ..addBundle(null, bundle),
- );
- resynthesizer.finishCoreAsyncLibraries();
- context.typeProvider = resynthesizer.typeProvider;
- }
- }
-
- void _buildPackageBundleBytes() {
- if (AnalysisDriver.useSummary2) {
- _computeLinkedLibraries2();
- } else {
- _computeLinkedLibraries1();
- }
- summaryBytes = _assembler.assemble().toBuffer();
- }
-
- void _computeLinkedLibraries1() {
- _fileCrawler.sourceToUnlinkedUnit.forEach((source, unlinkedUnit) {
- _assembler.addUnlinkedUnit(source, unlinkedUnit);
- });
-
- var linkResult = link(
- _fileCrawler.libraryUris.toSet(),
- (uri) => _summaryData.linkedMap[uri],
- (uri) =>
- _summaryData.unlinkedMap[uri] ??
- _fileCrawler.uriToUnlinkedUnit[uri],
- _declaredVariables,
- _analysisOptions);
- linkResult.forEach(_assembler.addLinkedLibrary);
+ _createElementFactory(bundle);
}
/// Link libraries, and fill [_assembler].
@@ -280,8 +236,6 @@
/// them as units.
final List<Source> _invalidLibrarySources = [];
- final Map<Source, UnlinkedUnitBuilder> sourceToUnlinkedUnit = {};
- final Map<String, UnlinkedUnitBuilder> uriToUnlinkedUnit = {};
final Map<Source, CompilationUnit> sourceToUnit = {};
final List<String> libraryUris = [];
final List<Source> librarySources = [];
@@ -330,10 +284,6 @@
var unit = file.parse();
sourceToUnit[source] = unit;
- var unlinkedUnit = serializeAstUnlinked(unit);
- uriToUnlinkedUnit[uriStr] = unlinkedUnit;
- sourceToUnlinkedUnit[source] = unlinkedUnit;
-
void enqueueSource(String relativeUri, bool shouldBeLibrary) {
var sourceUri = resolveRelativeUri(uri, Uri.parse(relativeUri));
if (_knownSources.add(sourceUri)) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index a637158..c71d4d3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -95,9 +95,6 @@
/// zero, we stop writing any new exception contexts in this process.
static int allowedNumberOfContextsToWrite = 10;
- /// Whether summary2 should be used to resynthesize elements.
- static bool useSummary2 = true;
-
/// The scheduler that schedules analysis work in this, and possibly other
/// analysis drivers.
final AnalysisDriverScheduler _scheduler;
@@ -140,11 +137,11 @@
/// The salt to mix into all hashes used as keys for unlinked data.
final Uint32List _unlinkedSalt =
- new Uint32List(3 + AnalysisOptionsImpl.unlinkedSignatureLength);
+ new Uint32List(2 + AnalysisOptionsImpl.unlinkedSignatureLength);
/// The salt to mix into all hashes used as keys for linked data.
final Uint32List _linkedSalt =
- new Uint32List(3 + AnalysisOptions.signatureLength);
+ new Uint32List(2 + AnalysisOptions.signatureLength);
/// The set of priority files, that should be analyzed sooner.
final _priorityFiles = new LinkedHashSet<String>();
@@ -1251,7 +1248,6 @@
sourceFactory,
libraryContext.isLibraryUri,
libraryContext.analysisContext,
- libraryContext.resynthesizer,
libraryContext.elementFactory,
libraryContext.inheritanceManager,
library,
@@ -1319,7 +1315,6 @@
sourceFactory,
libraryContext.isLibraryUri,
libraryContext.analysisContext,
- libraryContext.resynthesizer,
libraryContext.elementFactory,
libraryContext.inheritanceManager,
library,
@@ -1446,12 +1441,9 @@
sourceFactory: _sourceFactory,
externalSummaries: _externalSummaries,
targetLibrary: library,
- useSummary2: useSummary2,
);
- } else if (useSummary2) {
- _libraryContext.load2(library);
} else {
- _libraryContext.load(library);
+ _libraryContext.load2(library);
}
return _libraryContext;
}
@@ -1474,13 +1466,11 @@
void _fillSalt() {
_unlinkedSalt[0] = DATA_VERSION;
_unlinkedSalt[1] = enableIndex ? 1 : 0;
- _unlinkedSalt[2] = useSummary2 ? 1 : 0;
- _unlinkedSalt.setAll(3, _analysisOptions.unlinkedSignature);
+ _unlinkedSalt.setAll(2, _analysisOptions.unlinkedSignature);
_linkedSalt[0] = DATA_VERSION;
_linkedSalt[1] = enableIndex ? 1 : 0;
- _linkedSalt[2] = useSummary2 ? 1 : 0;
- _linkedSalt.setAll(3, _analysisOptions.signature);
+ _linkedSalt.setAll(2, _analysisOptions.signature);
}
/// Load the [AnalysisResult] for the given [file] from the [bytes]. Set
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index ffa3f84..ad3606f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -13,7 +13,6 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/defined_names.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/library_graph.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/referenced_names.dart';
@@ -30,7 +29,6 @@
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/name_filter.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary2/informative_data.dart';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
@@ -397,224 +395,6 @@
bool refresh({bool allowCached: false}) {
counterFileStateRefresh++;
- if (AnalysisDriver.useSummary2) {
- return _refresh2(allowCached: allowCached);
- }
-
- var timerWasRunning = timerFileStateRefresh.isRunning;
- if (!timerWasRunning) {
- timerFileStateRefresh.start();
- }
-
- _invalidateCurrentUnresolvedData();
-
- {
- var rawFileState = _fsState._fileContentCache.get(path, allowCached);
- _content = rawFileState.content;
- _exists = rawFileState.exists;
- _contentHash = rawFileState.contentHash;
- }
-
- // Prepare the unlinked bundle key.
- {
- var signature = new ApiSignature();
- signature.addUint32List(_fsState._unlinkedSalt);
- signature.addString(_contentHash);
- _unlinkedKey = '${signature.toHex()}.unlinked';
- }
-
- // Prepare bytes of the unlinked bundle - existing or new.
- List<int> bytes;
- {
- bytes = _fsState._byteStore.get(_unlinkedKey);
- if (bytes == null || bytes.isEmpty) {
- CompilationUnit unit = parse();
- _fsState._logger.run('Create unlinked for $path', () {
- UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
- DefinedNames definedNames = computeDefinedNames(unit);
- List<String> referencedNames = computeReferencedNames(unit).toList();
- List<String> subtypedNames = computeSubtypedNames(unit).toList();
- bytes = new AnalysisDriverUnlinkedUnitBuilder(
- unit: unlinkedUnit,
- definedTopLevelNames: definedNames.topLevelNames.toList(),
- definedClassMemberNames:
- definedNames.classMemberNames.toList(),
- referencedNames: referencedNames,
- subtypedNames: subtypedNames)
- .toBuffer();
- counterUnlinkedLinkedBytes += bytes.length;
- _fsState._byteStore.put(_unlinkedKey, bytes);
- });
- }
- }
-
- // Read the unlinked bundle.
- _driverUnlinkedUnit = new AnalysisDriverUnlinkedUnit.fromBuffer(bytes);
- _unlinked = _driverUnlinkedUnit.unit;
- _lineInfo = new LineInfo(_unlinked.lineStarts);
-
- // Prepare API signature.
- List<int> newApiSignature = new Uint8List.fromList(_unlinked.apiSignature);
- bool apiSignatureChanged = _apiSignature != null &&
- !_equalByteLists(_apiSignature, newApiSignature);
- _apiSignature = newApiSignature;
-
- // The API signature changed.
- // Flush affected library cycles.
- // Flush exported top-level declarations of all files.
- if (apiSignatureChanged) {
- _libraryCycle?.invalidate();
-
- // If this is a part, invalidate the libraries.
- var libraries = _fsState._partToLibraries[this];
- if (libraries != null) {
- for (var library in libraries) {
- library.libraryCycle?.invalidate();
- }
- }
- }
-
- // This file is potentially not a library for its previous parts anymore.
- if (_partedFiles != null) {
- for (FileState part in _partedFiles) {
- _fsState._partToLibraries[part]?.remove(this);
- }
- }
-
- // Build the graph.
- _importedFiles = <FileState>[];
- _exportedFiles = <FileState>[];
- _partedFiles = <FileState>[];
- _exportFilters = <NameFilter>[];
- for (UnlinkedImport import in _unlinked.imports) {
- String uri = import.isImplicit ? 'dart:core' : import.uri;
- FileState file = _fileForRelativeUri(uri);
- _importedFiles.add(file);
- }
- for (UnlinkedExportPublic export in _unlinked.publicNamespace.exports) {
- String uri = export.uri;
- FileState file = _fileForRelativeUri(uri);
- _exportedFiles.add(file);
- _exportFilters
- .add(new NameFilter.forUnlinkedCombinators(export.combinators));
- }
- for (String uri in _unlinked.publicNamespace.parts) {
- FileState file = _fileForRelativeUri(uri);
- _partedFiles.add(file);
- // TODO(scheglov) Sort for stable results?
- _fsState._partToLibraries
- .putIfAbsent(file, () => <FileState>[])
- .add(this);
- }
- _libraryFiles = [this]..addAll(_partedFiles);
-
- // Compute referenced files.
- _directReferencedFiles = new Set<FileState>()
- ..addAll(_importedFiles)
- ..addAll(_exportedFiles)
- ..addAll(_partedFiles);
- _directReferencedLibraries = Set<FileState>()
- ..addAll(_importedFiles)
- ..addAll(_exportedFiles);
-
- // Update mapping from subtyped names to files.
- for (var name in _driverUnlinkedUnit.subtypedNames) {
- var files = _fsState._subtypedNameToFiles[name];
- if (files == null) {
- files = new Set<FileState>();
- _fsState._subtypedNameToFiles[name] = files;
- }
- files.add(this);
- }
-
- if (!timerWasRunning) {
- timerFileStateRefresh.stop();
- }
-
- // Return whether the API signature changed.
- return apiSignatureChanged;
- }
-
- @override
- String toString() => path ?? '<unresolved>';
-
- CompilationUnit _createEmptyCompilationUnit(FeatureSet featureSet) {
- var token = new Token.eof(0);
- return astFactory.compilationUnit(
- beginToken: token, endToken: token, featureSet: featureSet)
- ..lineInfo = new LineInfo(const <int>[0]);
- }
-
- /**
- * Return the [FileState] for the given [relativeUri], maybe "unresolved"
- * file if the URI cannot be parsed, cannot correspond any file, etc.
- */
- FileState _fileForRelativeUri(String relativeUri) {
- if (relativeUri.isEmpty) {
- return _fsState.unresolvedFile;
- }
-
- Uri absoluteUri;
- try {
- absoluteUri = resolveRelativeUri(uri, Uri.parse(relativeUri));
- } on FormatException {
- return _fsState.unresolvedFile;
- }
-
- return _fsState.getFileForUri(absoluteUri);
- }
-
- /**
- * Invalidate any data that depends on the current unlinked data of the file,
- * because [refresh] is going to recompute the unlinked data.
- */
- void _invalidateCurrentUnresolvedData() {
- // Invalidate unlinked information.
- _definedTopLevelNames = null;
- _definedClassMemberNames = null;
- _referencedNames = null;
-
- if (_driverUnlinkedUnit != null) {
- for (var name in _driverUnlinkedUnit.subtypedNames) {
- var files = _fsState._subtypedNameToFiles[name];
- files?.remove(this);
- }
- }
- }
-
- CompilationUnit _parse(AnalysisErrorListener errorListener) {
- AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
- FeatureSet featureSet = analysisOptions.contextFeatures;
- if (source == null) {
- return _createEmptyCompilationUnit(featureSet);
- }
-
- CharSequenceReader reader = new CharSequenceReader(content);
- Scanner scanner = new Scanner(source, reader, errorListener)
- ..configureFeatures(featureSet);
- Token token = PerformanceStatistics.scan.makeCurrentWhile(() {
- return scanner.tokenize(reportScannerErrors: false);
- });
- LineInfo lineInfo = new LineInfo(scanner.lineStarts);
-
- bool useFasta = analysisOptions.useFastaParser;
- // Pass the feature set from the scanner to the parser
- // because the scanner may have detected a language version comment
- // and downgraded the feature set it holds.
- Parser parser = new Parser(source, errorListener,
- featureSet: scanner.featureSet, useFasta: useFasta);
- parser.enableOptionalNewAndConst = true;
- CompilationUnit unit = parser.parseCompilationUnit(token);
- unit.lineInfo = lineInfo;
-
- // StringToken uses a static instance of StringCanonicalizer, so we need
- // to clear it explicitly once we are done using it for this file.
- StringToken.canonicalizer.clear();
-
- return unit;
- }
-
- bool _refresh2({bool allowCached: false}) {
var timerWasRunning = timerFileStateRefresh.isRunning;
if (!timerWasRunning) {
timerFileStateRefresh.start();
@@ -747,6 +527,85 @@
return apiSignatureChanged;
}
+ @override
+ String toString() => path ?? '<unresolved>';
+
+ CompilationUnit _createEmptyCompilationUnit(FeatureSet featureSet) {
+ var token = new Token.eof(0);
+ return astFactory.compilationUnit(
+ beginToken: token, endToken: token, featureSet: featureSet)
+ ..lineInfo = new LineInfo(const <int>[0]);
+ }
+
+ /**
+ * Return the [FileState] for the given [relativeUri], maybe "unresolved"
+ * file if the URI cannot be parsed, cannot correspond any file, etc.
+ */
+ FileState _fileForRelativeUri(String relativeUri) {
+ if (relativeUri.isEmpty) {
+ return _fsState.unresolvedFile;
+ }
+
+ Uri absoluteUri;
+ try {
+ absoluteUri = resolveRelativeUri(uri, Uri.parse(relativeUri));
+ } on FormatException {
+ return _fsState.unresolvedFile;
+ }
+
+ return _fsState.getFileForUri(absoluteUri);
+ }
+
+ /**
+ * Invalidate any data that depends on the current unlinked data of the file,
+ * because [refresh] is going to recompute the unlinked data.
+ */
+ void _invalidateCurrentUnresolvedData() {
+ // Invalidate unlinked information.
+ _definedTopLevelNames = null;
+ _definedClassMemberNames = null;
+ _referencedNames = null;
+
+ if (_driverUnlinkedUnit != null) {
+ for (var name in _driverUnlinkedUnit.subtypedNames) {
+ var files = _fsState._subtypedNameToFiles[name];
+ files?.remove(this);
+ }
+ }
+ }
+
+ CompilationUnit _parse(AnalysisErrorListener errorListener) {
+ AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
+ FeatureSet featureSet = analysisOptions.contextFeatures;
+ if (source == null) {
+ return _createEmptyCompilationUnit(featureSet);
+ }
+
+ CharSequenceReader reader = new CharSequenceReader(content);
+ Scanner scanner = new Scanner(source, reader, errorListener)
+ ..configureFeatures(featureSet);
+ Token token = PerformanceStatistics.scan.makeCurrentWhile(() {
+ return scanner.tokenize(reportScannerErrors: false);
+ });
+ LineInfo lineInfo = new LineInfo(scanner.lineStarts);
+
+ bool useFasta = analysisOptions.useFastaParser;
+ // Pass the feature set from the scanner to the parser
+ // because the scanner may have detected a language version comment
+ // and downgraded the feature set it holds.
+ Parser parser = new Parser(source, errorListener,
+ featureSet: scanner.featureSet, useFasta: useFasta);
+ parser.enableOptionalNewAndConst = true;
+ CompilationUnit unit = parser.parseCompilationUnit(token);
+ unit.lineInfo = lineInfo;
+
+ // StringToken uses a static instance of StringCanonicalizer, so we need
+ // to clear it explicitly once we are done using it for this file.
+ StringToken.canonicalizer.clear();
+
+ return unit;
+ }
+
static UnlinkedUnit2Builder serializeAstUnlinked2(CompilationUnit unit) {
var exports = <String>[];
var imports = <String>[];
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 013e122..80d34b3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -11,7 +11,6 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/testing_data.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
@@ -21,7 +20,6 @@
import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/constant/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/resolver/ast_rewrite.dart';
@@ -68,7 +66,6 @@
final InheritanceManager3 _inheritance;
final bool Function(Uri) _isLibraryUri;
final AnalysisContext _context;
- final ElementResynthesizer _resynthesizer;
final LinkedElementFactory _elementFactory;
TypeProviderImpl _typeProvider;
@@ -100,7 +97,6 @@
this._sourceFactory,
this._isLibraryUri,
this._context,
- this._resynthesizer,
this._elementFactory,
this._inheritance,
this._library,
@@ -145,12 +141,7 @@
_resolveUriBasedDirectives(file, unit);
});
- if (_elementFactory != null) {
- _libraryElement = _elementFactory.libraryOfUri(_library.uriStr);
- } else {
- _libraryElement = _resynthesizer
- .getElement(new ElementLocationImpl.con3([_library.uriStr]));
- }
+ _libraryElement = _elementFactory.libraryOfUri(_library.uriStr);
_libraryScope = new LibraryScope(_libraryElement);
timerLibraryAnalyzerResolve.start();
@@ -511,11 +502,7 @@
definingCompilationUnit.element = _libraryElement.definingCompilationUnit;
bool matchNodeElement(Directive node, Element element) {
- if (AnalysisDriver.useSummary2) {
- return node.keyword.offset == element.nameOffset;
- } else {
- return node.offset == element.nameOffset;
- }
+ return node.keyword.offset == element.nameOffset;
}
ErrorReporter libraryErrorReporter = _getErrorReporter(_library);
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 56a3aed..ab1168e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -13,18 +13,14 @@
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
-import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/generated/engine.dart'
show AnalysisContext, AnalysisOptions;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/link.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/resynthesize.dart';
import 'package:analyzer/src/summary2/link.dart' as link2;
import 'package:analyzer/src/summary2/linked_bundle_context.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
@@ -59,7 +55,6 @@
int _linkedDataInBytes = 0;
RestrictedAnalysisContext analysisContext;
- SummaryResynthesizer resynthesizer;
LinkedElementFactory elementFactory;
InheritanceManager3 inheritanceManager;
@@ -75,7 +70,6 @@
@required SourceFactory sourceFactory,
@required this.externalSummaries,
@required FileState targetLibrary,
- @required bool useSummary2,
}) : this.logger = logger,
this.byteStore = byteStore,
this.analysisSession = session {
@@ -90,18 +84,8 @@
sourceFactory,
);
- if (useSummary2) {
- _createElementFactory();
- load2(targetLibrary);
- } else {
- // Fill the store with summaries required for the initial library.
- load(targetLibrary);
-
- resynthesizer = new StoreBasedSummaryResynthesizer(
- analysisContext, session, sourceFactory, true, store);
- analysisContext.typeProvider = resynthesizer.typeProvider;
- resynthesizer.finishCoreAsyncLibraries();
- }
+ _createElementFactory();
+ load2(targetLibrary);
inheritanceManager = new InheritanceManager3(analysisContext.typeSystem);
}
@@ -115,28 +99,18 @@
* Computes a [CompilationUnitElement] for the given library/unit pair.
*/
CompilationUnitElement computeUnitElement(FileState library, FileState unit) {
- if (elementFactory != null) {
- var reference = elementFactory.rootReference
- .getChild(library.uriStr)
- .getChild('@unit')
- .getChild(unit.uriStr);
- return elementFactory.elementOfReference(reference);
- } else {
- return resynthesizer.getElement(new ElementLocationImpl.con3(<String>[
- library.uriStr,
- unit.uriStr,
- ]));
- }
+ var reference = elementFactory.rootReference
+ .getChild(library.uriStr)
+ .getChild('@unit')
+ .getChild(unit.uriStr);
+ return elementFactory.elementOfReference(reference);
}
/**
* Get the [LibraryElement] for the given library.
*/
LibraryElement getLibraryElement(FileState library) {
- if (elementFactory != null) {
- return elementFactory.libraryOfUri(library.uriStr);
- }
- return resynthesizer.getLibraryElement(library.uriStr);
+ return elementFactory.libraryOfUri(library.uriStr);
}
/**
@@ -144,112 +118,7 @@
*/
bool isLibraryUri(Uri uri) {
String uriStr = uri.toString();
- if (elementFactory != null) {
- return elementFactory.isLibraryUri(uriStr);
- } else {
- return store.unlinkedMap[uriStr]?.isPartOf == false;
- }
- }
-
- /// Load data required to access elements of the given [targetLibrary].
- void load(FileState targetLibrary) {
- if (AnalysisDriver.useSummary2) {
- throw StateError('Unexpected with summary2.');
- }
-
- // The library is already a part of the context, nothing to do.
- if (store.linkedMap.containsKey(targetLibrary.uriStr)) {
- return;
- }
-
- timerLoad2.start();
-
- var libraries = <String, FileState>{};
- void appendLibraryFiles(FileState library) {
- // Stop if this library is already a part of the context.
- // Libraries from external summaries are also covered by this.
- if (store.linkedMap.containsKey(library.uriStr)) {
- return;
- }
-
- // Stop if we have already scheduled loading of this library.
- if (libraries.containsKey(library.uriStr)) {
- return;
- }
-
- // Schedule the library for loading or linking.
- libraries[library.uriStr] = library;
-
- // Append library units.
- for (FileState part in library.libraryFiles) {
- store.addUnlinkedUnit(part.uriStr, part.unlinked);
- }
-
- // Append referenced libraries.
- library.importedFiles.forEach(appendLibraryFiles);
- library.exportedFiles.forEach(appendLibraryFiles);
- }
-
- logger.run('Append library files', () {
- appendLibraryFiles(targetLibrary);
- });
-
- var libraryUrisToLink = new Set<String>();
- logger.run('Load linked bundles', () {
- for (FileState library in libraries.values) {
- if (library.exists || library == targetLibrary) {
- String key = library.transitiveSignatureLinked;
- List<int> bytes = byteStore.get(key);
- if (bytes != null) {
- LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes);
- store.addLinkedLibrary(library.uriStr, linked);
- _linkedDataInBytes += bytes.length;
- } else {
- libraryUrisToLink.add(library.uriStr);
- }
- }
- }
- int numOfLoaded = libraries.length - libraryUrisToLink.length;
- logger.writeln('Loaded $numOfLoaded linked bundles.');
- counterLoadedLibraries += numOfLoaded;
- });
-
- timerLinking.start();
- var linkedLibraries = <String, LinkedLibraryBuilder>{};
- logger.run('Link libraries', () {
- linkedLibraries = link(libraryUrisToLink, (String uri) {
- LinkedLibrary linkedLibrary = store.linkedMap[uri];
- return linkedLibrary;
- }, (String uri) {
- UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri];
- return unlinkedUnit;
- }, DeclaredVariables(), analysisContext.analysisOptions);
- logger.writeln('Linked ${linkedLibraries.length} libraries.');
- });
- timerLinking.stop();
- counterLinkedLibraries += linkedLibraries.length;
-
- // Store freshly linked libraries into the byte store.
- // Append them to the context.
- timerBundleToBytes.start();
- for (String uri in linkedLibraries.keys) {
- counterLoadedLibraries++;
- FileState library = libraries[uri];
- String key = library.transitiveSignatureLinked;
-
- timerBundleToBytes.start();
- LinkedLibraryBuilder linkedBuilder = linkedLibraries[uri];
- List<int> bytes = linkedBuilder.toBuffer();
- timerBundleToBytes.stop();
- byteStore.put(key, bytes);
- counterUnlinkedLinkedBytes += bytes.length;
-
- LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes);
- store.addLinkedLibrary(uri, linked);
- _linkedDataInBytes += bytes.length;
- }
- timerBundleToBytes.stop();
- timerLoad2.stop();
+ return elementFactory.isLibraryUri(uriStr);
}
/// Load data required to access elements of the given [targetLibrary].
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index c8395a2..0f2f144 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1618,7 +1618,7 @@
/// Return the constant value of the static constant represented by the given
/// [element]. The [node] is the node to be used if an error needs to be
/// reported.
- DartObjectImpl _getConstantValue(AstNode node, Element element) {
+ DartObjectImpl _getConstantValue(Expression node, Element element) {
Element variableElement =
element is PropertyAccessorElement ? element.variable : element;
if (variableElement is VariableElementImpl) {
@@ -1634,11 +1634,8 @@
} else if (variableElement is ExecutableElement) {
ExecutableElement function = element;
if (function.isStatic) {
- ParameterizedType functionType = function.type;
- if (functionType == null) {
- functionType = _typeProvider.functionType;
- }
- return new DartObjectImpl(functionType, new FunctionState(function));
+ var functionType = node.staticType;
+ return DartObjectImpl(functionType, FunctionState(function));
}
} else if (variableElement is ClassElement) {
var type = variableElement.instantiate(
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index 225fb0a..ef993d0 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -90,6 +90,20 @@
}
@override
+ PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) {
+ PrefixedIdentifierImpl copy = super.visitPrefixedIdentifier(node);
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ PropertyAccess visitPropertyAccess(PropertyAccess node) {
+ PropertyAccessImpl copy = super.visitPropertyAccess(node);
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
RedirectingConstructorInvocation node) {
RedirectingConstructorInvocation invocation =
@@ -110,9 +124,11 @@
@override
SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
- SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
- identifier.staticElement = node.staticElement;
- return identifier;
+ SimpleIdentifierImpl copy = super.visitSimpleIdentifier(node);
+ copy.staticElement = node.staticElement;
+ copy.staticType = node.staticType;
+ copy.tearOffTypeArgumentTypes = node.tearOffTypeArgumentTypes;
+ return copy;
}
@override
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index fc66691..6d27b90 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -941,7 +941,7 @@
TypeParameterType instantiate({
@required NullabilitySuffix nullabilitySuffix,
}) {
- return baseElement.instantiate(nullabilitySuffix: nullabilitySuffix);
+ return TypeParameterTypeImpl(this, nullabilitySuffix: nullabilitySuffix);
}
@override
@@ -968,37 +968,39 @@
}
static List<TypeParameterElement> from2(
- List<TypeParameterElement> formals,
+ List<TypeParameterElement> elements,
MapSubstitution substitution,
) {
if (substitution.map.isEmpty) {
- return formals;
+ return elements;
}
// Create type formals with specialized bounds.
// For example `<U extends T>` where T comes from an outer scope.
- var newElements = formals.toList(growable: false);
- var newTypes = List<TypeParameterType>(formals.length);
+ var newElements = List<TypeParameterElement>(elements.length);
+ var newTypes = List<TypeParameterType>(elements.length);
for (int i = 0; i < newElements.length; i++) {
- var formal = newElements[i];
- DartType bound = formal?.bound;
+ var element = elements[i];
+ var bound = element?.bound;
if (bound != null) {
bound = substitution.substituteType(bound);
- var member = TypeParameterMember(formal, substitution, bound);
- newElements[i] = member;
+ element = TypeParameterMember(element, substitution, bound);
}
- newTypes[i] = newElements[i].type;
+ newElements[i] = element;
+ newTypes[i] = newElements[i].instantiate(
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
}
// Recursive bounds are allowed too, so make sure these are updated
// to refer to any new TypeParameterMember we just made, rather than
// the original type parameter
- var substitution2 = Substitution.fromPairs(formals, newTypes);
- for (var formal in newElements) {
- if (formal is TypeParameterMember) {
+ var substitution2 = Substitution.fromPairs(elements, newTypes);
+ for (var newElement in newElements) {
+ if (newElement is TypeParameterMember) {
// TODO(jmesserly): this is required so substituting for the
// type formal will work. Investigate if there's a better solution.
- formal._bound = substitution2.substituteType(formal.bound);
+ newElement._bound = substitution2.substituteType(newElement.bound);
}
}
return newElements;
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index f5b08f4..68a0c7c 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -16,8 +16,6 @@
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/summary/resynthesize.dart'
- show RecursiveInstantiateToBounds;
/// Transforms the given [list] by applying [transform] to all its elements.
///
@@ -765,8 +763,9 @@
name = e.name + subscript;
counter++;
}
- TypeParameterTypeImpl t =
- new TypeParameterTypeImpl(new TypeParameterElementImpl(name, -1));
+ TypeParameterTypeImpl t = new TypeParameterTypeImpl(
+ new TypeParameterElementImpl(name, -1),
+ nullabilitySuffix: NullabilitySuffix.none);
t.appendTo(typeParametersBuffer, visitedTypes,
withNullability: withNullability);
instantiateTypeArgs.add(t);
@@ -1573,13 +1572,7 @@
@override
List<DartType> get typeArguments {
if (_typeArguments == null) {
- try {
- _typeArguments = _typeArgumentsComputer();
- } on RecursiveInstantiateToBounds {
- _typeArguments = new List<DartType>.filled(
- element.typeParameters.length,
- element.context.typeProvider.dynamicType);
- }
+ _typeArguments = _typeArgumentsComputer();
_typeArgumentsComputer = null;
}
return _typeArguments;
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index 9a60696..2a0a6e3 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -191,17 +191,6 @@
_FreshTypeParametersSubstitutor(_TypeSubstitutor outer) : super(outer);
- TypeParameterElement freshTypeParameter(TypeParameterElement element) {
- var freshElement = new TypeParameterElementImpl(element.name, -1);
- var freshType = new TypeParameterTypeImpl(freshElement);
- freshElement.type = freshType;
- substitution[element] = freshType;
- if (element.bound != null) {
- freshElement.bound = visit(element.bound);
- }
- return freshElement;
- }
-
@override
List<TypeParameterElement> freshTypeParameters(
List<TypeParameterElement> elements) {
@@ -445,7 +434,8 @@
return type;
}
- return new InterfaceTypeImpl.explicit(type.element, typeArguments);
+ return new InterfaceTypeImpl.explicit(type.element, typeArguments,
+ nullabilitySuffix: (type as TypeImpl).nullabilitySuffix);
}
@override
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 4548218..281fecf 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -748,7 +748,8 @@
"The class '{0}' wasn't exported from 'dart:core' until version 2.1, "
"but this code is required to be able to run on earlier versions.",
correction:
- "Try either importing 'dart:async' or updating the SDK constraints.");
+ "Try either importing 'dart:async' or updating the SDK constraints.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -804,7 +805,8 @@
"The use of an as expression in a constant expression wasn't "
"supported until version 2.3.2, but this code is required to be able "
"to run on earlier versions.",
- correction: "Try updating the SDK constraints.");
+ correction: "Try updating the SDK constraints.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -862,7 +864,8 @@
"The use of the operator '{0}' for 'bool' operands in a constant context "
"wasn't supported until version 2.3.2, but this code is required to "
"be able to run on earlier versions.",
- correction: "Try updating the SDK constraints.");
+ correction: "Try updating the SDK constraints.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -923,7 +926,8 @@
"Using the operator '==' for non-primitive types wasn't supported "
"until version 2.3.2, but this code is required to be able to "
"run on earlier versions.",
- correction: "Try updating the SDK constraints.");
+ correction: "Try updating the SDK constraints.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -982,7 +986,8 @@
'SDK_VERSION_EXTENSION_METHODS',
"Extension methods weren't supported until version 2.6.0, "
"but this code is required to be able to run on earlier versions.",
- correction: "Try updating the SDK constraints.");
+ correction: "Try updating the SDK constraints.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -1097,7 +1102,8 @@
"The use of an is expression in a constant context wasn't supported "
"until version 2.3.2, but this code is required to be able to run on "
"earlier versions.",
- correction: "Try updating the SDK constraints.");
+ correction: "Try updating the SDK constraints.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -1259,7 +1265,8 @@
'SDK_VERSION_UI_AS_CODE',
"The for, if, and spread elements weren't supported until version 2.2.2, "
"but this code is required to be able to run on earlier versions.",
- correction: "Try updating the SDK constraints.");
+ correction: "Try updating the SDK constraints.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -1322,7 +1329,8 @@
"The if and spread elements weren't supported in constant expressions "
"until version 2.5.0, but this code is required to be able to run on "
"earlier versions.",
- correction: "Try updating the SDK constraints.");
+ correction: "Try updating the SDK constraints.",
+ hasPublishedDocs: true);
/**
* When "strict-raw-types" is enabled, raw types must be inferred via the
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 89c7e91..adf8e53 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -852,8 +852,11 @@
* template. The correction associated with the error will be created from the
* given [correction] template.
*/
- const ParserErrorCode(String name, String message, {String correction})
- : super.temporary(name, message, correction: correction);
+ const ParserErrorCode(String name, String message,
+ {String correction, bool hasPublishedDocs})
+ : super.temporary(name, message,
+ correction: correction,
+ hasPublishedDocs: hasPublishedDocs ?? false);
@override
ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index 8a12c18..ab50520 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -253,17 +253,20 @@
const ParserErrorCode _EXTENSION_DECLARES_ABSTRACT_MEMBER =
const ParserErrorCode('EXTENSION_DECLARES_ABSTRACT_MEMBER',
r"Extensions can't declare abstract members.",
- correction: "Try providing an implementation for the member.");
+ correction: "Try providing an implementation for the member.",
+ hasPublishedDocs: true);
const ParserErrorCode _EXTENSION_DECLARES_CONSTRUCTOR = const ParserErrorCode(
'EXTENSION_DECLARES_CONSTRUCTOR', r"Extensions can't declare constructors.",
- correction: "Try removing the constructor declaration.");
+ correction: "Try removing the constructor declaration.",
+ hasPublishedDocs: true);
const ParserErrorCode _EXTENSION_DECLARES_INSTANCE_FIELD =
const ParserErrorCode('EXTENSION_DECLARES_INSTANCE_FIELD',
r"Extensions can't declare instance fields",
correction:
- "Try removing the field declaration or making it a static field");
+ "Try removing the field declaration or making it a static field",
+ hasPublishedDocs: true);
const ParserErrorCode _EXTERNAL_CLASS = const ParserErrorCode(
'EXTERNAL_CLASS', r"Classes can't be declared to be 'external'.",
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index a7a4a3e..683b8c1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -13,18 +13,18 @@
import 'package:meta/meta.dart';
class AnalyzerFunctionBodyAccess
- implements FunctionBodyAccess<VariableElement> {
+ implements FunctionBodyAccess<PromotableElement> {
final FunctionBody node;
AnalyzerFunctionBodyAccess(this.node);
@override
- bool isPotentiallyMutatedInClosure(VariableElement variable) {
+ bool isPotentiallyMutatedInClosure(PromotableElement variable) {
return node.isPotentiallyMutatedInClosure(variable);
}
@override
- bool isPotentiallyMutatedInScope(VariableElement variable) {
+ bool isPotentiallyMutatedInScope(PromotableElement variable) {
return node.isPotentiallyMutatedInScope(variable);
}
}
@@ -48,16 +48,16 @@
final NodeOperations<Expression> _nodeOperations;
/// The reused instance for creating new [FlowAnalysis] instances.
- final _TypeSystemTypeOperations _typeOperations;
+ final TypeSystemTypeOperations _typeOperations;
/// Precomputed sets of potentially assigned variables.
- final AssignedVariables<AstNode, VariableElement> assignedVariables;
+ final AssignedVariables<AstNode, PromotableElement> assignedVariables;
/// The result for post-resolution stages of analysis.
final FlowAnalysisResult result;
/// The current flow, when resolving a function body, or `null` otherwise.
- FlowAnalysis<Statement, Expression, VariableElement, DartType> flow;
+ FlowAnalysis<Statement, Expression, PromotableElement, DartType> flow;
int _blockFunctionBodyLevel = 0;
@@ -65,7 +65,7 @@
TypeSystem typeSystem, AstNode node, bool retainDataForTesting) {
return FlowAnalysisHelper._(
const AnalyzerNodeOperations(),
- _TypeSystemTypeOperations(typeSystem),
+ TypeSystemTypeOperations(typeSystem),
computeAssignedVariables(node),
retainDataForTesting ? FlowAnalysisResult() : null);
}
@@ -163,7 +163,7 @@
if (_blockFunctionBodyLevel > 1) {
assert(flow != null);
} else {
- flow = FlowAnalysis<Statement, Expression, VariableElement, DartType>(
+ flow = FlowAnalysis<Statement, Expression, PromotableElement, DartType>(
_nodeOperations,
_typeOperations,
AnalyzerFunctionBodyAccess(node),
@@ -173,7 +173,7 @@
var parameters = _enclosingExecutableParameters(node);
if (parameters != null) {
for (var parameter in parameters.parameters) {
- flow.add(parameter.declaredElement, assigned: true);
+ flow.write(parameter.declaredElement);
}
}
}
@@ -244,19 +244,14 @@
return false;
}
- void loopVariable(DeclaredIdentifier declaredVariable) {
- if (declaredVariable != null) {
- flow.add(declaredVariable.declaredElement, assigned: false);
- }
- }
-
void variableDeclarationList(VariableDeclarationList node) {
if (flow != null) {
var variables = node.variables;
for (var i = 0; i < variables.length; ++i) {
var variable = variables[i];
- flow.add(variable.declaredElement,
- assigned: variable.initializer != null);
+ if (variable.initializer != null) {
+ flow.write(variable.declaredElement);
+ }
}
}
}
@@ -276,9 +271,9 @@
}
/// Computes the [AssignedVariables] map for the given [node].
- static AssignedVariables<AstNode, VariableElement> computeAssignedVariables(
+ static AssignedVariables<AstNode, PromotableElement> computeAssignedVariables(
AstNode node) {
- var assignedVariables = AssignedVariables<AstNode, VariableElement>();
+ var assignedVariables = AssignedVariables<AstNode, PromotableElement>();
node.accept(_AssignedVariablesVisitor(assignedVariables));
return assignedVariables;
}
@@ -333,6 +328,33 @@
final List<AstNode> unassignedNodes = [];
}
+class TypeSystemTypeOperations
+ implements TypeOperations<PromotableElement, DartType> {
+ final TypeSystem typeSystem;
+
+ TypeSystemTypeOperations(this.typeSystem);
+
+ @override
+ bool isSameType(covariant TypeImpl type1, covariant TypeImpl type2) {
+ return type1 == type2;
+ }
+
+ @override
+ bool isSubtypeOf(DartType leftType, DartType rightType) {
+ return typeSystem.isSubtypeOf(leftType, rightType);
+ }
+
+ @override
+ DartType promoteToNonNull(DartType type) {
+ return typeSystem.promoteToNonNull(type);
+ }
+
+ @override
+ DartType variableType(PromotableElement variable) {
+ return variable.type;
+ }
+}
+
/// The visitor that gathers local variables that are potentially assigned
/// in corresponding statements, such as loops, `switch` and `try`.
class _AssignedVariablesVisitor extends RecursiveAstVisitor<void> {
@@ -458,35 +480,3 @@
return promotedType ?? variable.type;
}
}
-
-class _TypeSystemTypeOperations
- implements TypeOperations<VariableElement, DartType> {
- final TypeSystem typeSystem;
-
- _TypeSystemTypeOperations(this.typeSystem);
-
- @override
- bool isLocalVariable(VariableElement element) {
- return element is LocalVariableElement;
- }
-
- @override
- bool isSameType(covariant TypeImpl type1, covariant TypeImpl type2) {
- return type1 == type2;
- }
-
- @override
- bool isSubtypeOf(DartType leftType, DartType rightType) {
- return typeSystem.isSubtypeOf(leftType, rightType);
- }
-
- @override
- DartType promoteToNonNull(DartType type) {
- return typeSystem.promoteToNonNull(type);
- }
-
- @override
- DartType variableType(VariableElement variable) {
- return variable.type;
- }
-}
diff --git a/pkg/analyzer/lib/src/error/analyzer_error_code.dart b/pkg/analyzer/lib/src/error/analyzer_error_code.dart
index 29bcc8c..f8cb42d 100644
--- a/pkg/analyzer/lib/src/error/analyzer_error_code.dart
+++ b/pkg/analyzer/lib/src/error/analyzer_error_code.dart
@@ -13,11 +13,4 @@
correction: correction,
hasPublishedDocs: hasPublishedDocs ?? false,
isUnresolvedIdentifier: isUnresolvedIdentifier ?? false);
-
- String get url {
- if (hasPublishedDocs) {
- return 'https://dart.dev/tools/diagnostic-messages#${name.toLowerCase()}';
- }
- return null;
- }
}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index d7f00f5..b8ebccc 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -137,7 +137,8 @@
// rather than '{0}') or split into multiple codes.
static const CompileTimeErrorCode ABSTRACT_SUPER_MEMBER_REFERENCE =
const CompileTimeErrorCode('ABSTRACT_SUPER_MEMBER_REFERENCE',
- "The {0} '{1}' is always abstract in the supertype.");
+ "The {0} '{1}' is always abstract in the supertype.",
+ hasPublishedDocs: true);
/**
* Enum proposal: It is also a compile-time error to explicitly instantiate an
@@ -238,7 +239,8 @@
"neither is more specific.",
correction:
"Try using an extension override to specify the extension "
- "you want to to be chosen.");
+ "you want to to be chosen.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -453,7 +455,8 @@
static const CompileTimeErrorCode BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME =
const CompileTimeErrorCode('BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME',
"The built-in identifier '{0}' can't be used as an extension name.",
- correction: "Try choosing a different name for the extension.");
+ correction: "Try choosing a different name for the extension.",
+ hasPublishedDocs: true);
/**
* 16.33 Identifier Reference: It is a compile-time error if a built-in
@@ -980,7 +983,8 @@
// ```
static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_LIST_OR_SET =
const CompileTimeErrorCode('CONST_SPREAD_EXPECTED_LIST_OR_SET',
- "A list or a set is expected in this spread.");
+ "A list or a set is expected in this spread.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -1009,7 +1013,8 @@
// ```
static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_MAP =
const CompileTimeErrorCode(
- 'CONST_SPREAD_EXPECTED_MAP', "A map is expected in this spread.");
+ 'CONST_SPREAD_EXPECTED_MAP', "A map is expected in this spread.",
+ hasPublishedDocs: true);
/**
* 16.12.2 Const: If <i>T</i> is a parameterized type <i>S<U<sub>1</sub>,
@@ -1081,7 +1086,8 @@
const CompileTimeErrorCode('CONST_WITH_NON_CONSTANT_ARGUMENT',
"Arguments of a constant creation must be constant expressions.",
correction: "Try making the argument a valid constant, or "
- "use 'new' to call the constructor.");
+ "use 'new' to call the constructor.",
+ hasPublishedDocs: true);
/**
* 16.12.2 Const: It is a compile-time error if <i>T</i> is not a class
@@ -1267,7 +1273,8 @@
static const CompileTimeErrorCode DUPLICATE_DEFINITION =
const CompileTimeErrorCode(
'DUPLICATE_DEFINITION', "The name '{0}' is already defined.",
- correction: "Try renaming one of the declarations.");
+ correction: "Try renaming one of the declarations.",
+ hasPublishedDocs: true);
/**
* 18.3 Parts: It's a compile-time error if the same library contains two part
@@ -1327,7 +1334,8 @@
// returned by an iterator.
static const CompileTimeErrorCode EQUAL_ELEMENTS_IN_CONST_SET =
const CompileTimeErrorCode('EQUAL_ELEMENTS_IN_CONST_SET',
- "Two values in a constant set can't be equal.");
+ "Two values in a constant set can't be equal.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -1528,7 +1536,8 @@
static const CompileTimeErrorCode EXTENSION_AS_EXPRESSION =
const CompileTimeErrorCode('EXTENSION_AS_EXPRESSION',
"Extension '{0}' can't be used as an expression.",
- correction: "Try replacing it with a valid expression.");
+ correction: "Try replacing it with a valid expression.",
+ hasPublishedDocs: true);
/**
* Parameters:
@@ -1570,7 +1579,8 @@
"Extension '{0}' can't define static member '{1}' and an instance "
"member with the same name.",
correction:
- "Try renaming the member to a name that doesn't conflict.");
+ "Try renaming the member to a name that doesn't conflict.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -1607,7 +1617,8 @@
'EXTENSION_DECLARES_MEMBER_OF_OBJECT',
"Extensions can't declare members with the same name as a member "
"declared by 'Object'.",
- correction: "Try specifying a different name for the member.");
+ correction: "Try specifying a different name for the member.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -1651,7 +1662,8 @@
'EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER',
"An extension override can't be used to access a static member from "
"an extension.",
- correction: "Try using just the name of the extension.");
+ correction: "Try using just the name of the extension.",
+ hasPublishedDocs: true);
/**
* Parameters:
@@ -1699,7 +1711,8 @@
const CompileTimeErrorCode(
'EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE',
"The type of the argument to the extension override '{0}' "
- "isn't assignable to the extended type '{1}'.");
+ "isn't assignable to the extended type '{1}'.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -1742,7 +1755,8 @@
'EXTENSION_OVERRIDE_WITH_CASCADE',
"Extension overrides have no value so they can't be used as the "
"target of a cascade expression.",
- correction: "Try using '.' instead of '..'.");
+ correction: "Try using '.' instead of '..'.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -1797,7 +1811,8 @@
static const CompileTimeErrorCode EXTENSION_OVERRIDE_WITHOUT_ACCESS =
const CompileTimeErrorCode('EXTENSION_OVERRIDE_WITHOUT_ACCESS',
"An extension override can only be used to access instance members.",
- correction: 'Consider adding an access to an instance member.');
+ correction: "Consider adding an access to an instance member.",
+ hasPublishedDocs: true);
/**
* Parameters:
@@ -1833,7 +1848,8 @@
static const CompileTimeErrorCode EXTRA_POSITIONAL_ARGUMENTS =
const CompileTimeErrorCode('EXTRA_POSITIONAL_ARGUMENTS',
"Too many positional arguments: {0} expected, but {1} found.",
- correction: "Try removing the extra arguments.");
+ correction: "Try removing the extra arguments.",
+ hasPublishedDocs: true);
/**
* Parameters:
@@ -1882,7 +1898,8 @@
const CompileTimeErrorCode('EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED',
"Too many positional arguments: {0} expected, but {1} found.",
correction: "Try removing the extra positional arguments, "
- "or specifying the name for named arguments.");
+ "or specifying the name for named arguments.",
+ hasPublishedDocs: true);
/**
* 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It
@@ -2092,7 +2109,8 @@
"Classes and mixins can only implement other classes and mixins.",
correction:
"Try specifying a class or mixin, or remove the name from the "
- "list.");
+ "list.",
+ hasPublishedDocs: true);
/**
* 10.10 Superinterfaces: It is a compile-time error if two elements in the
@@ -2446,7 +2464,8 @@
'INVALID_EXTENSION_ARGUMENT_COUNT',
"Extension overrides must have exactly one argument: "
"the value of 'this' in the extension method.",
- correction: "Try specifying exactly one argument.");
+ correction: "Try specifying exactly one argument.",
+ hasPublishedDocs: true);
/**
* 7.6.2 Factories: It is a compile-time error if <i>M</i> is not the name of
@@ -2608,7 +2627,8 @@
static const CompileTimeErrorCode INVALID_USE_OF_COVARIANT_IN_EXTENSION =
const CompileTimeErrorCode('INVALID_USE_OF_COVARIANT_IN_EXTENSION',
"The 'covariant' keyword can't be used in an extension.",
- correction: "Try removing the 'covariant' keyword.");
+ correction: "Try removing the 'covariant' keyword.",
+ hasPublishedDocs: true);
/**
* 14.2 Exports: It is a compile-time error if the compilation unit found at
@@ -2708,12 +2728,13 @@
// ```dart
// const collection = <String>{'a', 'b'};
// ```
- static const CompileTimeErrorCode MAP_ENTRY_NOT_IN_MAP =
- const CompileTimeErrorCode('MAP_ENTRY_NOT_IN_MAP',
+ static const CompileTimeErrorCode
+ MAP_ENTRY_NOT_IN_MAP = const CompileTimeErrorCode('MAP_ENTRY_NOT_IN_MAP',
"Map entries can only be used in a map literal.",
correction:
"Try converting the collection to a map or removing the map "
- "entry.");
+ "entry.",
+ hasPublishedDocs: true);
/**
* 7 Classes: It is a compile time error if a class <i>C</i> declares a member
@@ -3148,7 +3169,8 @@
// ```
static const CompileTimeErrorCode NON_CONSTANT_CASE_EXPRESSION =
const CompileTimeErrorCode(
- 'NON_CONSTANT_CASE_EXPRESSION', "Case expressions must be constant.");
+ 'NON_CONSTANT_CASE_EXPRESSION', "Case expressions must be constant.",
+ hasPublishedDocs: true);
/**
* 13.9 Switch: Given a switch statement of the form <i>switch (e) {
@@ -3297,7 +3319,8 @@
static const CompileTimeErrorCode NON_CONSTANT_MAP_KEY =
const CompileTimeErrorCode('NON_CONSTANT_MAP_KEY',
"The keys in a const map literal must be constant.",
- correction: "Try removing the keyword 'const' from the map literal.");
+ correction: "Try removing the keyword 'const' from the map literal.",
+ hasPublishedDocs: true);
/**
* 12.7 Maps: It is a compile time error if either a key or a value of an
@@ -3349,7 +3372,8 @@
static const CompileTimeErrorCode NON_CONSTANT_MAP_VALUE =
const CompileTimeErrorCode('NON_CONSTANT_MAP_VALUE',
"The values in a const map literal must be constant.",
- correction: "Try removing the keyword 'const' from the map literal.");
+ correction: "Try removing the keyword 'const' from the map literal.",
+ hasPublishedDocs: true);
/**
* No parameters.
@@ -3398,7 +3422,8 @@
static const CompileTimeErrorCode NON_CONSTANT_MAP_ELEMENT =
const CompileTimeErrorCode('NON_CONSTANT_MAP_ELEMENT',
"The elements in a const map literal must be constant.",
- correction: "Try removing the keyword 'const' from the map literal.");
+ correction: "Try removing the keyword 'const' from the map literal.",
+ hasPublishedDocs: true);
/**
* 12.7 Maps: It is a compile time error if either a key or a value of an
@@ -3514,7 +3539,8 @@
static const CompileTimeErrorCode NOT_ENOUGH_POSITIONAL_ARGUMENTS =
const CompileTimeErrorCode('NOT_ENOUGH_POSITIONAL_ARGUMENTS',
"{0} positional argument(s) expected, but {1} found.",
- correction: "Try adding the missing arguments.");
+ correction: "Try adding the missing arguments.",
+ hasPublishedDocs: true);
@Deprecated('Use CompileTimeErrorCode NOT_ENOUGH_POSITIONAL_ARGUMENTS')
static const CompileTimeErrorCode NOT_ENOUGH_REQUIRED_ARGUMENTS =
@@ -3629,8 +3655,8 @@
// var m = <int, String>{...l.asMap()};
// ```
static const CompileTimeErrorCode NOT_MAP_SPREAD = const CompileTimeErrorCode(
- 'NOT_MAP_SPREAD',
- "Spread elements in map literals must implement 'Map'.");
+ 'NOT_MAP_SPREAD', "Spread elements in map literals must implement 'Map'.",
+ hasPublishedDocs: true);
static const CompileTimeErrorCode NOT_NULL_AWARE_NULL_SPREAD =
const CompileTimeErrorCode(
@@ -4051,7 +4077,8 @@
"Local variable '{0}' can't be referenced before it is declared.",
correction: "Try moving the declaration to before the first use, or "
"renaming the local variable so that it doesn't hide a name from "
- "an enclosing scope.");
+ "an enclosing scope.",
+ hasPublishedDocs: true);
/**
* 12.8.1 Rethrow: It is a compile-time error if an expression of the form
@@ -4144,7 +4171,8 @@
const CompileTimeErrorCode(
'SUPER_IN_EXTENSION',
"The 'super' keyword can't be used in an extension because an "
- "extension doesn't have a superclass.");
+ "extension doesn't have a superclass.",
+ hasPublishedDocs: true);
/**
* 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
@@ -4269,6 +4297,7 @@
'UNDEFINED_ANNOTATION', "Undefined name '{0}' used as an annotation.",
correction:
"Try defining the name or importing it from another library.",
+ hasPublishedDocs: true,
isUnresolvedIdentifier: true);
/**
@@ -4445,7 +4474,8 @@
"The getter '{0}' isn't defined for the extension '{1}'.",
correction:
"Try correcting the name to the name of an existing getter, or "
- "defining a getter named '{0}'.");
+ "defining a getter named '{0}'.",
+ hasPublishedDocs: true);
/**
* Parameters:
@@ -4545,7 +4575,8 @@
"The method '{0}' isn't defined for the extension '{1}'.",
correction:
"Try correcting the name to the name of an existing method, or "
- "defining a method named '{0}'.");
+ "defining a method named '{0}'.",
+ hasPublishedDocs: true);
/**
* Parameters:
@@ -4657,7 +4688,8 @@
"The setter '{0}' isn't defined for the extension '{1}'.",
correction:
"Try correcting the name to the name of an existing setter, or "
- "defining a setter named '{0}'.");
+ "defining a setter named '{0}'.",
+ hasPublishedDocs: true);
/**
* Parameters:
@@ -4799,7 +4831,8 @@
'UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE',
"Static members from the extended type or one of its superclasses "
"must be qualified by the name of the defining type.",
- correction: "Try adding '{0}.' before the name.");
+ correction: "Try adding '{0}.' before the name.",
+ hasPublishedDocs: true);
/**
* Parameters:
@@ -5133,7 +5166,8 @@
"A value of type '{0}' can't be assigned to a variable of type "
"'{1}'.",
correction: "Try changing the type of the variable, or "
- "casting the right-hand type to '{1}'.");
+ "casting the right-hand type to '{1}'.",
+ hasPublishedDocs: true);
/**
* Parameters:
@@ -5514,7 +5548,8 @@
"isn't defined in any of the libraries imported using that "
"prefix.",
correction: "Try correcting the prefix or "
- "importing the library that defines '{0}'.");
+ "importing the library that defines '{0}'.",
+ hasPublishedDocs: true);
/**
* Parameters:
@@ -5615,7 +5650,8 @@
"The method '{0}' isn't defined in a superclass of '{1}'.",
correction:
"Try correcting the name to the name of an existing method, or "
- "defining a method named '{0}' in a superclass.");
+ "defining a method named '{0}' in a superclass.",
+ hasPublishedDocs: true);
/**
* 12.18 Assignment: Evaluation of an assignment of the form
@@ -6000,7 +6036,8 @@
'CAST_TO_NON_TYPE',
"The name '{0}' isn't a type, so it can't be used in an 'as' expression.",
correction: "Try changing the name to the name of an existing type, or "
- "creating a type with the name '{0}'.");
+ "creating a type with the name '{0}'.",
+ hasPublishedDocs: true);
/**
* 7.4 Abstract Instance Members: It is a static warning if an abstract member
@@ -6170,7 +6207,8 @@
// TODO(brianwilkerson) Split this error code so that we can suggest
// initializing fields in constructors (FINAL_FIELD_NOT_INITIALIZED
// and FINAL_VARIABLE_NOT_INITIALIZED).
- correction: "Try initializing the variable.");
+ correction: "Try initializing the variable.",
+ hasPublishedDocs: true);
/**
* 7.6.1 Generative Constructors: Each final instance variable <i>f</i>
@@ -6829,7 +6867,8 @@
"expression.",
correction:
"Try changing the name to the name of an existing type, or "
- "creating a type with the name '{0}'.");
+ "creating a type with the name '{0}'.",
+ hasPublishedDocs: true);
/**
* 10 Generics: However, a type parameter is considered to be a malformed type
@@ -7300,7 +7339,8 @@
{String correction, bool hasPublishedDocs})
: type = type,
super.temporary(name, message,
- correction: correction, hasPublishedDocs: hasPublishedDocs);
+ correction: correction,
+ hasPublishedDocs: hasPublishedDocs ?? false);
@override
ErrorSeverity get errorSeverity => type.severity;
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 078a9da..df889e0 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -2090,7 +2090,8 @@
}
@override
- void endTypeVariable(Token token, int index, Token extendsOrSuper) {
+ void endTypeVariable(
+ Token token, int index, Token extendsOrSuper, Token variance) {
debugEvent("TypeVariable");
assert(extendsOrSuper == null ||
optional('extends', extendsOrSuper) ||
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index b2d006f..a8dfa2e 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
@@ -234,9 +233,7 @@
_setGenericFunctionType(node.returnType, element.returnType);
(node.functionExpression as FunctionExpressionImpl).declaredElement =
element;
- if (AnalysisDriver.useSummary2 && _enclosingUnit.linkedContext != null) {
- node.returnType?.accept(this);
- }
+ node.returnType?.accept(this);
_walker._elementHolder?.addFunction(element);
_walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
super.visitFunctionDeclaration(node);
@@ -278,35 +275,13 @@
@override
void visitGenericFunctionType(GenericFunctionType node) {
- if (AnalysisDriver.useSummary2 && _enclosingUnit.linkedContext != null) {
- var builder = new LocalElementBuilder(ElementHolder(), _enclosingUnit);
- node.accept(builder);
+ var builder = new LocalElementBuilder(ElementHolder(), _enclosingUnit);
+ node.accept(builder);
- var nodeImpl = node as GenericFunctionTypeImpl;
- _enclosingUnit.encloseElement(
- nodeImpl.declaredElement as GenericFunctionTypeElementImpl,
- );
- return;
- }
- if (_walker.elementBuilder != null) {
- _walker.elementBuilder.visitGenericFunctionType(node);
- } else {
- var element = node.type?.element;
- if (element is GenericFunctionTypeElement) {
- _setGenericFunctionType(node.returnType, element.returnType);
- _walk(new ElementWalker.forGenericFunctionType(element), () {
- super.visitGenericFunctionType(node);
- });
- } else {
- var builder = new LocalElementBuilder(ElementHolder(), _enclosingUnit);
- node.accept(builder);
-
- var nodeImpl = node as GenericFunctionTypeImpl;
- _enclosingUnit.encloseElement(
- nodeImpl.declaredElement as GenericFunctionTypeElementImpl,
- );
- }
- }
+ var nodeImpl = node as GenericFunctionTypeImpl;
+ _enclosingUnit.encloseElement(
+ nodeImpl.declaredElement as GenericFunctionTypeElementImpl,
+ );
}
@override
@@ -379,9 +354,7 @@
}
}
_setGenericFunctionType(node.returnType, element.returnType);
- if (AnalysisDriver.useSummary2 && _enclosingUnit.linkedContext != null) {
- node.returnType?.accept(this);
- }
+ node.returnType?.accept(this);
_walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
super.visitMethodDeclaration(node);
});
@@ -456,19 +429,11 @@
@override
void visitTypeParameter(TypeParameter node) {
- if (node.parent.parent is FunctionTypedFormalParameter &&
- !AnalysisDriver.useSummary2) {
- // Work around dartbug.com/28515.
- // TODO(paulberry): remove this once dartbug.com/28515 is fixed.
- var element = new TypeParameterElementImpl.forNode(node.name);
- node.name?.staticElement = element;
- } else {
- TypeParameterElement element =
- _match(node.name, _walker.getTypeParameter());
- _setGenericFunctionType(node.bound, element.bound);
- super.visitTypeParameter(node);
- resolveMetadata(node, node.metadata, element);
- }
+ TypeParameterElement element =
+ _match(node.name, _walker.getTypeParameter());
+ _setGenericFunctionType(node.bound, element.bound);
+ super.visitTypeParameter(node);
+ resolveMetadata(node, node.metadata, element);
}
@override
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 566e931..53038fc 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -9,11 +9,11 @@
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/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
@@ -939,13 +939,6 @@
}
}
- // TODO(paulberry): remove this once dartbug.com/28515 is fixed.
- if (node.typeParameters != null && !AnalysisDriver.useSummary2) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.GENERIC_FUNCTION_TYPED_PARAM_UNSUPPORTED,
- node);
- }
-
super.visitFunctionTypedFormalParameter(node);
} finally {
_isInFunctionTypedFormalParameter = old;
@@ -1378,7 +1371,6 @@
void visitTypeParameter(TypeParameter node) {
_checkForBuiltInIdentifierAsName(node.name,
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME);
- _checkForTypeParameterSupertypeOfItsBound(node);
_checkForTypeAnnotationDeferredClass(node.bound);
_checkForImplicitDynamicType(node.bound);
_checkForGenericFunctionType(node.bound);
@@ -1389,6 +1381,7 @@
@override
void visitTypeParameterList(TypeParameterList node) {
_duplicateDefinitionVerifier.checkTypeParameters(node);
+ _checkForTypeParameterBoundRecursion(node.typeParameters);
super.visitTypeParameterList(node);
}
@@ -3114,20 +3107,23 @@
if (_enclosingFunction.isAsynchronous) {
if (_enclosingFunction.isGenerator) {
_checkForIllegalReturnTypeCode(
- returnType,
- _typeProvider.streamDynamicType,
- StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE);
+ returnType,
+ _typeProvider.streamElement,
+ StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
+ );
} else {
_checkForIllegalReturnTypeCode(
- returnType,
- _typeProvider.futureDynamicType,
- StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE);
+ returnType,
+ _typeProvider.futureElement,
+ StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE,
+ );
}
} else if (_enclosingFunction.isGenerator) {
_checkForIllegalReturnTypeCode(
- returnType,
- _typeProvider.iterableDynamicType,
- StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE);
+ returnType,
+ _typeProvider.iterableElement,
+ StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE,
+ );
}
}
@@ -3139,7 +3135,7 @@
* and if not report [errorCode].
*/
void _checkForIllegalReturnTypeCode(TypeAnnotation returnTypeName,
- DartType expectedType, StaticTypeWarningCode errorCode) {
+ ClassElement expectedElement, StaticTypeWarningCode errorCode) {
DartType returnType = _enclosingFunction.returnType;
//
// When checking an async/sync*/async* method, we know the exact type
@@ -3159,8 +3155,10 @@
//
// Similar logic applies for sync* and async*.
//
- InterfaceType genericType = (expectedType.element as ClassElement).type;
- DartType lowerBound = genericType.instantiate([BottomTypeImpl.instance]);
+ var lowerBound = expectedElement.instantiate(
+ typeArguments: [BottomTypeImpl.instance],
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
if (!_typeSystem.isSubtypeOf(lowerBound, returnType)) {
_errorReporter.reportErrorForNode(errorCode, returnTypeName);
}
@@ -4931,6 +4929,44 @@
}
}
+ /**
+ * Check that none of the type [parameters] references itself in its bound.
+ *
+ * See [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND].
+ */
+ void _checkForTypeParameterBoundRecursion(List<TypeParameter> parameters) {
+ Map<TypeParameterElement, TypeParameter> elementToNode;
+ for (var parameter in parameters) {
+ if (parameter.bound != null) {
+ if (elementToNode == null) {
+ elementToNode = {};
+ for (var parameter in parameters) {
+ elementToNode[parameter.declaredElement] = parameter;
+ }
+ }
+
+ TypeParameter current = parameter;
+ for (var step = 0; current != null; step++) {
+ var bound = current.bound;
+ if (bound is TypeName) {
+ current = elementToNode[bound.name.staticElement];
+ } else {
+ current = null;
+ }
+ if (step == parameters.length) {
+ var element = parameter.declaredElement;
+ _errorReporter.reportErrorForNode(
+ StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
+ parameter,
+ [element.displayName, element.bound.displayName],
+ );
+ break;
+ }
+ }
+ }
+ }
+ }
+
void _checkForTypeParameterReferencedByStatic(SimpleIdentifier identifier) {
if (_isInStaticMethod || _isInStaticVariableDeclaration) {
var element = identifier.staticElement;
@@ -4946,29 +4982,6 @@
}
/**
- * Check whether the given type [parameter] is a supertype of its bound.
- *
- * See [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND].
- */
- void _checkForTypeParameterSupertypeOfItsBound(TypeParameter parameter) {
- TypeParameterElement element = parameter.declaredElement;
- // prepare bound
- DartType bound = element.bound;
- if (bound == null) {
- return;
- }
- // OK, type parameter is not supertype of its bound
- if (!_typeSystem.isSubtypeOf(bound, element.type)) {
- return;
- }
-
- _errorReporter.reportErrorForNode(
- StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
- parameter,
- [element.displayName, bound.displayName]);
- }
-
- /**
* Check that if the given generative [constructor] has neither an explicit
* super constructor invocation nor a redirecting constructor invocation, that
* the superclass has a default generative constructor.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 66c7f6c..16c150d 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -344,6 +344,12 @@
}
@override
+ void visitFunctionTypeAlias(FunctionTypeAlias node) {
+ _checkStrictInferenceReturnType(node.returnType, node, node.name.name);
+ super.visitFunctionTypeAlias(node);
+ }
+
+ @override
void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
_checkStrictInferenceReturnType(
node.returnType, node, node.identifier.name);
@@ -352,6 +358,25 @@
}
@override
+ void visitGenericFunctionType(GenericFunctionType node) {
+ // GenericTypeAlias is handled in [visitGenericTypeAlias], where a proper
+ // name can be reported in any message.
+ if (node.parent is! GenericTypeAlias) {
+ _checkStrictInferenceReturnType(node.returnType, node, node.toString());
+ }
+ super.visitGenericFunctionType(node);
+ }
+
+ @override
+ void visitGenericTypeAlias(GenericTypeAlias node) {
+ if (node.functionType != null) {
+ _checkStrictInferenceReturnType(
+ node.functionType.returnType, node, node.name.name);
+ }
+ super.visitGenericTypeAlias(node);
+ }
+
+ @override
void visitImportDirective(ImportDirective node) {
_checkForDeprecatedMemberUse(node.uriElement, node);
ImportElement importElement = node.element;
@@ -384,6 +409,18 @@
void visitMethodDeclaration(MethodDeclaration node) {
bool wasInDeprecatedMember = _inDeprecatedMember;
ExecutableElement element = node.declaredElement;
+ bool elementIsOverride() {
+ if (element is ClassMemberElement) {
+ Name name = new Name(_currentLibrary.source.uri, element.name);
+ Element enclosingElement = element.enclosingElement;
+ if (enclosingElement is ClassElement) {
+ InterfaceType classType = enclosingElement.thisType;
+ return _inheritanceManager.getOverridden(classType, name) != null;
+ }
+ }
+ return false;
+ }
+
if (element != null && element.hasDeprecated) {
_inDeprecatedMember = true;
}
@@ -392,7 +429,9 @@
//checkForOverridingPrivateMember(node);
_checkForMissingReturn(node.returnType, node.body, element, node);
_checkForUnnecessaryNoSuchMethod(node);
- _checkStrictInferenceReturnType(node.returnType, node, node.name.name);
+ if (_strictInference && !node.isSetter && !elementIsOverride()) {
+ _checkStrictInferenceReturnType(node.returnType, node, node.name.name);
+ }
_checkStrictInferenceInParameters(node.parameters);
super.visitMethodDeclaration(node);
} finally {
@@ -2964,7 +3003,8 @@
const ResolverErrorCode(String name, String message,
{String correction, bool hasPublishedDocs})
: super.temporary(name, message,
- correction: correction, hasPublishedDocs: hasPublishedDocs);
+ correction: correction,
+ hasPublishedDocs: hasPublishedDocs ?? false);
@override
ErrorSeverity get errorSeverity => type.severity;
@@ -2983,6 +3023,11 @@
final AnalysisOptionsImpl _analysisOptions;
+ /**
+ * The feature set that is enabled for the current unit.
+ */
+ final FeatureSet _featureSet;
+
final bool _uiAsCodeEnabled;
/// Helper for extension method resolution.
@@ -3090,6 +3135,7 @@
reportConstEvaluationErrors,
this._flowAnalysis)
: _analysisOptions = definingLibrary.context.analysisOptions,
+ _featureSet = featureSet,
_uiAsCodeEnabled =
featureSet.isEnabled(Feature.control_flow_collections) ||
featureSet.isEnabled(Feature.spread_collections),
@@ -3125,6 +3171,17 @@
}
}
+ NullabilitySuffix get _noneOrStarSuffix {
+ return _nonNullableEnabled
+ ? NullabilitySuffix.none
+ : NullabilitySuffix.star;
+ }
+
+ /**
+ * Return `true` if NNBD is enabled for this compilation unit.
+ */
+ bool get _nonNullableEnabled => _featureSet.isEnabled(Feature.non_nullable);
+
/// Return the static element associated with the given expression whose type
/// can be overridden, or `null` if there is no element whose type can be
/// overridden.
@@ -3182,10 +3239,11 @@
// Same number of type formals. Instantiate the function type so its
// parameter and return type are in terms of the surrounding context.
- return fnType.instantiate(typeParameters
- .map((TypeParameter t) =>
- (t.name.staticElement as TypeParameterElement).type)
- .toList());
+ return fnType.instantiate(typeParameters.map((TypeParameter t) {
+ return t.declaredElement.instantiate(
+ nullabilitySuffix: _noneOrStarSuffix,
+ );
+ }).toList());
}
/// If it is appropriate to do so, override the current type of the static
@@ -3825,7 +3883,6 @@
// variable cannot be in scope while visiting the iterator.
//
iterable?.accept(this);
- _flowAnalysis?.loopVariable(loopVariable);
loopVariable?.accept(this);
_flowAnalysis?.flow?.forEach_bodyBegin(
_flowAnalysis.assignedVariables.writtenInNode(node),
@@ -3905,7 +3962,6 @@
// cannot be in scope while visiting the iterator.
//
iterable?.accept(this);
- _flowAnalysis?.loopVariable(loopVariable);
loopVariable?.accept(this);
_flowAnalysis?.flow?.forEach_bodyBegin(
@@ -4452,10 +4508,10 @@
var catchClause = catchClauses[i];
flow.tryCatchStatement_catchBegin();
if (catchClause.exceptionParameter != null) {
- flow.add(catchClause.exceptionParameter.staticElement, assigned: true);
+ flow.write(catchClause.exceptionParameter.staticElement);
}
if (catchClause.stackTraceParameter != null) {
- flow.add(catchClause.stackTraceParameter.staticElement, assigned: true);
+ flow.write(catchClause.stackTraceParameter.staticElement);
}
catchClause.accept(this);
flow.tryCatchStatement_catchEnd();
@@ -5835,6 +5891,10 @@
: dynamicType = typeProvider.dynamicType,
analysisOptions = definingLibrary.context.analysisOptions;
+ NullabilitySuffix get _noneOrStarSuffix {
+ return isNonNullableUnit ? NullabilitySuffix.none : NullabilitySuffix.star;
+ }
+
/// Report an error with the given error code and arguments.
///
/// @param errorCode the error code of the error to be reported
@@ -5995,8 +6055,10 @@
SimpleIdentifier identifier =
(typeName as PrefixedIdentifier).identifier;
Element prefixElement = nameScope.lookup(prefix, definingLibrary);
+ ClassElement classElement;
ConstructorElement constructorElement;
if (prefixElement is ClassElement) {
+ classElement = prefixElement;
constructorElement =
prefixElement.getNamedConstructor(identifier.name);
}
@@ -6006,10 +6068,16 @@
argumentList,
[prefix.name, identifier.name]);
prefix.staticElement = prefixElement;
- prefix.staticType = (prefixElement as ClassElement).type;
+ prefix.staticType = classElement.instantiate(
+ typeArguments: List.filled(
+ classElement.typeParameters.length,
+ dynamicType,
+ ),
+ nullabilitySuffix: _noneOrStarSuffix,
+ );
identifier.staticElement = constructorElement;
identifier.staticType = constructorElement.type;
- typeName.staticType = constructorElement.enclosingElement.type;
+ typeName.staticType = prefix.staticType;
AstNode grandParent = node.parent.parent;
if (grandParent is InstanceCreationExpressionImpl) {
grandParent.staticElement = constructorElement;
@@ -6056,7 +6124,7 @@
return;
}
- TypeImpl type = null;
+ DartType type = null;
if (element == DynamicElementImpl.instance) {
_setElement(typeName, element);
type = DynamicTypeImpl.instance;
@@ -6067,13 +6135,14 @@
);
} else if (element is FunctionTypeAliasElement) {
_setElement(typeName, element);
- type = element.type as TypeImpl;
} else if (element is TypeParameterElement) {
_setElement(typeName, element);
- type = element.type as TypeImpl;
+ type = element.instantiate(
+ nullabilitySuffix: _getNullability(node.question != null),
+ );
} else if (element is MultiplyDefinedElement) {
- List<Element> elements = element.conflictingElements;
- type = _getTypeWhenMultiplyDefined(elements) as TypeImpl;
+ var elements = (element as MultiplyDefinedElement).conflictingElements;
+ element = _getElementWhenMultiplyDefined(elements);
} else {
// The name does not represent a type.
if (_isTypeNameInCatchClause(node)) {
@@ -6116,9 +6185,15 @@
return;
}
if (argumentList != null) {
+ var parameters = const <TypeParameterElement>[];
+ if (element is ClassElement) {
+ parameters = element.typeParameters;
+ } else if (element is FunctionTypeAliasElement) {
+ parameters = element.typeParameters;
+ }
+
NodeList<TypeAnnotation> arguments = argumentList.arguments;
int argumentCount = arguments.length;
- List<DartType> parameters = typeSystem.typeFormalsAsTypes(type);
int parameterCount = parameters.length;
List<DartType> typeArguments = new List<DartType>(parameterCount);
if (argumentCount == parameterCount) {
@@ -6139,6 +6214,9 @@
} else {
type = typeSystem.instantiateType(type, typeArguments);
}
+ type = (type as TypeImpl).withNullability(
+ _getNullability(node.question != null),
+ );
} else {
if (element is GenericTypeAliasElementImpl) {
List<DartType> typeArguments =
@@ -6146,18 +6224,36 @@
type = GenericTypeAliasElementImpl.typeAfterSubstitution(
element, typeArguments) ??
dynamicType;
+ type = (type as TypeImpl).withNullability(
+ _getNullability(node.question != null),
+ );
} else {
type = typeSystem.instantiateToBounds(type);
}
}
- var nullability = _getNullability(node.question != null);
- type = type.withNullability(nullability);
-
typeName.staticType = type;
node.type = type;
}
+ /// Given the multiple elements to which a single name could potentially be
+ /// resolved, return the single [ClassElement] that should be used, or `null`
+ /// if there is no clear choice.
+ ///
+ /// @param elements the elements to which a single name could potentially be
+ /// resolved
+ /// @return the single interface type that should be used for the type name
+ ClassElement _getElementWhenMultiplyDefined(List<Element> elements) {
+ int length = elements.length;
+ for (int i = 0; i < length; i++) {
+ Element element = elements[i];
+ if (element is ClassElement) {
+ return element;
+ }
+ }
+ return null;
+ }
+
DartType _getInferredMixinType(
ClassElement classElement, ClassElement mixinElement) {
for (var candidateMixin in classElement.mixins) {
@@ -6229,28 +6325,6 @@
}
}
- /// Given the multiple elements to which a single name could potentially be
- /// resolved, return the single interface type that should be used, or `null`
- /// if there is no clear choice.
- ///
- /// @param elements the elements to which a single name could potentially be
- /// resolved
- /// @return the single interface type that should be used for the type name
- InterfaceType _getTypeWhenMultiplyDefined(List<Element> elements) {
- InterfaceType type = null;
- int length = elements.length;
- for (int i = 0; i < length; i++) {
- Element element = elements[i];
- if (element is ClassElement) {
- if (type != null) {
- return null;
- }
- type = element.type;
- }
- }
- return type;
- }
-
/// If the [node] is the type name in a redirected factory constructor,
/// infer type arguments using the enclosing class declaration. Return `null`
/// otherwise.
@@ -6814,13 +6888,6 @@
/// [nameScope] was computed.
bool _localModeScopeReady = false;
- /// Indicates whether the ClassElement fields interfaces, mixins, and
- /// supertype should be set by this visitor.
- ///
- /// This is needed when using the old task model, but causes problems with the
- /// new driver.
- final bool shouldSetElementSupertypes;
-
/// Initialize a newly created visitor to resolve the nodes in an AST node.
///
/// [definingLibrary] is the element for the library containing the node being
@@ -6843,8 +6910,7 @@
@Deprecated('Use featureSet instead') bool isNonNullableUnit: false,
FeatureSet featureSet,
this.mode: TypeResolverMode.everything,
- bool shouldUseWithClauseInferredTypes: true,
- this.shouldSetElementSupertypes: false})
+ bool shouldUseWithClauseInferredTypes: true})
: isNonNullableUnit = featureSet?.isEnabled(Feature.non_nullable) ??
// ignore: deprecated_member_use_from_same_package
isNonNullableUnit,
@@ -6939,22 +7005,11 @@
WithClause withClause = node.withClause;
ImplementsClause implementsClause = node.implementsClause;
ClassElementImpl classElement = _getClassElement(node.name);
- InterfaceType superclassType = null;
if (extendsClause != null) {
ErrorCode errorCode = (withClause == null
? CompileTimeErrorCode.EXTENDS_NON_CLASS
: CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS);
- superclassType =
- _resolveType(extendsClause.superclass, errorCode, asClass: true);
- }
- if (shouldSetElementSupertypes && classElement != null) {
- if (superclassType == null) {
- InterfaceType objectType = typeProvider.objectType;
- if (!identical(classElement.type, objectType)) {
- superclassType = objectType;
- }
- }
- classElement.supertype = superclassType;
+ _resolveType(extendsClause.superclass, errorCode, asClass: true);
}
_resolveWithClause(classElement, withClause);
_resolveImplementsClause(classElement, implementsClause);
@@ -6988,16 +7043,12 @@
@override
void visitClassTypeAlias(ClassTypeAlias node) {
super.visitClassTypeAlias(node);
- ErrorCode errorCode = CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS;
- InterfaceType superclassType =
- _resolveType(node.superclass, errorCode, asClass: true);
- if (superclassType == null) {
- superclassType = typeProvider.objectType;
- }
+ _resolveType(
+ node.superclass,
+ CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS,
+ asClass: true,
+ );
ClassElementImpl classElement = _getClassElement(node.name);
- if (shouldSetElementSupertypes && classElement != null) {
- classElement.supertype = superclassType;
- }
_resolveWithClause(classElement, node.withClause);
_resolveImplementsClause(classElement, node.implementsClause);
}
@@ -7437,27 +7488,20 @@
void _resolveImplementsClause(
ClassElementImpl classElement, ImplementsClause clause) {
if (clause != null) {
- NodeList<TypeName> interfaces = clause.interfaces;
- List<InterfaceType> interfaceTypes =
- _resolveTypes(interfaces, CompileTimeErrorCode.IMPLEMENTS_NON_CLASS);
- if (shouldSetElementSupertypes && classElement != null) {
- classElement.interfaces = interfaceTypes;
- }
+ _resolveTypes(
+ clause.interfaces, CompileTimeErrorCode.IMPLEMENTS_NON_CLASS);
}
}
void _resolveOnClause(MixinElementImpl classElement, OnClause clause) {
List<InterfaceType> types;
if (clause != null) {
- types = _resolveTypes(clause.superclassConstraints,
+ _resolveTypes(clause.superclassConstraints,
CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE);
}
if (types == null || types.isEmpty) {
types = [typeProvider.objectType];
}
- if (shouldSetElementSupertypes) {
- classElement.superclassConstraints = types;
- }
}
/// Return the [InterfaceType] of the given [typeName].
@@ -7467,7 +7511,7 @@
/// The flag [asClass] specifies if the type will be used as a class, so mixin
/// declarations are not valid (they declare interfaces and mixins, but not
/// classes).
- InterfaceType _resolveType(TypeName typeName, ErrorCode errorCode,
+ void _resolveType(TypeName typeName, ErrorCode errorCode,
{bool asClass: false}) {
DartType type = typeName.type;
if (type is InterfaceType) {
@@ -7475,10 +7519,10 @@
if (element != null) {
if (element.isEnum || element.isMixin && asClass) {
errorReporter.reportErrorForNode(errorCode, typeName);
- return null;
+ return;
}
}
- return type;
+ return;
}
// If the type is not an InterfaceType, then visitTypeName() sets the type
// to be a DynamicTypeImpl
@@ -7486,7 +7530,6 @@
if (!nameScope.shouldIgnoreUndefined(name)) {
errorReporter.reportErrorForNode(errorCode, name, [name.name]);
}
- return null;
}
/// Resolve the types in the given list of type names.
@@ -7498,25 +7541,15 @@
/// be an enum
/// @param dynamicTypeError the error to produce if the type name is "dynamic"
/// @return an array containing all of the types that were resolved.
- List<InterfaceType> _resolveTypes(
- NodeList<TypeName> typeNames, ErrorCode errorCode) {
- List<InterfaceType> types = new List<InterfaceType>();
+ void _resolveTypes(NodeList<TypeName> typeNames, ErrorCode errorCode) {
for (TypeName typeName in typeNames) {
- InterfaceType type = _resolveType(typeName, errorCode);
- if (type != null) {
- types.add(type);
- }
+ _resolveType(typeName, errorCode);
}
- return types;
}
void _resolveWithClause(ClassElementImpl classElement, WithClause clause) {
if (clause != null) {
- List<InterfaceType> mixinTypes = _resolveTypes(
- clause.mixinTypes, CompileTimeErrorCode.MIXIN_OF_NON_CLASS);
- if (shouldSetElementSupertypes) {
- classElement.mixins = mixinTypes;
- }
+ _resolveTypes(clause.mixinTypes, CompileTimeErrorCode.MIXIN_OF_NON_CLASS);
}
}
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 1263674..e8108bb 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -9,7 +9,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/analysis/driver.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;
@@ -2177,12 +2176,8 @@
static DartType _getFreshType(DartType type) {
if (type is FunctionType) {
- if (AnalysisDriver.useSummary2) {
- var parameters = getFreshTypeParameters(type.typeFormals);
- return parameters.applyToFunctionType(type);
- } else {
- return new FunctionTypeImpl.fresh(type);
- }
+ var parameters = getFreshTypeParameters(type.typeFormals);
+ return parameters.applyToFunctionType(type);
} else {
return type;
}
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 5f384f0..7a84adf 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -13,7 +13,6 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_system.dart' as public;
import 'package:analyzer/error/listener.dart' show ErrorReporter;
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember;
import 'package:analyzer/src/dart/element/type.dart';
@@ -379,15 +378,13 @@
parameters ??= <TypeParameterElement>[];
parameters.add(element);
}
- } else if (AnalysisDriver.useSummary2) {
+ } else {
if (type is FunctionType) {
appendParameters(type.returnType);
type.parameters.map((p) => p.type).forEach(appendParameters);
} else if (type is InterfaceType) {
type.typeArguments.forEach(appendParameters);
}
- } else if (type is ParameterizedType) {
- type.typeArguments.forEach(appendParameters);
}
}
@@ -461,13 +458,9 @@
return const <DartType>[];
}
- if (AnalysisDriver.useSummary2) {
- return typeParameters
- .map((p) => (p as TypeParameterElementImpl).defaultType)
- .toList();
- } else {
- return instantiateTypeFormalsToBounds(typeParameters);
- }
+ return typeParameters
+ .map((p) => (p as TypeParameterElementImpl).defaultType)
+ .toList();
}
@override
@@ -2141,7 +2134,7 @@
static int _computeLongestInheritancePathToObject(
ClassElement element, int depth, Set<ClassElement> visitedElements) {
// Object case
- if (element.supertype == null || visitedElements.contains(element)) {
+ if (element.isDartCoreObject || visitedElements.contains(element)) {
return depth;
}
int longestPath = 1;
@@ -2790,13 +2783,7 @@
// Calculate the LUB of the return type.
DartType returnType = getLeastUpperBound(f.returnType, g.returnType);
- if (AnalysisDriver.useSummary2) {
- return FunctionTypeImpl.synthetic(returnType, typeFormals, parameters);
- }
-
- var element = FunctionElementImpl.synthetic(parameters, returnType);
- element.typeParameters = typeFormals;
- return element.type;
+ return FunctionTypeImpl.synthetic(returnType, typeFormals, parameters);
}
/**
diff --git a/pkg/analyzer/lib/src/summary/expr_builder.dart b/pkg/analyzer/lib/src/summary/expr_builder.dart
deleted file mode 100644
index ed9493b..0000000
--- a/pkg/analyzer/lib/src/summary/expr_builder.dart
+++ /dev/null
@@ -1,1127 +0,0 @@
-// Copyright (c) 2018, 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/standard_ast_factory.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/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/resolver/ast_rewrite.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/testing/token_factory.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/resynthesize.dart';
-
-bool _isSpreadOrControlFlowEnabled(ExperimentStatus experimentStatus) =>
- experimentStatus.spread_collections ||
- experimentStatus.control_flow_collections;
-
-/**
- * Builder of [Expression]s from [UnlinkedExpr]s.
- */
-class ExprBuilder {
- static const ARGUMENT_LIST = 'ARGUMENT_LIST';
-
- final UnitResynthesizer resynthesizer;
- final ElementImpl context;
- final UnlinkedExpr _uc;
- final bool requireValidConst;
- final bool isSpreadOrControlFlowEnabled;
- final bool becomeSetOrMap;
-
- int intPtr = 0;
- int doublePtr = 0;
- int stringPtr = 0;
- int refPtr = 0;
- int assignmentOperatorPtr = 0;
-
- // The stack of values. Note that they are usually [Expression]s, but may be
- // any [CollectionElement] to support map/set/list literals.
- final List<AstNode> stack = <AstNode>[];
-
- final List<UnlinkedExecutable> localFunctions;
-
- final _VariablesInScope variablesInScope;
-
- ExprBuilder(
- this.resynthesizer,
- this.context,
- this._uc, {
- this.requireValidConst: true,
- this.localFunctions,
- _VariablesInScope variablesInScope,
- this.becomeSetOrMap: true,
- }) : this.variablesInScope = variablesInScope ?? _parametersInScope(context),
- this.isSpreadOrControlFlowEnabled = _isSpreadOrControlFlowEnabled(
- (resynthesizer.library.context.analysisOptions
- as AnalysisOptionsImpl)
- .experimentStatus);
-
- bool get hasNonEmptyExpr => _uc != null && _uc.operations.isNotEmpty;
-
- Expression build() {
- if (requireValidConst && !_uc.isValidConst) {
- return null;
- }
- int startingVariableCount = variablesInScope.count;
- for (UnlinkedExprOperation operation in _uc.operations) {
- switch (operation) {
- case UnlinkedExprOperation.pushNull:
- _push(AstTestFactory.nullLiteral());
- break;
- // bool
- case UnlinkedExprOperation.pushFalse:
- _push(AstTestFactory.booleanLiteral(false));
- break;
- case UnlinkedExprOperation.pushTrue:
- _push(AstTestFactory.booleanLiteral(true));
- break;
- // literals
- case UnlinkedExprOperation.pushInt:
- int value = _uc.ints[intPtr++];
- _push(AstTestFactory.integer(value));
- break;
- case UnlinkedExprOperation.pushLongInt:
- int value = 0;
- int count = _uc.ints[intPtr++];
- for (int i = 0; i < count; i++) {
- int next = _uc.ints[intPtr++];
- value = value << 32 | next;
- }
- _push(AstTestFactory.integer(value));
- break;
- case UnlinkedExprOperation.pushDouble:
- double value = _uc.doubles[doublePtr++];
- _push(AstTestFactory.doubleLiteral(value));
- break;
- case UnlinkedExprOperation.makeSymbol:
- String component = _uc.strings[stringPtr++];
- _push(AstTestFactory.symbolLiteral([component]));
- break;
- // String
- case UnlinkedExprOperation.pushString:
- String value = _uc.strings[stringPtr++];
- _push(AstTestFactory.string2(value));
- break;
- case UnlinkedExprOperation.concatenate:
- int count = _uc.ints[intPtr++];
- List<InterpolationElement> elements = <InterpolationElement>[];
- for (int i = 0; i < count; i++) {
- Expression expr = _pop();
- InterpolationElement element = _newInterpolationElement(expr);
- elements.insert(0, element);
- }
- _push(AstTestFactory.string(elements));
- break;
- // binary
- case UnlinkedExprOperation.equal:
- _pushBinary(TokenType.EQ_EQ);
- break;
- case UnlinkedExprOperation.notEqual:
- _pushBinary(TokenType.BANG_EQ);
- break;
- case UnlinkedExprOperation.and:
- _pushBinary(TokenType.AMPERSAND_AMPERSAND);
- break;
- case UnlinkedExprOperation.or:
- _pushBinary(TokenType.BAR_BAR);
- break;
- case UnlinkedExprOperation.bitXor:
- _pushBinary(TokenType.CARET);
- break;
- case UnlinkedExprOperation.bitAnd:
- _pushBinary(TokenType.AMPERSAND);
- break;
- case UnlinkedExprOperation.bitOr:
- _pushBinary(TokenType.BAR);
- break;
- case UnlinkedExprOperation.bitShiftLeft:
- _pushBinary(TokenType.LT_LT);
- break;
- case UnlinkedExprOperation.bitShiftRight:
- _pushBinary(TokenType.GT_GT);
- break;
- case UnlinkedExprOperation.bitShiftRightLogical:
- _pushBinary(TokenType.GT_GT_GT);
- break;
- case UnlinkedExprOperation.add:
- _pushBinary(TokenType.PLUS);
- break;
- case UnlinkedExprOperation.subtract:
- _pushBinary(TokenType.MINUS);
- break;
- case UnlinkedExprOperation.multiply:
- _pushBinary(TokenType.STAR);
- break;
- case UnlinkedExprOperation.divide:
- _pushBinary(TokenType.SLASH);
- break;
- case UnlinkedExprOperation.floorDivide:
- _pushBinary(TokenType.TILDE_SLASH);
- break;
- case UnlinkedExprOperation.modulo:
- _pushBinary(TokenType.PERCENT);
- break;
- case UnlinkedExprOperation.greater:
- _pushBinary(TokenType.GT);
- break;
- case UnlinkedExprOperation.greaterEqual:
- _pushBinary(TokenType.GT_EQ);
- break;
- case UnlinkedExprOperation.less:
- _pushBinary(TokenType.LT);
- break;
- case UnlinkedExprOperation.lessEqual:
- _pushBinary(TokenType.LT_EQ);
- break;
- // prefix
- case UnlinkedExprOperation.complement:
- _pushPrefix(TokenType.TILDE);
- break;
- case UnlinkedExprOperation.negate:
- _pushPrefix(TokenType.MINUS);
- break;
- case UnlinkedExprOperation.not:
- _pushPrefix(TokenType.BANG);
- break;
- // conditional
- case UnlinkedExprOperation.conditional:
- Expression elseExpr = _pop();
- Expression thenExpr = _pop();
- Expression condition = _pop();
- _push(AstTestFactory.conditionalExpression(
- condition, thenExpr, elseExpr));
- break;
- case UnlinkedExprOperation.invokeMethodRef:
- _pushInvokeMethodRef();
- break;
- case UnlinkedExprOperation.invokeMethod:
- List<Expression> arguments = _buildArguments();
- TypeArgumentList typeArguments = _buildTypeArguments();
- Expression target = _pop();
- String name = _uc.strings[stringPtr++];
- _push(AstTestFactory.methodInvocation3(
- target, name, typeArguments, arguments));
- break;
- // containers
- case UnlinkedExprOperation.makeUntypedList:
- _pushList(null);
- break;
- case UnlinkedExprOperation.makeTypedList:
- TypeAnnotation itemType = _newTypeName();
- _pushList(
- AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType]));
- break;
- case UnlinkedExprOperation.makeUntypedSetOrMap:
- _pushSetOrMap(null);
- break;
- case UnlinkedExprOperation.makeUntypedMap:
- _pushMap(null);
- break;
- case UnlinkedExprOperation.makeTypedMap:
- TypeAnnotation keyType = _newTypeName();
- TypeAnnotation valueType = _newTypeName();
- _pushMap(AstTestFactory.typeArgumentList(
- <TypeAnnotation>[keyType, valueType]));
- break;
- case UnlinkedExprOperation.makeMapLiteralEntry:
- _pushMapLiteralEntry();
- break;
- case UnlinkedExprOperation.makeTypedMap2:
- TypeAnnotation keyType = _newTypeName();
- TypeAnnotation valueType = _newTypeName();
- _pushSetOrMap(AstTestFactory.typeArgumentList(
- <TypeAnnotation>[keyType, valueType]));
- break;
- case UnlinkedExprOperation.makeUntypedSet:
- _pushSet(null);
- break;
- case UnlinkedExprOperation.makeTypedSet:
- TypeAnnotation itemType = _newTypeName();
- if (isSpreadOrControlFlowEnabled) {
- _pushSetOrMap(
- AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType]));
- } else {
- _pushSet(
- AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType]));
- }
- break;
- case UnlinkedExprOperation.pushReference:
- _pushReference();
- break;
- case UnlinkedExprOperation.extractProperty:
- _pushExtractProperty();
- break;
- case UnlinkedExprOperation.invokeConstructor:
- _pushInstanceCreation();
- break;
- case UnlinkedExprOperation.pushParameter:
- String name = _uc.strings[stringPtr++];
- SimpleIdentifier identifier = AstTestFactory.identifier3(name);
- identifier.staticElement = variablesInScope[name];
- _push(identifier);
- break;
- case UnlinkedExprOperation.ifNull:
- _pushBinary(TokenType.QUESTION_QUESTION);
- break;
- case UnlinkedExprOperation.await:
- Expression expression = _pop();
- _push(AstTestFactory.awaitExpression(expression));
- break;
- case UnlinkedExprOperation.pushLocalFunctionReference:
- _pushLocalFunctionReference();
- break;
- case UnlinkedExprOperation.assignToRef:
- var ref = _createReference();
- _push(_createAssignment(ref));
- break;
- case UnlinkedExprOperation.typeCast:
- Expression expression = _pop();
- TypeAnnotation type = _newTypeName();
- _push(AstTestFactory.asExpression(expression, type));
- break;
- case UnlinkedExprOperation.typeCheck:
- Expression expression = _pop();
- TypeAnnotation type = _newTypeName();
- _push(AstTestFactory.isExpression(expression, false, type));
- break;
- case UnlinkedExprOperation.throwException:
- Expression expression = _pop();
- _push(AstTestFactory.throwExpression2(expression));
- break;
- case UnlinkedExprOperation.assignToProperty:
- Expression target = _pop();
- String name = _uc.strings[stringPtr++];
- SimpleIdentifier propertyNode = AstTestFactory.identifier3(name);
- PropertyAccess propertyAccess =
- AstTestFactory.propertyAccess(target, propertyNode);
- _push(_createAssignment(propertyAccess));
- break;
- case UnlinkedExprOperation.assignToIndex:
- Expression index = _pop();
- Expression target = _pop();
- IndexExpression indexExpression =
- AstTestFactory.indexExpression(target, index);
- _push(_createAssignment(indexExpression));
- break;
- case UnlinkedExprOperation.extractIndex:
- Expression index = _pop();
- Expression target = _pop();
- _push(AstTestFactory.indexExpression(target, index));
- break;
- case UnlinkedExprOperation.pushSuper:
- _push(AstTestFactory.superExpression());
- break;
- case UnlinkedExprOperation.pushThis:
- _push(AstTestFactory.thisExpression());
- break;
- case UnlinkedExprOperation.spreadElement:
- _pushSpread(TokenType.PERIOD_PERIOD_PERIOD);
- break;
- case UnlinkedExprOperation.nullAwareSpreadElement:
- _pushSpread(TokenType.PERIOD_PERIOD_PERIOD_QUESTION);
- break;
- case UnlinkedExprOperation.ifElement:
- _pushIfElement(false);
- break;
- case UnlinkedExprOperation.ifElseElement:
- _pushIfElement(true);
- break;
- case UnlinkedExprOperation.forParts:
- _pushForParts();
- break;
- case UnlinkedExprOperation.forElement:
- _pushForElement(false);
- break;
- case UnlinkedExprOperation.forElementWithAwait:
- _pushForElement(true);
- break;
- case UnlinkedExprOperation.pushEmptyExpression:
- _push(null);
- break;
- case UnlinkedExprOperation.variableDeclarationStart:
- _variableDeclarationStart();
- break;
- case UnlinkedExprOperation.variableDeclaration:
- _variableDeclaration();
- break;
- case UnlinkedExprOperation.forInitializerDeclarationsUntyped:
- _forInitializerDeclarations(false);
- break;
- case UnlinkedExprOperation.forInitializerDeclarationsTyped:
- _forInitializerDeclarations(true);
- break;
- case UnlinkedExprOperation.assignToParameter:
- String name = _uc.strings[stringPtr++];
- SimpleIdentifier identifier = AstTestFactory.identifier3(name);
- identifier.staticElement = variablesInScope[name];
- _push(_createAssignment(identifier));
- break;
- case UnlinkedExprOperation.forEachPartsWithIdentifier:
- _forEachPartsWithIdentifier();
- break;
- case UnlinkedExprOperation.forEachPartsWithUntypedDeclaration:
- _forEachPartsWithDeclaration(false);
- break;
- case UnlinkedExprOperation.forEachPartsWithTypedDeclaration:
- _forEachPartsWithDeclaration(true);
- break;
- case UnlinkedExprOperation.cascadeSectionBegin:
- case UnlinkedExprOperation.cascadeSectionEnd:
- case UnlinkedExprOperation.pushLocalFunctionReference:
- case UnlinkedExprOperation.pushError:
- case UnlinkedExprOperation.pushTypedAbstract:
- case UnlinkedExprOperation.pushUntypedAbstract:
- throw new UnimplementedError(
- 'Unexpected $operation in a constant expression.');
- }
- }
- assert(startingVariableCount == variablesInScope.count);
- return stack.single;
- }
-
- List<Expression> _buildArguments() {
- List<Expression> arguments;
- {
- int numNamedArgs = _uc.ints[intPtr++];
- int numPositionalArgs = _uc.ints[intPtr++];
- int numArgs = numNamedArgs + numPositionalArgs;
- arguments = _removeTopExpressions(numArgs);
- // add names to the named arguments
- for (int i = 0; i < numNamedArgs; i++) {
- String name = _uc.strings[stringPtr++];
- int index = numPositionalArgs + i;
- arguments[index] =
- AstTestFactory.namedExpression2(name, arguments[index]);
- }
- }
- return arguments;
- }
-
- /// Given the sequence of identifiers in [node], and the [classElement] or
- /// [constructorElement] to which this sequence resolves, build the
- /// [InstanceCreationExpression].
- InstanceCreationExpression _buildCreation(
- Expression node,
- TypeArgumentList typeArguments,
- ArgumentList argumentList, {
- ClassElement classElement,
- ConstructorElement constructorElement,
- }) {
- InstanceCreationExpression composeCreation(
- DartType type,
- ConstructorName constructorName,
- ConstructorElement constructorElement,
- ArgumentList argumentList) {
- TypeName typeName = constructorName.type;
- typeName.type = type;
-
- constructorName.name?.staticElement = constructorElement;
-
- var creation = astFactory.instanceCreationExpression(
- _uc.isValidConst
- ? TokenFactory.tokenFromKeyword(Keyword.CONST)
- : TokenFactory.tokenFromKeyword(Keyword.NEW),
- constructorName,
- argumentList);
-
- creation.staticElement = constructorElement;
- creation.staticType = type;
- return creation;
- }
-
- classElement ??= constructorElement?.enclosingElement;
- var type = AstRewriteVisitor.getType(
- resynthesizer.typeSystem, classElement, typeArguments);
-
- // C()
- if (node is SimpleIdentifier && classElement != null) {
- constructorElement = type.lookUpConstructor('', resynthesizer.library);
- node.staticType = type;
- return composeCreation(
- type,
- astFactory.constructorName(
- astFactory.typeName(node, typeArguments),
- null,
- null,
- ),
- constructorElement,
- argumentList,
- );
- }
- if (node is PrefixedIdentifier) {
- // C.n()
- if (constructorElement != null) {
- constructorElement =
- type.lookUpConstructor(node.identifier.name, resynthesizer.library);
- node.prefix.staticType = type;
- return composeCreation(
- type,
- astFactory.constructorName(
- astFactory.typeName(node.prefix, typeArguments),
- TokenFactory.tokenFromType(TokenType.PERIOD),
- node.identifier,
- ),
- constructorElement,
- argumentList,
- );
- }
- // p.C()
- if (classElement != null) {
- constructorElement = type.lookUpConstructor('', resynthesizer.library);
- node.identifier.staticType = type;
- return composeCreation(
- type,
- astFactory.constructorName(
- astFactory.typeName(node.identifier, typeArguments),
- null,
- null,
- ),
- constructorElement,
- argumentList,
- );
- }
- }
- // p.C.n()
- if (node is PropertyAccess && constructorElement != null) {
- constructorElement =
- type.lookUpConstructor(node.propertyName.name, resynthesizer.library);
- var typeIdentifier = (node.target as PrefixedIdentifier).identifier;
- typeIdentifier.staticType = type;
- return composeCreation(
- type,
- astFactory.constructorName(
- astFactory.typeName(typeIdentifier, typeArguments),
- TokenFactory.tokenFromType(TokenType.PERIOD),
- node.propertyName,
- ),
- constructorElement,
- argumentList,
- );
- }
-
- throw new UnimplementedError('For ${node?.runtimeType}: $node; '
- 'class: $classElement; constructor: $constructorElement');
- }
-
- /**
- * Build the identifier sequence (a single or prefixed identifier, or a
- * property access) corresponding to the given reference [info].
- */
- Expression _buildIdentifierSequence(ReferenceInfo info) {
- Expression enclosing;
- if (info.enclosing != null) {
- enclosing = _buildIdentifierSequence(info.enclosing);
- }
- Element element = info.element;
- if (element == null && info.name == 'length') {
- element = _getStringLengthElement();
- }
- if (enclosing == null) {
- return AstTestFactory.identifier3(info.name)..staticElement = element;
- }
- if (enclosing is SimpleIdentifier) {
- SimpleIdentifier identifier = AstTestFactory.identifier3(info.name)
- ..staticElement = element;
- return AstTestFactory.identifier(enclosing, identifier);
- }
- SimpleIdentifier property = AstTestFactory.identifier3(info.name)
- ..staticElement = element;
- return AstTestFactory.propertyAccess(enclosing, property);
- }
-
- TypeArgumentList _buildTypeArguments() {
- int numTypeArguments = _uc.ints[intPtr++];
- if (numTypeArguments == 0) {
- return null;
- }
-
- var typeNames = new List<TypeAnnotation>(numTypeArguments);
- for (int i = 0; i < numTypeArguments; i++) {
- typeNames[i] = _newTypeName();
- }
- return AstTestFactory.typeArgumentList(typeNames);
- }
-
- TypeAnnotation _buildTypeAst(DartType type) {
- List<TypeAnnotation> argumentNodes;
- if (type is ParameterizedType) {
- if (!resynthesizer.doesTypeHaveImplicitArguments(type)) {
- List<DartType> typeArguments = type.typeArguments;
- argumentNodes = typeArguments.every((a) => a.isDynamic)
- ? null
- : typeArguments.map(_buildTypeAst).toList();
- }
- }
- TypeName node = AstTestFactory.typeName4(type.name, argumentNodes);
- node.type = type;
- (node.name as SimpleIdentifier).staticElement = type.element;
- return node;
- }
-
- Expression _createAssignment(Expression lhs) {
- Expression binary(TokenType tokenType) {
- return AstTestFactory.assignmentExpression(lhs, tokenType, _pop());
- }
-
- Expression prefix(TokenType tokenType) {
- return AstTestFactory.prefixExpression(tokenType, lhs);
- }
-
- Expression postfix(TokenType tokenType) {
- return AstTestFactory.postfixExpression(lhs, tokenType);
- }
-
- switch (_uc.assignmentOperators[assignmentOperatorPtr++]) {
- case UnlinkedExprAssignOperator.assign:
- return binary(TokenType.EQ);
- case UnlinkedExprAssignOperator.ifNull:
- return binary(TokenType.QUESTION_QUESTION_EQ);
- case UnlinkedExprAssignOperator.multiply:
- return binary(TokenType.STAR_EQ);
- case UnlinkedExprAssignOperator.divide:
- return binary(TokenType.SLASH_EQ);
- case UnlinkedExprAssignOperator.floorDivide:
- return binary(TokenType.TILDE_SLASH_EQ);
- case UnlinkedExprAssignOperator.modulo:
- return binary(TokenType.PERCENT_EQ);
- case UnlinkedExprAssignOperator.plus:
- return binary(TokenType.PLUS_EQ);
- case UnlinkedExprAssignOperator.minus:
- return binary(TokenType.MINUS_EQ);
- case UnlinkedExprAssignOperator.shiftLeft:
- return binary(TokenType.LT_LT_EQ);
- case UnlinkedExprAssignOperator.shiftRight:
- return binary(TokenType.GT_GT_EQ);
- case UnlinkedExprAssignOperator.bitAnd:
- return binary(TokenType.AMPERSAND_EQ);
- case UnlinkedExprAssignOperator.bitXor:
- return binary(TokenType.CARET_EQ);
- case UnlinkedExprAssignOperator.bitOr:
- return binary(TokenType.BAR_EQ);
- case UnlinkedExprAssignOperator.prefixIncrement:
- return prefix(TokenType.PLUS_PLUS);
- case UnlinkedExprAssignOperator.prefixDecrement:
- return prefix(TokenType.MINUS_MINUS);
- case UnlinkedExprAssignOperator.postfixIncrement:
- return postfix(TokenType.PLUS_PLUS);
- case UnlinkedExprAssignOperator.postfixDecrement:
- return postfix(TokenType.MINUS_MINUS);
- default:
- throw new UnimplementedError('Unexpected UnlinkedExprAssignOperator');
- }
- }
-
- Expression _createReference() {
- EntityRef ref = _uc.references[refPtr++];
- if (ref.paramReference != 0) {
- // This is a reference to a type parameter. For type inference purposes
- // we don't actually need to know which type parameter it's a reference
- // to; we just need to know that it represents a type. So map it to
- // `Object`.
- return AstTestFactory.identifier3('Object')
- ..staticElement = resynthesizer.typeProvider.objectType.element;
- }
- ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
- return _buildIdentifierSequence(info);
- }
-
- void _forEachPartsWithDeclaration(bool hasType) {
- var iterable = _pop();
- var name = _uc.strings[stringPtr++];
- var element = LocalVariableElementImpl(name, -1);
- var keyword = hasType ? null : Keyword.VAR;
- var type = hasType ? _newTypeName() : null;
- var loopVariable = AstTestFactory.declaredIdentifier2(keyword, type, name);
- loopVariable.identifier.staticElement = element;
- if (hasType) {
- element.type = type.type;
- }
- _pushNode(
- AstTestFactory.forEachPartsWithDeclaration(loopVariable, iterable));
- variablesInScope.push(element);
- }
-
- void _forEachPartsWithIdentifier() {
- var iterable = _pop();
- SimpleIdentifier identifier = _pop();
- _pushNode(AstTestFactory.forEachPartsWithIdentifier(identifier, iterable));
- }
-
- void _forInitializerDeclarations(bool hasType) {
- var count = _uc.ints[intPtr++];
- var variables = List<VariableDeclaration>.filled(count, null);
- for (int i = 0; i < count; i++) {
- variables[count - 1 - i] = _popNode();
- }
- var type = hasType ? _newTypeName() : null;
- var keyword = hasType ? null : Keyword.VAR;
- _pushNode(AstTestFactory.variableDeclarationList(keyword, type, variables));
- }
-
- PropertyAccessorElement _getStringLengthElement() =>
- resynthesizer.typeProvider.stringType.getGetter('length');
-
- FormalParameter _makeParameter(ParameterElement param) {
- SimpleFormalParameterImpl simpleParam =
- AstTestFactory.simpleFormalParameter(null, param.name);
- simpleParam.identifier.staticElement = param;
- simpleParam.declaredElement = param;
- var unlinkedParam = (param as ParameterElementImpl).unlinkedParam;
- if (unlinkedParam.kind == UnlinkedParamKind.optionalPositional) {
- return AstTestFactory.positionalFormalParameter(simpleParam, null);
- } else if (unlinkedParam.kind == UnlinkedParamKind.requiredNamed ||
- unlinkedParam.kind == UnlinkedParamKind.optionalNamed) {
- return AstTestFactory.namedFormalParameter(simpleParam, null);
- } else {
- return simpleParam;
- }
- }
-
- InterpolationElement _newInterpolationElement(Expression expr) {
- if (expr is SimpleStringLiteral) {
- return astFactory.interpolationString(expr.literal, expr.value);
- } else {
- return astFactory.interpolationExpression(
- TokenFactory.tokenFromType(TokenType.STRING_INTERPOLATION_EXPRESSION),
- expr,
- TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
- }
- }
-
- /**
- * Convert the next reference to the [DartType] and return the AST
- * corresponding to this type.
- */
- TypeAnnotation _newTypeName() {
- EntityRef typeRef = _uc.references[refPtr++];
- DartType type = resynthesizer.buildType(context, typeRef);
- return _buildTypeAst(type);
- }
-
- Expression _pop() => stack.removeLast() as Expression;
-
- CollectionElement _popCollectionElement() =>
- stack.removeLast() as CollectionElement;
-
- AstNode _popNode() => stack.removeLast();
-
- void _push(Expression expr) {
- stack.add(expr);
- }
-
- void _pushBinary(TokenType operator) {
- Expression right = _pop();
- Expression left = _pop();
- _push(AstTestFactory.binaryExpression(left, operator, right));
- }
-
- void _pushCollectionElement(CollectionElement collectionElement) {
- stack.add(collectionElement);
- }
-
- void _pushExtractProperty() {
- Expression target = _pop();
- String name = _uc.strings[stringPtr++];
- SimpleIdentifier propertyNode = AstTestFactory.identifier3(name);
- // Only String.length property access can be potentially resolved.
- if (name == 'length') {
- propertyNode.staticElement = _getStringLengthElement();
- }
- _push(AstTestFactory.propertyAccess(target, propertyNode));
- }
-
- void _pushForElement(bool hasAwait) {
- var body = _popCollectionElement();
- var forLoopParts = _popNode() as ForLoopParts;
- if (forLoopParts is ForPartsWithDeclarations) {
- variablesInScope.pop(forLoopParts.variables.variables.length);
- } else if (forLoopParts is ForEachPartsWithDeclaration) {
- variablesInScope.pop(1);
- }
- _pushCollectionElement(
- AstTestFactory.forElement(forLoopParts, body, hasAwait: hasAwait));
- }
-
- void _pushForParts() {
- var updaterCount = _uc.ints[intPtr++];
- var updaters = <Expression>[];
- for (int i = 0; i < updaterCount; i++) {
- updaters.insert(0, _pop());
- }
- Expression condition = _pop();
- AstNode initialization = _popNode();
- if (initialization is Expression || initialization == null) {
- _pushNode(AstTestFactory.forPartsWithExpression(
- initialization, condition, updaters));
- } else if (initialization is VariableDeclarationList) {
- _pushNode(AstTestFactory.forPartsWithDeclarations(
- initialization, condition, updaters));
- } else {
- throw StateError('Unrecognized for parts');
- }
- }
-
- void _pushIfElement(bool hasElse) {
- CollectionElement elseElement = hasElse ? _popCollectionElement() : null;
- CollectionElement thenElement = _popCollectionElement();
- Expression condition = _pop();
- _pushCollectionElement(
- AstTestFactory.ifElement(condition, thenElement, elseElement));
- }
-
- void _pushInstanceCreation() {
- EntityRef ref = _uc.references[refPtr++];
- ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
- // prepare ConstructorElement
- TypeName typeNode;
- String constructorName;
- ConstructorElement constructorElement;
- if (info.element != null) {
- if (info.element is ConstructorElement) {
- constructorName = info.name;
- } else if (info.element is ClassElement) {
- constructorName = null;
- } else {
- // Unexpected element, consider it unresolved.
- _buildArguments();
- var identifier = AstTestFactory.identifier3('__unresolved__')
- ..staticType = resynthesizer.typeProvider.dynamicType;
- _push(identifier);
- return;
- }
- InterfaceType definingType = resynthesizer.createConstructorDefiningType(
- context, info, ref.typeArguments);
- constructorElement =
- resynthesizer.getConstructorForInfo(definingType, info);
- typeNode = _buildTypeAst(definingType);
- } else {
- if (info.enclosing != null) {
- if (info.enclosing.enclosing != null) {
- PrefixedIdentifier typeName = AstTestFactory.identifier5(
- info.enclosing.enclosing.name, info.enclosing.name);
- typeName.prefix.staticElement = info.enclosing.enclosing.element;
- typeName.identifier.staticElement = info.enclosing.element;
- typeName.identifier.staticType = info.enclosing.type;
- typeNode = AstTestFactory.typeName3(typeName);
- typeNode.type = info.enclosing.type;
- constructorName = info.name;
- } else if (info.enclosing.element != null) {
- SimpleIdentifier typeName =
- AstTestFactory.identifier3(info.enclosing.name);
- typeName.staticElement = info.enclosing.element;
- typeName.staticType = info.enclosing.type;
- typeNode = AstTestFactory.typeName3(typeName);
- typeNode.type = info.enclosing.type;
- constructorName = info.name;
- } else {
- typeNode = AstTestFactory.typeName3(
- AstTestFactory.identifier5(info.enclosing.name, info.name));
- constructorName = null;
- }
- } else {
- typeNode = AstTestFactory.typeName4(info.name);
- }
- }
- // prepare arguments
- List<Expression> arguments = _buildArguments();
- // create ConstructorName
- ConstructorName constructorNode;
- if (constructorName != null) {
- constructorNode =
- AstTestFactory.constructorName(typeNode, constructorName);
- constructorNode.name.staticElement = constructorElement;
- } else {
- constructorNode = AstTestFactory.constructorName(typeNode, null);
- }
- constructorNode.staticElement = constructorElement;
- // create InstanceCreationExpression
- InstanceCreationExpression instanceCreation =
- AstTestFactory.instanceCreationExpression(
- requireValidConst ? Keyword.CONST : Keyword.NEW,
- constructorNode,
- arguments);
- instanceCreation.staticElement = constructorElement;
- _push(instanceCreation);
- }
-
- void _pushInvokeMethodRef() {
- List<Expression> arguments = _buildArguments();
- EntityRef ref = _uc.references[refPtr++];
- ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
- Expression node = _buildIdentifierSequence(info);
- TypeArgumentList typeArguments = _buildTypeArguments();
- var period = TokenFactory.tokenFromType(TokenType.PERIOD);
- var argumentList = AstTestFactory.argumentList(arguments);
-
- // Check for optional new/const.
- if (info.element is ClassElement) {
- _push(_buildCreation(node, typeArguments, argumentList,
- classElement: info.element));
- return;
- }
- if (info.element is ConstructorElement) {
- _push(_buildCreation(node, typeArguments, argumentList,
- constructorElement: info.element));
- return;
- }
-
- if (node is SimpleIdentifier) {
- _push(astFactory.methodInvocation(
- null, period, node, typeArguments, argumentList));
- } else if (node is PropertyAccess) {
- _push(astFactory.methodInvocation(
- node.target, period, node.propertyName, typeArguments, argumentList));
- } else if (node is PrefixedIdentifier) {
- _push(astFactory.methodInvocation(
- node.prefix, period, node.identifier, typeArguments, argumentList));
- } else {
- throw new UnimplementedError('For ${node?.runtimeType}: $node');
- }
- }
-
- void _pushList(TypeArgumentList typeArguments) {
- int count = _uc.ints[intPtr++];
- List<CollectionElement> elements =
- isSpreadOrControlFlowEnabled ? <CollectionElement>[] : <Expression>[];
- for (int i = 0; i < count; i++) {
- elements.insert(0, _popCollectionElement());
- }
- var typeArg = typeArguments == null
- ? resynthesizer.typeProvider.dynamicType
- : typeArguments.arguments[0].type;
- var staticType = resynthesizer.typeProvider.listType2(typeArg);
- _push(AstTestFactory.listLiteral2(Keyword.CONST, typeArguments, elements)
- ..staticType = staticType);
- }
-
- void _pushLocalFunctionReference() {
- int popCount = _uc.ints[intPtr++];
- // Note: nonzero popCount is no longer used.
- assert(popCount == 0);
- int functionIndex = _uc.ints[intPtr++];
- var localFunction = localFunctions[functionIndex];
- var functionElement =
- new FunctionElementImpl.forSerialized(localFunction, context);
- for (ParameterElementImpl parameter in functionElement.parameters) {
- variablesInScope.push(parameter);
- if (parameter.unlinkedParam.type == null) {
- // Store a type of `dynamic` for the parameter; this prevents
- // resynthesis from trying to read a type out of the summary (which
- // wouldn't work anyway, since nested functions don't have their
- // parameter types stored in the summary anyhow).
- parameter.type = resynthesizer.typeProvider.dynamicType;
- }
- }
- var parameters = functionElement.parameters.map(_makeParameter).toList();
- var asyncKeyword = localFunction.isAsynchronous
- ? TokenFactory.tokenFromKeyword(Keyword.ASYNC)
- : null;
- FunctionBody functionBody;
- if (localFunction.bodyExpr == null) {
- // Most likely the original source code contained a block function body
- // here. Block function bodies aren't supported by the summary mechanism.
- // But they are tolerated when their presence doesn't affect inferred
- // types.
- functionBody = AstTestFactory.blockFunctionBody(AstTestFactory.block());
- } else {
- var bodyExpr = new ExprBuilder(
- resynthesizer, functionElement, localFunction.bodyExpr,
- requireValidConst: requireValidConst,
- variablesInScope: variablesInScope,
- localFunctions: localFunction.localFunctions)
- .build();
- functionBody = astFactory.expressionFunctionBody(asyncKeyword,
- TokenFactory.tokenFromType(TokenType.FUNCTION), bodyExpr, null);
- }
- variablesInScope.pop(functionElement.parameters.length);
- FunctionExpressionImpl functionExpression = astFactory.functionExpression(
- null, AstTestFactory.formalParameterList(parameters), functionBody);
- functionExpression.declaredElement = functionElement;
- _push(functionExpression);
- }
-
- void _pushMap(TypeArgumentList typeArguments) {
- int count = _uc.ints[intPtr++];
- List<MapLiteralEntry> entries = <MapLiteralEntry>[];
- for (int i = 0; i < count; i++) {
- Expression value = _pop();
- Expression key = _pop();
- entries.insert(0, AstTestFactory.mapLiteralEntry2(key, value));
- }
- var keyType = typeArguments == null
- ? resynthesizer.typeProvider.dynamicType
- : typeArguments.arguments[0].type;
- var valueType = typeArguments == null
- ? resynthesizer.typeProvider.dynamicType
- : typeArguments.arguments[1].type;
- var staticType = resynthesizer.typeProvider.mapType2(keyType, valueType);
- SetOrMapLiteralImpl literal =
- AstTestFactory.setOrMapLiteral(Keyword.CONST, typeArguments, entries);
- literal.becomeMap();
- literal.staticType = staticType;
- _push(literal);
- }
-
- void _pushMapLiteralEntry() {
- Expression value = _pop();
- Expression key = _pop();
- _pushCollectionElement(AstTestFactory.mapLiteralEntry2(key, value));
- }
-
- void _pushNode(AstNode node) {
- stack.add(node);
- }
-
- void _pushPrefix(TokenType operator) {
- Expression operand = _pop();
- _push(AstTestFactory.prefixExpression(operator, operand));
- }
-
- void _pushReference() {
- _push(_createReference());
- }
-
- void _pushSet(TypeArgumentList typeArguments) {
- int count = _uc.ints[intPtr++];
- List<Expression> elements = <Expression>[];
- for (int i = 0; i < count; i++) {
- elements.insert(0, _pop());
- }
- SetOrMapLiteralImpl literal =
- AstTestFactory.setOrMapLiteral(Keyword.CONST, typeArguments, elements);
- literal.becomeSet();
- _push(literal);
- }
-
- void _pushSetOrMap(TypeArgumentList typeArguments) {
- int count = _uc.ints[intPtr++];
- List<CollectionElement> elements = <CollectionElement>[];
- for (int i = 0; i < count; i++) {
- elements.insert(0, _popCollectionElement());
- }
-
- bool isMap = true; // assume Map unless can prove otherwise
- DartType staticType;
- if (typeArguments != null) {
- if (typeArguments.arguments.length == 2) {
- var keyType = typeArguments.arguments[0].type;
- var valueType = typeArguments.arguments[1].type;
- staticType = resynthesizer.typeProvider.mapType2(keyType, valueType);
- } else if (typeArguments.arguments.length == 1) {
- isMap = false;
- var valueType = typeArguments == null
- ? resynthesizer.typeProvider.dynamicType
- : typeArguments.arguments[0].type;
- staticType = resynthesizer.typeProvider.setType2(valueType);
- }
- } else {
- for (var i = 0; i < elements.length; ++i) {
- var element = elements[i];
- if (element is Expression) {
- isMap = false;
- }
- }
- }
-
- SetOrMapLiteral setOrMapLiteral = astFactory.setOrMapLiteral(
- constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
- typeArguments: typeArguments,
- leftBracket: TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
- elements: elements,
- rightBracket: TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET),
- );
- if (becomeSetOrMap) {
- if (isMap) {
- (setOrMapLiteral as SetOrMapLiteralImpl).becomeMap();
- } else {
- (setOrMapLiteral as SetOrMapLiteralImpl).becomeSet();
- }
- }
- _push(setOrMapLiteral..staticType = staticType);
- }
-
- void _pushSpread(TokenType operator) {
- Expression operand = _pop();
- _pushCollectionElement(AstTestFactory.spreadElement(operator, operand));
- }
-
- List<Expression> _removeTopExpressions(int count) {
- int start = stack.length - count;
- int end = stack.length;
- List<Expression> items = List<Expression>.from(stack.getRange(start, end));
- stack.removeRange(start, end);
- return items;
- }
-
- void _variableDeclaration() {
- var index = _uc.ints[intPtr++];
- var element = variablesInScope.recent(index);
- var initializer = _pop();
- var variableDeclaration =
- AstTestFactory.variableDeclaration2(element.name, initializer);
- variableDeclaration.name.staticElement = element;
- _pushNode(variableDeclaration);
- }
-
- void _variableDeclarationStart() {
- var name = _uc.strings[stringPtr++];
- variablesInScope.push(LocalVariableElementImpl(name, -1));
- }
-
- /// Figures out the default value of [parametersInScope] based on [context].
- ///
- /// If [context] is (or contains) a constructor, then its parameters are used.
- /// Otherwise, no parameters are considered to be in scope.
- static _VariablesInScope _parametersInScope(Element context) {
- var result = _VariablesInScope();
- for (Element e = context; e != null; e = e.enclosingElement) {
- if (e is ConstructorElement) {
- for (var parameter in e.parameters) {
- result.push(parameter);
- }
- return result;
- }
- }
- return result;
- }
-}
-
-/// Tracks the set of variables that are in scope while resynthesizing an
-/// expression from a summary.
-class _VariablesInScope {
- final _variableElements = <VariableElement>[];
-
- /// Returns the number of variables that have been pushed but not popped.
- int get count => _variableElements.length;
-
- /// Looks up the variable with the given [name]. Returns `null` if no
- /// variable is found.
- VariableElement operator [](String name) {
- for (int i = _variableElements.length - 1; i >= 0; i--) {
- if (_variableElements[i].name == name) return _variableElements[i];
- }
- return null;
- }
-
- /// Un-does the effect of the last [count] calls to `push`.
- void pop(int count) {
- _variableElements.length -= count;
- }
-
- /// Stores a new declaration based on the given [variableElement]. The
- /// declaration shadows any previous declaration with the same name.
- void push(VariableElement variableElement) {
- _variableElements.add(variableElement);
- }
-
- /// Retrieves the [index]th most recently pushed element (that hasn't been
- /// popped). [index] counts from zero.
- VariableElement recent(int index) =>
- _variableElements[_variableElements.length - 1 - index];
-}
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index db8ae22..d0bd245 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -2,2153 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-/// This library is capable of producing linked summaries from unlinked
-/// ones (or prelinked ones). It functions by building a miniature
-/// element model to represent the contents of the summaries, and then
-/// scanning the element model to gather linked information and adding
-/// it to the summary data structures.
-///
-/// The reason we use a miniature element model to do the linking
-/// (rather than resynthesizing the full element model from the
-/// summaries) is that it is expected that we will only need to
-/// traverse a small subset of the element properties in order to link.
-/// Resynthesizing only those properties that we need should save
-/// substantial CPU time.
-///
-/// The element model implements the same interfaces as the full
-/// element model, so we can re-use code elsewhere in the analysis
-/// engine to do the linking. However, only a small subset of the
-/// methods and getters defined in the full element model are
-/// implemented here. To avoid static warnings, each element model
-/// class contains an implementation of `noSuchMethod`.
-///
-/// The miniature element model follows the following design
-/// principles:
-///
-/// - With few exceptions, resynthesis is done incrementally on demand,
-/// so that we don't pay the cost of resynthesizing elements (or
-/// properties of elements) that aren't referenced from a part of the
-/// element model that is relevant to linking.
-///
-/// - Computation of values in the miniature element model is similar
-/// to the task model, but much lighter weight. Instead of declaring
-/// tasks and their relationships using classes, each task is simply
-/// a method (frequently a getter) that computes a value. Instead of
-/// using a general purpose cache, values are cached by the methods
-/// themselves in private fields (with `null` typically representing
-/// "not yet cached").
-///
-/// - No attempt is made to detect cyclic dependencies due to bugs in
-/// the analyzer. This saves time because dependency evaluation
-/// doesn't have to be a separate step from evaluating a value; we
-/// can simply call the getter.
-///
-/// - However, for cases where cyclic dependencies may occur in the
-/// absence of analyzer bugs (e.g. because of errors in the code
-/// being analyzed, or cycles between top level and static variables
-/// undergoing type inference), we do precompute dependencies, and we
-/// use Tarjan's strongly connected components algorithm to detect
-/// cycles.
-///
-/// - As much as possible, bookkeeping data is pointed to directly by
-/// the element objects, rather than being stored in maps.
-///
-/// - Where possible, we favor method dispatch instead of "is" and "as"
-/// checks. E.g. see [ReferenceableElementForLink.asConstructor].
-import 'package:analyzer/dart/analysis/declared_variables.dart';
-import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_ast_factory.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/nullability_suffix.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/constant/value.dart';
-import 'package:analyzer/src/dart/element/builder.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_provider.dart';
-import 'package:analyzer/src/dart/resolver/ast_rewrite.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/summary/expr_builder.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/prelink.dart';
-import 'package:analyzer/src/summary/resynthesize.dart';
-import 'package:analyzer/src/task/strong_mode.dart';
-import 'package:meta/meta.dart';
-
-final _typesWithImplicitArguments = new Expando();
-
-bool isIncrementOrDecrement(UnlinkedExprAssignOperator operator) {
- switch (operator) {
- case UnlinkedExprAssignOperator.prefixDecrement:
- case UnlinkedExprAssignOperator.prefixIncrement:
- case UnlinkedExprAssignOperator.postfixDecrement:
- case UnlinkedExprAssignOperator.postfixIncrement:
- return true;
- default:
- return false;
- }
-}
-
-/// Link together the build unit consisting of [libraryUris], using
-/// [getDependency] to fetch the [LinkedLibrary] objects from other
-/// build units, and [getUnit] to fetch the [UnlinkedUnit] objects from
-/// both this build unit and other build units.
-///
-/// The [strong] flag controls whether type inference is performed in strong
-/// mode or spec mode. Note that in spec mode, the only types that are inferred
-/// are the types of initializing formals, which are inferred from the types of
-/// the corresponding fields.
-///
-/// If [getAst] is provided, it is used to obtain ASTs of source files in this
-/// build unit, and these ASTs are used for type inference.
-///
-/// A map is returned whose keys are the URIs of the libraries in this
-/// build unit, and whose values are the corresponding
-/// [LinkedLibraryBuilder]s.
-Map<String, LinkedLibraryBuilder> link(
- Set<String> libraryUris,
- GetDependencyCallback getDependency,
- GetUnitCallback getUnit,
- DeclaredVariables declaredVariables,
- AnalysisOptions analysisOptions,
- [GetAstCallback getAst]) {
- Map<String, LinkedLibraryBuilder> linkedLibraries =
- setupForLink(libraryUris, getUnit, declaredVariables);
- _relink(linkedLibraries, getDependency, getUnit, getAst, analysisOptions);
- return linkedLibraries;
-}
-
-/// Prepare to link together the build unit consisting of [libraryUris], using
-/// [getUnit] to fetch the [UnlinkedUnit] objects from both this build unit and
-/// other build units.
-///
-/// The libraries are prelinked, and a map is returned whose keys are the URIs
-/// of the libraries in this build unit, and whose values are the corresponding
-/// [LinkedLibraryBuilder]s.
-Map<String, LinkedLibraryBuilder> setupForLink(Set<String> libraryUris,
- GetUnitCallback getUnit, DeclaredVariables declaredVariables) {
- Map<String, LinkedLibraryBuilder> linkedLibraries =
- <String, LinkedLibraryBuilder>{};
- for (String absoluteUri in libraryUris) {
- linkedLibraries[absoluteUri] = prelink(
- absoluteUri,
- getUnit(absoluteUri),
- getUnit,
- (String absoluteUri) => getUnit(absoluteUri)?.publicNamespace,
- declaredVariables);
- }
- return linkedLibraries;
-}
-
-/// Collects all the type references appearing on the "right hand side" of a
-/// typedef.
-///
-/// The "right hand side" of a typedef is the type appearing after the "=" in a
-/// new style typedef declaration, or for an old style typedef declaration, the
-/// type that *would* appear after the "=" if it were converted to a new style
-/// typedef declaration. This means that type parameter declarations and their
-/// bounds are not included.
-List<EntityRef> _collectTypedefRhsTypes(UnlinkedTypedef unlinkedTypedef) {
- var types = <EntityRef>[];
- void visitParams(List<UnlinkedParam> params) {
- for (var param in params) {
- var type = param.type;
- if (type != null) {
- types.add(type);
- }
- if (param.isFunctionTyped) {
- visitParams(param.parameters);
- }
- }
- }
-
- var returnType = unlinkedTypedef.returnType;
- if (returnType != null) {
- types.add(returnType);
- }
- visitParams(unlinkedTypedef.parameters);
- return types;
-}
-
-/// Create an [EntityRefBuilder] representing the given [type], in a form
-/// suitable for inclusion in [LinkedUnit.types]. [compilationUnit] is the
-/// compilation unit in which the type will be used. If [slot] is provided, it
-/// is stored in [EntityRefBuilder.slot].
-EntityRefBuilder _createLinkedType(
- DartType type,
- CompilationUnitElementInBuildUnit compilationUnit,
- TypeParameterSerializationContext typeParameterContext,
- {int slot}) {
- EntityRefBuilder result = new EntityRefBuilder(
- slot: slot,
- nullabilitySuffix:
- encodeNullabilitySuffix((type as TypeImpl).nullabilitySuffix));
- if (type is InterfaceType) {
- ClassElementForLink element = type.element;
- result.reference = compilationUnit.addReference(element);
- _storeTypeArguments(
- type.typeArguments, result, compilationUnit, typeParameterContext);
- return result;
- } else if (type.isDynamic) {
- result.reference = compilationUnit.addRawReference('dynamic');
- return result;
- } else if (type is VoidTypeImpl) {
- result.reference = compilationUnit.addRawReference('void');
- return result;
- } else if (type is BottomTypeImpl) {
- result.reference = compilationUnit.addRawReference('*bottom*');
- return result;
- } else if (type is TypeParameterType) {
- TypeParameterElement element = type.element;
- var deBruijnIndex = typeParameterContext?.computeDeBruijnIndex(element);
- if (deBruijnIndex != null) {
- result.paramReference = deBruijnIndex;
- } else {
- throw new StateError('The type parameter $type (in ${element?.location}) '
- 'is out of scope.');
- }
- return result;
- } else if (type is FunctionType) {
- Element element = type.element;
- if (element is FunctionElementForLink_FunctionTypedParam) {
- result.reference =
- compilationUnit.addReference(element.typeParameterContext);
- result.implicitFunctionTypeIndices = element.implicitFunctionTypeIndices;
- _storeTypeArguments(
- type.typeArguments, result, compilationUnit, typeParameterContext);
- return result;
- }
- if (element is TopLevelFunctionElementForLink) {
- result.reference = compilationUnit.addReference(element);
- _storeTypeArguments(
- type.typeArguments, result, compilationUnit, typeParameterContext);
- return result;
- }
- if (element is MethodElementForLink) {
- result.reference = compilationUnit.addReference(element);
- _storeTypeArguments(
- type.typeArguments, result, compilationUnit, typeParameterContext);
- return result;
- }
- if (element is FunctionTypeAliasElementForLink) {
- result.reference = compilationUnit.addReference(element);
- _storeTypeArguments(
- type.typeArguments, result, compilationUnit, typeParameterContext);
- return result;
- }
- if (element is FunctionElement) {
- // We store all function elements by value. Synthetic elements, e.g.
- // created for LUB, don't have actual elements; and local functions
- // are not exposed from element model.
- _storeFunctionElementByValue(result, element, compilationUnit);
- // TODO(paulberry): do I need to store type arguments?
- return result;
- }
- if (element is GenericFunctionTypeElementImpl) {
- // Function types are their own type parameter context
- typeParameterContext =
- new InlineFunctionTypeParameterContext(element, typeParameterContext);
- result.entityKind = EntityRefKind.genericFunctionType;
- result.syntheticReturnType = _createLinkedType(
- type.returnType, compilationUnit, typeParameterContext);
- result.syntheticParams = type.parameters
- .map((ParameterElement param) => _serializeSyntheticParam(
- param, compilationUnit, typeParameterContext))
- .toList();
- _storeTypeArguments(
- type.typeArguments, result, compilationUnit, typeParameterContext);
- return result;
- }
- // TODO(paulberry): implement other cases.
- throw new UnimplementedError('${element.runtimeType}');
- }
- // TODO(paulberry): implement other cases.
- throw new UnimplementedError('${type.runtimeType}');
-}
-
-DartType _dynamicIfBottom(DartType type) {
- if (type == null || type.isBottom) {
- return DynamicTypeImpl.instance;
- }
- return type;
-}
-
-DartType _dynamicIfNull(DartType type) {
- if (type == null || type.isBottom || type.isDartCoreNull) {
- return DynamicTypeImpl.instance;
- }
- return type;
-}
-
-/// Given [libraries] (a map from URI to [LinkedLibraryBuilder]
-/// containing correct prelinked information), rebuild linked
-/// information, using [getDependency] to fetch the [LinkedLibrary]
-/// objects from other build units, and [getUnit] to fetch the
-/// [UnlinkedUnit] objects from both this build unit and other build
-/// units.
-///
-/// If a non-null [getAst] is provided, it is used to obtain ASTs of source
-/// files in this build unit, and these ASTs are used for type inference.
-///
-/// The [strong] flag controls whether type inference is performed in strong
-/// mode or spec mode. Note that in spec mode, the only types that are inferred
-/// are the types of initializing formals, which are inferred from the types of
-/// the corresponding fields.
-void _relink(
- Map<String, LinkedLibraryBuilder> libraries,
- GetDependencyCallback getDependency,
- GetUnitCallback getUnit,
- GetAstCallback getAst,
- AnalysisOptions analysisOptions) {
- new Linker(libraries, getDependency, getUnit, getAst, analysisOptions).link();
-}
-
-/// Create an [UnlinkedParam] representing the given [parameter], which should
-/// be a parameter of a synthetic function type (e.g. one produced during type
-/// inference as a result of computing the least upper bound of two function
-/// types).
-UnlinkedParamBuilder _serializeSyntheticParam(
- ParameterElement parameter,
- CompilationUnitElementInBuildUnit compilationUnit,
- TypeParameterSerializationContext typeParameterContext) {
- UnlinkedParamBuilder b = new UnlinkedParamBuilder();
- b.name = parameter.name;
- if (parameter.isRequiredPositional) {
- b.kind = UnlinkedParamKind.requiredPositional;
- } else if (parameter.isRequiredNamed) {
- b.kind = UnlinkedParamKind.requiredNamed;
- } else if (parameter.isOptionalPositional) {
- b.kind = UnlinkedParamKind.optionalPositional;
- } else if (parameter.isOptionalNamed) {
- b.kind = UnlinkedParamKind.optionalNamed;
- }
- DartType type = parameter.type;
- if (!parameter.hasImplicitType) {
- if (type is FunctionType && type.element.isSynthetic) {
- b.isFunctionTyped = true;
- b.type = _createLinkedType(
- type.returnType, compilationUnit, typeParameterContext);
- b.parameters = type.parameters
- .map((parameter) => _serializeSyntheticParam(
- parameter, compilationUnit, typeParameterContext))
- .toList();
- } else {
- b.type = _createLinkedType(type, compilationUnit, typeParameterContext);
- }
- }
- return b;
-}
-
-/// Create an [UnlinkedTypeParamBuilder] representing the given [typeParameter],
-/// which should be a type parameter of a synthetic function type (e.g. one
-/// produced during type inference as a result of computing the least upper
-/// bound of two function types).
-UnlinkedTypeParamBuilder _serializeSyntheticTypeParameter(
- TypeParameterElement typeParameter,
- CompilationUnitElementInBuildUnit compilationUnit,
- TypeParameterSerializationContext typeParameterContext) {
- TypeParameterElementImpl impl = typeParameter as TypeParameterElementImpl;
- EntityRefBuilder boundBuilder = typeParameter.bound != null
- ? _createLinkedType(
- typeParameter.bound, compilationUnit, typeParameterContext)
- : null;
- CodeRangeBuilder codeRangeBuilder =
- new CodeRangeBuilder(offset: impl.codeOffset, length: impl.codeLength);
- return new UnlinkedTypeParamBuilder(
- name: typeParameter.name,
- nameOffset: typeParameter.nameOffset,
- bound: boundBuilder,
- codeRange: codeRangeBuilder);
-}
-
-/// Store the given function [element] into the [entity] by value.
-void _storeFunctionElementByValue(
- EntityRefBuilder entity,
- FunctionElement element,
- CompilationUnitElementInBuildUnit compilationUnit) {
- // Element is a local function, or a synthetic function element that was
- // generated on the fly to represent a type that has no associated source
- // code location. Store it as value.
- if (element is FunctionElementImpl) {
- entity.syntheticReturnType =
- _createLinkedType(element.returnType, compilationUnit, element);
- entity.entityKind = EntityRefKind.syntheticFunction;
- entity.syntheticParams = element.parameters
- .map((ParameterElement param) =>
- _serializeSyntheticParam(param, compilationUnit, element))
- .toList();
- entity.typeParameters = element.typeParameters
- .map((TypeParameterElement e) =>
- _serializeSyntheticTypeParameter(e, compilationUnit, element))
- .toList();
- }
-}
-
-/// Store the given [typeArguments] in [encodedType], using [compilationUnit]
-/// and [typeParameterContext] to serialize them.
-void _storeTypeArguments(
- List<DartType> typeArguments,
- EntityRefBuilder encodedType,
- CompilationUnitElementInBuildUnit compilationUnit,
- TypeParameterSerializationContext typeParameterContext) {
- int count = typeArguments.length;
- List<EntityRefBuilder> encodedTypeArguments =
- new List<EntityRefBuilder>(count);
- for (int i = 0; i < count; i++) {
- encodedTypeArguments[i] = _createLinkedType(
- typeArguments[i], compilationUnit, typeParameterContext);
- }
- encodedType.typeArguments = encodedTypeArguments;
-}
-
-/// Type of the callback used by [link] to request [CompilationUnit] objects.
-typedef CompilationUnit GetAstCallback(String absoluteUri);
-
-/// Type of the callback used by [link] and [relink] to request
-/// [LinkedLibrary] objects from other build units.
-typedef LinkedLibrary GetDependencyCallback(String absoluteUri);
-
-/// Type of the callback used by [link] and [relink] to request
-/// [UnlinkedUnit] objects.
-typedef UnlinkedUnit GetUnitCallback(String absoluteUri);
-
-class AnalysisSessionForLink implements AnalysisSession {
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/// Element representing a class or enum resynthesized from a summary
-/// during linking.
-abstract class ClassElementForLink
- with ReferenceableElementForLink
- implements AbstractClassElementImpl {
- Map<String, ReferenceableElementForLink> _containedNames;
-
- @override
- final CompilationUnitElementForLink enclosingElement;
-
- /// TODO(brianwilkerson) This appears to be unused and might be removable.
- bool hasBeenInferred;
-
- DartType _typeWithDefaultBounds;
-
- ClassElementForLink(CompilationUnitElementForLink enclosingElement)
- : enclosingElement = enclosingElement,
- hasBeenInferred = !enclosingElement.isInBuildUnit;
-
- @override
- List<PropertyAccessorElementForLink> get accessors;
-
- @override
- ClassElementForLink get asClass => this;
-
- @override
- ConstructorElementForLink get asConstructor => unnamedConstructor;
-
- @override
- DartType get asStaticType =>
- enclosingElement.enclosingElement._linker.typeProvider.typeType;
-
- @override
- List<ConstructorElementForLink> get constructors;
-
- @override
- CompilationUnitElementForLink get enclosingUnit => enclosingElement;
-
- @override
- List<FieldElementForLink> get fields;
-
- /// Indicates whether this is the core class `Object`.
- bool get isObject;
-
- @override
- LibraryElementForLink get library => enclosingElement.library;
-
- @override
- Source get librarySource => library.source;
-
- @override
- get linkedNode => null;
-
- @override
- List<MethodElementForLink> get methods;
-
- @override
- String get name;
-
- @override
- InterfaceType get thisType {
- return type;
- }
-
- DartType get typeWithDefaultBounds => _typeWithDefaultBounds ??=
- enclosingElement.library._linker.typeSystem.instantiateToBounds(type);
-
- @override
- ConstructorElementForLink get unnamedConstructor;
-
- @override
- ReferenceableElementForLink getContainedName(String name) {
- if (_containedNames == null) {
- _containedNames = <String, ReferenceableElementForLink>{};
- // TODO(paulberry): what's the correct way to handle name conflicts?
- for (ConstructorElementForLink constructor in constructors) {
- _containedNames[constructor.name] = constructor;
- }
- for (PropertyAccessorElementForLink accessor in accessors) {
- _containedNames[accessor.name] = accessor;
- }
- for (MethodElementForLink method in methods) {
- _containedNames[method.name] = method;
- }
- }
- return _containedNames.putIfAbsent(
- name, () => UndefinedElementForLink.instance);
- }
-
- @override
- FieldElement getField(String name) {
- for (FieldElement fieldElement in fields) {
- if (name == fieldElement.name) {
- return fieldElement;
- }
- }
- return null;
- }
-
- @override
- PropertyAccessorElement getGetter(String getterName) {
- for (PropertyAccessorElement accessor in accessors) {
- if (accessor.isGetter && accessor.name == getterName) {
- return accessor;
- }
- }
- return null;
- }
-
- @override
- MethodElement getMethod(String methodName) {
- for (MethodElement method in methods) {
- if (method.name == methodName) {
- return method;
- }
- }
- return null;
- }
-
- @override
- InterfaceType instantiate({
- @required List<DartType> typeArguments,
- @required NullabilitySuffix nullabilitySuffix,
- }) {
- if (typeArguments.length != typeParameters.length) {
- var ta = 'typeArguments.length (${typeArguments.length})';
- var tp = 'typeParameters.length (${typeParameters.length})';
- throw ArgumentError('$ta != $tp');
- }
- return InterfaceTypeImpl.explicit(
- this,
- typeArguments,
- nullabilitySuffix: nullabilitySuffix,
- );
- }
-
- /// Perform type inference and cycle detection on this class and
- /// store the resulting information in [compilationUnit].
- void link(CompilationUnitElementInBuildUnit compilationUnit);
-
- @override
- MethodElement lookUpMethod(String methodName, LibraryElement library) {
- return AbstractClassElementImpl.lookUpMethodInClass(
- this, methodName, library);
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/// Element representing a class resynthesized from a summary during
-/// linking.
-class ClassElementForLink_Class extends ClassElementForLink
- with TypeParameterizedElementMixin, SimplyBoundableForLinkMixin
- implements ClassElementImpl, ClassMemberContainerForLink {
- /// The unlinked representation of the class in the summary.
- final UnlinkedClass _unlinkedClass;
-
- @override
- final bool isMixin;
-
- /// If non-null, the AST for the class or mixin declaration; this is used to
- /// obtain initializer expressions for type inference.
- final ClassOrMixinDeclaration _astForInference;
-
- List<ConstructorElementForLink> _constructors;
- ConstructorElementForLink _unnamedConstructor;
- bool _unnamedConstructorComputed = false;
- List<FieldElementForLink_ClassField> _fields;
- InterfaceType _supertype;
- InterfaceType _type;
- List<MethodElementForLink> _methods;
- List<InterfaceType> _mixins;
- List<InterfaceType> _interfaces;
- List<InterfaceType> _superclassConstraints;
- List<PropertyAccessorElementForLink> _accessors;
-
- ClassElementForLink_Class(CompilationUnitElementForLink enclosingElement,
- this._unlinkedClass, this.isMixin, this._astForInference)
- : super(enclosingElement) {
- _initSimplyBoundable();
- }
-
- @override
- List<PropertyAccessorElementForLink> get accessors {
- if (_accessors == null) {
- _accessors = <PropertyAccessorElementForLink>[];
- Map<String, SyntheticVariableElementForLink> syntheticVariables =
- <String, SyntheticVariableElementForLink>{};
- for (UnlinkedExecutable unlinkedExecutable
- in _unlinkedClass.executables) {
- if (unlinkedExecutable.kind == UnlinkedExecutableKind.getter ||
- unlinkedExecutable.kind == UnlinkedExecutableKind.setter) {
- String name = unlinkedExecutable.name;
- if (unlinkedExecutable.kind == UnlinkedExecutableKind.setter) {
- assert(name.endsWith('='));
- name = name.substring(0, name.length - 1);
- }
- SyntheticVariableElementForLink syntheticVariable = syntheticVariables
- .putIfAbsent(name, () => new SyntheticVariableElementForLink());
- PropertyAccessorElementForLink_Executable accessor =
- new PropertyAccessorElementForLink_Executable(enclosingElement,
- this, unlinkedExecutable, syntheticVariable);
- _accessors.add(accessor);
- if (unlinkedExecutable.kind == UnlinkedExecutableKind.getter) {
- syntheticVariable._getter = accessor;
- } else {
- syntheticVariable._setter = accessor;
- }
- }
- }
- for (FieldElementForLink_ClassField field in fields) {
- _accessors.add(field.getter);
- if (!field.isConst && !field.isFinal) {
- _accessors.add(field.setter);
- }
- }
- }
- return _accessors;
- }
-
- @override
- List<ConstructorElementForLink> get constructors {
- if (_constructors == null) {
- _constructors = <ConstructorElementForLink>[];
- for (UnlinkedExecutable unlinkedExecutable
- in _unlinkedClass.executables) {
- if (unlinkedExecutable.kind == UnlinkedExecutableKind.constructor) {
- _constructors
- .add(new ConstructorElementForLink(this, unlinkedExecutable));
- }
- }
- if (_constructors.isEmpty) {
- _unnamedConstructorComputed = true;
- _unnamedConstructor = new ConstructorElementForLink_Synthetic(this);
- _constructors.add(_unnamedConstructor);
- }
- }
- return _constructors;
- }
-
- @override
- ContextForLink get context => enclosingUnit.context;
-
- @override
- String get displayName => _unlinkedClass.name;
-
- @override
- TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
-
- @override
- List<FieldElementForLink_ClassField> get fields {
- if (_fields == null) {
- _fields = <FieldElementForLink_ClassField>[];
- List<Expression> initializerExpressionsForInference;
- if (_astForInference != null) {
- initializerExpressionsForInference = [];
- for (var member in _astForInference.members) {
- if (member is FieldDeclaration) {
- for (var variable in member.fields.variables) {
- initializerExpressionsForInference.add(variable.initializer);
- }
- }
- }
- assert(initializerExpressionsForInference.length ==
- _unlinkedClass.fields.length);
- }
- for (int i = 0; i < _unlinkedClass.fields.length; i++) {
- var field = _unlinkedClass.fields[i];
- _fields.add(new FieldElementForLink_ClassField(
- this,
- field,
- initializerExpressionsForInference == null
- ? null
- : initializerExpressionsForInference[i]));
- }
- }
- return _fields;
- }
-
- @override
- String get identifier => name;
-
- @override
- List<InterfaceType> get interfaces => _interfaces ??=
- _unlinkedClass.interfaces.map(_computeInterfaceType).toList();
-
- @override
- bool get isAbstract => _unlinkedClass.isAbstract;
-
- @override
- bool get isEnum => false;
-
- @override
- bool get isMixinApplication => _unlinkedClass.isMixinApplication;
-
- @override
- bool get isObject => _unlinkedClass.hasNoSupertype;
-
- @override
- LibraryElementForLink get library => enclosingElement.library;
-
- @override
- List<MethodElementForLink> get methods {
- if (_methods == null) {
- _methods = <MethodElementForLink>[];
- for (UnlinkedExecutable unlinkedExecutable
- in _unlinkedClass.executables) {
- if (unlinkedExecutable.kind ==
- UnlinkedExecutableKind.functionOrMethod) {
- _methods.add(new MethodElementForLink(this, unlinkedExecutable));
- }
- }
- }
- return _methods;
- }
-
- @override
- List<InterfaceType> get mixins {
- if (_mixins == null) {
- // Note: in the event of a loop in the class hierarchy, the calls to
- // collectAllSupertypes below will wind up reentrantly calling
- // this.mixins. So to prevent infinite recursion we need to set _mixins
- // to non-null now. It's ok that we populate it gradually; in the event
- // of a reentrant call, the user's code is known to have errors, so it's
- // ok if the reentrant call doesn't return the complete set of mixins; we
- // just need to ensure that analysis terminates.
- _mixins = <InterfaceType>[];
- List<InterfaceType> supertypesForMixinInference; // populated lazily
- for (var entity in _unlinkedClass.mixins) {
- var mixin = _computeInterfaceType(entity);
- var mixinElement = mixin.element;
- var slot = entity.refinedSlot;
- if (slot != 0 && mixinElement.typeParameters.isNotEmpty) {
- CompilationUnitElementForLink enclosingElement =
- this.enclosingElement;
- if (enclosingElement is CompilationUnitElementInBuildUnit) {
- var mixinSupertypeConstraints = context.typeSystem
- .gatherMixinSupertypeConstraintsForInference(mixinElement);
- if (mixinSupertypeConstraints.isNotEmpty) {
- if (supertypesForMixinInference == null) {
- supertypesForMixinInference = <InterfaceType>[];
- ClassElementImpl.collectAllSupertypes(
- supertypesForMixinInference, supertype, type);
- for (var previousMixin in _mixins) {
- ClassElementImpl.collectAllSupertypes(
- supertypesForMixinInference, previousMixin, type);
- }
- }
- var matchingInterfaceTypes = _findInterfaceTypesForConstraints(
- mixinSupertypeConstraints, supertypesForMixinInference);
- // Note: if matchingInterfaceType is null, that's an error. Also,
- // if there are multiple matching interface types that use
- // different type parameters, that's also an error. But we can't
- // report errors from the linker, so we just use the
- // first matching interface type (if there is one). The error
- // detection logic is implemented in the ErrorVerifier.
- if (matchingInterfaceTypes != null) {
- // Try to pattern match matchingInterfaceTypes against
- // mixinSupertypeConstraints to find the correct set of type
- // parameters to apply to the mixin.
- var inferredMixin = context.typeSystem
- .matchSupertypeConstraints(mixinElement,
- mixinSupertypeConstraints, matchingInterfaceTypes);
- if (inferredMixin != null) {
- mixin = inferredMixin;
- enclosingElement._storeLinkedType(slot, mixin, this);
- }
- }
- }
- } else {
- var refinedMixin = enclosingElement.getLinkedType(this, slot);
- if (refinedMixin is InterfaceType) {
- mixin = refinedMixin;
- }
- }
- }
- _mixins.add(mixin);
- if (supertypesForMixinInference != null) {
- ClassElementImpl.collectAllSupertypes(
- supertypesForMixinInference, mixin, type);
- }
- }
- }
- return _mixins;
- }
-
- @override
- String get name => _unlinkedClass.name;
-
- @override
- AnalysisSession get session => enclosingUnit.session;
-
- @override
- List<InterfaceType> get superclassConstraints {
- if (_superclassConstraints == null) {
- if (isMixin) {
- _superclassConstraints = _unlinkedClass.superclassConstraints
- .map(_computeInterfaceType)
- .toList();
- if (_superclassConstraints.isEmpty) {
- _superclassConstraints = [
- enclosingElement.enclosingElement._linker.typeProvider.objectType
- ];
- }
- } else {
- _superclassConstraints = const <InterfaceType>[];
- }
- }
- return _superclassConstraints;
- }
-
- @override
- InterfaceType get supertype {
- if (isObject) {
- return null;
- }
- return _supertype ??= _computeInterfaceType(_unlinkedClass.supertype);
- }
-
- @override
- InterfaceType get type =>
- _type ??= buildType((int i) => typeParameterTypes[i], null);
-
- @override
- List<UnlinkedTypeParam> get unlinkedTypeParams =>
- _unlinkedClass.typeParameters;
-
- @override
- ConstructorElementForLink get unnamedConstructor {
- if (!_unnamedConstructorComputed) {
- for (ConstructorElementForLink constructor in constructors) {
- if (constructor.name.isEmpty) {
- _unnamedConstructor = constructor;
- break;
- }
- }
- _unnamedConstructorComputed = true;
- }
- return _unnamedConstructor;
- }
-
- @override
- int get version => 0;
-
- @override
- int get _notSimplyBoundedSlot => _unlinkedClass.notSimplyBoundedSlot;
-
- @override
- List<EntityRef> get _rhsTypesForSimplyBoundable => const [];
-
- @override
- List<UnlinkedTypeParam> get _typeParametersForSimplyBoundable {
- return _unlinkedClass.typeParameters;
- }
-
- @override
- DartType buildType(
- DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
- int numTypeParameters = _unlinkedClass.typeParameters.length;
- if (numTypeParameters != 0) {
- List<DartType> typeArguments =
- new List<DartType>.generate(numTypeParameters, getTypeArgument);
- if (typeArguments.contains(null)) {
- return context.typeSystem.instantiateToBounds(this.type);
- } else {
- return new InterfaceTypeImpl.elementWithNameAndArgs(
- this, name, () => typeArguments);
- }
- } else {
- return _type ??= new InterfaceTypeImpl(this);
- }
- }
-
- @override
- ConstructorElement getNamedConstructor(String name) =>
- ClassElementImpl.getNamedConstructorFromList(name, constructors);
-
- @override
- PropertyAccessorElement getSetter(String setterName) =>
- AbstractClassElementImpl.getSetterFromAccessors(setterName, accessors);
-
- @override
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- // Force mixins to be inferred by calling this.mixins. We don't need the
- // return value from the getter; we just need it to execute and record the
- // mixin inference results as a side effect.
- this.mixins;
-
- _linkSimplyBoundable();
-
- for (ConstructorElementForLink constructorElement in constructors) {
- constructorElement.link(compilationUnit);
- }
- for (MethodElementForLink methodElement in methods) {
- methodElement.link(compilationUnit);
- }
- for (PropertyAccessorElementForLink propertyAccessorElement in accessors) {
- propertyAccessorElement.link(compilationUnit);
- }
- for (FieldElementForLink_ClassField fieldElement in fields) {
- fieldElement.link(compilationUnit);
- }
- }
-
- @override
- String toString() => '$enclosingElement.$name';
-
- /// Convert [typeRef] into an [InterfaceType].
- InterfaceType _computeInterfaceType(EntityRef typeRef) {
- if (typeRef != null) {
- DartType type = enclosingElement.resolveTypeRef(this, typeRef);
- if (type is InterfaceType && !type.element.isEnum) {
- return type;
- }
- // In the event that the `typeRef` isn't an interface type (which may
- // happen in the event of erroneous code) just fall through and pretend
- // the supertype is `Object`.
- }
- return enclosingElement.enclosingElement._linker.typeProvider.objectType;
- }
-
- InterfaceType _findInterfaceTypeForElement(
- ClassElement element, List<InterfaceType> interfaceTypes) {
- for (var interfaceType in interfaceTypes) {
- if (interfaceType.element == element) return interfaceType;
- }
- return null;
- }
-
- List<InterfaceType> _findInterfaceTypesForConstraints(
- List<InterfaceType> constraints, List<InterfaceType> interfaceTypes) {
- var result = <InterfaceType>[];
- for (var constraint in constraints) {
- var interfaceType =
- _findInterfaceTypeForElement(constraint.element, interfaceTypes);
- if (interfaceType == null) {
- // No matching interface type found, so inference fails.
- return null;
- }
- result.add(interfaceType);
- }
- return result;
- }
-}
-
-/// Element representing an enum resynthesized from a summary during
-/// linking.
-class ClassElementForLink_Enum extends ClassElementForLink
- implements EnumElementImpl {
- /// The unlinked representation of the enum in the summary.
- final UnlinkedEnum _unlinkedEnum;
-
- InterfaceType _type;
- List<FieldElementForLink> _fields;
- List<PropertyAccessorElementForLink> _accessors;
- DartType _valuesType;
-
- ClassElementForLink_Enum(
- CompilationUnitElementForLink enclosingElement, this._unlinkedEnum)
- : super(enclosingElement);
-
- @override
- List<PropertyAccessorElementForLink> get accessors {
- if (_accessors == null) {
- _accessors = <PropertyAccessorElementForLink>[];
- for (FieldElementForLink field in fields) {
- _accessors.add(field.getter);
- }
- }
- return _accessors;
- }
-
- @override
- List<ConstructorElementForLink> get constructors => const [];
-
- @override
- String get displayName => _unlinkedEnum.name;
-
- @override
- List<FieldElementForLink> get fields {
- if (_fields == null) {
- _fields = <FieldElementForLink>[];
- _fields.add(new FieldElementForLink_EnumField_values(this));
- for (UnlinkedEnumValue value in _unlinkedEnum.values) {
- _fields.add(new FieldElementForLink_EnumField_value(this, value));
- }
- _fields.add(new FieldElementForLink_EnumField_index(this));
- }
- return _fields;
- }
-
- @override
- List<InterfaceType> get interfaces => const [];
-
- @override
- bool get isAbstract => false;
-
- @override
- bool get isEnum => true;
-
- @override
- bool get isMixin => false;
-
- @override
- bool get isObject => false;
-
- @override
- List<MethodElementForLink> get methods => const [];
-
- @override
- List<InterfaceType> get mixins => const [];
-
- @override
- String get name => _unlinkedEnum.name;
-
- @override
- List<InterfaceType> get superclassConstraints => const [];
-
- @override
- InterfaceType get supertype => library._linker.typeProvider.objectType;
-
- @override
- InterfaceType get type => _type ??= new InterfaceTypeImpl(this);
-
- @override
- List<TypeParameterElement> get typeParameters => const [];
-
- @override
- ConstructorElementForLink get unnamedConstructor => null;
-
- /// Get the type of the enum's static member `values`.
- DartType get valuesType =>
- _valuesType ??= library._linker.typeProvider.listType.instantiate([type]);
-
- @override
- DartType buildType(DartType getTypeArgument(int i),
- List<int> implicitFunctionTypeIndices) =>
- type;
-
- @override
- ConstructorElement getNamedConstructor(String name) => null;
-
- @override
- void link(CompilationUnitElementInBuildUnit compilationUnit) {}
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-abstract class ClassMemberContainerForLink
- implements ReferenceableElementForLink, TypeParameterizedElementMixin {}
-
-/// Element representing a compilation unit resynthesized from a
-/// summary during linking.
-abstract class CompilationUnitElementForLink
- implements CompilationUnitElementImpl, ResynthesizerContext {
- final _UnitResynthesizer _unitResynthesizer;
-
- /// The unlinked representation of the compilation unit in the
- /// summary.
- final UnlinkedUnit _unlinkedUnit;
-
- /// For each entry in [UnlinkedUnit.references], the element referred
- /// to by the reference, or `null` if it hasn't been located yet.
- final List<_ReferenceInfo> _references;
-
- /// The absolute URI of this compilation unit.
- final String _absoluteUri;
-
- List<ClassElementForLink_Class> _mixins;
- List<ClassElementForLink_Class> _types;
- Map<String, ReferenceableElementForLink> _containedNames;
- List<TopLevelVariableElementForLink> _topLevelVariables;
- List<ClassElementForLink_Enum> _enums;
- List<ExtensionElementForLink> _extensions;
- List<TopLevelFunctionElementForLink> _functions;
- List<PropertyAccessorElementForLink> _accessors;
- List<FunctionTypeAliasElementForLink> _functionTypeAliases;
-
- /// Index of this unit in the list of units in the enclosing library.
- final int unitNum;
-
- @override
- final Source source;
-
- /// If non-null, the AST for the compilation unit; this is used to obtain
- /// initializer expressions for type inference.
- final CompilationUnit _astForInference;
-
- CompilationUnitElementForLink(UnlinkedUnit unlinkedUnit, this.unitNum,
- int numReferences, this._absoluteUri, this._astForInference)
- : _references = new List<_ReferenceInfo>(numReferences),
- _unlinkedUnit = unlinkedUnit,
- source = new InSummarySource(Uri.parse(_absoluteUri), null),
- _unitResynthesizer = new _UnitResynthesizer() {
- _unitResynthesizer._unit = this;
- }
-
- @override
- List<PropertyAccessorElementForLink> get accessors {
- if (_accessors == null) {
- _accessors = <PropertyAccessorElementForLink>[];
- Map<String, SyntheticVariableElementForLink> syntheticVariables =
- <String, SyntheticVariableElementForLink>{};
- for (UnlinkedExecutable unlinkedExecutable in _unlinkedUnit.executables) {
- if (unlinkedExecutable.kind == UnlinkedExecutableKind.getter ||
- unlinkedExecutable.kind == UnlinkedExecutableKind.setter) {
- String name = unlinkedExecutable.name;
- if (unlinkedExecutable.kind == UnlinkedExecutableKind.setter) {
- assert(name.endsWith('='));
- name = name.substring(0, name.length - 1);
- }
- SyntheticVariableElementForLink syntheticVariable = syntheticVariables
- .putIfAbsent(name, () => new SyntheticVariableElementForLink());
- PropertyAccessorElementForLink_Executable accessor =
- new PropertyAccessorElementForLink_Executable(
- this, null, unlinkedExecutable, syntheticVariable);
- _accessors.add(accessor);
- if (unlinkedExecutable.kind == UnlinkedExecutableKind.getter) {
- syntheticVariable._getter = accessor;
- } else {
- syntheticVariable._setter = accessor;
- }
- }
- }
- for (TopLevelVariableElementForLink variable in topLevelVariables) {
- _accessors.add(variable.getter);
- if (!variable.isConst && !variable.isFinal) {
- _accessors.add(variable.setter);
- }
- }
- }
- return _accessors;
- }
-
- @override
- ContextForLink get context => library.context;
-
- @override
- LibraryElementForLink get enclosingElement;
-
- @override
- List<ClassElementForLink_Enum> get enums {
- if (_enums == null) {
- _enums = <ClassElementForLink_Enum>[];
- for (UnlinkedEnum unlinkedEnum in _unlinkedUnit.enums) {
- _enums.add(new ClassElementForLink_Enum(this, unlinkedEnum));
- }
- }
- return _enums;
- }
-
- @override
- List<ExtensionElementForLink> get extensions {
- if (_extensions == null) {
- _extensions = <ExtensionElementForLink>[];
- for (UnlinkedExtension unlinkedExtension in _unlinkedUnit.extensions) {
- _extensions.add(ExtensionElementForLink(this, unlinkedExtension));
- }
- }
- return _extensions;
- }
-
- @override
- List<TopLevelFunctionElementForLink> get functions {
- if (_functions == null) {
- _functions = <TopLevelFunctionElementForLink>[];
- for (UnlinkedExecutable executable in _unlinkedUnit.executables) {
- if (executable.kind == UnlinkedExecutableKind.functionOrMethod) {
- _functions.add(new TopLevelFunctionElementForLink(this, executable));
- }
- }
- }
- return _functions;
- }
-
- @override
- List<FunctionTypeAliasElementForLink> get functionTypeAliases =>
- _functionTypeAliases ??= _unlinkedUnit.typedefs.map((UnlinkedTypedef t) {
- if (t.style == TypedefStyle.functionType) {
- return new FunctionTypeAliasElementForLink(this, t);
- } else if (t.style == TypedefStyle.genericFunctionType) {
- return new GenericTypeAliasElementForLink(this, t);
- } else {
- throw new StateError('Unhandled style of typedef: ${t.style}');
- }
- }).toList();
-
- @override
- String get identifier => _absoluteUri;
-
- /// Indicates whether this compilation element is part of the build unit
- /// currently being linked.
- bool get isInBuildUnit;
-
- /// Determine whether type inference is complete in this compilation unit.
- bool get isTypeInferenceComplete {
- LibraryCycleForLink libraryCycleForLink = library.libraryCycleForLink;
- if (libraryCycleForLink == null) {
- return true;
- } else {
- return libraryCycleForLink._node.isEvaluated;
- }
- }
-
- @override
- LibraryElementForLink get library => enclosingElement;
-
- @override
- List<ClassElementForLink_Class> get mixins {
- if (_mixins == null) {
- List<MixinDeclaration> declarationsForInference;
- if (_astForInference != null) {
- declarationsForInference = [];
- for (var declaration in _astForInference.declarations) {
- if (declaration is MixinDeclaration) {
- declarationsForInference.add(declaration);
- }
- }
- assert(declarationsForInference.length == _unlinkedUnit.mixins.length);
- }
- _mixins = <ClassElementForLink_Class>[];
- for (int i = 0; i < _unlinkedUnit.mixins.length; i++) {
- var unlinkedClass = _unlinkedUnit.mixins[i];
- _mixins.add(new ClassElementForLink_Class(
- this,
- unlinkedClass,
- true,
- declarationsForInference == null
- ? null
- : declarationsForInference[i]));
- }
- }
- return _mixins;
- }
-
- @override
- ResynthesizerContext get resynthesizerContext => this;
-
- @override
- AnalysisSession get session => library.session;
-
- @override
- List<TopLevelVariableElementForLink> get topLevelVariables {
- if (_topLevelVariables == null) {
- List<Expression> initializerExpressionsForInference;
- if (_astForInference != null) {
- initializerExpressionsForInference = [];
- for (var declaration in _astForInference.declarations) {
- if (declaration is TopLevelVariableDeclaration) {
- for (var variable in declaration.variables.variables) {
- initializerExpressionsForInference.add(variable.initializer);
- }
- }
- }
- assert(initializerExpressionsForInference.length ==
- _unlinkedUnit.variables.length);
- }
- _topLevelVariables = <TopLevelVariableElementForLink>[];
- for (int i = 0; i < _unlinkedUnit.variables.length; i++) {
- var unlinkedVariable = _unlinkedUnit.variables[i];
- _topLevelVariables.add(new TopLevelVariableElementForLink(
- this,
- unlinkedVariable,
- initializerExpressionsForInference == null
- ? null
- : initializerExpressionsForInference[i]));
- }
- }
- return _topLevelVariables;
- }
-
- @override
- List<ClassElementForLink_Class> get types {
- if (_types == null) {
- List<ClassDeclaration> declarationsForInference;
- if (_astForInference != null) {
- declarationsForInference = [];
- for (var declaration in _astForInference.declarations) {
- if (declaration is ClassDeclaration) {
- declarationsForInference.add(declaration);
- } else if (declaration is ClassTypeAlias) {
- declarationsForInference.add(null);
- }
- }
- assert(declarationsForInference.length == _unlinkedUnit.classes.length);
- }
- _types = <ClassElementForLink_Class>[];
- for (int i = 0; i < _unlinkedUnit.classes.length; i++) {
- var unlinkedClass = _unlinkedUnit.classes[i];
- _types.add(new ClassElementForLink_Class(
- this,
- unlinkedClass,
- false,
- declarationsForInference == null
- ? null
- : declarationsForInference[i]));
- }
- }
- return _types;
- }
-
- /// The linked representation of the compilation unit in the summary.
- LinkedUnit get _linkedUnit;
-
- /// Search the unit for a top level element with the given [name].
- /// If no name is found, return the singleton instance of
- /// [UndefinedElementForLink].
- ReferenceableElementForLink getContainedName(name) {
- if (_containedNames == null) {
- _containedNames = <String, ReferenceableElementForLink>{};
- // TODO(paulberry): what's the correct way to handle name conflicts?
- for (ClassElementForLink_Class type in types) {
- _containedNames[type.name] = type;
- }
- for (ClassElementForLink_Class mixin in mixins) {
- _containedNames[mixin.name] = mixin;
- }
- for (ClassElementForLink_Enum enm in enums) {
- _containedNames[enm.name] = enm;
- }
- for (TopLevelFunctionElementForLink function in functions) {
- _containedNames[function.name] = function;
- }
- for (PropertyAccessorElementForLink accessor in accessors) {
- _containedNames[accessor.name] = accessor;
- }
- for (FunctionTypeAliasElementForLink functionTypeAlias
- in functionTypeAliases) {
- _containedNames[functionTypeAlias.name] = functionTypeAlias;
- }
- // TODO(paulberry): fill in other top level entities (typedefs
- // and executables).
- }
- return _containedNames.putIfAbsent(
- name, () => UndefinedElementForLink.instance);
- }
-
- /// Compute the type referred to by the given linked type [slot] (interpreted
- /// in [context]). If there is no inferred type in the
- /// given slot, `dynamic` is returned.
- DartType getLinkedType(ElementImpl context, int slot);
-
- @override
- ClassElement getType(String className) =>
- CompilationUnitElementImpl.getTypeFromTypes(className, types);
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- /// Return the class element for the constructor referred to by the given
- /// [index] in [UnlinkedUnit.references]. If the reference is unresolved,
- /// return [UndefinedElementForLink.instance].
- ReferenceableElementForLink resolveConstructorClassRef(int index) {
- LinkedReference linkedReference = _linkedUnit.references[index];
- if (linkedReference.kind == ReferenceKind.classOrEnum) {
- return resolveRef(index);
- }
- if (index < _unlinkedUnit.references.length) {
- UnlinkedReference unlinkedReference = _unlinkedUnit.references[index];
- return resolveRef(unlinkedReference.prefixReference);
- }
- return UndefinedElementForLink.instance;
- }
-
- /// Return the element referred to by the given [index] in
- /// [UnlinkedUnit.references]. If the reference is unresolved,
- /// return [UndefinedElementForLink.instance].
- ReferenceableElementForLink resolveRef(int index) =>
- resolveRefToInfo(index).element;
-
- _ReferenceInfo resolveRefToInfo(int index) {
- if (_references[index] == null) {
- UnlinkedReference unlinkedReference =
- index < _unlinkedUnit.references.length
- ? _unlinkedUnit.references[index]
- : null;
- LinkedReference linkedReference = _linkedUnit.references[index];
- String name = unlinkedReference == null
- ? linkedReference.name
- : unlinkedReference.name;
- int containingReference = unlinkedReference == null
- ? linkedReference.containingReference
- : unlinkedReference.prefixReference;
- _ReferenceInfo enclosingInfo = containingReference != 0
- ? resolveRefToInfo(containingReference)
- : null;
- ReferenceableElementForLink element;
- if (containingReference != 0 &&
- _linkedUnit.references[containingReference].kind !=
- ReferenceKind.prefix) {
- element = enclosingInfo.element.getContainedName(name);
- } else if (linkedReference.dependency == 0) {
- if (linkedReference.kind == ReferenceKind.unresolved) {
- element = UndefinedElementForLink.instance;
- } else if (name == 'void') {
- element = enclosingElement._linker.voidElement;
- } else if (name == '*bottom*') {
- element = enclosingElement._linker.bottomElement;
- } else if (name == 'dynamic') {
- element = enclosingElement._linker.dynamicElement;
- } else {
- element = enclosingElement.getContainedName(name);
- }
- } else {
- LibraryElementForLink dependency =
- enclosingElement.buildImportedLibrary(linkedReference.dependency);
- element = dependency.getContainedName(name);
- }
- _references[index] = new _ReferenceInfo(
- enclosingInfo, element, name, linkedReference.numTypeParameters != 0);
- }
- return _references[index];
- }
-
- @override
- DartType resolveTypeRef(ElementImpl context, EntityRef entity,
- {bool defaultVoid: false,
- bool instantiateToBoundsAllowed: true,
- bool declaredType: false}) {
- if (entity == null) {
- if (defaultVoid) {
- return VoidTypeImpl.instance;
- } else {
- return DynamicTypeImpl.instance;
- }
- }
- DartType result;
- if (entity.paramReference != 0) {
- result = context.typeParameterContext
- .getTypeParameterType(entity.paramReference);
- } else if (entity.entityKind == EntityRefKind.genericFunctionType) {
- result = new GenericFunctionTypeElementForLink(
- this,
- context,
- entity.typeParameters,
- entity.syntheticReturnType,
- entity.syntheticParams)
- .type;
- } else if (entity.syntheticReturnType != null) {
- FunctionElementImpl element =
- new FunctionElementForLink_Synthetic(this, context, entity);
- result = element.type;
- } else if (entity.implicitFunctionTypeIndices.isNotEmpty) {
- DartType type = resolveRef(entity.reference).asStaticType;
- for (int index in entity.implicitFunctionTypeIndices) {
- type = (type as FunctionType).parameters[index].type;
- }
- result = type;
- } else {
- ReferenceableElementForLink element = resolveRef(entity.reference);
- bool implicitTypeArgumentsInUse = false;
-
- DartType getTypeArgument(int i) {
- if (i < entity.typeArguments.length) {
- return resolveTypeRef(context, entity.typeArguments[i]);
- } else {
- implicitTypeArgumentsInUse = true;
- if (!instantiateToBoundsAllowed) {
- // Do not allow buildType to instantiate the bounds; force dynamic.
- return DynamicTypeImpl.instance;
- } else {
- return null;
- }
- }
- }
-
- result = element.buildType(
- getTypeArgument, entity.implicitFunctionTypeIndices);
- if (implicitTypeArgumentsInUse) {
- _typesWithImplicitArguments[result] = true;
- }
- }
- var nullabilitySuffix = decodeNullabilitySuffix(entity.nullabilitySuffix);
- return (result as TypeImpl).withNullability(nullabilitySuffix);
- }
-
- @override
- String toString() => enclosingElement.toString();
-}
-
-/// Element representing a compilation unit which is part of the build
-/// unit being linked.
-class CompilationUnitElementInBuildUnit extends CompilationUnitElementForLink {
- @override
- final LinkedUnitBuilder _linkedUnit;
-
- @override
- final LibraryElementInBuildUnit enclosingElement;
-
- CompilationUnitElementInBuildUnit(
- this.enclosingElement,
- UnlinkedUnit unlinkedUnit,
- this._linkedUnit,
- int unitNum,
- String absoluteUri,
- CompilationUnit astForInference)
- : super(unlinkedUnit, unitNum, unlinkedUnit.references.length,
- absoluteUri, astForInference);
-
- @override
- bool get isInBuildUnit => true;
-
- @override
- LibraryElementInBuildUnit get library => enclosingElement;
-
- /// If this compilation unit already has a reference in its references table
- /// matching [dependency], [name], [numTypeParameters], [unitNum],
- /// [containingReference], and [kind], return its index. Otherwise add a new
- /// reference to the table and return its index.
- int addRawReference(String name,
- {int dependency: 0,
- int numTypeParameters: 0,
- int unitNum: 0,
- int containingReference: 0,
- ReferenceKind kind: ReferenceKind.classOrEnum}) {
- List<LinkedReferenceBuilder> linkedReferences = _linkedUnit.references;
- List<UnlinkedReference> unlinkedReferences = _unlinkedUnit.references;
- for (int i = 0; i < linkedReferences.length; i++) {
- LinkedReferenceBuilder linkedReference = linkedReferences[i];
- int candidateContainingReference = i < unlinkedReferences.length
- ? unlinkedReferences[i].prefixReference
- : linkedReference.containingReference;
- if (candidateContainingReference != 0 &&
- linkedReferences[candidateContainingReference].kind ==
- ReferenceKind.prefix) {
- // We don't need to match containing references when they are prefixes,
- // since the relevant information is in linkedReference.dependency.
- candidateContainingReference = 0;
- }
- if (linkedReference.dependency == dependency &&
- (i < unlinkedReferences.length
- ? unlinkedReferences[i].name
- : linkedReference.name) ==
- name &&
- linkedReference.numTypeParameters == numTypeParameters &&
- linkedReference.unit == unitNum &&
- candidateContainingReference == containingReference &&
- linkedReference.kind == kind) {
- return i;
- }
- }
- int result = linkedReferences.length;
- linkedReferences.add(new LinkedReferenceBuilder(
- dependency: dependency,
- name: name,
- numTypeParameters: numTypeParameters,
- unit: unitNum,
- containingReference: containingReference,
- kind: kind));
- return result;
- }
-
- /// If this compilation unit already has a reference in its references table
- /// to [element], return its index. Otherwise add a new reference to the
- /// table and return its index.
- int addReference(Element element) {
- if (element is ClassElementForLink) {
- return addRawReference(element.name,
- dependency: library.addDependency(element.library),
- numTypeParameters: element.typeParameters.length,
- unitNum: element.enclosingElement.unitNum);
- } else if (element is FunctionTypeAliasElementForLink) {
- return addRawReference(element.name,
- dependency: library.addDependency(element.library),
- numTypeParameters: element.typeParameters.length,
- unitNum: element.enclosingElement.unitNum,
- kind: ReferenceKind.typedef);
- } else if (element is ExecutableElementForLink_NonLocal) {
- ClassElementForLink_Class enclosingClass = element.enclosingClass;
- ReferenceKind kind;
- switch (element.serializedExecutable.kind) {
- case UnlinkedExecutableKind.functionOrMethod:
- kind = enclosingClass != null
- ? ReferenceKind.method
- : ReferenceKind.topLevelFunction;
- break;
- case UnlinkedExecutableKind.setter:
- kind = ReferenceKind.propertyAccessor;
- break;
- default:
- // TODO(paulberry): implement other cases as necessary
- throw new UnimplementedError('${element.serializedExecutable.kind}');
- }
- if (enclosingClass == null) {
- return addRawReference(element.name,
- numTypeParameters: element.typeParameters.length,
- dependency:
- library.addDependency(element.library as LibraryElementForLink),
- unitNum: element.compilationUnit.unitNum,
- kind: kind);
- } else {
- return addRawReference(element.name,
- numTypeParameters: element.typeParameters.length,
- containingReference: addReference(enclosingClass),
- kind: kind);
- }
- } else if (element is FunctionElementForLink_Initializer) {
- return addRawReference('',
- containingReference: addReference(element.enclosingElement),
- kind: ReferenceKind.function);
- } else if (element is TopLevelVariableElementForLink) {
- return addRawReference(element.name,
- dependency: library.addDependency(element.library),
- unitNum: element.compilationUnit.unitNum,
- kind: ReferenceKind.topLevelPropertyAccessor);
- } else if (element is FieldElementForLink_ClassField) {
- ClassElementForLink_Class enclosingClass = element.enclosingElement;
- // Note: even if the class has type parameters, we don't need to set
- // numTypeParameters because numTypeParameters does not count type
- // parameters of parent elements (see
- // [LinkedReference.numTypeParameters]).
- return addRawReference(element.name,
- containingReference: addReference(enclosingClass),
- kind: ReferenceKind.propertyAccessor);
- }
- // TODO(paulberry): implement other cases
- throw new UnimplementedError('${element.runtimeType}');
- }
-
- @override
- DartType getLinkedType(ElementImpl context, int slot) {
- // This method should only be called on compilation units that come from
- // dependencies, never on compilation units that are part of the current
- // build unit.
- throw new StateError(
- 'Linker tried to access linked type from current build unit');
- }
-
- /// Perform type inference and const cycle detection on this
- /// compilation unit.
- void link() {
- new InstanceMemberInferrer(
- library._linker.typeProvider,
- library._linker.inheritanceManager,
- ).inferCompilationUnit(this);
- for (TopLevelVariableElementForLink variable in topLevelVariables) {
- variable.link(this);
- }
- for (ClassElementForLink classElement in types) {
- classElement.link(this);
- }
- for (ClassElementForLink classElement in mixins) {
- classElement.link(this);
- }
- for (var functionTypeAlias in functionTypeAliases) {
- functionTypeAlias.link(this);
- }
- }
-
- /// Throw away any information stored in the summary by a previous call to
- /// [link].
- void unlink() {
- _linkedUnit.constCycles.clear();
- _linkedUnit.parametersInheritingCovariant.clear();
- _linkedUnit.references.length = _unlinkedUnit.references.length;
- _linkedUnit.types.clear();
- _linkedUnit.notSimplyBounded.clear();
- }
-
- /// Store the fact that the given [slot] represents a constant constructor
- /// that is part of a cycle.
- void _storeConstCycle(int slot) {
- _linkedUnit.constCycles.add(slot);
- }
-
- /// Store the fact that the given [slot] represents a parameter that inherits
- /// `@covariant` behavior.
- void _storeInheritsCovariant(int slot) {
- _linkedUnit.parametersInheritingCovariant.add(slot);
- }
-
- /// Store the given [linkedType] in the given [slot] of the this compilation
- /// unit's linked type list.
- void _storeLinkedType(int slot, DartType linkedType,
- TypeParameterSerializationContext typeParameterContext) {
- if (slot != 0) {
- if (linkedType != null && !linkedType.isDynamic) {
- _linkedUnit.types.add(_createLinkedType(
- linkedType, this, typeParameterContext,
- slot: slot));
- }
- }
- }
-
- /// Store the given error [error] in the given [slot].
- void _storeLinkedTypeError(int slot, TopLevelInferenceErrorBuilder error) {
- if (slot != 0) {
- if (error != null) {
- error.slot = slot;
- _linkedUnit.topLevelInferenceErrors.add(error);
- }
- }
- }
-}
-
-/// Element representing a compilation unit which is depended upon
-/// (either directly or indirectly) by the build unit being linked.
-///
-/// TODO(paulberry): ensure that inferred types in dependencies are properly
-/// resynthesized.
-class CompilationUnitElementInDependency extends CompilationUnitElementForLink {
- @override
- final LinkedUnit _linkedUnit;
-
- /// Set of slot ids corresponding to parameters that inherit `covariant`.
- Set<int> parametersInheritingCovariant;
-
- List<EntityRef> _linkedTypeRefs;
-
- @override
- final LibraryElementInDependency enclosingElement;
-
- CompilationUnitElementInDependency(
- this.enclosingElement,
- UnlinkedUnit unlinkedUnit,
- LinkedUnit linkedUnit,
- int unitNum,
- String absoluteUri)
- : _linkedUnit = linkedUnit,
- super(unlinkedUnit, unitNum, linkedUnit.references.length, absoluteUri,
- null) {
- parametersInheritingCovariant =
- _linkedUnit.parametersInheritingCovariant.toSet();
- // Make one pass through the linked types to determine the lengths for
- // _linkedTypeRefs and _linkedTypes. TODO(paulberry): add an int to the
- // summary to make this unnecessary.
- int maxLinkedTypeSlot = 0;
- for (EntityRef ref in _linkedUnit.types) {
- if (ref.slot > maxLinkedTypeSlot) {
- maxLinkedTypeSlot = ref.slot;
- }
- }
- // Initialize _linkedTypeRefs.
- _linkedTypeRefs = new List<EntityRef>(maxLinkedTypeSlot + 1);
- for (EntityRef ref in _linkedUnit.types) {
- _linkedTypeRefs[ref.slot] = ref;
- }
- }
-
- @override
- bool get isInBuildUnit => false;
-
- @override
- DartType getLinkedType(ElementImpl context, int slot) {
- if (slot < _linkedTypeRefs.length) {
- return resolveTypeRef(context, _linkedTypeRefs[slot]);
- } else {
- return DynamicTypeImpl.instance;
- }
- }
-}
-
-/// Instance of [ConstNode] representing a constant constructor.
-class ConstConstructorNode extends ConstNode {
- /// The [ConstructorElement] to which this node refers.
- final ConstructorElementForLink constructorElement;
-
- /// Once this node has been evaluated, indicates whether the
- /// constructor is free of constant evaluation cycles.
- bool isCycleFree = false;
-
- ConstConstructorNode(this.constructorElement);
-
- @override
- List<ConstNode> computeDependencies() {
- List<ConstNode> dependencies = <ConstNode>[];
- void safeAddDependency(ConstNode target) {
- if (target != null) {
- dependencies.add(target);
- }
- }
-
- UnlinkedExecutable unlinkedExecutable =
- constructorElement.serializedExecutable;
- ClassElementForLink_Class enclosingClass =
- constructorElement.enclosingElement;
- ConstructorElementForLink redirectedConstructor =
- _getFactoryRedirectedConstructor();
- if (redirectedConstructor != null) {
- if (redirectedConstructor._constNode != null) {
- safeAddDependency(redirectedConstructor._constNode);
- }
- } else if (unlinkedExecutable.isFactory) {
- // Factory constructor, but getConstRedirectedConstructor returned
- // null. This can happen if we're visiting one of the special external
- // const factory constructors in the SDK, or if the code contains
- // errors (such as delegating to a non-const constructor, or delegating
- // to a constructor that can't be resolved). In any of these cases,
- // we'll evaluate calls to this constructor without having to refer to
- // any other constants. So we don't need to report any dependencies.
- } else {
- ClassElementForLink superClass = enclosingClass.supertype?.element;
- bool defaultSuperInvocationNeeded = true;
- for (UnlinkedConstructorInitializer constructorInitializer
- in constructorElement.serializedExecutable.constantInitializers) {
- if (constructorInitializer.kind ==
- UnlinkedConstructorInitializerKind.superInvocation) {
- defaultSuperInvocationNeeded = false;
- if (superClass != null && !superClass.isObject) {
- ConstructorElementForLink constructor = superClass
- .getContainedName(constructorInitializer.name)
- .asConstructor;
- safeAddDependency(constructor?._constNode);
- }
- } else if (constructorInitializer.kind ==
- UnlinkedConstructorInitializerKind.thisInvocation) {
- defaultSuperInvocationNeeded = false;
- ConstructorElementForLink constructor = constructorElement
- .enclosingClass
- .getContainedName(constructorInitializer.name)
- .asConstructor;
- safeAddDependency(constructor?._constNode);
- }
- CompilationUnitElementForLink compilationUnit =
- constructorElement.enclosingElement.enclosingElement;
- collectDependencies(
- dependencies, constructorInitializer.expression, compilationUnit);
- for (UnlinkedExpr unlinkedConst in constructorInitializer.arguments) {
- collectDependencies(dependencies, unlinkedConst, compilationUnit);
- }
- }
-
- if (defaultSuperInvocationNeeded) {
- // No explicit superconstructor invocation found, so we need to
- // manually insert a reference to the implicit superconstructor.
- if (superClass != null && !superClass.isObject) {
- ConstructorElementForLink unnamedConstructor =
- superClass.unnamedConstructor;
- safeAddDependency(unnamedConstructor?._constNode);
- }
- }
- for (FieldElementForLink field in enclosingClass.fields) {
- // Note: non-static const isn't allowed but we handle it anyway so
- // that we won't be confused by incorrect code.
- if ((field.isFinal || field.isConst) && !field.isStatic) {
- safeAddDependency(field.getter.asConstVariable);
- }
- }
- for (ParameterElementForLink parameterElement
- in constructorElement.parameters) {
- safeAddDependency(parameterElement._constNode);
- }
- }
- return dependencies;
- }
-
- /// If [constructorElement] redirects to another constructor via a factory
- /// redirect, return the constructor it redirects to.
- ConstructorElementForLink _getFactoryRedirectedConstructor() {
- EntityRef redirectedConstructor =
- constructorElement.serializedExecutable.redirectedConstructor;
- if (redirectedConstructor != null) {
- return constructorElement.compilationUnit
- .resolveRef(redirectedConstructor.reference)
- .asConstructor;
- } else {
- return null;
- }
- }
-}
-
-/// Specialization of [DependencyWalker] for detecting constant
-/// evaluation cycles.
-class ConstDependencyWalker extends DependencyWalker<ConstNode> {
- @override
- void evaluate(ConstNode v) {
- if (v is ConstConstructorNode) {
- v.isCycleFree = true;
- }
- v.isEvaluated = true;
- }
-
- @override
- void evaluateScc(List<ConstNode> scc) {
- for (ConstNode v in scc) {
- if (v is ConstConstructorNode) {
- v.isCycleFree = false;
- }
- v.isEvaluated = true;
- }
- }
-}
-
-/// Specialization of [Node] used to construct the constant evaluation
-/// dependency graph.
-abstract class ConstNode extends Node<ConstNode> {
- @override
- bool isEvaluated = false;
-
- /// Collect the dependencies in [unlinkedConst] (which should be
- /// interpreted relative to [compilationUnit]) and store them in
- /// [dependencies].
- void collectDependencies(
- List<ConstNode> dependencies,
- UnlinkedExpr unlinkedConst,
- CompilationUnitElementForLink compilationUnit) {
- if (unlinkedConst == null) {
- return;
- }
- int refPtr = 0;
- int intPtr = 0;
- for (UnlinkedExprOperation operation in unlinkedConst.operations) {
- switch (operation) {
- case UnlinkedExprOperation.pushInt:
- intPtr++;
- break;
- case UnlinkedExprOperation.pushLongInt:
- int numInts = unlinkedConst.ints[intPtr++];
- intPtr += numInts;
- break;
- case UnlinkedExprOperation.concatenate:
- intPtr++;
- break;
- case UnlinkedExprOperation.pushReference:
- EntityRef ref = unlinkedConst.references[refPtr++];
- ConstVariableNode variable =
- compilationUnit.resolveRef(ref.reference).asConstVariable;
- if (variable != null) {
- dependencies.add(variable);
- }
- break;
- case UnlinkedExprOperation.makeUntypedList:
- case UnlinkedExprOperation.makeUntypedMap:
- case UnlinkedExprOperation.makeUntypedSet:
- case UnlinkedExprOperation.makeUntypedSetOrMap:
- case UnlinkedExprOperation.forParts:
- case UnlinkedExprOperation.variableDeclaration:
- case UnlinkedExprOperation.forInitializerDeclarationsUntyped:
- intPtr++;
- break;
- case UnlinkedExprOperation.assignToRef:
- case UnlinkedExprOperation.forEachPartsWithTypedDeclaration:
- refPtr++;
- break;
- case UnlinkedExprOperation.invokeMethodRef:
- EntityRef ref = unlinkedConst.references[refPtr++];
- ConstVariableNode variable =
- compilationUnit.resolveRef(ref.reference).asConstVariable;
- if (variable != null) {
- dependencies.add(variable);
- }
- intPtr += 2;
- int numTypeArguments = unlinkedConst.ints[intPtr++];
- refPtr += numTypeArguments;
- break;
- case UnlinkedExprOperation.invokeMethod:
- intPtr += 2;
- int numTypeArguments = unlinkedConst.ints[intPtr++];
- refPtr += numTypeArguments;
- break;
- case UnlinkedExprOperation.makeTypedList:
- case UnlinkedExprOperation.makeTypedSet:
- case UnlinkedExprOperation.forInitializerDeclarationsTyped:
- refPtr++;
- intPtr++;
- break;
- case UnlinkedExprOperation.makeTypedMap:
- case UnlinkedExprOperation.makeTypedMap2:
- refPtr += 2;
- intPtr++;
- break;
- case UnlinkedExprOperation.invokeConstructor:
- EntityRef ref = unlinkedConst.references[refPtr++];
- ConstructorElementForLink element =
- compilationUnit.resolveRef(ref.reference).asConstructor;
- if (element?._constNode != null) {
- dependencies.add(element._constNode);
- }
- intPtr += 2;
- break;
- case UnlinkedExprOperation.typeCast:
- case UnlinkedExprOperation.typeCheck:
- refPtr++;
- break;
- case UnlinkedExprOperation.pushLocalFunctionReference:
- intPtr += 2;
- break;
- default:
- break;
- }
- }
- assert(refPtr == unlinkedConst.references.length);
- assert(intPtr == unlinkedConst.ints.length);
- }
-}
-
-/// Instance of [ConstNode] representing a parameter with a default
-/// value.
-class ConstParameterNode extends ConstNode {
- /// The [ParameterElement] to which this node refers.
- final ParameterElementForLink parameterElement;
-
- ConstParameterNode(this.parameterElement);
-
- @override
- List<ConstNode> computeDependencies() {
- List<ConstNode> dependencies = <ConstNode>[];
- collectDependencies(
- dependencies,
- parameterElement.unlinkedParam.initializer?.bodyExpr,
- parameterElement.compilationUnit);
- return dependencies;
- }
-}
-
-/// Element representing a constructor resynthesized from a summary
-/// during linking.
-class ConstructorElementForLink extends ExecutableElementForLink_NonLocal
- with ReferenceableElementForLink
- implements ConstructorElementImpl {
- /// If this is a `const` constructor and the enclosing library is
- /// part of the build unit being linked, the constructor's node in
- /// the constant evaluation dependency graph. Otherwise `null`.
- ConstConstructorNode _constNode;
-
- ConstructorElementForLink(ClassElementForLink_Class enclosingClass,
- UnlinkedExecutable unlinkedExecutable)
- : super(enclosingClass.enclosingElement, enclosingClass,
- unlinkedExecutable) {
- if (enclosingClass.enclosingElement.isInBuildUnit &&
- serializedExecutable != null &&
- serializedExecutable.constCycleSlot != 0) {
- _constNode = new ConstConstructorNode(this);
- }
- }
-
- @override
- ConstructorElementForLink get asConstructor => this;
-
- @override
- ClassElementImpl get enclosingElement =>
- super.enclosingClass as ClassElementImpl;
-
- @override
- String get identifier => name;
-
- @override
- bool get isConst => serializedExecutable.isConst;
-
- @override
- bool get isCycleFree {
- if (!_constNode.isEvaluated) {
- new ConstDependencyWalker().walk(_constNode);
- }
- return _constNode.isCycleFree;
- }
-
- @override
- DartType get returnType => enclosingElement.type;
-
- @override
- List<TypeParameterElement> get typeParameters => const [];
-
- /// Perform const cycle detection on this constructor.
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- if (_constNode != null && !isCycleFree) {
- compilationUnit._storeConstCycle(serializedExecutable.constCycleSlot);
- }
- // TODO(paulberry): call super.
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/// A synthetic constructor.
-class ConstructorElementForLink_Synthetic extends ConstructorElementForLink {
- ConstructorElementForLink_Synthetic(
- ClassElementForLink_Class enclosingElement)
- : super(enclosingElement, null);
-
- @override
- String get name => '';
-
- @override
- List<ParameterElement> get parameters => const <ParameterElement>[];
-}
-
-/// Instance of [ConstNode] representing a constant field or constant
-/// top level variable.
-class ConstVariableNode extends ConstNode {
- /// The [FieldElement] or [TopLevelVariableElement] to which this
- /// node refers.
- final VariableElementForLink variableElement;
-
- ConstVariableNode(this.variableElement);
-
- @override
- List<ConstNode> computeDependencies() {
- List<ConstNode> dependencies = <ConstNode>[];
- collectDependencies(
- dependencies,
- variableElement.unlinkedVariable.initializer?.bodyExpr,
- variableElement.compilationUnit);
- return dependencies;
- }
-}
-
-/// Stub implementation of [AnalysisContext] which provides just those methods
-/// needed during linking.
-class ContextForLink implements AnalysisContext {
- final Linker _linker;
-
- ContextForLink(this._linker);
-
- @override
- AnalysisOptions get analysisOptions => _linker.analysisOptions;
-
- @override
- TypeProvider get typeProvider => _linker.typeProvider;
-
- @override
- TypeSystem get typeSystem => _linker.typeSystem;
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
/**
* An instance of [DependencyWalker] contains the core algorithms for
* walking a dependency graph and evaluating nodes in a safe order.
@@ -2275,1988 +128,6 @@
}
}
-/// Base class for executable elements resynthesized from a summary during
-/// linking.
-abstract class ExecutableElementForLink
- with TypeParameterizedElementMixin, ParameterParentElementForLink
- implements ExecutableElementImpl {
- /// The unlinked representation of the method in the summary.
- final UnlinkedExecutable serializedExecutable;
-
- DartType _declaredReturnType;
- DartType _inferredReturnType;
- FunctionTypeImpl _type;
- String _name;
- String _displayName;
-
- final CompilationUnitElementForLink compilationUnit;
-
- ExecutableElementForLink(this.compilationUnit, this.serializedExecutable);
-
- @override
- ContextForLink get context => compilationUnit.context;
-
- /// If the executable element had an explicitly declared return type, return
- /// it. Otherwise return `null`.
- DartType get declaredReturnType {
- if (serializedExecutable.returnType == null) {
- return null;
- } else {
- return _declaredReturnType ??=
- compilationUnit.resolveTypeRef(this, serializedExecutable.returnType);
- }
- }
-
- @override
- String get displayName {
- if (_displayName == null) {
- _displayName = serializedExecutable.name;
- if (serializedExecutable.kind == UnlinkedExecutableKind.setter) {
- _displayName = _displayName.substring(0, _displayName.length - 1);
- }
- }
- return _displayName;
- }
-
- @override
- CompilationUnitElementImpl get enclosingUnit => compilationUnit;
-
- /// Return a list containing all of the functions defined within this
- /// executable element.
- List<FunctionElement> get functions {
- return [];
- }
-
- @override
- bool get hasImplicitReturnType => serializedExecutable.returnType == null;
-
- @override
- List<int> get implicitFunctionTypeIndices => const <int>[];
-
- /// Return the inferred return type of the executable element. Should only be
- /// called if no return type was explicitly declared.
- DartType get inferredReturnType {
- // We should only try to infer a return type when none is explicitly
- // declared.
- assert(serializedExecutable.returnType == null);
- if (Linker._initializerTypeInferenceCycle != null &&
- Linker._initializerTypeInferenceCycle ==
- compilationUnit.library.libraryCycleForLink) {
- // We are currently computing the type of an initializer expression in the
- // current library cycle, so type inference results should be ignored.
- return _computeDefaultReturnType();
- }
- if (_inferredReturnType == null) {
- if (serializedExecutable.kind == UnlinkedExecutableKind.constructor) {
- // TODO(paulberry): implement.
- throw new UnimplementedError();
- } else if (compilationUnit.isInBuildUnit) {
- _inferredReturnType = _computeDefaultReturnType();
- } else {
- _inferredReturnType = compilationUnit.getLinkedType(
- this, serializedExecutable.inferredReturnTypeSlot);
- }
- }
- return _inferredReturnType;
- }
-
- @override
- bool get isAbstract => serializedExecutable.isAbstract;
-
- @override
- bool get isGenerator => serializedExecutable.isGenerator;
-
- @override
- bool get isStatic => serializedExecutable.isStatic;
-
- @override
- bool get isSynthetic => false;
-
- @override
- LibraryElement get library => enclosingElement.library;
-
- @override
- get linkedNode => null;
-
- @override
- String get name {
- if (_name == null) {
- _name = serializedExecutable.name;
- if (_name == '-' && serializedExecutable.parameters.isEmpty) {
- _name = 'unary-';
- }
- }
- return _name;
- }
-
- @override
- DartType get returnType => declaredReturnType ?? inferredReturnType;
-
- @override
- void set returnType(DartType inferredType) {
- _inferredReturnType = inferredType;
- }
-
- @override
- AnalysisSession get session => compilationUnit.session;
-
- @override
- FunctionTypeImpl get type => _type ??= new FunctionTypeImpl(this);
-
- @override
- TypeParameterizedElementMixin get typeParameterContext => this;
-
- @override
- List<UnlinkedParam> get unlinkedParameters => serializedExecutable.parameters;
-
- @override
- List<UnlinkedTypeParam> get unlinkedTypeParams =>
- serializedExecutable.typeParameters;
-
- @override
- bool isAccessibleIn(LibraryElement library) =>
- !Identifier.isPrivateName(name) || identical(this.library, library);
-
- /// Compute the default return type for this type of executable element (if no
- /// return type is declared and strong mode type inference cannot infer a
- /// better return type).
- DartType _computeDefaultReturnType() {
- var kind = serializedExecutable.kind;
- var isMethod = kind == UnlinkedExecutableKind.functionOrMethod;
- var isSetter = kind == UnlinkedExecutableKind.setter;
- if ((isSetter || isMethod && serializedExecutable.name == '[]=')) {
- // In strong mode, setters and `[]=` operators without an explicit
- // return type are considered to return `void`.
- return VoidTypeImpl.instance;
- } else {
- return DynamicTypeImpl.instance;
- }
- }
-}
-
-/// Base class for executable elements that are resynthesized from a summary
-/// during linking and are not local functions.
-abstract class ExecutableElementForLink_NonLocal
- extends ExecutableElementForLink {
- /// Return the class in which this executable appears, maybe `null` for a
- /// top-level function.
- final ClassMemberContainerForLink enclosingClass;
-
- ExecutableElementForLink_NonLocal(
- CompilationUnitElementForLink compilationUnit,
- this.enclosingClass,
- UnlinkedExecutable unlinkedExecutable)
- : super(compilationUnit, unlinkedExecutable);
-
- @override
- Element get enclosingElement => enclosingClass ?? compilationUnit;
-
- @override
- TypeParameterizedElementMixin get enclosingTypeParameterContext =>
- enclosingClass;
-
- /// Store the results of type inference for this method in [compilationUnit].
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- if (serializedExecutable.returnType == null) {
- compilationUnit._storeLinkedType(
- serializedExecutable.inferredReturnTypeSlot,
- inferredReturnType,
- this);
- }
- for (ParameterElementForLink parameterElement in parameters) {
- parameterElement.link(compilationUnit);
- }
- }
-}
-
-class ExprTypeComputer {
- final ExprBuilder _builder;
-
- final AstRewriteVisitor _astRewriteVisitor;
-
- final ResolverVisitor _resolverVisitor;
-
- final TypeResolverVisitor _typeResolverVisitor;
-
- final VariableResolverVisitor _variableResolverVisitor;
-
- final PartialResolverVisitor _partialResolverVisitor;
-
- final Linker _linker;
-
- FunctionElementForLink_Local _functionElement;
-
- factory ExprTypeComputer(FunctionElementForLink_Local functionElement) {
- ClassElement enclosingClass =
- functionElement.getAncestor((e) => e is ClassElement);
- CompilationUnitElementForLink unit = functionElement.compilationUnit;
- LibraryElementForLink library = unit.enclosingElement;
- Linker linker = library._linker;
- TypeProvider typeProvider = linker.typeProvider;
- var unlinkedExecutable = functionElement.serializedExecutable;
- UnlinkedExpr unlinkedConst = unlinkedExecutable.bodyExpr;
- var errorListener = AnalysisErrorListener.NULL_LISTENER;
- var source = unit.source;
- var astRewriteVisitor = new AstRewriteVisitor(
- linker.typeSystem, library, source, typeProvider, errorListener);
- EnclosedScope nameScope = new LibraryScope(library);
- if (enclosingClass != null) {
- nameScope = new ClassScope(
- new TypeParameterScope(nameScope, enclosingClass), enclosingClass);
- }
- var inheritance = new InheritanceManager3(linker.typeSystem);
- // Note: this is a bit of a hack; we ought to use the feature set for the
- // compilation unit being analyzed, but that's not feasible because sumaries
- // don't record the feature set. This should be resolved when we switch to
- // the "summary2" mechanism.
- var featureSet = FeatureSet.fromEnableFlags([]);
- var resolverVisitor = new ResolverVisitor(
- inheritance, library, source, typeProvider, errorListener,
- featureSet: featureSet,
- nameScope: nameScope,
- propagateTypes: false,
- reportConstEvaluationErrors: false);
- var typeResolverVisitor = new TypeResolverVisitor(
- library, source, typeProvider, errorListener,
- featureSet: featureSet, nameScope: nameScope);
- var variableResolverVisitor = new VariableResolverVisitor(
- library, source, typeProvider, errorListener,
- nameScope: nameScope, localVariableInfo: LocalVariableInfo());
- var partialResolverVisitor = new PartialResolverVisitor(
- inheritance, library, source, typeProvider, errorListener, featureSet,
- nameScope: nameScope);
- return new ExprTypeComputer._(
- unit._unitResynthesizer,
- astRewriteVisitor,
- resolverVisitor,
- typeResolverVisitor,
- variableResolverVisitor,
- partialResolverVisitor,
- linker,
- errorListener,
- functionElement,
- unlinkedConst,
- unlinkedExecutable.localFunctions);
- }
-
- ExprTypeComputer._(
- UnitResynthesizer unitResynthesizer,
- this._astRewriteVisitor,
- this._resolverVisitor,
- this._typeResolverVisitor,
- this._variableResolverVisitor,
- this._partialResolverVisitor,
- this._linker,
- AnalysisErrorListener _errorListener,
- this._functionElement,
- UnlinkedExpr unlinkedConst,
- List<UnlinkedExecutable> localFunctions)
- : _builder = new ExprBuilder(
- unitResynthesizer, _functionElement, unlinkedConst,
- requireValidConst: false,
- localFunctions: localFunctions,
- becomeSetOrMap: false);
-
- TopLevelInferenceErrorKind get errorKind {
- // TODO(paulberry): should we return TopLevelInferenceErrorKind.assignment
- // sometimes?
- return null;
- }
-
- DartType compute() {
- Expression expression;
- if (_linker.getAst != null) {
- var expressionForInference = _functionElement._expressionForInference;
- if (expressionForInference != null) {
- expression = AstCloner().cloneNode(expressionForInference);
- expression.accept(LocalElementBuilder(ElementHolder(), null));
- }
- } else if (_builder.hasNonEmptyExpr) {
- expression = _builder.build();
- }
- if (expression == null) {
- // No function body was stored for this function, so we can't infer its
- // return type. Assume `dynamic`.
- return DynamicTypeImpl.instance;
- }
- var container =
- astFactory.expressionFunctionBody(null, null, expression, null);
- expression.accept(_astRewriteVisitor);
- expression = container.expression;
- if (_linker.getAst != null) {
- expression.accept(_typeResolverVisitor);
- }
- expression.accept(_variableResolverVisitor);
- if (_linker.getAst != null) {
- expression.accept(_partialResolverVisitor);
- }
- expression.accept(_resolverVisitor);
- return expression.staticType;
- }
-}
-
-class ExtensionElementForLink
- with ReferenceableElementForLink
- implements ClassMemberContainerForLink, ExtensionElementImpl {
- @override
- final CompilationUnitElementForLink enclosingElement;
-
- final UnlinkedExtension _unlinkedExtension;
-
- Map<String, ReferenceableElementForLink> _containedNames;
-
- List<PropertyAccessorElementForLink> _accessors;
- List<FieldElementForLink_ClassField> _fields;
- List<MethodElement> _methods;
-
- ExtensionElementForLink(this.enclosingElement, this._unlinkedExtension);
-
- @override
- List<PropertyAccessorElementForLink> get accessors {
- if (_accessors == null) {
- _accessors = <PropertyAccessorElementForLink>[];
- Map<String, SyntheticVariableElementForLink> syntheticVariables =
- <String, SyntheticVariableElementForLink>{};
- for (UnlinkedExecutable unlinkedExecutable
- in _unlinkedExtension.executables) {
- if (unlinkedExecutable.kind == UnlinkedExecutableKind.getter ||
- unlinkedExecutable.kind == UnlinkedExecutableKind.setter) {
- String name = unlinkedExecutable.name;
- if (unlinkedExecutable.kind == UnlinkedExecutableKind.setter) {
- assert(name.endsWith('='));
- name = name.substring(0, name.length - 1);
- }
- SyntheticVariableElementForLink syntheticVariable = syntheticVariables
- .putIfAbsent(name, () => new SyntheticVariableElementForLink());
- PropertyAccessorElementForLink_Executable accessor =
- new PropertyAccessorElementForLink_Executable(enclosingElement,
- this, unlinkedExecutable, syntheticVariable);
- _accessors.add(accessor);
- if (unlinkedExecutable.kind == UnlinkedExecutableKind.getter) {
- syntheticVariable._getter = accessor;
- } else {
- syntheticVariable._setter = accessor;
- }
- }
- }
- for (FieldElementForLink_ClassField field in fields) {
- _accessors.add(field.getter);
- if (!field.isConst && !field.isFinal) {
- _accessors.add(field.setter);
- }
- }
- }
- return _accessors;
- }
-
- @override
- List<FieldElementForLink_ClassField> get fields {
- if (_fields == null) {
- _fields = <FieldElementForLink_ClassField>[];
- for (int i = 0; i < _unlinkedExtension.fields.length; i++) {
- var field = _unlinkedExtension.fields[i];
- _fields.add(new FieldElementForLink_ClassField(this, field, null));
- }
- }
- return _fields;
- }
-
- @override
- List<MethodElement> get methods {
- if (_methods == null) {
- _methods = <MethodElementForLink>[];
- for (UnlinkedExecutable unlinkedExecutable
- in _unlinkedExtension.executables) {
- if (unlinkedExecutable.kind ==
- UnlinkedExecutableKind.functionOrMethod) {
- _methods.add(new MethodElementForLink(this, unlinkedExecutable));
- }
- }
- }
- return _methods;
- }
-
- @override
- String get name => _unlinkedExtension.name;
-
- @override
- ReferenceableElementForLink getContainedName(String name) {
- if (_containedNames == null) {
- _containedNames = <String, ReferenceableElementForLink>{};
- // TODO(paulberry): what's the correct way to handle name conflicts?
- for (PropertyAccessorElementForLink accessor in accessors) {
- _containedNames[accessor.name] = accessor;
- }
- for (MethodElementForLink method in methods) {
- _containedNames[method.name] = method;
- }
- }
- return _containedNames.putIfAbsent(
- name, () => UndefinedElementForLink.instance);
- }
-
- @override
- PropertyAccessorElement getGetter(String getterName) {
- for (PropertyAccessorElement accessor in accessors) {
- if (accessor.isGetter && accessor.name == getterName) {
- return accessor;
- }
- }
- return null;
- }
-
- @override
- MethodElement getMethod(String methodName) {
- for (MethodElement method in methods) {
- if (method.name == methodName) {
- return method;
- }
- }
- return null;
- }
-
- @override
- PropertyAccessorElement getSetter(String setterName) =>
- AbstractClassElementImpl.getSetterFromAccessors(setterName, accessors);
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/// Element representing a field resynthesized from a summary during
-/// linking.
-abstract class FieldElementForLink implements FieldElement {
- @override
- PropertyAccessorElementForLink get getter;
-
- @override
- PropertyAccessorElementForLink get setter;
-}
-
-/// Specialization of [FieldElementForLink] for class fields.
-class FieldElementForLink_ClassField extends VariableElementForLink
- implements FieldElementForLink {
- @override
- final ClassMemberContainerForLink enclosingElement;
-
- /// If this is an instance field, the type that was computed by
- /// [InstanceMemberInferrer] (if any). Otherwise `null`.
- DartType _inferredInstanceType;
-
- TopLevelInferenceErrorBuilder _inferenceError;
-
- FieldElementForLink_ClassField(ClassMemberContainerForLink enclosingElement,
- UnlinkedVariable unlinkedVariable, Expression initializerForInference)
- : enclosingElement = enclosingElement,
- super(unlinkedVariable, enclosingElement.enclosingElement,
- initializerForInference);
-
- @override
- bool get isLate => unlinkedVariable.isLate;
-
- @override
- bool get isStatic => unlinkedVariable.isStatic;
-
- @override
- DartType get type {
- if (declaredType != null) {
- return declaredType;
- }
- if (Linker._isPerformingVariableTypeInference && !isStatic) {
- return DynamicTypeImpl.instance;
- }
- return inferredType;
- }
-
- @override
- void set type(DartType inferredType) {
- assert(!isStatic);
- assert(_inferredInstanceType == null);
- _inferredInstanceType = inferredType;
- }
-
- @override
- TypeParameterizedElementMixin get _typeParameterContext => enclosingElement;
-
- /// Store the results of type inference for this field in
- /// [compilationUnit].
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- if (hasImplicitType) {
- compilationUnit._storeLinkedType(
- unlinkedVariable.inferredTypeSlot,
- isStatic ? inferredType : _inferredInstanceType,
- _typeParameterContext);
- compilationUnit._storeLinkedTypeError(
- unlinkedVariable.inferredTypeSlot, _inferenceError);
- if (initializer != null) {
- compilationUnit._storeLinkedTypeError(
- unlinkedVariable.inferredTypeSlot, initializer._inferenceError);
- initializer.link(compilationUnit);
- }
- }
- }
-
- void setInferenceError(TopLevelInferenceErrorBuilder error) {
- assert(_inferenceError == null);
- _inferenceError = error;
- }
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-/// Specialization of [FieldElementForLink] for enum fields.
-class FieldElementForLink_EnumField extends FieldElementForLink
- implements FieldElement {
- PropertyAccessorElementForLink_EnumField _getter;
-
- @override
- final ClassElementForLink_Enum enclosingElement;
-
- FieldElementForLink_EnumField(this.enclosingElement);
-
- @override
- PropertyAccessorElementForLink_EnumField get getter =>
- _getter ??= new PropertyAccessorElementForLink_EnumField(this);
-
- @override
- bool get isSynthetic => false;
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-/// Specialization of [FieldElementForLink] for the 'index' enum field.
-class FieldElementForLink_EnumField_index
- extends FieldElementForLink_EnumField {
- FieldElementForLink_EnumField_index(ClassElementForLink_Enum enclosingElement)
- : super(enclosingElement);
-
- @override
- bool get isStatic => false;
-
- @override
- String get name => 'index';
-
- @override
- DartType get type =>
- enclosingElement.enclosingElement.library._linker.typeProvider.intType;
-}
-
-/// Specialization of [FieldElementForLink] for enum fields.
-class FieldElementForLink_EnumField_value
- extends FieldElementForLink_EnumField {
- /// The unlinked representation of the field in the summary.
- final UnlinkedEnumValue unlinkedEnumValue;
-
- FieldElementForLink_EnumField_value(
- ClassElementForLink_Enum enclosingElement, this.unlinkedEnumValue)
- : super(enclosingElement);
-
- @override
- bool get isStatic => true;
-
- @override
- String get name => unlinkedEnumValue.name;
-
- @override
- DartType get type => enclosingElement.type;
-}
-
-/// Specialization of [FieldElementForLink] for the 'values' enum field.
-class FieldElementForLink_EnumField_values
- extends FieldElementForLink_EnumField {
- FieldElementForLink_EnumField_values(
- ClassElementForLink_Enum enclosingElement)
- : super(enclosingElement);
-
- @override
- bool get isStatic => true;
-
- @override
- String get name => 'values';
-
- @override
- DartType get type => enclosingElement.valuesType;
-}
-
-class FieldFormalParameterElementForLink extends ParameterElementForLink
- implements FieldFormalParameterElement {
- FieldElement _field;
- DartType _type;
-
- FieldFormalParameterElementForLink(
- ParameterParentElementForLink enclosingElement,
- UnlinkedParam unlinkedParam,
- TypeParameterizedElementMixin typeParameterContext,
- CompilationUnitElementForLink compilationUnit,
- int parameterIndex)
- : super(enclosingElement, unlinkedParam, typeParameterContext,
- compilationUnit, parameterIndex);
-
- @override
- FieldElement get field {
- if (_field == null) {
- Element enclosingConstructor = enclosingElement;
- if (enclosingConstructor is ConstructorElement) {
- Element enclosingClass = enclosingConstructor.enclosingElement;
- if (enclosingClass is ClassElement) {
- FieldElement field = enclosingClass.getField(unlinkedParam.name);
- if (field != null && !field.isSynthetic) {
- _field = field;
- }
- }
- }
- }
- return _field;
- }
-
- @override
- bool get isInitializingFormal => true;
-
- @override
- DartType get type {
- return _type ??= field?.type ?? DynamicTypeImpl.instance;
- }
-}
-
-/// Element representing a function-typed parameter resynthesied from a summary
-/// during linking.
-class FunctionElementForLink_FunctionTypedParam
- with ParameterParentElementForLink
- implements FunctionElement {
- @override
- final ParameterElementForLink enclosingElement;
-
- @override
- final TypeParameterizedElementMixin typeParameterContext;
-
- @override
- final List<UnlinkedParam> unlinkedParameters;
-
- DartType _returnType;
- List<int> _implicitFunctionTypeIndices;
-
- FunctionElementForLink_FunctionTypedParam(this.enclosingElement,
- this.typeParameterContext, this.unlinkedParameters);
-
- @override
- List<int> get implicitFunctionTypeIndices {
- if (_implicitFunctionTypeIndices == null) {
- _implicitFunctionTypeIndices = enclosingElement
- .enclosingElement.implicitFunctionTypeIndices
- .toList();
- _implicitFunctionTypeIndices.add(enclosingElement._parameterIndex);
- }
- return _implicitFunctionTypeIndices;
- }
-
- @override
- bool get isSynthetic => true;
-
- @override
- DartType get returnType {
- if (_returnType == null) {
- if (enclosingElement.unlinkedParam.type == null) {
- _returnType = DynamicTypeImpl.instance;
- } else {
- _returnType = enclosingElement.compilationUnit.resolveTypeRef(
- enclosingElement, enclosingElement.unlinkedParam.type);
- }
- }
- return _returnType;
- }
-
- @override
- List<TypeParameterElement> get typeParameters => const [];
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/// Element representing the initializer expression of a variable.
-class FunctionElementForLink_Initializer
- with ReferenceableElementForLink, TypeParameterizedElementMixin
- implements FunctionElementForLink_Local {
- /// The variable for which this element is the initializer.
- final VariableElementForLink _variable;
-
- @override
- final Expression _expressionForInference;
-
- /// The type inference node for this function, or `null` if it hasn't been
- /// computed yet.
- TypeInferenceNode _typeInferenceNode;
-
- List<FunctionElementForLink_Local_NonSynthetic> _functions;
- DartType _inferredReturnType;
- TopLevelInferenceErrorBuilder _inferenceError;
-
- FunctionElementForLink_Initializer(
- this._variable, this._expressionForInference);
-
- @override
- TypeInferenceNode get asTypeInferenceNode =>
- _typeInferenceNode ??= new TypeInferenceNode(this);
-
- @override
- CompilationUnitElementForLink get compilationUnit =>
- _variable.compilationUnit;
-
- @override
- VariableElementForLink get enclosingElement => _variable;
-
- TypeParameterizedElementMixin get enclosingTypeParameterContext =>
- _variable.enclosingElement is ClassElementForLink
- ? _variable.enclosingElement
- : null;
-
- @override
- CompilationUnitElementForLink get enclosingUnit => _variable.compilationUnit;
-
- @override
- List<FunctionElementForLink_Local_NonSynthetic> get functions =>
- _functions ??= _computeFunctions();
-
- @override
- String get identifier => '';
-
- @override
- bool get isAsynchronous => serializedExecutable.isAsynchronous;
-
- @override
- get linkedNode => null;
-
- @override
- DartType get returnType {
- // If this is a variable whose type needs inferring, infer it.
- if (_variable.hasImplicitType) {
- return _variable.inferredType;
- } else {
- // There's no reason linking should need to access the type of
- // this FunctionElement, since the variable doesn't need its
- // type inferred.
- assert(false);
- // But for robustness, return the dynamic type.
- return DynamicTypeImpl.instance;
- }
- }
-
- @override
- void set returnType(DartType newType) {
- // InstanceMemberInferrer stores the new type both here and on the variable
- // element. We don't need to record both values, so we ignore it here.
- }
-
- @override
- UnlinkedExecutable get serializedExecutable =>
- _variable.unlinkedVariable.initializer;
-
- @override
- TypeParameterizedElementMixin get typeParameterContext => this;
-
- @override
- List<UnlinkedTypeParam> get unlinkedTypeParams => const [];
-
- @override
- bool get _hasTypeBeenInferred => _inferredReturnType != null;
-
- @override
- E getAncestor<E extends Element>(Predicate<Element> predicate) {
- return ElementImpl.getAncestorStatic(enclosingElement, predicate);
- }
-
- @override
- FunctionElementForLink_Local getLocalFunction(int index) {
- List<FunctionElementForLink_Local_NonSynthetic> functions = this.functions;
- return index < functions.length ? functions[index] : null;
- }
-
- /// Store the results of type inference for this initializer in
- /// [compilationUnit].
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- compilationUnit._storeLinkedType(
- serializedExecutable.inferredReturnTypeSlot,
- _inferredReturnType,
- typeParameterContext);
- for (FunctionElementForLink_Local_NonSynthetic function in functions) {
- function.link(compilationUnit);
- }
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => _variable.toString();
-
- List<FunctionElementForLink_Local_NonSynthetic> _computeFunctions() {
- var localFunctionsFromSummary =
- _variable.unlinkedVariable.initializer.localFunctions;
- var count = localFunctionsFromSummary.length;
- var result = List<FunctionElementForLink_Local_NonSynthetic>(count);
- for (int i = 0; i < count; i++) {
- result[i] = FunctionElementForLink_Local_NonSynthetic(
- _variable.compilationUnit,
- this,
- localFunctionsFromSummary[i],
- i == 0 ? _expressionForInference : null);
- }
- return result;
- }
-
- @override
- void _setInferenceError(TopLevelInferenceErrorBuilder error) {
- assert(!_hasTypeBeenInferred);
- _inferenceError = error;
- }
-
- @override
- void _setInferredType(DartType type) {
- assert(!_hasTypeBeenInferred);
- _inferredReturnType = type;
- _variable._inferredType = _dynamicIfNull(type);
- }
-}
-
-/// Element representing a local function (possibly a closure).
-abstract class FunctionElementForLink_Local
- implements
- ExecutableElementForLink,
- FunctionElementImpl,
- ReferenceableElementForLink {
- /// If this function element represents the initializer of a field or a
- /// top-level variable, returns the AST for the initializer expression; this
- /// is used for inferring the expression type.
- Expression get _expressionForInference;
-
- /// Indicates whether type inference has completed for this function.
- bool get _hasTypeBeenInferred;
-
- /// Stores the given [error] as the type inference error for this function.
- /// Should only be called if [_hasTypeBeenInferred] is `false`.
- void _setInferenceError(TopLevelInferenceErrorBuilder error);
-
- /// Stores the given [type] as the inferred return type for this function.
- /// Should only be called if [_hasTypeBeenInferred] is `false`.
- void _setInferredType(DartType type);
-}
-
-/// Element representing a local function (possibly a closure) inside another
-/// executable.
-class FunctionElementForLink_Local_NonSynthetic extends ExecutableElementForLink
- with ReferenceableElementForLink
- implements FunctionElementForLink_Local {
- @override
- final ExecutableElementForLink enclosingElement;
-
- @override
- final Expression _expressionForInference;
-
- List<FunctionElementForLink_Local_NonSynthetic> _functions;
-
- /// The type inference node for this function, or `null` if it hasn't been
- /// computed yet.
- TypeInferenceNode _typeInferenceNode;
-
- FunctionElementForLink_Local_NonSynthetic(
- CompilationUnitElementForLink compilationUnit,
- this.enclosingElement,
- UnlinkedExecutable unlinkedExecutable,
- this._expressionForInference)
- : super(compilationUnit, unlinkedExecutable);
-
- @override
- TypeInferenceNode get asTypeInferenceNode =>
- _typeInferenceNode ??= new TypeInferenceNode(this);
-
- @override
- TypeParameterizedElementMixin get enclosingTypeParameterContext =>
- enclosingElement;
-
- @override
- List<FunctionElementForLink_Local_NonSynthetic> get functions =>
- _functions ??= serializedExecutable.localFunctions
- .map((UnlinkedExecutable ex) =>
- new FunctionElementForLink_Local_NonSynthetic(
- compilationUnit, this, ex, null))
- .toList();
-
- @override
- String get identifier {
- String identifier = serializedExecutable.name;
- Element enclosing = this.enclosingElement;
- if (enclosing is ExecutableElementForLink) {
- int id =
- ElementImpl.findElementIndexUsingIdentical(enclosing.functions, this);
- identifier += "@$id";
- }
- return identifier;
- }
-
- @override
- bool get isAsynchronous => serializedExecutable.isAsynchronous;
-
- @override
- bool get _hasTypeBeenInferred => _inferredReturnType != null;
-
- @override
- DartType buildType(
- DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
- assert(implicitFunctionTypeIndices.isEmpty);
- return type;
- }
-
- @override
- E getAncestor<E extends Element>(Predicate<Element> predicate) {
- return ElementImpl.getAncestorStatic(enclosingElement, predicate);
- }
-
- @override
- FunctionElementForLink_Local getLocalFunction(int index) {
- List<FunctionElementForLink_Local_NonSynthetic> functions = this.functions;
- return index < functions.length ? functions[index] : null;
- }
-
- /// Store the results of type inference for this function in
- /// [compilationUnit].
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- if (serializedExecutable.returnType == null) {
- compilationUnit._storeLinkedType(
- serializedExecutable.inferredReturnTypeSlot,
- inferredReturnType,
- this);
- }
- for (FunctionElementForLink_Local_NonSynthetic function in functions) {
- function.link(compilationUnit);
- }
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => enclosingElement.toString();
-
- @override
- void _setInferenceError(TopLevelInferenceErrorBuilder error) {}
-
- @override
- void _setInferredType(DartType type) {
- // TODO(paulberry): store the inferred return type in the summary.
- assert(!_hasTypeBeenInferred);
- _inferredReturnType = _dynamicIfBottom(type);
- }
-}
-
-/// Synthetic function element which is created for local functions.
-class FunctionElementForLink_Synthetic extends ExecutableElementForLink
- with ReferenceableElementForLink
- implements FunctionElementForLink_Local {
- @override
- final Element enclosingElement;
-
- final EntityRef _entityRef;
-
- FunctionElementForLink_Synthetic(
- CompilationUnitElementForLink compilationUnit,
- this.enclosingElement,
- this._entityRef)
- : super(compilationUnit, null);
-
- @override
- TypeParameterizedElementMixin get enclosingTypeParameterContext {
- if (enclosingElement is TypeParameterizedElementMixin) {
- return enclosingElement;
- }
- return null;
- }
-
- @override
- DartType get returnType {
- return _declaredReturnType ??= enclosingUnit.resynthesizerContext
- .resolveTypeRef(this, _entityRef.syntheticReturnType);
- }
-
- @override
- List<UnlinkedParam> get unlinkedParameters => _entityRef.syntheticParams;
-
- @override
- List<UnlinkedTypeParam> get unlinkedTypeParams => _entityRef.typeParameters;
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/// Element representing a typedef resynthesized from a summary during linking.
-class FunctionTypeAliasElementForLink
- with
- TypeParameterizedElementMixin,
- ParameterParentElementForLink,
- ReferenceableElementForLink,
- SimplyBoundableForLinkMixin
- implements FunctionTypeAliasElement, ElementImpl {
- @override
- final CompilationUnitElementForLink enclosingElement;
-
- /// The unlinked representation of the typedef in the summary.
- final UnlinkedTypedef _unlinkedTypedef;
-
- FunctionTypeImpl _type;
- DartType _returnType;
- GenericFunctionTypeElementForLink _function;
-
- FunctionTypeAliasElementForLink(
- this.enclosingElement, this._unlinkedTypedef) {
- _initSimplyBoundable();
- }
-
- @override
- DartType get asStaticType {
- return enclosingElement.enclosingElement._linker.typeProvider.typeType;
- }
-
- @override
- ContextForLink get context => enclosingElement.context;
-
- @override
- TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
-
- @override
- CompilationUnitElementForLink get enclosingUnit => enclosingElement;
-
- @override
- GenericFunctionTypeElementImpl get function =>
- _function ??= new GenericFunctionTypeElementForLink(enclosingUnit, this,
- const [], _unlinkedTypedef.returnType, _unlinkedTypedef.parameters);
-
- @override
- String get identifier => _unlinkedTypedef.name;
-
- @override
- List<int> get implicitFunctionTypeIndices => const <int>[];
-
- @override
- bool get isSynthetic => false;
-
- @override
- LibraryElementForLink get library => enclosingElement.library;
-
- @override
- get linkedNode => null;
-
- @override
- String get name => _unlinkedTypedef.name;
-
- @override
- DartType get returnType => _returnType ??=
- enclosingElement.resolveTypeRef(this, _unlinkedTypedef.returnType);
-
- @override
- AnalysisSession get session => enclosingElement.session;
-
- @override
- TypeParameterizedElementMixin get typeParameterContext => this;
-
- @override
- List<UnlinkedParam> get unlinkedParameters => _unlinkedTypedef.parameters;
-
- @override
- List<UnlinkedTypeParam> get unlinkedTypeParams =>
- _unlinkedTypedef.typeParameters;
-
- @override
- int get _notSimplyBoundedSlot => _unlinkedTypedef.notSimplyBoundedSlot;
-
- @override
- List<EntityRef> get _rhsTypesForSimplyBoundable =>
- _collectTypedefRhsTypes(_unlinkedTypedef);
-
- @override
- List<UnlinkedTypeParam> get _typeParametersForSimplyBoundable =>
- _unlinkedTypedef.typeParameters;
-
- @override
- DartType buildType(
- DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
- int numTypeParameters = _unlinkedTypedef.typeParameters.length;
- if (numTypeParameters != 0) {
- List<DartType> typeArguments =
- new List<DartType>.generate(numTypeParameters, getTypeArgument);
- if (typeArguments.contains(null)) {
- return context.typeSystem
- .instantiateToBounds(new FunctionTypeImpl.forTypedef(this));
- } else {
- return GenericTypeAliasElementImpl.doInstantiate(this, typeArguments);
- }
- } else {
- return _type ??= new FunctionTypeImpl.forTypedef(this);
- }
- }
-
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- _linkSimplyBoundable();
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-/// Element representing a generic function resynthesized from a summary during
-/// linking.
-class GenericFunctionTypeElementForLink
- with
- TypeParameterizedElementMixin,
- ParameterParentElementForLink,
- ReferenceableElementForLink
- implements GenericFunctionTypeElementImpl, ElementImpl {
- @override
- final CompilationUnitElementForLink enclosingUnit;
-
- @override
- final ElementImpl enclosingElement;
-
- @override
- final List<UnlinkedTypeParam> unlinkedTypeParams;
-
- /// The representation of the generic function's return type in the summary.
- final EntityRef _unlinkedReturnType;
-
- @override
- final List<UnlinkedParam> unlinkedParameters;
-
- DartType _returnType;
- FunctionTypeImpl _type;
-
- GenericFunctionTypeElementForLink(
- this.enclosingUnit,
- this.enclosingElement,
- this.unlinkedTypeParams,
- this._unlinkedReturnType,
- this.unlinkedParameters);
-
- @override
- DartType get asStaticType {
- return enclosingUnit.enclosingElement._linker.typeProvider.typeType;
- }
-
- @override
- ContextForLink get context => enclosingElement.context;
-
- @override
- TypeParameterizedElementMixin get enclosingTypeParameterContext {
- return enclosingElement.typeParameterContext;
- }
-
- @override
- String get identifier => name;
-
- @override
- List<int> get implicitFunctionTypeIndices => const <int>[];
-
- @override
- bool get isSynthetic => false;
-
- @override
- LibraryElementForLink get library => enclosingElement.library;
-
- @override
- get linkedNode => null;
-
- @override
- String get name => '-';
-
- @override
- DartType get returnType =>
- _returnType ??= enclosingUnit.resolveTypeRef(this, _unlinkedReturnType);
-
- @override
- AnalysisSession get session => enclosingElement.session;
-
- @override
- FunctionType get type {
- return _type ??= new FunctionTypeImpl(this);
- }
-
- @override
- TypeParameterizedElementMixin get typeParameterContext => this;
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-/// Element representing a generic typedef resynthesized from a summary during
-/// linking.
-class GenericTypeAliasElementForLink
- with
- TypeParameterizedElementMixin,
- ParameterParentElementForLink,
- ReferenceableElementForLink,
- SimplyBoundableForLinkMixin
- implements FunctionTypeAliasElementForLink, GenericTypeAliasElementImpl {
- @override
- final CompilationUnitElementForLink enclosingElement;
-
- /// The unlinked representation of the typedef in the summary.
- final UnlinkedTypedef _unlinkedTypedef;
-
- GenericFunctionTypeElementForLink _function;
-
- GenericTypeAliasElementForLink(this.enclosingElement, this._unlinkedTypedef) {
- _initSimplyBoundable();
- }
-
- @override
- DartType get asStaticType {
- return enclosingElement.enclosingElement._linker.typeProvider.typeType;
- }
-
- @override
- ContextForLink get context => enclosingElement.context;
-
- @override
- TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
-
- @override
- CompilationUnitElementForLink get enclosingUnit => enclosingElement;
-
- @override
- GenericFunctionTypeElementImpl get function {
- var unlinkedType = _unlinkedTypedef.returnType;
- return _function ??= new GenericFunctionTypeElementForLink(
- enclosingUnit,
- this,
- unlinkedType.typeParameters,
- unlinkedType.syntheticReturnType,
- unlinkedType.syntheticParams);
- }
-
- @override
- String get identifier => _unlinkedTypedef.name;
-
- @override
- List<int> get implicitFunctionTypeIndices => const <int>[];
-
- @override
- bool get isSynthetic => false;
-
- @override
- LibraryElementForLink get library => enclosingElement.library;
-
- @override
- get linkedNode => null;
-
- @override
- String get name => _unlinkedTypedef.name;
-
- @override
- DartType get returnType => enclosingElement.resolveTypeRef(
- this, _unlinkedTypedef.returnType.syntheticReturnType);
-
- @override
- AnalysisSession get session => enclosingElement.session;
-
- @override
- TypeParameterizedElementMixin get typeParameterContext => this;
-
- @override
- List<UnlinkedParam> get unlinkedParameters =>
- _unlinkedTypedef.returnType.syntheticParams;
-
- @override
- List<UnlinkedTypeParam> get unlinkedTypeParams {
- var result = _unlinkedTypedef.typeParameters.toList();
- result.addAll(_unlinkedTypedef.returnType.typeParameters);
- return result;
- }
-
- @override
- int get _notSimplyBoundedSlot => _unlinkedTypedef.notSimplyBoundedSlot;
-
- @override
- List<EntityRef> get _rhsTypesForSimplyBoundable =>
- _collectTypedefRhsTypes(_unlinkedTypedef);
-
- @override
- List<UnlinkedTypeParam> get _typeParametersForSimplyBoundable =>
- _unlinkedTypedef.typeParameters;
-
- @override
- DartType buildType(
- DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
- int numTypeParameters = _unlinkedTypedef.typeParameters.length;
- if (numTypeParameters != 0) {
- List<DartType> typeArguments =
- new List<DartType>.generate(numTypeParameters, getTypeArgument);
- if (typeArguments.contains(null)) {
- return context.typeSystem
- .instantiateToBounds(new FunctionTypeImpl.forTypedef(this));
- } else {
- return GenericTypeAliasElementImpl.doInstantiate(this, typeArguments);
- }
- } else {
- return new FunctionTypeImpl.forTypedef(this);
- }
- }
-
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- _linkSimplyBoundable();
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-/// Context for serializing a possibly generic function type that is used in
-/// another context.
-class InlineFunctionTypeParameterContext
- implements TypeParameterSerializationContext {
- final GenericFunctionTypeElementImpl _functionTypeElement;
-
- final TypeParameterSerializationContext _usageContext;
-
- InlineFunctionTypeParameterContext(
- this._functionTypeElement, this._usageContext);
-
- @override
- int computeDeBruijnIndex(TypeParameterElement typeParameter,
- {int offset: 0}) {
- var typeFormals = _functionTypeElement.typeParameters;
- var numTypeFormals = typeFormals.length;
- for (int i = 0; i < numTypeFormals; i++) {
- if (typeFormals[i] == typeParameter) return i + offset + 1;
- }
- return _usageContext.computeDeBruijnIndex(typeParameter,
- offset: offset + numTypeFormals);
- }
-}
-
-/// Specialization of [DependencyWalker] for linking library cycles.
-class LibraryCycleDependencyWalker extends DependencyWalker<LibraryCycleNode> {
- @override
- void evaluate(LibraryCycleNode v) {
- v.link();
- }
-
- @override
- void evaluateScc(List<LibraryCycleNode> scc) {
- // There should never be a cycle among library cycles.
- throw new StateError('Cycle among library cycles');
- }
-}
-
-/// An instance of [LibraryCycleForLink] represents a single library cycle
-/// discovered during linking; it consists of one or more libraries in the build
-/// unit being linked.
-class LibraryCycleForLink {
- /// The libraries in the cycle.
- final List<LibraryElementInBuildUnit> libraries;
-
- /// The library cycles which this library depends on.
- final List<LibraryCycleForLink> dependencies;
-
- /// The [LibraryCycleNode] for this library cycle.
- LibraryCycleNode _node;
-
- LibraryCycleForLink(this.libraries, this.dependencies) {
- _node = new LibraryCycleNode(this);
- }
-
- LibraryCycleNode get node => _node;
-
- /// Link this library cycle and any library cycles it depends on. Does
- /// nothing if this library cycle has already been linked.
- void ensureLinked() {
- if (!node.isEvaluated) {
- new LibraryCycleDependencyWalker().walk(node);
- }
- }
-}
-
-/// Specialization of [Node] used to link library cycles in proper dependency
-/// order.
-class LibraryCycleNode extends Node<LibraryCycleNode> {
- /// The library cycle this [Node] represents.
- final LibraryCycleForLink libraryCycle;
-
- /// Indicates whether this library cycle has been linked yet.
- bool _isLinked = false;
-
- LibraryCycleNode(this.libraryCycle);
-
- @override
- bool get isEvaluated => _isLinked;
-
- @override
- List<LibraryCycleNode> computeDependencies() => libraryCycle.dependencies
- .map((LibraryCycleForLink cycle) => cycle.node)
- .toList();
-
- /// Link this library cycle.
- void link() {
- for (LibraryElementInBuildUnit library in libraryCycle.libraries) {
- library.link();
- }
- _isLinked = true;
- }
-}
-
-/// Specialization of [DependencyWalker] for computing library cycles.
-class LibraryDependencyWalker extends DependencyWalker<LibraryNode> {
- @override
- void evaluate(LibraryNode v) => evaluateScc(<LibraryNode>[v]);
-
- @override
- void evaluateScc(List<LibraryNode> scc) {
- Set<LibraryCycleForLink> dependentCycles = new Set<LibraryCycleForLink>();
- for (LibraryNode node in scc) {
- for (LibraryNode dependency in Node.getDependencies(node)) {
- if (dependency.isEvaluated) {
- dependentCycles.add(dependency._libraryCycle);
- }
- }
- }
- LibraryCycleForLink cycle = new LibraryCycleForLink(
- scc.map((LibraryNode n) => n.library).toList(),
- dependentCycles.toList());
- for (LibraryNode node in scc) {
- node._libraryCycle = cycle;
- }
- }
-}
-
-/// Element representing a library resynthesied from a summary during
-/// linking. The type parameter, [UnitElement], represents the type
-/// that will be used for the compilation unit elements.
-abstract class LibraryElementForLink<
- UnitElement extends CompilationUnitElementForLink>
- extends LibraryResynthesizerContextMixin implements LibraryElementImpl {
- final _LibraryResynthesizer resynthesizer;
-
- /// Pointer back to the linker.
- final Linker _linker;
-
- /// The absolute URI of this library.
- final Uri _absoluteUri;
-
- List<UnitElement> _units;
- List<UnitElement> _parts;
- final Map<String, ReferenceableElementForLink> _containedNames =
- <String, ReferenceableElementForLink>{};
- final List<LibraryElementForLink> _dependencies = <LibraryElementForLink>[];
- UnlinkedUnit _unlinkedDefiningUnit;
- List<LibraryElementForLink> _importedLibraries;
- List<LibraryElementForLink> _exportedLibraries;
-
- Namespace _exportNamespace;
-
- Namespace _publicNamespace;
-
- FunctionElement _loadLibraryFunction;
-
- LibraryElementForLink(this._linker, this._absoluteUri)
- : resynthesizer = new _LibraryResynthesizer() {
- resynthesizer._library = this;
- if (_linkedLibrary != null) {
- _dependencies.length = _linkedLibrary.dependencies.length;
- }
- }
-
- @override
- ContextForLink get context => _linker.context;
-
- @override
- UnitElement get definingCompilationUnit => units[0];
-
- @override
- Element get enclosingElement => null;
-
- @override
- List<LibraryElementForLink> get exportedLibraries =>
- _exportedLibraries ??= _linkedLibrary.exportDependencies
- .map(buildImportedLibrary)
- .where((library) => library != null)
- .toList();
-
- @override
- Namespace get exportNamespace =>
- _exportNamespace ??= resynthesizerContext.buildExportNamespace();
-
- @override
- String get identifier => _absoluteUri.toString();
-
- @override
- List<LibraryElementForLink> get importedLibraries => _importedLibraries ??=
- _linkedLibrary.importDependencies.map(buildImportedLibrary).toList();
-
- @override
- bool get isDartAsync => _absoluteUri.toString() == 'dart:async';
-
- @override
- bool get isDartCore => _absoluteUri.toString() == 'dart:core';
-
- @override
- bool get isInSdk => _absoluteUri.scheme == 'dart';
-
- @override
- bool get isNonNullableByDefault => _unlinkedDefiningUnit.isNNBD;
-
- @override
- bool get isSynthetic => _linkedLibrary == null;
-
- /// If this library is part of the build unit being linked, return the library
- /// cycle it is part of. Otherwise return `null`.
- LibraryCycleForLink get libraryCycleForLink;
-
- @override
- FunctionElement get loadLibraryFunction => _loadLibraryFunction ??=
- LibraryElementImpl.createLoadLibraryFunctionForLibrary(
- _linker.typeProvider, this);
-
- @override
- String get name {
- return _unlinkedDefiningUnit.libraryName;
- }
-
- List<UnitElement> get parts => _parts ??= units.sublist(1);
-
- @override
- Namespace get publicNamespace =>
- _publicNamespace ??= resynthesizerContext.buildPublicNamespace();
-
- @override
- LibraryResynthesizerContext get resynthesizerContext => this;
-
- @override
- AnalysisSession get session => _linker.session;
-
- @override
- Source get source => definingCompilationUnit.source;
-
- @override
- List<UnitElement> get units {
- if (_units == null) {
- UnlinkedUnit definingUnit = unlinkedDefiningUnit;
- _units = <UnitElement>[
- _makeUnitElement(definingUnit, 0, _absoluteUri.toString())
- ];
- int numParts = definingUnit.parts.length;
- for (int i = 0; i < numParts; i++) {
- String partRelativeUriStr = definingUnit.publicNamespace.parts[i];
-
- if (partRelativeUriStr.isEmpty) {
- continue;
- }
-
- Uri partRelativeUri;
- try {
- partRelativeUri = Uri.parse(partRelativeUriStr);
- } on FormatException {
- continue;
- }
-
- String partAbsoluteUri =
- resolveRelativeUri(_absoluteUri, partRelativeUri).toString();
- UnlinkedUnit partUnit = _linker.getUnit(partAbsoluteUri);
- _units.add(_makeUnitElement(
- partUnit ?? new UnlinkedUnitBuilder(), i + 1, partAbsoluteUri));
- }
- }
- return _units;
- }
-
- @override
- UnlinkedUnit get unlinkedDefiningUnit => _unlinkedDefiningUnit ??=
- _linker.getUnit(_absoluteUri.toString()) ?? new UnlinkedUnitBuilder();
-
- List<LinkedExportName> get _linkedExportNames =>
- _linkedLibrary == null ? [] : _linkedLibrary.exportNames;
-
- /// The linked representation of the library in the summary.
- LinkedLibrary get _linkedLibrary;
-
- /// Return the [LibraryElement] corresponding to the given dependency [index].
- LibraryElementForLink buildImportedLibrary(int index) {
- LibraryElementForLink result = _dependencies[index];
- if (result == null) {
- Uri uri;
- String uriStr = _linkedLibrary.dependencies[index].uri;
- if (uriStr.isEmpty) {
- uri = _absoluteUri;
- } else {
- try {
- uri = Uri.parse(uriStr);
- } on FormatException {
- return null;
- }
- }
-
- result = _linker.getLibrary(uri);
- _dependencies[index] = result;
- }
- return result;
- }
-
- /// Search all the units for a top level element with the given
- /// [name]. If no name is found, return the singleton instance of
- /// [UndefinedElementForLink].
- ReferenceableElementForLink getContainedName(String name) =>
- _containedNames.putIfAbsent(name, () {
- for (UnitElement unit in units) {
- ReferenceableElementForLink element = unit.getContainedName(name);
- if (!identical(element, UndefinedElementForLink.instance)) {
- return element;
- }
- }
- return UndefinedElementForLink.instance;
- });
-
- @override
- List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) =>
- LibraryElementImpl.getImportsWithPrefixFromImports(
- prefixElement, imports);
-
- @override
- ClassElement getType(String className) => LibraryElementImpl.getTypeFromParts(
- className, definingCompilationUnit, parts);
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => _absoluteUri.toString();
-
- /// Create a [UnitElement] for one of the library's compilation
- /// units.
- UnitElement _makeUnitElement(
- UnlinkedUnit unlinkedUnit, int i, String absoluteUri);
-}
-
-/// Element representing a library which is part of the build unit
-/// being linked.
-class LibraryElementInBuildUnit
- extends LibraryElementForLink<CompilationUnitElementInBuildUnit> {
- @override
- final LinkedLibraryBuilder _linkedLibrary;
-
- /// The [LibraryNode] representing this library in the library dependency
- /// graph.
- LibraryNode _libraryNode;
-
- List<ImportElement> _imports;
-
- List<PrefixElement> _prefixes;
-
- LibraryElementInBuildUnit(Linker linker, Uri absoluteUri, this._linkedLibrary)
- : super(linker, absoluteUri) {
- _libraryNode = new LibraryNode(this);
- }
-
- @override
- List<ImportElement> get imports =>
- _imports ??= LibraryElementImpl.buildImportsFromSummary(this,
- _unlinkedDefiningUnit.imports, _linkedLibrary.importDependencies);
-
- @override
- LibraryCycleForLink get libraryCycleForLink {
- if (!_libraryNode.isEvaluated) {
- new LibraryDependencyWalker().walk(_libraryNode);
- }
- return _libraryNode._libraryCycle;
- }
-
- @override
- List<PrefixElement> get prefixes =>
- _prefixes ??= LibraryElementImpl.buildPrefixesFromImports(imports);
-
- /// If this library already has a dependency in its dependencies table
- /// matching [library], return its index. Otherwise add a new dependency to
- /// table and return its index.
- int addDependency(LibraryElementForLink library) {
- for (int i = 0; i < _linkedLibrary.dependencies.length; i++) {
- if (identical(buildImportedLibrary(i), library)) {
- return i;
- }
- }
- int result = _linkedLibrary.dependencies.length;
- Uri libraryUri = library._absoluteUri;
- List<String> partsRelativeToDependency =
- library.unlinkedDefiningUnit.publicNamespace.parts;
- List<String> partsAbsolute = partsRelativeToDependency
- .map((partUri) =>
- resolveRelativeUri(libraryUri, Uri.parse(partUri)).toString())
- .toList();
- _linkedLibrary.dependencies.add(new LinkedDependencyBuilder(
- parts: partsAbsolute, uri: libraryUri.toString()));
- _dependencies.add(library);
- return result;
- }
-
- /// Perform type inference and const cycle detection on this library.
- void link() {
- for (CompilationUnitElementInBuildUnit unit in units) {
- unit.link();
- }
- }
-
- /// Throw away any information stored in the summary by a previous call to
- /// [link].
- void unlink() {
- _linkedLibrary.dependencies.length =
- _linkedLibrary.numPrelinkedDependencies;
- for (CompilationUnitElementInBuildUnit unit in units) {
- unit.unlink();
- }
- }
-
- @override
- CompilationUnitElementInBuildUnit _makeUnitElement(
- UnlinkedUnit unlinkedUnit, int i, String absoluteUri) {
- var astNodeForInference =
- _linker.getAst == null ? null : _linker.getAst(absoluteUri);
- return new CompilationUnitElementInBuildUnit(this, unlinkedUnit,
- _linkedLibrary.units[i], i, absoluteUri, astNodeForInference);
- }
-}
-
-/// Element representing a library which is depended upon (either
-/// directly or indirectly) by the build unit being linked.
-class LibraryElementInDependency
- extends LibraryElementForLink<CompilationUnitElementInDependency> {
- @override
- final LinkedLibrary _linkedLibrary;
-
- LibraryElementInDependency(
- Linker linker, Uri absoluteUri, this._linkedLibrary)
- : super(linker, absoluteUri);
-
- @override
- LibraryCycleForLink get libraryCycleForLink => null;
-
- @override
- CompilationUnitElementInDependency _makeUnitElement(
- UnlinkedUnit unlinkedUnit, int i, String absoluteUri) =>
- new CompilationUnitElementInDependency(
- this,
- unlinkedUnit,
- _linkedLibrary == null
- ? new LinkedUnitBuilder()
- : _linkedLibrary.units[i],
- i,
- absoluteUri);
-}
-
-/// Specialization of [Node] used to construct the library dependency graph.
-class LibraryNode extends Node<LibraryNode> {
- /// The library this [Node] represents.
- final LibraryElementInBuildUnit library;
-
- /// The library cycle to which [library] belongs, if it has been computed.
- /// Otherwise `null`.
- LibraryCycleForLink _libraryCycle;
-
- LibraryNode(this.library);
-
- @override
- bool get isEvaluated => _libraryCycle != null;
-
- @override
- List<LibraryNode> computeDependencies() {
- // Note: we only need to consider dependencies within the build unit being
- // linked; dependencies in other build units can't participate in library
- // cycles with us.
- List<LibraryNode> dependencies = <LibraryNode>[];
- for (LibraryElement dependency in library.importedLibraries) {
- if (dependency is LibraryElementInBuildUnit) {
- dependencies.add(dependency._libraryNode);
- }
- }
- for (LibraryElement dependency in library.exportedLibraries) {
- if (dependency is LibraryElementInBuildUnit) {
- dependencies.add(dependency._libraryNode);
- }
- }
- return dependencies;
- }
-}
-
-/// Instances of [Linker] contain the necessary information to link
-/// together a single build unit.
-class Linker {
- /// During linking, if type inference is currently being performed on the
- /// initializer of a static or instance variable, the library cycle in
- /// which inference is being performed. Otherwise, `null`.
- ///
- /// This allows us to suppress instance member type inference results from a
- /// library cycle while doing inference on the right hand sides of static and
- /// instance variables in that same cycle.
- static LibraryCycleForLink _initializerTypeInferenceCycle;
-
- /// If a top-level or an instance variable type inference is in progress,
- /// this flag it set to `true`. It is used to prevent type inference for
- /// other instance variables (when they don't have declared type).
- static bool _isPerformingVariableTypeInference = false;
-
- /// Callback to ask the client for a [LinkedLibrary] for a
- /// dependency.
- final GetDependencyCallback getDependency;
-
- /// Callback to ask the client for an [UnlinkedUnit].
- final GetUnitCallback getUnit;
-
- /// Callback to ask the client for a [CompilationUnit].
- final GetAstCallback getAst;
-
- /// Map containing all library elements accessed during linking,
- /// whether they are part of the build unit being linked or whether
- /// they are dependencies.
- final Map<Uri, LibraryElementForLink> _libraries =
- <Uri, LibraryElementForLink>{};
-
- /// List of library elements for the libraries in the build unit
- /// being linked.
- final List<LibraryElementInBuildUnit> _librariesInBuildUnit =
- <LibraryElementInBuildUnit>[];
-
- LibraryElementForLink _coreLibrary;
-
- LibraryElementForLink _asyncLibrary;
- TypeProviderForLink _typeProvider;
- TypeSystem _typeSystem;
- SpecialTypeElementForLink _voidElement;
- SpecialTypeElementForLink _dynamicElement;
- SpecialTypeElementForLink _bottomElement;
- InheritanceManager3 _inheritanceManager;
- ContextForLink _context;
- AnalysisSessionForLink _session;
-
- /// Gets an instance of [AnalysisOptions] for use during linking.
- final AnalysisOptions analysisOptions;
-
- Linker(Map<String, LinkedLibraryBuilder> linkedLibraries, this.getDependency,
- this.getUnit, this.getAst, this.analysisOptions) {
- // Create elements for the libraries to be linked. The rest of
- // the element model will be created on demand.
- linkedLibraries
- .forEach((String absoluteUri, LinkedLibraryBuilder linkedLibrary) {
- Uri uri = Uri.parse(absoluteUri);
- _librariesInBuildUnit.add(_libraries[uri] =
- new LibraryElementInBuildUnit(this, uri, linkedLibrary));
- });
- }
-
- /// Get the library element for `dart:async`.
- LibraryElementForLink get asyncLibrary =>
- _asyncLibrary ??= getLibrary(Uri.parse('dart:async'));
-
- /// Get the element representing the "bottom" type.
- SpecialTypeElementForLink get bottomElement => _bottomElement ??=
- new SpecialTypeElementForLink(this, BottomTypeImpl.instance);
-
- /// Get a stub implementation of [AnalysisContext] which can be used during
- /// linking.
- get context => _context ??= new ContextForLink(this);
-
- /// Get the library element for `dart:core`.
- LibraryElementForLink get coreLibrary =>
- _coreLibrary ??= getLibrary(Uri.parse('dart:core'));
-
- /// Get the element representing `dynamic`.
- SpecialTypeElementForLink get dynamicElement => _dynamicElement ??=
- new SpecialTypeElementForLink(this, DynamicTypeImpl.instance);
-
- /// Get an instance of [InheritanceManager3] for use during linking.
- InheritanceManager3 get inheritanceManager =>
- _inheritanceManager ??= new InheritanceManager3(typeSystem);
-
- /// Get a stub implementation of [AnalysisContext] which can be used during
- /// linking.
- get session => _session ??= new AnalysisSessionForLink();
-
- /// Indicates whether type inference should use strong mode rules.
- @deprecated
- bool get strongMode => true;
-
- /// Get an instance of [TypeProvider] for use during linking.
- TypeProviderForLink get typeProvider =>
- _typeProvider ??= new TypeProviderForLink(this);
-
- /// Get an instance of [TypeSystem] for use during linking.
- TypeSystem get typeSystem =>
- _typeSystem ??= new Dart2TypeSystem(typeProvider);
-
- /// Get the element representing `void`.
- SpecialTypeElementForLink get voidElement => _voidElement ??=
- new SpecialTypeElementForLink(this, VoidTypeImpl.instance);
-
- /// Get the library element for the library having the given [uri].
- LibraryElementForLink getLibrary(Uri uri) => _libraries.putIfAbsent(
- uri,
- () => new LibraryElementInDependency(
- this, uri, getDependency(uri.toString())));
-
- /// Perform type inference and const cycle detection on all libraries
- /// in the build unit being linked.
- void link() {
- // Link library cycles in appropriate dependency order.
- for (LibraryElementInBuildUnit library in _librariesInBuildUnit) {
- library.libraryCycleForLink.ensureLinked();
- }
- // TODO(paulberry): set dependencies.
- }
-
- /// Throw away any information stored in the summary by a previous call to
- /// [link].
- void unlink() {
- for (LibraryElementInBuildUnit library in _librariesInBuildUnit) {
- library.unlink();
- }
- }
-}
-
-/// Element representing a method resynthesized from a summary during linking.
-class MethodElementForLink extends ExecutableElementForLink_NonLocal
- with ReferenceableElementForLink
- implements MethodElementImpl {
- MethodElementForLink(ClassMemberContainerForLink enclosingClass,
- UnlinkedExecutable unlinkedExecutable)
- : super(enclosingClass.enclosingElement, enclosingClass,
- unlinkedExecutable);
-
- @override
- DartType get asStaticType => type;
-
- @override
- String get identifier => name;
-
- @override
- ElementKind get kind => ElementKind.METHOD;
-
- @override
- FunctionElementForLink_Local getLocalFunction(int index) {
- // TODO(paulberry): implement.
- return null;
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
/**
* Instances of [Node] represent nodes in a dependency graph. The
* type parameter, [NodeType], is the derived type (this affords some
@@ -4297,1728 +168,3 @@
return node._dependencies ??= node.computeDependencies();
}
}
-
-/// Element used for references that result from trying to access a non-static
-/// member of an element that is not a container (e.g. accessing the "length"
-/// property of a constant).
-///
-/// Accesses to a chain of non-static members separated by '.' are handled by
-/// creating a [NonstaticMemberElementForLink] that points to another
-/// [NonstaticMemberElementForLink], to whatever nesting level is necessary.
-class NonstaticMemberElementForLink with ReferenceableElementForLink {
- /// The [ReferenceableElementForLink] which is the target of the non-static
- /// reference.
- final ReferenceableElementForLink _target;
-
- /// The name of the non-static members that is being accessed.
- final String _name;
-
- /// The library in which the access occurs. This determines whether private
- /// names are accessible.
- final LibraryElementForLink _library;
-
- /// Whether the [_element] was computed (even if to `null`).
- bool _elementReady = false;
-
- /// The cached [ExecutableElement] represented by this element.
- ExecutableElement _element;
-
- NonstaticMemberElementForLink(this._library, this._target, this._name);
-
- @override
- ConstVariableNode get asConstVariable => _target.asConstVariable;
-
- /// Return the [ExecutableElement] represented by this element.
- ExecutableElement get asExecutableElement {
- if (!_elementReady) {
- _elementReady = true;
- DartType targetType = _target.asStaticType;
- if (targetType.isDynamic) {
- targetType = _library._linker.typeProvider.objectType;
- }
- if (targetType is InterfaceType) {
- _element =
- targetType.lookUpInheritedGetterOrMethod(_name, library: _library);
- }
- // TODO(paulberry): handle .call on function types and .toString or
- // .hashCode on all types.
- }
- return _element;
- }
-
- @override
- DartType get asStaticType {
- ExecutableElement element = asExecutableElement;
- if (element != null) {
- if (element is PropertyAccessorElement) {
- return element.returnType;
- } else {
- // Method tear-off
- return element.type;
- }
- }
- return DynamicTypeImpl.instance;
- }
-
- @override
- TypeInferenceNode get asTypeInferenceNode => _target.asTypeInferenceNode;
-
- @override
- ReferenceableElementForLink getContainedName(String name) {
- return new NonstaticMemberElementForLink(_library, this, name);
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$_target.(dynamic)$_name';
-}
-
-/// Element representing a function or method parameter resynthesized
-/// from a summary during linking.
-class ParameterElementForLink implements ParameterElementImpl {
- /// The unlinked representation of the parameter in the summary.
- final UnlinkedParam unlinkedParam;
-
- /// The innermost enclosing element that can declare type parameters.
- final TypeParameterizedElementMixin _typeParameterContext;
-
- /// If this parameter has a default value and the enclosing library
- /// is part of the build unit being linked, the parameter's node in
- /// the constant evaluation dependency graph. Otherwise `null`.
- ConstNode _constNode;
-
- /// The compilation unit in which this parameter appears.
- final CompilationUnitElementForLink compilationUnit;
-
- /// The index of this parameter within [enclosingElement]'s parameter list.
- final int _parameterIndex;
-
- @override
- final ParameterParentElementForLink enclosingElement;
-
- DartType _inferredType;
- TopLevelInferenceErrorBuilder _inferenceError;
- DartType _declaredType;
- bool _inheritsCovariant = false;
-
- ParameterElementForLink(this.enclosingElement, this.unlinkedParam,
- this._typeParameterContext, this.compilationUnit, this._parameterIndex) {
- if (unlinkedParam.initializer?.bodyExpr != null) {
- _constNode = new ConstParameterNode(this);
- }
- if (compilationUnit is CompilationUnitElementInDependency) {
- _inheritsCovariant =
- (compilationUnit as CompilationUnitElementInDependency)
- .parametersInheritingCovariant
- .contains(unlinkedParam.inheritsCovariantSlot);
- }
- }
-
- factory ParameterElementForLink.forFactory(
- ParameterParentElementForLink enclosingElement,
- UnlinkedParam unlinkedParameter,
- TypeParameterizedElementMixin typeParameterContext,
- CompilationUnitElementForLink compilationUnit,
- int parameterIndex) {
- if (unlinkedParameter.isInitializingFormal) {
- return new FieldFormalParameterElementForLink(
- enclosingElement,
- unlinkedParameter,
- typeParameterContext,
- typeParameterContext.enclosingUnit.resynthesizerContext
- as CompilationUnitElementForLink,
- parameterIndex);
- } else {
- return new ParameterElementForLink(
- enclosingElement,
- unlinkedParameter,
- typeParameterContext,
- typeParameterContext.enclosingUnit.resynthesizerContext
- as CompilationUnitElementForLink,
- parameterIndex);
- }
- }
-
- @override
- String get displayName => unlinkedParam.name;
-
- @override
- bool get hasImplicitType =>
- !unlinkedParam.isFunctionTyped && unlinkedParam.type == null;
-
- @override
- String get identifier => name;
-
- @override
- bool get inheritsCovariant => _inheritsCovariant;
-
- @override
- void set inheritsCovariant(bool value) {
- _inheritsCovariant = value;
- }
-
- @override
- FunctionElement get initializer => null;
-
- @override
- bool get isCovariant {
- if (isExplicitlyCovariant || inheritsCovariant) {
- return true;
- }
- return false;
- }
-
- @override
- bool get isExplicitlyCovariant => unlinkedParam.isExplicitlyCovariant;
-
- @override
- bool get isInitializingFormal => unlinkedParam.isInitializingFormal;
-
- @override
- bool get isNamed =>
- parameterKind == ParameterKind.NAMED ||
- parameterKind == ParameterKind.NAMED_REQUIRED;
-
- @override
- bool get isNotOptional =>
- parameterKind == ParameterKind.REQUIRED ||
- parameterKind == ParameterKind.NAMED_REQUIRED;
-
- @override
- bool get isOptional =>
- parameterKind == ParameterKind.NAMED ||
- parameterKind == ParameterKind.POSITIONAL;
-
- @override
- bool get isOptionalNamed => parameterKind == ParameterKind.NAMED;
-
- @override
- bool get isOptionalPositional => parameterKind == ParameterKind.POSITIONAL;
-
- @override
- bool get isPositional =>
- parameterKind == ParameterKind.POSITIONAL ||
- parameterKind == ParameterKind.REQUIRED;
-
- @override
- bool get isRequiredNamed => parameterKind == ParameterKind.NAMED_REQUIRED;
-
- @override
- bool get isRequiredPositional => parameterKind == ParameterKind.REQUIRED;
-
- @override
- get linkedNode => null;
-
- @override
- String get name => unlinkedParam.name;
-
- @override
- ParameterKind get parameterKind {
- switch (unlinkedParam.kind) {
- case UnlinkedParamKind.requiredPositional:
- return ParameterKind.REQUIRED;
- case UnlinkedParamKind.requiredNamed:
- return ParameterKind.NAMED_REQUIRED;
- case UnlinkedParamKind.optionalPositional:
- return ParameterKind.POSITIONAL;
- case UnlinkedParamKind.optionalNamed:
- return ParameterKind.NAMED;
- }
- return null;
- }
-
- @override
- DartType get type {
- if (_inferredType != null) {
- return _inferredType;
- } else if (_declaredType == null) {
- if (unlinkedParam.isFunctionTyped) {
- _declaredType = new FunctionTypeImpl(
- new FunctionElementForLink_FunctionTypedParam(
- this, _typeParameterContext, unlinkedParam.parameters));
- } else if (unlinkedParam.type == null) {
- if (!compilationUnit.isInBuildUnit) {
- _inferredType = compilationUnit.getLinkedType(
- this, unlinkedParam.inferredTypeSlot);
- return _inferredType;
- } else {
- _declaredType = DynamicTypeImpl.instance;
- }
- } else {
- _declaredType =
- compilationUnit.resolveTypeRef(this, unlinkedParam.type);
- }
- }
- return _declaredType;
- }
-
- @override
- void set type(DartType inferredType) {
- assert(_inferredType == null);
- _inferredType = inferredType;
- }
-
- @override
- TypeParameterizedElementMixin get typeParameterContext {
- return _typeParameterContext;
- }
-
- /// Store the results of type inference for this parameter in
- /// [compilationUnit].
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- compilationUnit._storeLinkedType(
- unlinkedParam.inferredTypeSlot, _inferredType, _typeParameterContext);
- compilationUnit._storeLinkedTypeError(
- unlinkedParam.inferredTypeSlot, _inferenceError);
- if (inheritsCovariant) {
- compilationUnit
- ._storeInheritsCovariant(unlinkedParam.inheritsCovariantSlot);
- }
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- void setInferenceError(TopLevelInferenceErrorBuilder error) {
- assert(_inferenceError == null);
- _inferenceError = error;
- }
-}
-
-/// Element representing the parameter of a synthetic setter for a variable
-/// resynthesized during linking.
-class ParameterElementForLink_VariableSetter implements ParameterElementImpl {
- @override
- final PropertyAccessorElementForLink_Variable enclosingElement;
-
- @override
- bool inheritsCovariant = false;
-
- ParameterElementForLink_VariableSetter(this.enclosingElement);
-
- @override
- bool get isCovariant => isExplicitlyCovariant || inheritsCovariant;
-
- @override
- bool get isExplicitlyCovariant => enclosingElement.variable.isCovariant;
-
- bool get isInitializingFormal => unlinkedParam.isInitializingFormal;
-
- @override
- bool get isNamed =>
- parameterKind == ParameterKind.NAMED ||
- parameterKind == ParameterKind.NAMED_REQUIRED;
-
- @override
- bool get isNotOptional =>
- parameterKind == ParameterKind.REQUIRED ||
- parameterKind == ParameterKind.NAMED_REQUIRED;
-
- @override
- bool get isOptional =>
- parameterKind == ParameterKind.NAMED ||
- parameterKind == ParameterKind.POSITIONAL;
-
- @override
- bool get isOptionalNamed => parameterKind == ParameterKind.NAMED;
-
- @override
- bool get isOptionalPositional => parameterKind == ParameterKind.POSITIONAL;
-
- @override
- bool get isPositional =>
- parameterKind == ParameterKind.POSITIONAL ||
- parameterKind == ParameterKind.REQUIRED;
-
- @override
- bool get isRequiredNamed => parameterKind == ParameterKind.NAMED_REQUIRED;
-
- @override
- bool get isRequiredPositional => parameterKind == ParameterKind.REQUIRED;
-
- @override
- bool get isSynthetic => true;
-
- @override
- String get name => 'x';
-
- @override
- ParameterKind get parameterKind => ParameterKind.REQUIRED;
-
- @override
- DartType get type => enclosingElement.variable.type;
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/// Mixin used by elements that can have parameters.
-abstract class ParameterParentElementForLink implements Element {
- List<ParameterElement> _parameters;
-
- /// Get the appropriate integer list to store in
- /// [EntityRef.implicitFunctionTypeIndices] to refer to this element. For an
- /// element representing a function-typed parameter, this should return a
- /// non-empty list. For an element representing an executable, this should
- /// return the empty list.
- List<int> get implicitFunctionTypeIndices;
-
- /// Get all the parameters of this element.
- List<ParameterElement> get parameters {
- if (_parameters == null) {
- List<UnlinkedParam> unlinkedParameters = this.unlinkedParameters;
- int numParameters = unlinkedParameters.length;
- _parameters = new List<ParameterElement>(numParameters);
- for (int i = 0; i < numParameters; i++) {
- UnlinkedParam unlinkedParam = unlinkedParameters[i];
- _parameters[i] = new ParameterElementForLink.forFactory(
- this,
- unlinkedParam,
- typeParameterContext,
- typeParameterContext.enclosingUnit.resynthesizerContext
- as CompilationUnitElementForLink,
- i);
- }
- }
- return _parameters;
- }
-
- /// Get the innermost enclosing element that can declare type parameters
- /// (which may be [this], or may be a parent when there are function-typed
- /// parameters).
- TypeParameterizedElementMixin get typeParameterContext;
-
- /// Get the list of unlinked parameters of this element.
- List<UnlinkedParam> get unlinkedParameters;
-}
-
-/// Element representing a getter or setter resynthesized from a summary during
-/// linking.
-abstract class PropertyAccessorElementForLink
- implements PropertyAccessorElementImpl, ReferenceableElementForLink {
- void link(CompilationUnitElementInBuildUnit compilationUnit);
-}
-
-/// Specialization of [PropertyAccessorElementForLink] for synthetic accessors
-/// implied by the synthetic fields of an enum declaration.
-class PropertyAccessorElementForLink_EnumField
- with ReferenceableElementForLink
- implements PropertyAccessorElementForLink {
- @override
- final FieldElementForLink_EnumField variable;
-
- FunctionTypeImpl _type;
-
- PropertyAccessorElementForLink_EnumField(this.variable);
-
- @override
- DartType get asStaticType => returnType;
-
- @override
- Element get enclosingElement => variable.enclosingElement;
-
- @override
- bool get isAbstract => false;
-
- @override
- bool get isGetter => true;
-
- @override
- bool get isSetter => false;
-
- @override
- bool get isStatic => variable.isStatic;
-
- @override
- bool get isSynthetic => true;
-
- @override
- ElementKind get kind => ElementKind.GETTER;
-
- @override
- LibraryElementForLink get library =>
- variable.enclosingElement.enclosingElement.enclosingElement;
-
- @override
- String get name => variable.name;
-
- @override
- List<ParameterElement> get parameters => const [];
-
- @override
- DartType get returnType => variable.type;
-
- @override
- FunctionTypeImpl get type => _type ??= new FunctionTypeImpl(this);
-
- @override
- List<TypeParameterElement> get typeParameters => const [];
-
- @override
- ReferenceableElementForLink getContainedName(String name) {
- return new NonstaticMemberElementForLink(library, this, name);
- }
-
- @override
- FunctionElementForLink_Local getLocalFunction(int index) {
- // TODO(paulberry): implement (should return the synthetic function element
- // for the enum field's initializer).
- return null;
- }
-
- @override
- bool isAccessibleIn(LibraryElement library) =>
- !Identifier.isPrivateName(name) || identical(this.library, library);
-
- @override
- void link(CompilationUnitElementInBuildUnit compilationUnit) {}
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-/// Specialization of [PropertyAccessorElementForLink] for non-synthetic
-/// accessors explicitly declared in the source code.
-class PropertyAccessorElementForLink_Executable
- extends ExecutableElementForLink_NonLocal
- with ReferenceableElementForLink
- implements PropertyAccessorElementForLink {
- @override
- PropertyInducingElement variable;
-
- PropertyAccessorElementForLink_Executable(
- CompilationUnitElementForLink enclosingUnit,
- ClassMemberContainerForLink enclosingClass,
- UnlinkedExecutable unlinkedExecutable,
- this.variable)
- : super(enclosingUnit, enclosingClass, unlinkedExecutable);
-
- @override
- DartType get asStaticType => returnType;
-
- @override
- PropertyAccessorElementForLink_Executable get correspondingGetter =>
- variable.getter;
-
- @override
- bool get isGetter =>
- serializedExecutable.kind == UnlinkedExecutableKind.getter;
-
- @override
- bool get isSetter =>
- serializedExecutable.kind == UnlinkedExecutableKind.setter;
-
- @override
- bool get isStatic => enclosingClass == null || super.isStatic;
-
- @override
- ElementKind get kind =>
- serializedExecutable.kind == UnlinkedExecutableKind.getter
- ? ElementKind.GETTER
- : ElementKind.SETTER;
-
- @override
- ReferenceableElementForLink getContainedName(String name) {
- return new NonstaticMemberElementForLink(
- library as LibraryElementForLink, this, name);
- }
-
- @override
- FunctionElementForLink_Local getLocalFunction(int index) {
- // TODO(paulberry): implement
- return null;
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-/// Specialization of [PropertyAccessorElementForLink] for synthetic accessors
-/// implied by a field or variable declaration.
-class PropertyAccessorElementForLink_Variable
- with ReferenceableElementForLink
- implements PropertyAccessorElementForLink {
- @override
- final bool isSetter;
-
- final VariableElementForLink variable;
- FunctionTypeImpl _type;
- ParameterElementForLink_VariableSetter _parameter;
- List<ParameterElement> _parameters;
-
- PropertyAccessorElementForLink_Variable(this.variable, this.isSetter);
-
- @override
- ConstVariableNode get asConstVariable => variable._constNode;
-
- @override
- DartType get asStaticType => returnType;
-
- @override
- TypeInferenceNode get asTypeInferenceNode => variable._typeInferenceNode;
-
- @override
- String get displayName => variable.displayName;
-
- @override
- Element get enclosingElement => variable.enclosingElement;
-
- @override
- bool get isAbstract => false;
-
- @override
- bool get isGetter => !isSetter;
-
- @override
- bool get isStatic => variable.isStatic;
-
- @override
- bool get isSynthetic => true;
-
- @override
- ElementKind get kind => isSetter ? ElementKind.SETTER : ElementKind.GETTER;
-
- @override
- LibraryElementForLink get library =>
- variable.compilationUnit.enclosingElement;
-
- @override
- String get name => isSetter ? '${variable.name}=' : variable.name;
-
- @override
- List<ParameterElement> get parameters {
- if (_parameters == null) {
- _parameters = <ParameterElementForLink_VariableSetter>[];
- if (isSetter) {
- _parameter = new ParameterElementForLink_VariableSetter(this);
- _parameters.add(_parameter);
- }
- }
- return _parameters;
- }
-
- @override
- DartType get returnType {
- if (isSetter) {
- return VoidTypeImpl.instance;
- } else {
- return variable.type;
- }
- }
-
- @override
- FunctionTypeImpl get type => _type ??= new FunctionTypeImpl(this);
-
- @override
- List<TypeParameterElement> get typeParameters {
- // TODO(paulberry): is this correct for fields in generic classes?
- return const [];
- }
-
- @override
- ReferenceableElementForLink getContainedName(String name) {
- return new NonstaticMemberElementForLink(library, this, name);
- }
-
- @override
- FunctionElementForLink_Local getLocalFunction(int index) {
- if (index == 0) {
- return variable.initializer;
- } else {
- return null;
- }
- }
-
- @override
- bool isAccessibleIn(LibraryElement library) =>
- !Identifier.isPrivateName(name) || identical(this.library, library);
-
- @override
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- if (isSetter && _parameter != null) {
- if (_parameter.inheritsCovariant) {
- compilationUnit._storeInheritsCovariant(
- variable.unlinkedVariable.inheritsCovariantSlot);
- }
- }
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-/// Base class representing an element which can be the target of a reference.
-/// When used as a mixin, implements the default behavior shared by most
-/// elements.
-mixin ReferenceableElementForLink implements Element {
- /// If this element is a class reference, return it. Otherwise return `null`.
- ClassElementForLink get asClass => null;
-
- /// If this element can be used in a constructor invocation context,
- /// return the associated constructor (which may be `this` or some
- /// other element). Otherwise return `null`.
- ConstructorElementForLink get asConstructor => null;
-
- /// If this element can be used in a getter context to refer to a
- /// constant variable, return the [ConstVariableNode] for the
- /// constant value. Otherwise return `null`.
- ConstVariableNode get asConstVariable => null;
-
- /// Return the static type (possibly inferred) of the entity referred to by
- /// this element.
- DartType get asStaticType => DynamicTypeImpl.instance;
-
- /// If this element can be used in a getter context as a type inference
- /// dependency, return the [TypeInferenceNode] for the inferred type.
- /// Otherwise return `null`.
- TypeInferenceNode get asTypeInferenceNode => null;
-
- /// See [TypeParameterElement.isSimplyBounded].
- bool get isSimplyBounded => true;
-
- @override
- ElementLocation get location => new ElementLocationImpl.con1(this);
-
- /// If non-null, the [SimplyBoundedNode] for determining whether this element
- /// is simply bounded.
- ///
- /// If null, this element is known to be simply bounded based on its unlinked
- /// representation alone (for example, it is a class declaration with no type
- /// parameters, or it is a class declaration whose type parameters all lack
- /// explicit bounds). Or it is an element for which simple boundedness is
- /// not relevant.
- SimplyBoundedNode get _simplyBoundedNode => null;
-
- /// Return the type indicated by this element when it is used in a
- /// type instantiation context. If this element can't legally be
- /// instantiated as a type, return the dynamic type.
- ///
- /// If the type is parameterized, [getTypeArgument] will be called to retrieve
- /// the type parameters. It should return `null` for unspecified type
- /// parameters.
- DartType buildType(DartType getTypeArgument(int i),
- List<int> implicitFunctionTypeIndices) =>
- DynamicTypeImpl.instance;
-
- /// If this element contains other named elements, return the
- /// contained element having the given [name]. If this element can't
- /// contain other named elements, or it doesn't contain an element
- /// with the given name, return the singleton of
- /// [UndefinedElementForLink].
- ReferenceableElementForLink getContainedName(String name) {
- // TODO(paulberry): handle references to `call` for function types.
- return UndefinedElementForLink.instance;
- }
-
- /// If this element contains local functions, return the contained local
- /// function having the given [index]. If this element doesn't contain local
- /// functions, or the index is out of range, return `null`.
- FunctionElementForLink_Local getLocalFunction(int index) => null;
-}
-
-/// Mixin providing the implementation of
-/// [ReferenceableElementForLink.isSimplyBounded] for elements representing a
-/// type.
-abstract class SimplyBoundableForLinkMixin
- implements ReferenceableElementForLink {
- @override
- SimplyBoundedNode _simplyBoundedNode;
-
- CompilationUnitElementForLink get enclosingUnit;
-
- @override
- bool get isSimplyBounded {
- var slot = _notSimplyBoundedSlot;
- if (slot == 0) return true;
- if (enclosingUnit.isInBuildUnit) {
- assert(_simplyBoundedNode.isEvaluated);
- return _simplyBoundedNode.isSimplyBounded;
- } else {
- return !enclosingUnit._linkedUnit.notSimplyBounded.contains(slot);
- }
- }
-
- int get _notSimplyBoundedSlot;
-
- List<EntityRef> get _rhsTypesForSimplyBoundable;
-
- List<UnlinkedTypeParam> get _typeParametersForSimplyBoundable;
-
- void _initSimplyBoundable() {
- if (enclosingUnit.isInBuildUnit && _notSimplyBoundedSlot != 0) {
- _simplyBoundedNode = SimplyBoundedNode(enclosingUnit,
- _typeParametersForSimplyBoundable, _rhsTypesForSimplyBoundable);
- }
- }
-
- void _linkSimplyBoundable() {
- if (_simplyBoundedNode != null) {
- if (!_simplyBoundedNode.isEvaluated) {
- new SimplyBoundedDependencyWalker().walk(_simplyBoundedNode);
- }
- if (!_simplyBoundedNode.isSimplyBounded) {
- enclosingUnit._linkedUnit.notSimplyBounded.add(_notSimplyBoundedSlot);
- }
- }
- }
-}
-
-/// Specialization of [DependencyWalker] for evaluating whether types are simply
-/// bounded.
-class SimplyBoundedDependencyWalker
- extends DependencyWalker<SimplyBoundedNode> {
- @override
- void evaluate(SimplyBoundedNode v) {
- v._evaluate();
- }
-
- @override
- void evaluateScc(List<SimplyBoundedNode> scc) {
- for (var node in scc) {
- node._markCircular();
- }
- }
-}
-
-/// Specialization of [Node] used to construct the dependency graph for
-/// evaluating whether types are simply bounded.
-class SimplyBoundedNode extends Node<SimplyBoundedNode> {
- /// The compilation unit enclosing the type whose simple-boundedness we need
- /// to check
- final CompilationUnitElementForLink _unit;
-
- /// The type parameters of the type whose simple-boundedness we need to check
- final List<UnlinkedTypeParam> _typeParameters;
-
- /// If the type whose simple-boundedness we need to check is a typedef, the
- /// types appering in its "right hand side"
- final List<EntityRef> _rhsTypes;
-
- @override
- bool isEvaluated = false;
-
- /// After execution of [_evaluate], indicates whether the type is
- /// simply bounded.
- ///
- /// Prior to execution of [computeDependencies], `true`.
- ///
- /// Between execution of [computeDependencies] and [_evaluate], `true`
- /// indicates that the type is simply bounded only if all of its dependencies
- /// are simply bounded; `false` indicates that the type is not simply bounded.
- bool isSimplyBounded = true;
-
- SimplyBoundedNode(this._unit, this._typeParameters, this._rhsTypes);
-
- @override
- List<SimplyBoundedNode> computeDependencies() {
- var dependencies = <SimplyBoundedNode>[];
- for (var typeParameter in _typeParameters) {
- var bound = typeParameter.bound;
- if (bound != null) {
- if (!_visitType(dependencies, bound, true)) {
- // Note: we might consider setting isEvaluated=true here to prevent an
- // unnecessary call to SimplyBoundedDependencyWalker.evaluate.
- // However, we'd have to be careful to make sure this doesn't violate
- // an invariant of the DependencyWalker algorithm, since normally it
- // only expects isEvaluated to change during a call to .evaluate or
- // .evaluateScc.
- isSimplyBounded = false;
- return const [];
- }
- }
- }
- for (var type in _rhsTypes) {
- if (!_visitType(dependencies, type, false)) {
- // Note: we might consider setting isEvaluated=true here to prevent an
- // unnecessary call to SimplyBoundedDependencyWalker.evaluate.
- // However, we'd have to be careful to make sure this doesn't violate
- // an invariant of the DependencyWalker algorithm, since normally it
- // only expects isEvaluated to change during a call to .evaluate or
- // .evaluateScc.
- isSimplyBounded = false;
- return const [];
- }
- }
- return dependencies;
- }
-
- void _evaluate() {
- for (var dependency in _dependencies) {
- if (!dependency.isSimplyBounded) {
- isSimplyBounded = false;
- break;
- }
- }
- isEvaluated = true;
- }
-
- void _markCircular() {
- isSimplyBounded = false;
- isEvaluated = true;
- }
-
- /// Visits the parameters in [params], storing the [SimplyBoundedNode] for any
- /// types they reference in [dependencies].
- ///
- /// If a type is found that is already known to be not simply bounded (because
- /// it is in another build unit), or [disallowTypeParamReferences] is `true`
- /// and a reference to a type parameter is found, `false` is returned and
- /// further visiting is short-circuited. Otherwise `true` is returned.
- bool _visitParams(List<SimplyBoundedNode> dependencies,
- List<UnlinkedParam> params, bool disallowTypeParamReferences) {
- for (var param in params) {
- if (!_visitType(dependencies, param.type, disallowTypeParamReferences)) {
- return false;
- }
- if (isSimplyBounded && param.isFunctionTyped) {
- if (!_visitParams(
- dependencies, param.parameters, disallowTypeParamReferences)) {
- return false;
- }
- }
- }
- return true;
- }
-
- /// Visits the type specified by [type], storing the [SimplyBoundedNode] for
- /// any types it references in [dependencies].
- ///
- /// If a type is found that is already known to be not simply bounded (because
- /// it is in another build unit), or [disallowTypeParamReferences] is `true`
- /// and a reference to a type parameter is found, `false` is returned and
- // /// further visiting is short-circuited. Otherwise `true` is returned.
- bool _visitType(List<SimplyBoundedNode> dependencies, EntityRef type,
- bool disallowTypeParamReferences) {
- if (type != null) {
- if (type.paramReference != 0) {
- if (disallowTypeParamReferences) {
- return false;
- }
- } else if (type.entityKind == EntityRefKind.genericFunctionType) {
- if (!_visitParams(
- dependencies, type.syntheticParams, disallowTypeParamReferences)) {
- return false;
- }
- if (!_visitType(dependencies, type.syntheticReturnType,
- disallowTypeParamReferences)) {
- return false;
- }
- } else {
- if (type.typeArguments.isEmpty) {
- var ref = _unit.resolveRef(type.reference);
- var dep = ref._simplyBoundedNode;
- if (dep == null) {
- if (!ref.isSimplyBounded) {
- return false;
- }
- } else {
- dependencies.add(dep);
- }
- } else {
- for (var typeArgument in type.typeArguments) {
- if (!_visitType(
- dependencies, typeArgument, disallowTypeParamReferences)) {
- return false;
- }
- }
- }
- }
- }
- return true;
- }
-}
-
-/// Element used for references to special types such as `void`.
-class SpecialTypeElementForLink with ReferenceableElementForLink {
- final Linker linker;
- final DartType type;
-
- SpecialTypeElementForLink(this.linker, this.type);
-
- @override
- DartType get asStaticType => linker.typeProvider.typeType;
-
- @override
- DartType buildType(
- DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
- return type;
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => type.toString();
-}
-
-/// Element representing a synthetic variable resynthesized from a summary
-/// during linking.
-class SyntheticVariableElementForLink implements PropertyInducingElementImpl {
- PropertyAccessorElementForLink_Executable _getter;
- PropertyAccessorElementForLink_Executable _setter;
-
- @override
- PropertyAccessorElementForLink_Executable get getter => _getter;
-
- @override
- bool get isFinal => _setter == null;
-
- @override
- bool get isSynthetic => true;
-
- @override
- PropertyAccessorElementForLink_Executable get setter => _setter;
-
- @override
- void set type(DartType inferredType) {}
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/// Element representing a top-level function.
-class TopLevelFunctionElementForLink extends ExecutableElementForLink_NonLocal
- with ReferenceableElementForLink
- implements FunctionElementImpl {
- DartType _returnType;
-
- TopLevelFunctionElementForLink(
- CompilationUnitElementForLink enclosingUnit, UnlinkedExecutable _buf)
- : super(enclosingUnit, null, _buf);
-
- @override
- DartType get asStaticType => type;
-
- @override
- String get identifier => serializedExecutable.name;
-
- @override
- bool get isStatic => true;
-
- @override
- ElementKind get kind => ElementKind.FUNCTION;
-
- @override
- FunctionElementForLink_Local getLocalFunction(int index) {
- // TODO(paulberry): implement.
- return null;
- }
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-/// Element representing a top level variable resynthesized from a
-/// summary during linking.
-class TopLevelVariableElementForLink extends VariableElementForLink
- implements TopLevelVariableElement {
- TopLevelVariableElementForLink(CompilationUnitElementForLink enclosingElement,
- UnlinkedVariable unlinkedVariable, Expression initializerForInference)
- : super(unlinkedVariable, enclosingElement, initializerForInference);
-
- @override
- CompilationUnitElementForLink get enclosingElement => compilationUnit;
-
- @override
- bool get isStatic => true;
-
- @override
- LibraryElementForLink get library => compilationUnit.library;
-
- @override
- TypeParameterizedElementMixin get _typeParameterContext => null;
-
- /// Store the results of type inference for this variable in
- /// [compilationUnit].
- void link(CompilationUnitElementInBuildUnit compilationUnit) {
- if (hasImplicitType) {
- TypeInferenceNode typeInferenceNode = this._typeInferenceNode;
- if (typeInferenceNode != null) {
- compilationUnit._storeLinkedType(
- unlinkedVariable.inferredTypeSlot, inferredType, null);
- compilationUnit._storeLinkedTypeError(
- unlinkedVariable.inferredTypeSlot, initializer._inferenceError);
- }
- initializer?.link(compilationUnit);
- }
- }
-}
-
-/// Specialization of [DependencyWalker] for performing type inference on static
-/// and top level variables.
-class TypeInferenceDependencyWalker
- extends DependencyWalker<TypeInferenceNode> {
- @override
- void evaluate(TypeInferenceNode v) {
- v.evaluate(null);
- }
-
- @override
- void evaluateScc(List<TypeInferenceNode> scc) {
- for (TypeInferenceNode v in scc) {
- v.evaluate(scc);
- }
- }
-}
-
-/// Specialization of [Node] used to construct the type inference dependency
-/// graph.
-class TypeInferenceNode extends Node<TypeInferenceNode> {
- /// The [FunctionElementForLink_Local] to which this node refers.
- final FunctionElementForLink_Local functionElement;
-
- TypeInferenceNode(this.functionElement);
-
- @override
- bool get isEvaluated => functionElement._hasTypeBeenInferred;
-
- /// Collect the type inference dependencies in [unlinkedExecutable] (which
- /// should be interpreted relative to [compilationUnit]) and store them in
- /// [dependencies].
- void collectDependencies(
- List<TypeInferenceNode> dependencies,
- UnlinkedExecutable unlinkedExecutable,
- CompilationUnitElementForLink compilationUnit) {
- UnlinkedExpr unlinkedConst = unlinkedExecutable?.bodyExpr;
- if (unlinkedConst == null) {
- return;
- }
- int refPtr = 0;
- int intPtr = 0;
-
- for (UnlinkedExprOperation operation in unlinkedConst.operations) {
- switch (operation) {
- case UnlinkedExprOperation.pushInt:
- intPtr++;
- break;
- case UnlinkedExprOperation.pushLongInt:
- int numInts = unlinkedConst.ints[intPtr++];
- intPtr += numInts;
- break;
- case UnlinkedExprOperation.concatenate:
- intPtr++;
- break;
- case UnlinkedExprOperation.pushReference:
- EntityRef ref = unlinkedConst.references[refPtr++];
- // TODO(paulberry): cache these resolved references for
- // later use by evaluate().
- TypeInferenceNode dependency =
- compilationUnit.resolveRef(ref.reference).asTypeInferenceNode;
- if (dependency != null) {
- dependencies.add(dependency);
- }
- break;
- case UnlinkedExprOperation.invokeConstructor:
- refPtr++;
- intPtr += 2;
- break;
- case UnlinkedExprOperation.makeUntypedList:
- case UnlinkedExprOperation.makeUntypedMap:
- case UnlinkedExprOperation.makeUntypedSet:
- case UnlinkedExprOperation.makeUntypedSetOrMap:
- case UnlinkedExprOperation.forParts:
- case UnlinkedExprOperation.variableDeclaration:
- case UnlinkedExprOperation.forInitializerDeclarationsUntyped:
- intPtr++;
- break;
- case UnlinkedExprOperation.makeTypedList:
- case UnlinkedExprOperation.makeTypedSet:
- case UnlinkedExprOperation.forInitializerDeclarationsTyped:
- refPtr++;
- intPtr++;
- break;
- case UnlinkedExprOperation.makeTypedMap:
- case UnlinkedExprOperation.makeTypedMap2:
- refPtr += 2;
- intPtr++;
- break;
- case UnlinkedExprOperation.assignToRef:
- EntityRef ref = unlinkedConst.references[refPtr++];
- // TODO(paulberry): cache these resolved references for
- // later use by evaluate().
- TypeInferenceNode dependency =
- compilationUnit.resolveRef(ref.reference).asTypeInferenceNode;
- if (dependency != null) {
- dependencies.add(dependency);
- }
- break;
- case UnlinkedExprOperation.invokeMethodRef:
- EntityRef ref = unlinkedConst.references[refPtr++];
- TypeInferenceNode dependency =
- compilationUnit.resolveRef(ref.reference).asTypeInferenceNode;
- if (dependency != null) {
- dependencies.add(dependency);
- }
- intPtr += 2;
- int numTypeArguments = unlinkedConst.ints[intPtr++];
- refPtr += numTypeArguments;
- break;
- case UnlinkedExprOperation.invokeMethod:
- intPtr += 2;
- int numTypeArguments = unlinkedConst.ints[intPtr++];
- refPtr += numTypeArguments;
- break;
- case UnlinkedExprOperation.typeCast:
- case UnlinkedExprOperation.typeCheck:
- case UnlinkedExprOperation.forEachPartsWithTypedDeclaration:
- refPtr++;
- break;
- case UnlinkedExprOperation.pushLocalFunctionReference:
- int popCount = unlinkedConst.ints[intPtr++];
- assert(popCount == 0); // TODO(paulberry): handle the nonzero case.
- dependencies.add(functionElement
- .getLocalFunction(unlinkedConst.ints[intPtr++])
- .asTypeInferenceNode);
- break;
- default:
- break;
- }
- }
- assert(refPtr == unlinkedConst.references.length);
- assert(intPtr == unlinkedConst.ints.length);
- }
-
- @override
- List<TypeInferenceNode> computeDependencies() {
- List<TypeInferenceNode> dependencies = <TypeInferenceNode>[];
- collectDependencies(dependencies, functionElement.serializedExecutable,
- functionElement.compilationUnit);
- return dependencies;
- }
-
- void evaluate(List<TypeInferenceNode> cycle) {
- if (cycle != null) {
- List<String> cycleNames = cycle
- .map((node) {
- Element e = node.functionElement;
- while (e != null) {
- if (e is VariableElement) {
- return e.name;
- }
- e = e.enclosingElement;
- }
- return '<unknown>';
- })
- .toSet()
- .toList();
- functionElement._setInferenceError(new TopLevelInferenceErrorBuilder(
- kind: TopLevelInferenceErrorKind.dependencyCycle,
- arguments: cycleNames));
- functionElement._setInferredType(DynamicTypeImpl.instance);
- } else {
- var computer = new ExprTypeComputer(functionElement);
- DartType bodyType = computer.compute();
- if (computer.errorKind != null) {
- functionElement._setInferenceError(
- new TopLevelInferenceErrorBuilder(kind: computer.errorKind));
- functionElement._setInferredType(DynamicTypeImpl.instance);
- } else {
- if (functionElement.isAsynchronous) {
- var linker = functionElement.compilationUnit.library._linker;
- var typeProvider = linker.typeProvider;
- var typeSystem = linker.typeSystem;
- if (bodyType.isDartAsyncFutureOr) {
- bodyType = (bodyType as InterfaceType).typeArguments[0];
- }
- bodyType = typeProvider.futureType
- .instantiate([typeSystem.flatten(bodyType)]);
- }
- functionElement._setInferredType(bodyType);
- }
- }
- }
-
- @override
- String toString() => 'TypeInferenceNode($functionElement)';
-}
-
-class TypeProviderForLink extends TypeProviderBase {
- final Linker _linker;
-
- InterfaceType _boolType;
- InterfaceType _deprecatedType;
- InterfaceType _doubleType;
- InterfaceType _functionType;
- InterfaceType _futureDynamicType;
- InterfaceType _futureNullType;
- InterfaceType _futureOrNullType;
- InterfaceType _futureOrType;
- InterfaceType _futureType;
- InterfaceType _intType;
- InterfaceType _iterableDynamicType;
- InterfaceType _iterableObjectType;
- InterfaceType _iterableType;
- InterfaceType _listType;
- InterfaceType _mapType;
- InterfaceType _mapObjectObjectType;
- InterfaceType _nullType;
- InterfaceType _numType;
- InterfaceType _objectType;
- InterfaceType _setType;
- InterfaceType _stackTraceType;
- InterfaceType _streamDynamicType;
- InterfaceType _streamType;
- InterfaceType _stringType;
- InterfaceType _symbolType;
- InterfaceType _typeType;
-
- TypeProviderForLink(this._linker);
-
- @override
- InterfaceType get boolType =>
- _boolType ??= _buildInterfaceType(_linker.coreLibrary, 'bool');
-
- @override
- DartType get bottomType => BottomTypeImpl.instance;
-
- @override
- InterfaceType get deprecatedType => _deprecatedType ??=
- _buildInterfaceType(_linker.coreLibrary, 'Deprecated');
-
- @override
- InterfaceType get doubleType =>
- _doubleType ??= _buildInterfaceType(_linker.coreLibrary, 'double');
-
- @override
- DartType get dynamicType => DynamicTypeImpl.instance;
-
- @override
- InterfaceType get functionType =>
- _functionType ??= _buildInterfaceType(_linker.coreLibrary, 'Function');
-
- @override
- InterfaceType get futureDynamicType =>
- _futureDynamicType ??= futureType.instantiate(<DartType>[dynamicType]);
-
- @override
- ClassElement get futureElement => futureType.element;
-
- @override
- InterfaceType get futureNullType =>
- _futureNullType ??= futureType.instantiate(<DartType>[nullType]);
-
- @override
- ClassElement get futureOrElement => futureOrType.element;
-
- @override
- InterfaceType get futureOrNullType =>
- _futureOrNullType ??= futureOrType.instantiate(<DartType>[nullType]);
-
- @override
- InterfaceType get futureOrType =>
- _futureOrType ??= _buildInterfaceType(_linker.asyncLibrary, 'FutureOr');
-
- @override
- InterfaceType get futureType =>
- _futureType ??= _buildInterfaceType(_linker.asyncLibrary, 'Future');
-
- @override
- InterfaceType get intType =>
- _intType ??= _buildInterfaceType(_linker.coreLibrary, 'int');
-
- @override
- InterfaceType get iterableDynamicType => _iterableDynamicType ??=
- iterableType.instantiate(<DartType>[dynamicType]);
-
- @override
- ClassElement get iterableElement => iterableType.element;
-
- @override
- InterfaceType get iterableObjectType =>
- _iterableObjectType ??= iterableType.instantiate(<DartType>[objectType]);
-
- @override
- InterfaceType get iterableType =>
- _iterableType ??= _buildInterfaceType(_linker.coreLibrary, 'Iterable');
-
- @override
- ClassElement get listElement => listType.element;
-
- @override
- InterfaceType get listType =>
- _listType ??= _buildInterfaceType(_linker.coreLibrary, 'List');
-
- @override
- ClassElement get mapElement => mapType.element;
-
- @override
- InterfaceType get mapObjectObjectType => _mapObjectObjectType ??=
- mapType.instantiate(<DartType>[objectType, objectType]);
-
- @override
- InterfaceType get mapType =>
- _mapType ??= _buildInterfaceType(_linker.coreLibrary, 'Map');
-
- @override
- DartType get neverType => BottomTypeImpl.instance;
-
- @override
- DartObjectImpl get nullObject {
- // TODO(paulberry): implement if needed
- throw new UnimplementedError();
- }
-
- @override
- InterfaceType get nullType =>
- _nullType ??= _buildInterfaceType(_linker.coreLibrary, 'Null');
-
- @override
- InterfaceType get numType =>
- _numType ??= _buildInterfaceType(_linker.coreLibrary, 'num');
-
- @override
- InterfaceType get objectType =>
- _objectType ??= _buildInterfaceType(_linker.coreLibrary, 'Object');
-
- @override
- ClassElement get setElement => setType.element;
-
- @override
- InterfaceType get setType =>
- _setType ??= _buildInterfaceType(_linker.coreLibrary, 'Set');
-
- @override
- InterfaceType get stackTraceType => _stackTraceType ??=
- _buildInterfaceType(_linker.coreLibrary, 'StackTrace');
-
- @override
- InterfaceType get streamDynamicType =>
- _streamDynamicType ??= streamType.instantiate(<DartType>[dynamicType]);
-
- @override
- ClassElement get streamElement => streamType.element;
-
- @override
- InterfaceType get streamType =>
- _streamType ??= _buildInterfaceType(_linker.asyncLibrary, 'Stream');
-
- @override
- InterfaceType get stringType =>
- _stringType ??= _buildInterfaceType(_linker.coreLibrary, 'String');
-
- @override
- ClassElement get symbolElement => symbolType.element;
-
- @override
- InterfaceType get symbolType =>
- _symbolType ??= _buildInterfaceType(_linker.coreLibrary, 'Symbol');
-
- @override
- InterfaceType get typeType =>
- _typeType ??= _buildInterfaceType(_linker.coreLibrary, 'Type');
-
- @override
- VoidType get voidType => VoidTypeImpl.instance;
-
- @override
- InterfaceType futureOrType2(DartType valueType) {
- return futureOrType.instantiate([valueType]);
- }
-
- @override
- InterfaceType futureType2(DartType valueType) {
- return futureType.instantiate([valueType]);
- }
-
- @override
- InterfaceType iterableType2(DartType elementType) {
- return iterableType.instantiate([elementType]);
- }
-
- @override
- InterfaceType listType2(DartType elementType) {
- return listType.instantiate([elementType]);
- }
-
- @override
- InterfaceType mapType2(DartType keyType, DartType valueType) {
- return mapType.instantiate([keyType, valueType]);
- }
-
- @override
- InterfaceType setType2(DartType elementType) {
- return setType.instantiate([elementType]);
- }
-
- @override
- InterfaceType streamType2(DartType elementType) {
- return streamType.instantiate([elementType]);
- }
-
- InterfaceType _buildInterfaceType(
- LibraryElementForLink library, String name) {
- return library.getContainedName(name).buildType((int i) {
- // TODO(scheglov) accept type parameter names
- var element = new TypeParameterElementImpl('T$i', -1);
- return new TypeParameterTypeImpl(element);
- }, const []);
- }
-}
-
-/// Singleton element used for unresolved references.
-class UndefinedElementForLink with ReferenceableElementForLink {
- static final UndefinedElementForLink instance =
- new UndefinedElementForLink._();
-
- UndefinedElementForLink._();
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/// Element representing a top level variable resynthesized from a
-/// summary during linking.
-abstract class VariableElementForLink
- implements NonParameterVariableElementImpl, PropertyInducingElement {
- /// The unlinked representation of the variable in the summary.
- final UnlinkedVariable unlinkedVariable;
-
- /// If non-null, the AST for the initializer expression; this is used for
- /// inferring the expression type.
- final Expression _initializerForInference;
-
- /// If this variable is declared `const` and the enclosing library is
- /// part of the build unit being linked, the variable's node in the
- /// constant evaluation dependency graph. Otherwise `null`.
- ConstNode _constNode;
-
- /// If this variable has an initializer and an implicit type, and the
- /// enclosing library is part of the build unit being linked, the variable's
- /// node in the type inference dependency graph. Otherwise `null`.
- TypeInferenceNode _typeInferenceNode;
-
- FunctionElementForLink_Initializer _initializer;
- DartType _inferredType;
- DartType _declaredType;
- PropertyAccessorElementForLink_Variable _getter;
- PropertyAccessorElementForLink_Variable _setter;
-
- /// The compilation unit in which this variable appears.
- final CompilationUnitElementForLink compilationUnit;
-
- VariableElementForLink(this.unlinkedVariable, this.compilationUnit,
- this._initializerForInference) {
- if (!compilationUnit.isInBuildUnit) return;
- if (unlinkedVariable.initializer?.bodyExpr == null) {
- if (_initializerForInference == null) return;
- } else {
- _constNode = new ConstVariableNode(this);
- }
- if (unlinkedVariable.type == null) {
- _typeInferenceNode = initializer.asTypeInferenceNode;
- }
- }
-
- /// If the variable has an explicitly declared return type, return it.
- /// Otherwise return `null`.
- DartType get declaredType {
- if (unlinkedVariable.type == null) {
- return null;
- } else {
- return _declaredType ??=
- compilationUnit.resolveTypeRef(this, unlinkedVariable.type);
- }
- }
-
- @override
- String get displayName => unlinkedVariable.name;
-
- @override
- PropertyAccessorElementForLink_Variable get getter =>
- _getter ??= new PropertyAccessorElementForLink_Variable(this, false);
-
- @override
- bool get hasImplicitType => unlinkedVariable.type == null;
-
- @override
- String get identifier => unlinkedVariable.name;
-
- /// Return the inferred type of the variable element. Should only be called
- /// if no type was explicitly declared.
- DartType get inferredType {
- // We should only try to infer a type when none is explicitly declared.
- assert(unlinkedVariable.type == null);
- if (_inferredType == null) {
- if (_typeInferenceNode != null) {
- assert(Linker._initializerTypeInferenceCycle == null);
- Linker._initializerTypeInferenceCycle =
- compilationUnit.library.libraryCycleForLink;
- Linker._isPerformingVariableTypeInference = true;
- try {
- new TypeInferenceDependencyWalker().walk(_typeInferenceNode);
- assert(_inferredType != null);
- } finally {
- Linker._initializerTypeInferenceCycle = null;
- Linker._isPerformingVariableTypeInference = false;
- }
- } else if (compilationUnit.isInBuildUnit) {
- _inferredType = DynamicTypeImpl.instance;
- } else {
- _inferredType = compilationUnit.getLinkedType(
- this, unlinkedVariable.inferredTypeSlot);
- }
- }
- return _inferredType;
- }
-
- @override
- FunctionElementForLink_Initializer get initializer {
- if (unlinkedVariable.initializer == null) {
- return null;
- } else {
- return _initializer ??= new FunctionElementForLink_Initializer(
- this, _initializerForInference);
- }
- }
-
- @override
- bool get isConst => unlinkedVariable.isConst;
-
- /// Return `true` if this variable is a field that was explicitly marked as
- /// being covariant (in the setter's parameter).
- bool get isCovariant => unlinkedVariable.isCovariant;
-
- @override
- bool get isFinal => unlinkedVariable.isFinal;
-
- @override
- bool get isStatic;
-
- @override
- bool get isSynthetic => false;
-
- @override
- String get name => unlinkedVariable.name;
-
- @override
- DartType get propagatedType {
- return DynamicTypeImpl.instance;
- }
-
- @override
- PropertyAccessorElementForLink_Variable get setter {
- if (!isConst && !isFinal) {
- return _setter ??=
- new PropertyAccessorElementForLink_Variable(this, true);
- } else {
- return null;
- }
- }
-
- @override
- DartType get type => declaredType ?? inferredType;
-
- @override
- void set type(DartType newType) {
- // TODO(paulberry): store inferred type.
- }
-
- @override
- TypeParameterizedElementMixin get typeParameterContext {
- return _typeParameterContext;
- }
-
- /// The context in which type parameters should be interpreted, or `null` if
- /// there are no type parameters in scope.
- TypeParameterizedElementMixin get _typeParameterContext;
-
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
- @override
- String toString() => '$enclosingElement.$name';
-}
-
-/// Specialization of [LibraryResynthesizer] for resynthesis during linking.
-class _LibraryResynthesizer extends LibraryResynthesizerMixin {
- LibraryElementForLink _library;
-
- @override
- LibraryElement get library => _library;
-
- @override
- List<LinkedExportName> get linkedExportNames => _library._linkedExportNames;
-
- @override
- Element buildExportName(LinkedExportName exportName) {
- LibraryElementForLink dependency =
- _library.buildImportedLibrary(exportName.dependency);
- return dependency.getContainedName(exportName.name);
- }
-}
-
-/// Specialization of [ReferenceInfo] for resynthesis during linking.
-class _ReferenceInfo extends ReferenceInfo {
- @override
- final ReferenceableElementForLink element;
-
- @override
- final ReferenceInfo enclosing;
-
- @override
- final String name;
-
- @override
- final bool hasTypeParameters;
-
- _ReferenceInfo(
- this.enclosing, this.element, this.name, this.hasTypeParameters);
-
- /// TODO(paulberry): this method doesn't seem to be used. Investigate whether
- /// it is needed.
- @override
- DartType get type => throw new UnimplementedError();
-}
-
-/// Specialization of [UnitResynthesizer] for resynthesis during linking.
-class _UnitResynthesizer extends UnitResynthesizer with UnitResynthesizerMixin {
- CompilationUnitElementForLink _unit;
-
- @override
- LibraryElement get library => _unit.library;
-
- @override
- TypeProvider get typeProvider => _unit.library._linker.typeProvider;
-
- @override
- TypeSystem get typeSystem => _unit.library._linker._typeSystem;
-
- @override
- DartType buildType(ElementImpl context, EntityRef type) =>
- _unit.resolveTypeRef(context, type);
-
- @override
- DartType buildTypeForClassInfo(
- info, int numTypeArguments, DartType Function(int i) getTypeArgument) {
- ClassElementForLink class_ = info.element;
- if (numTypeArguments == 0) {
- DartType type = class_.typeWithDefaultBounds;
- _typesWithImplicitArguments[type] = true;
- return type;
- }
- return class_.buildType(getTypeArgument, const []);
- }
-
- @override
- bool doesTypeHaveImplicitArguments(ParameterizedType type) =>
- _typesWithImplicitArguments[type] != null;
-
- @override
- _ReferenceInfo getReferenceInfo(int index) {
- return _unit.resolveRefToInfo(index);
- }
-}
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index 4de81f7..ca70dd2 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -5,15 +5,12 @@
import 'dart:io' as io;
import 'dart:math' show min;
-import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/resynthesize.dart';
/**
* A [ConflictingSummaryException] indicates that two different summaries
@@ -131,54 +128,15 @@
Source resolveAbsolute(Uri uri, [Uri actualUri]) {
actualUri ??= uri;
String uriString = uri.toString();
- if (AnalysisDriver.useSummary2) {
- String summaryPath = _dataStore.uriToSummaryPath[uriString];
- if (summaryPath != null) {
- return new InSummarySource(actualUri, summaryPath);
- }
- } else {
- UnlinkedUnit unit = _dataStore.unlinkedMap[uriString];
- if (unit != null) {
- String summaryPath = _dataStore.uriToSummaryPath[uriString];
- return new InSummarySource(actualUri, summaryPath);
- }
+ String summaryPath = _dataStore.uriToSummaryPath[uriString];
+ if (summaryPath != null) {
+ return new InSummarySource(actualUri, summaryPath);
}
return null;
}
}
/**
- * A concrete resynthesizer that serves summaries from [SummaryDataStore].
- */
-class StoreBasedSummaryResynthesizer extends SummaryResynthesizer {
- final SummaryDataStore _dataStore;
-
- StoreBasedSummaryResynthesizer(
- AnalysisContext context,
- AnalysisSession session,
- SourceFactory sourceFactory,
- bool _,
- this._dataStore)
- : super(context, session, sourceFactory, true);
-
- @override
- LinkedLibrary getLinkedSummary(String uri) {
- return _dataStore.linkedMap[uri];
- }
-
- @override
- UnlinkedUnit getUnlinkedSummary(String uri) {
- return _dataStore.unlinkedMap[uri];
- }
-
- @override
- bool hasLibrarySummary(String uri) {
- LinkedLibrary linkedLibrary = _dataStore.linkedMap[uri];
- return linkedLibrary != null;
- }
-}
-
-/**
* A [SummaryDataStore] is a container for the data extracted from a set of
* summary package bundles. It contains maps which can be used to find linked
* and unlinked summaries by URI.
@@ -319,11 +277,7 @@
* with the given absolute [uri].
*/
bool hasLinkedLibrary(String uri) {
- if (AnalysisDriver.useSummary2) {
- return _libraryUris.contains(uri);
- } else {
- return linkedMap.containsKey(uri);
- }
+ return _libraryUris.contains(uri);
}
/**
@@ -331,22 +285,14 @@
* with the given absolute [uri].
*/
bool hasUnlinkedUnit(String uri) {
- if (AnalysisDriver.useSummary2) {
- return uriToSummaryPath.containsKey(uri);
- } else {
- return unlinkedMap.containsKey(uri);
- }
+ return uriToSummaryPath.containsKey(uri);
}
/**
* Return `true` if the unit with the [uri] is a part unit in the store.
*/
bool isPartUnit(String uri) {
- if (AnalysisDriver.useSummary2) {
- return _partUris.contains(uri);
- } else {
- return !linkedMap.containsKey(uri);
- }
+ return _partUris.contains(uri);
}
void _fillMaps(String path, ResourceProvider resourceProvider) {
diff --git a/pkg/analyzer/lib/src/summary/prelink.dart b/pkg/analyzer/lib/src/summary/prelink.dart
deleted file mode 100644
index b0116e6..0000000
--- a/pkg/analyzer/lib/src/summary/prelink.dart
+++ /dev/null
@@ -1,723 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/analysis/declared_variables.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/name_filter.dart';
-
-/**
- * Create a [LinkedLibraryBuilder] corresponding to the given [definingUnitUri]
- * and [definingUnit], which should be the defining compilation unit for a
- * library. Compilation units referenced by the defining compilation unit via
- * `part` declarations will be retrieved using [getPart]. Public namespaces
- * for libraries referenced by the defining compilation unit via `import`
- * declarations (and files reachable from them via `part` and `export`
- * declarations) will be retrieved using [getImport].
- */
-LinkedLibraryBuilder prelink(
- String definingUnitUri,
- UnlinkedUnit definingUnit,
- GetPartCallback getPart,
- GetImportCallback getImport,
- DeclaredVariables declaredVariables) {
- return new _Prelinker(
- definingUnitUri, definingUnit, getPart, getImport, declaredVariables)
- .prelink();
-}
-
-/**
- * Type of the callback used by the prelinker to obtain public namespace
- * information about libraries with the given [absoluteUri] imported by the
- * library to be prelinked (and the transitive closure of parts and exports
- * reachable from those libraries).
- *
- * If no file exists at the given uri, `null` should be returned.
- */
-typedef UnlinkedPublicNamespace GetImportCallback(String absoluteUri);
-
-/**
- * Type of the callback used by the prelinker to obtain unlinked summaries of
- * part files of the library to be prelinked.
- *
- * If no file exists at the given uri, `null` should be returned.
- */
-typedef UnlinkedUnit GetPartCallback(String absoluteUri);
-
-/**
- * A [_Meaning] representing a class.
- */
-class _ClassMeaning extends _Meaning {
- final _Namespace namespace;
-
- _ClassMeaning(int unit, int dependency, int numTypeParameters, this.namespace)
- : super(unit, ReferenceKind.classOrEnum, dependency, numTypeParameters);
-}
-
-/**
- * A node in computing exported namespaces.
- */
-class _ExportNamespace {
- static int nextId = 0;
-
- /**
- * The export namespace, full (with all exports included), or partial (with
- * public namespace, and only some of the exports included).
- */
- final _Namespace namespace;
-
- /**
- * This field is set to non-zero when we start computing the export namespace
- * for the corresponding library, and is set back to zero when we finish
- * computation.
- */
- int id = 0;
-
- /**
- * Whether the [namespace] is full, so we don't need chasing exports.
- */
- bool isFull = false;
-
- _ExportNamespace(this.namespace);
-}
-
-/**
- * A [_Meaning] stores all the information necessary to find the declaration
- * referred to by a name in a namespace.
- */
-class _Meaning {
- /**
- * Which unit in the dependent library contains the declared entity.
- */
- final int unit;
-
- /**
- * The kind of entity being referred to.
- */
- final ReferenceKind kind;
-
- /**
- * Which of the dependencies of the library being prelinked contains the
- * declared entity.
- */
- final int dependency;
-
- /**
- * If the entity being referred to is generic, the number of type parameters
- * it accepts. Otherwise zero.
- */
- final int numTypeParameters;
-
- _Meaning(this.unit, this.kind, this.dependency, this.numTypeParameters);
-
- /**
- * Encode this [_Meaning] as a [LinkedExportName], using the given [name].
- */
- LinkedExportName encodeExportName(String name) {
- return new LinkedExportNameBuilder(
- name: name, dependency: dependency, unit: unit, kind: kind);
- }
-
-/**
- * Encode this [_Meaning] as a [LinkedReference].
- */
- LinkedReferenceBuilder encodeReference() {
- return new LinkedReferenceBuilder(
- unit: unit,
- kind: kind,
- dependency: dependency,
- numTypeParameters: numTypeParameters);
- }
-}
-
-/**
- * Mapping from names to corresponding unique [_Meaning]s.
- */
-class _Namespace {
- final Set<String> namesWithConflictingDefinitions = new Set<String>();
- final Set<String> libraryNames = new Set<String>();
- final Map<String, _Meaning> map = <String, _Meaning>{};
-
- /**
- * Return the [_Meaning] of the name, or `null` is not defined.
- */
- _Meaning operator [](String name) {
- return map[name];
- }
-
- /**
- * Define that the [name] has the given [value]. If the [name] already been
- * defined with a different value, then it becomes undefined.
- */
- void add(String name, _Meaning value) {
- // Already determined to be a conflict.
- if (namesWithConflictingDefinitions.contains(name)) {
- return;
- }
-
- _Meaning currentValue = map[name];
- if (currentValue == null) {
- map[name] = value;
- } else if (currentValue == value) {
- // The same value, ignore.
- } else {
- // A conflict, remember it, and un-define the name.
- namesWithConflictingDefinitions.add(name);
- map.remove(name);
- }
- }
-
- /**
- * Return `true` if the [name] was defined before [rememberLibraryNames]
- * invocation.
- */
- bool definesLibraryName(String name) => libraryNames.contains(name);
-
- /**
- * Return `true` if the [name] is already defined.
- */
- bool definesName(String name) => map.containsKey(name);
-
- /**
- * Apply [f] to each name-meaning pair.
- */
- void forEach(void f(String key, _Meaning value)) {
- map.forEach(f);
- }
-
- /**
- * This method should be invoked after defining all names that are defined
- * in a library, before defining imported names.
- */
- void rememberLibraryNames() {
- libraryNames.addAll(map.keys);
- }
-}
-
-/**
- * A [_Meaning] representing a prefix introduced by an import directive.
- */
-class _PrefixMeaning extends _Meaning {
- final _Namespace namespace = new _Namespace();
-
- _PrefixMeaning() : super(0, ReferenceKind.prefix, 0, 0);
-}
-
-/**
- * Helper class containing temporary data structures needed to prelink a single
- * library.
- */
-class _Prelinker {
- final String definingUnitUri;
- final UnlinkedUnit definingUnit;
- final GetPartCallback getPart;
- final GetImportCallback getImport;
- final DeclaredVariables declaredVariables;
-
- /**
- * Cache of values returned by [getImport].
- */
- final Map<String, UnlinkedPublicNamespace> importCache =
- <String, UnlinkedPublicNamespace>{};
-
- /**
- * Cache of values returned by [getPart].
- */
- final Map<String, UnlinkedUnit> partCache = <String, UnlinkedUnit>{};
-
- /**
- * Names defined inside the library being prelinked.
- */
- final _Namespace privateNamespace = new _Namespace()
- ..add('dynamic', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0))
- ..add('void', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0));
-
- /**
- * List of dependencies of the library being prelinked. This will be output
- * to [LinkedLibrary.dependencies].
- */
- final List<LinkedDependencyBuilder> dependencies =
- <LinkedDependencyBuilder>[];
-
- /**
- * Map from the absolute URI of a dependent library to the index of the
- * corresponding entry in [dependencies].
- */
- final Map<String, int> uriToDependency = <String, int>{};
-
- /**
- * List of public namespaces corresponding to each entry in [dependencies].
- */
- final List<_Namespace> dependencyToPublicNamespace = <_Namespace>[];
-
- /**
- * Map from absolute URI of a library to its export namespace.
- */
- final Map<String, _ExportNamespace> exportNamespaces = {};
-
- _Prelinker(this.definingUnitUri, this.definingUnit, this.getPart,
- this.getImport, this.declaredVariables) {
- partCache[definingUnitUri] = definingUnit;
- importCache[definingUnitUri] = definingUnit.publicNamespace;
- }
-
- void addClassToPrivateNamespace(int unitNum, UnlinkedClass cls) {
- _Namespace namespace = new _Namespace();
- cls.fields.forEach((field) {
- if (field.isStatic && field.isConst) {
- namespace.add(field.name,
- new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0));
- }
- });
- cls.executables.forEach((executable) {
- ReferenceKind kind = null;
- if (executable.kind == UnlinkedExecutableKind.constructor) {
- kind = ReferenceKind.constructor;
- } else if (executable.kind == UnlinkedExecutableKind.functionOrMethod &&
- executable.isStatic) {
- kind = ReferenceKind.method;
- } else if (executable.kind == UnlinkedExecutableKind.getter &&
- executable.isStatic) {
- kind = ReferenceKind.propertyAccessor;
- }
- if (kind != null && executable.name.isNotEmpty) {
- namespace.add(executable.name,
- new _Meaning(unitNum, kind, 0, executable.typeParameters.length));
- }
- });
- privateNamespace.add(cls.name,
- new _ClassMeaning(unitNum, 0, cls.typeParameters.length, namespace));
- }
-
- /**
- * Compute the public namespace for the library whose URI is reachable from
- * [definingUnit] via [absoluteUri], by aggregating together public namespace
- * information from all of its parts.
- */
- _Namespace aggregatePublicNamespace(String absoluteUri) {
- if (uriToDependency.containsKey(absoluteUri)) {
- return dependencyToPublicNamespace[uriToDependency[absoluteUri]];
- }
- assert(dependencies.length == dependencyToPublicNamespace.length);
- int dependency = dependencies.length;
- uriToDependency[absoluteUri] = dependency;
- List<String> unitUris = getUnitUris(absoluteUri);
- LinkedDependencyBuilder linkedDependency = new LinkedDependencyBuilder(
- uri: absoluteUri,
- parts: unitUris.skip(1).map((uri) => uri ?? '').toList());
- dependencies.add(linkedDependency);
-
- _Namespace aggregated = new _Namespace();
-
- for (int unitNum = 0; unitNum < unitUris.length; unitNum++) {
- String unitUri = unitUris[unitNum];
- UnlinkedPublicNamespace importedNamespace = getImportCached(unitUri);
- if (importedNamespace == null) {
- continue;
- }
- for (UnlinkedPublicName name in importedNamespace.names) {
- if (name.kind == ReferenceKind.classOrEnum) {
- _Namespace namespace = new _Namespace();
- name.members.forEach((executable) {
- namespace.add(
- executable.name,
- new _Meaning(
- unitNum, executable.kind, 0, executable.numTypeParameters));
- });
- aggregated.add(
- name.name,
- new _ClassMeaning(
- unitNum, dependency, name.numTypeParameters, namespace));
- } else {
- aggregated.add(
- name.name,
- new _Meaning(
- unitNum, name.kind, dependency, name.numTypeParameters));
- }
- }
- }
-
- aggregated.rememberLibraryNames();
-
- dependencyToPublicNamespace.add(aggregated);
- return aggregated;
- }
-
- /**
- * Compute the export namespace for the library whose URI is reachable from
- * [definingUnit] via [absoluteUri], by aggregating together public namespace
- * information from the library and the transitive closure of its exports.
- */
- _Namespace computeExportNamespace(String absoluteUri) {
- int firstCycleIdOfLastCall = 0;
- _Namespace chaseExports(String absoluteUri) {
- _ExportNamespace exportNamespace = getExportNamespace(absoluteUri);
-
- // If the export namespace is ready, return it.
- if (exportNamespace.isFull) {
- firstCycleIdOfLastCall = 0;
- return exportNamespace.namespace;
- }
-
- // If we are computing the export namespace for this library, and we
- // reached here, then we found a cycle.
- if (exportNamespace.id != 0) {
- firstCycleIdOfLastCall = exportNamespace.id;
- return null;
- }
-
- // Give each library a unique identifier.
- exportNamespace.id = _ExportNamespace.nextId++;
-
- // Append from exports.
- int firstCycleId = 0;
- UnlinkedPublicNamespace publicNamespace = getImportCached(absoluteUri);
- if (publicNamespace != null) {
- for (UnlinkedExportPublic export in publicNamespace.exports) {
- String unlinkedExportUri =
- _selectUri(export.uri, export.configurations);
- String exportUri = resolveUri(absoluteUri, unlinkedExportUri);
- if (exportUri != null) {
- NameFilter filter =
- new NameFilter.forUnlinkedCombinators(export.combinators);
- _Namespace exported = chaseExports(exportUri);
- exported?.forEach((String name, _Meaning meaning) {
- if (filter.accepts(name) &&
- !exportNamespace.namespace.definesLibraryName(name)) {
- exportNamespace.namespace.add(name, meaning);
- }
- });
- if (firstCycleIdOfLastCall != 0) {
- if (firstCycleId == 0 || firstCycleId > firstCycleIdOfLastCall) {
- firstCycleId = firstCycleIdOfLastCall;
- }
- }
- }
- }
- }
-
- // If this library is the first component of the cycle, then we are at
- // the beginning of this cycle, and combination of partial export
- // namespaces of other exported libraries and declarations of this
- // library is the full export namespace of this library.
- if (firstCycleId != 0 && firstCycleId == exportNamespace.id) {
- firstCycleId = 0;
- }
-
- // We're done with this library, successfully or not.
- exportNamespace.id = 0;
-
- // If no cycle detected in exports, mark the export namespace as full.
- if (firstCycleId == 0) {
- exportNamespace.isFull = true;
- }
-
- // Return the full or partial result.
- firstCycleIdOfLastCall = firstCycleId;
- return exportNamespace.namespace;
- }
-
- _ExportNamespace.nextId = 1;
- return chaseExports(absoluteUri);
- }
-
- /**
- * Extract all the names defined in [unit] (which is the [unitNum]th unit in
- * the library being prelinked) and store them in [privateNamespace].
- * Excludes names introduced by `import` statements.
- */
- void extractPrivateNames(UnlinkedUnit unit, int unitNum) {
- for (UnlinkedClass cls in unit.classes) {
- addClassToPrivateNamespace(unitNum, cls);
- }
- for (UnlinkedEnum enm in unit.enums) {
- _Namespace namespace = new _Namespace();
- enm.values.forEach((UnlinkedEnumValue value) {
- namespace.add(value.name,
- new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0));
- });
- namespace.add('values',
- new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0));
- privateNamespace.add(
- enm.name, new _ClassMeaning(unitNum, 0, 0, namespace));
- }
- for (UnlinkedExecutable executable in unit.executables) {
- privateNamespace.add(
- executable.name,
- new _Meaning(
- unitNum,
- executable.kind == UnlinkedExecutableKind.functionOrMethod
- ? ReferenceKind.topLevelFunction
- : ReferenceKind.topLevelPropertyAccessor,
- 0,
- executable.typeParameters.length));
- }
- for (UnlinkedClass mixin in unit.mixins) {
- addClassToPrivateNamespace(unitNum, mixin);
- }
- for (UnlinkedTypedef typedef in unit.typedefs) {
- ReferenceKind kind;
- switch (typedef.style) {
- case TypedefStyle.functionType:
- kind = ReferenceKind.typedef;
- break;
- case TypedefStyle.genericFunctionType:
- kind = ReferenceKind.genericFunctionTypedef;
- break;
- }
- assert(kind != null);
- privateNamespace.add(typedef.name,
- new _Meaning(unitNum, kind, 0, typedef.typeParameters.length));
- }
- for (UnlinkedVariable variable in unit.variables) {
- privateNamespace.add(variable.name,
- new _Meaning(unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0));
- if (!(variable.isConst || variable.isFinal)) {
- privateNamespace.add(
- variable.name + '=',
- new _Meaning(
- unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0));
- }
- }
- }
-
- /**
- * Filter the export namespace for the library whose URI is reachable the
- * given [absoluteUri], retaining only those names accepted by
- * [combinators], and store the resulting names in [result]. Names that
- * already exist in [result] are not overwritten.
- */
- void filterExportNamespace(String absoluteUri,
- List<UnlinkedCombinator> combinators, _Namespace result) {
- _Namespace exportNamespace = computeExportNamespace(absoluteUri);
- if (result == null) {
- // This can happen if the import prefix was shadowed by a local name, so
- // the imported symbols are inaccessible.
- return;
- }
- NameFilter filter = new NameFilter.forUnlinkedCombinators(combinators);
- exportNamespace.forEach((String name, _Meaning meaning) {
- if (filter.accepts(name) && !result.definesLibraryName(name)) {
- result.add(name, meaning);
- }
- });
- }
-
- /**
- * Return the [_ExportNamespace] for the library with the given [absoluteUri].
- * The export namespace might be full (will all exports included), or
- * partial (with public namespace, and only some of the exports included).
- */
- _ExportNamespace getExportNamespace(String absoluteUri) {
- _ExportNamespace exportNamespace = exportNamespaces[absoluteUri];
- if (exportNamespace == null) {
- _Namespace publicNamespace = aggregatePublicNamespace(absoluteUri);
- exportNamespace = new _ExportNamespace(publicNamespace);
- exportNamespaces[absoluteUri] = exportNamespace;
- }
- return exportNamespace;
- }
-
- /**
- * Wrapper around [getImport] that caches the return value in [importCache].
- */
- UnlinkedPublicNamespace getImportCached(String absoluteUri) {
- return importCache.putIfAbsent(absoluteUri, () => getImport(absoluteUri));
- }
-
- /**
- * Wrapper around [getPart] that caches the return value in [partCache] and
- * updates [importCache] appropriately.
- */
- UnlinkedUnit getPartCached(String absoluteUri) {
- return partCache.putIfAbsent(absoluteUri, () {
- UnlinkedUnit unit = getPart(absoluteUri);
- importCache[absoluteUri] = unit?.publicNamespace;
- return unit;
- });
- }
-
- /**
- * Compute the set of absolute URIs of all the compilation units in the
- * library whose URI is reachable from [definingUnit] via [absoluteUri].
- */
- List<String> getUnitUris(String absoluteUri) {
- List<String> result = <String>[absoluteUri];
- UnlinkedPublicNamespace publicNamespace = getImportCached(absoluteUri);
- if (publicNamespace != null) {
- result.addAll(publicNamespace.parts.map((String uri) {
- return resolveUri(absoluteUri, uri);
- }));
- }
- return result;
- }
-
- /**
- * Process a single `import` declaration in the library being prelinked. The
- * return value is the index of the imported library in [dependencies].
- */
- int handleImport(UnlinkedImport import) {
- String unlinkedUri = import.isImplicit
- ? 'dart:core'
- : _selectUri(import.uri, import.configurations);
- String absoluteUri = resolveUri(definingUnitUri, unlinkedUri);
-
- _Namespace targetNamespace = null;
- if (import.prefixReference != 0) {
- // The name introduced by an import declaration can't have a prefix of
- // its own.
- assert(
- definingUnit.references[import.prefixReference].prefixReference == 0);
- String prefix = definingUnit.references[import.prefixReference].name;
- _Meaning prefixMeaning = privateNamespace[prefix];
- if (prefixMeaning is _PrefixMeaning) {
- targetNamespace = prefixMeaning.namespace;
- }
- } else {
- targetNamespace = privateNamespace;
- }
- filterExportNamespace(absoluteUri, import.combinators, targetNamespace);
- return uriToDependency[absoluteUri];
- }
-
- /**
- * Produce a [LinkedUnit] for the given [unit], by resolving every one of
- * its references.
- */
- LinkedUnitBuilder linkUnit(UnlinkedUnit unit) {
- if (unit == null) {
- return new LinkedUnitBuilder();
- }
- Map<int, _Namespace> prefixNamespaces = <int, _Namespace>{};
- List<LinkedReferenceBuilder> references = <LinkedReferenceBuilder>[];
- for (int i = 0; i < unit.references.length; i++) {
- UnlinkedReference reference = unit.references[i];
- _Namespace namespace;
- if (reference.prefixReference == 0) {
- namespace = privateNamespace;
- } else {
- // Prefix references must always point backward.
- assert(reference.prefixReference < i);
- namespace = prefixNamespaces[reference.prefixReference];
- // Expressions like 'a.b.c.d' cannot be prelinked.
- namespace ??= new _Namespace();
- }
- _Meaning meaning = namespace[reference.name];
- if (meaning != null) {
- if (meaning is _PrefixMeaning) {
- prefixNamespaces[i] = meaning.namespace;
- } else if (meaning is _ClassMeaning) {
- prefixNamespaces[i] = meaning.namespace;
- }
- references.add(meaning.encodeReference());
- } else {
- references
- .add(new LinkedReferenceBuilder(kind: ReferenceKind.unresolved));
- }
- }
- return new LinkedUnitBuilder(references: references);
- }
-
- /**
- * Form the [LinkedLibrary] for the [definingUnit] that was passed to the
- * constructor.
- */
- LinkedLibraryBuilder prelink() {
- aggregatePublicNamespace(definingUnitUri);
-
- // Gather up the unlinked summaries for all the compilation units in the
- // library.
- List<String> unitUris = getUnitUris(definingUnitUri);
- List<UnlinkedUnit> units = unitUris.map(getPartCached).toList();
-
- // Create the private namespace for the library by gathering all the names
- // defined in its compilation units.
- for (int unitNum = 0; unitNum < units.length; unitNum++) {
- UnlinkedUnit unit = units[unitNum];
- if (unit != null) {
- extractPrivateNames(unit, unitNum);
- }
- }
-
- // Fill in exported names. This must be done before filling in prefixes
- // defined in import declarations, because prefixes shouldn't shadow
- // exports.
- List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[];
- computeExportNamespace(definingUnitUri)
- .forEach((String name, _Meaning meaning) {
- if (!privateNamespace.definesName(name)) {
- exportNames.add(meaning.encodeExportName(name));
- }
- });
-
- // Fill in prefixes defined in import declarations.
- for (UnlinkedImport import in units[0].imports) {
- if (import.prefixReference != 0) {
- String name = units[0].references[import.prefixReference].name;
- if (!privateNamespace.definesName(name)) {
- privateNamespace.add(name, new _PrefixMeaning());
- }
- }
- }
-
- // All the names defined so far are library local, they take precedence
- // over anything imported from other libraries.
- privateNamespace.rememberLibraryNames();
-
- // Fill in imported and exported names.
- List<int> importDependencies =
- definingUnit.imports.map(handleImport).toList();
- List<int> exportDependencies = definingUnit.publicNamespace.exports
- .map((UnlinkedExportPublic exp) {
- String unlinkedUri = _selectUri(exp.uri, exp.configurations);
- String absoluteUri = resolveUri(definingUnitUri, unlinkedUri);
- return uriToDependency[absoluteUri];
- })
- .where((dependency) => dependency != null)
- .toList();
-
- // Link each compilation unit.
- List<LinkedUnitBuilder> linkedUnits = units.map(linkUnit).toList();
-
- return new LinkedLibraryBuilder(
- units: linkedUnits,
- dependencies: dependencies,
- importDependencies: importDependencies,
- exportDependencies: exportDependencies,
- exportNames: exportNames,
- numPrelinkedDependencies: dependencies.length);
- }
-
- /**
- * Resolve [relativeUri] relative to [containingUri]. Return `null` if
- * [relativeUri] is invalid or empty, so cannot be resolved.
- */
- String resolveUri(String containingUri, String relativeUri) {
- if (relativeUri == '') {
- return null;
- }
- try {
- Uri containingUriObj = Uri.parse(containingUri);
- Uri relativeUriObj = Uri.parse(relativeUri);
- return resolveRelativeUri(containingUriObj, relativeUriObj).toString();
- } on FormatException {
- return null;
- }
- }
-
- /**
- * Return the URI of the first configuration from the given [configurations]
- * which condition is satisfied, or the [defaultUri].
- */
- String _selectUri(
- String defaultUri, List<UnlinkedConfiguration> configurations) {
- for (UnlinkedConfiguration configuration in configurations) {
- if (declaredVariables.get(configuration.name) == configuration.value) {
- return configuration.uri;
- }
- }
- return defaultUri;
- }
-}
diff --git a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
deleted file mode 100644
index 4c2e4db..0000000
--- a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright (c) 2015, 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/visitor.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
-
-/**
- * Compute the public namespace portion of the summary for the given [unit],
- * which is presumed to be an unresolved AST.
- */
-UnlinkedPublicNamespaceBuilder computePublicNamespace(CompilationUnit unit) {
- _PublicNamespaceVisitor visitor = new _PublicNamespaceVisitor();
- unit.accept(visitor);
- return new UnlinkedPublicNamespaceBuilder(
- names: visitor.names, exports: visitor.exports, parts: visitor.parts);
-}
-
-/**
- * Serialize a [Configuration] into a [UnlinkedConfigurationBuilder].
- */
-UnlinkedConfigurationBuilder serializeConfiguration(
- Configuration configuration) {
- return new UnlinkedConfigurationBuilder(
- name: configuration.name.components.map((i) => i.name).join('.'),
- value: configuration.value?.stringValue ?? 'true',
- uri: configuration.uri.stringValue);
-}
-
-class _CombinatorEncoder extends SimpleAstVisitor<UnlinkedCombinatorBuilder> {
- _CombinatorEncoder();
-
- List<String> encodeNames(NodeList<SimpleIdentifier> names) =>
- names.map((SimpleIdentifier id) => id.name).toList();
-
- @override
- UnlinkedCombinatorBuilder visitHideCombinator(HideCombinator node) {
- return new UnlinkedCombinatorBuilder(hides: encodeNames(node.hiddenNames));
- }
-
- @override
- UnlinkedCombinatorBuilder visitShowCombinator(ShowCombinator node) {
- return new UnlinkedCombinatorBuilder(
- shows: encodeNames(node.shownNames),
- offset: node.offset,
- end: node.end);
- }
-}
-
-class _PublicNamespaceVisitor extends RecursiveAstVisitor {
- final List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[];
- final List<UnlinkedExportPublicBuilder> exports =
- <UnlinkedExportPublicBuilder>[];
- final List<String> parts = <String>[];
-
- _PublicNamespaceVisitor();
-
- UnlinkedPublicNameBuilder addNameIfPublic(
- String name, ReferenceKind kind, int numTypeParameters) {
- if (isPublic(name)) {
- UnlinkedPublicNameBuilder b = new UnlinkedPublicNameBuilder(
- name: name, kind: kind, numTypeParameters: numTypeParameters);
- names.add(b);
- return b;
- }
- return null;
- }
-
- bool isPublic(String name) => !name.startsWith('_');
-
- @override
- visitClassDeclaration(ClassDeclaration node) {
- UnlinkedPublicNameBuilder cls = addNameIfPublic(
- node.name.name,
- ReferenceKind.classOrEnum,
- node.typeParameters?.typeParameters?.length ?? 0);
- if (cls != null) {
- _addClassMembers(cls, node.members);
- }
- }
-
- @override
- visitClassTypeAlias(ClassTypeAlias node) {
- addNameIfPublic(node.name.name, ReferenceKind.classOrEnum,
- node.typeParameters?.typeParameters?.length ?? 0);
- }
-
- @override
- visitEnumDeclaration(EnumDeclaration node) {
- UnlinkedPublicNameBuilder enm =
- addNameIfPublic(node.name.name, ReferenceKind.classOrEnum, 0);
- if (enm != null) {
- enm.members.add(new UnlinkedPublicNameBuilder(
- name: 'values',
- kind: ReferenceKind.propertyAccessor,
- numTypeParameters: 0));
- for (EnumConstantDeclaration enumConstant in node.constants) {
- String name = enumConstant.name.name;
- if (isPublic(name)) {
- enm.members.add(new UnlinkedPublicNameBuilder(
- name: name,
- kind: ReferenceKind.propertyAccessor,
- numTypeParameters: 0));
- }
- }
- }
- }
-
- @override
- visitExportDirective(ExportDirective node) {
- exports.add(new UnlinkedExportPublicBuilder(
- uri: node.uri.stringValue,
- combinators: node.combinators
- .map((Combinator c) => c.accept(new _CombinatorEncoder()))
- .toList(),
- configurations:
- node.configurations.map(serializeConfiguration).toList()));
- }
-
- @override
- visitFunctionDeclaration(FunctionDeclaration node) {
- String name = node.name.name;
- if (node.isSetter) {
- name += '=';
- }
- addNameIfPublic(
- name,
- node.isGetter || node.isSetter
- ? ReferenceKind.topLevelPropertyAccessor
- : ReferenceKind.topLevelFunction,
- node.functionExpression.typeParameters?.typeParameters?.length ?? 0);
- }
-
- @override
- visitFunctionTypeAlias(FunctionTypeAlias node) {
- addNameIfPublic(node.name.name, ReferenceKind.typedef,
- node.typeParameters?.typeParameters?.length ?? 0);
- }
-
- @override
- visitGenericTypeAlias(GenericTypeAlias node) {
- addNameIfPublic(node.name.name, ReferenceKind.genericFunctionTypedef,
- node.typeParameters?.typeParameters?.length ?? 0);
- }
-
- @override
- visitMixinDeclaration(MixinDeclaration node) {
- UnlinkedPublicNameBuilder mixin = addNameIfPublic(
- node.name.name,
- ReferenceKind.classOrEnum,
- node.typeParameters?.typeParameters?.length ?? 0);
- if (mixin != null) {
- _addClassMembers(mixin, node.members);
- }
- }
-
- @override
- visitPartDirective(PartDirective node) {
- parts.add(node.uri.stringValue ?? '');
- }
-
- @override
- visitVariableDeclaration(VariableDeclaration node) {
- String name = node.name.name;
- addNameIfPublic(name, ReferenceKind.topLevelPropertyAccessor, 0);
- if (!node.isFinal && !node.isConst) {
- addNameIfPublic('$name=', ReferenceKind.topLevelPropertyAccessor, 0);
- }
- }
-
- void _addClassMembers(
- UnlinkedPublicNameBuilder builder, List<ClassMember> members) {
- for (ClassMember member in members) {
- if (member is FieldDeclaration && member.isStatic) {
- for (VariableDeclaration field in member.fields.variables) {
- String name = field.name.name;
- if (isPublic(name)) {
- builder.members.add(new UnlinkedPublicNameBuilder(
- name: name,
- kind: ReferenceKind.propertyAccessor,
- numTypeParameters: 0));
- }
- }
- }
- if (member is MethodDeclaration &&
- member.isStatic &&
- !member.isSetter &&
- !member.isOperator) {
- String name = member.name.name;
- if (isPublic(name)) {
- builder.members.add(new UnlinkedPublicNameBuilder(
- name: name,
- kind: member.isGetter
- ? ReferenceKind.propertyAccessor
- : ReferenceKind.method,
- numTypeParameters:
- member.typeParameters?.typeParameters?.length ?? 0));
- }
- }
- if (member is ConstructorDeclaration && member.name != null) {
- String name = member.name.name;
- if (isPublic(name)) {
- builder.members.add(new UnlinkedPublicNameBuilder(
- name: name,
- kind: ReferenceKind.constructor,
- numTypeParameters: 0));
- }
- }
- }
- }
-}
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
deleted file mode 100644
index 0b8c5ac..0000000
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ /dev/null
@@ -1,1671 +0,0 @@
-// Copyright (c) 2015, 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 'dart:collection';
-
-import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/nullability_suffix.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/handle.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_provider.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/summary/expr_builder.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
-
-/**
- * Expando for marking types with implicit type arguments, which are the same as
- * type parameter bounds (in strong mode), or `dynamic` (in spec mode).
- *
- * If a type is associated with a non-null value in this expando, then it has
- * implicit type arguments.
- */
-final _typesWithImplicitTypeArguments = new Expando();
-
-NullabilitySuffix decodeNullabilitySuffix(EntityRefNullabilitySuffix suffix) {
- switch (suffix) {
- case EntityRefNullabilitySuffix.none:
- return NullabilitySuffix.none;
- case EntityRefNullabilitySuffix.question:
- return NullabilitySuffix.question;
- case EntityRefNullabilitySuffix.starOrIrrelevant:
- return NullabilitySuffix.star;
- }
- throw new StateError('Unrecognized nullability suffix');
-}
-
-EntityRefNullabilitySuffix encodeNullabilitySuffix(NullabilitySuffix suffix) {
- switch (suffix) {
- case NullabilitySuffix.none:
- return EntityRefNullabilitySuffix.none;
- case NullabilitySuffix.question:
- return EntityRefNullabilitySuffix.question;
- case NullabilitySuffix.star:
- return EntityRefNullabilitySuffix.starOrIrrelevant;
- }
- throw new StateError('Unrecognized nullability suffix');
-}
-
-/// An instance of [LibraryResynthesizer] is responsible for resynthesizing the
-/// elements in a single library from that library's summary.
-abstract class LibraryResynthesizer {
- /// Builds the export namespace for the library by aggregating together its
- /// public namespace and export names.
- Namespace buildExportNamespace();
-
- /// Builds the public namespace for the library.
- Namespace buildPublicNamespace();
-}
-
-/// [LibraryResynthesizerContextMixin] contains methods useful for implementing
-/// the [LibraryResynthesizerContext] interface.
-abstract class LibraryResynthesizerContextMixin
- implements LibraryResynthesizerContext {
- /// Gets the associated [LibraryResynthesizer].
- LibraryResynthesizer get resynthesizer;
-
- @override
- Namespace buildExportNamespace() => resynthesizer.buildExportNamespace();
-
- @override
- Namespace buildPublicNamespace() => resynthesizer.buildPublicNamespace();
-}
-
-/// [LibraryResynthesizerMixin] contains methods useful for implementing the
-/// [LibraryResynthesizer] interface.
-abstract class LibraryResynthesizerMixin implements LibraryResynthesizer {
- /// Gets the library element being resynthesized.
- LibraryElement get library;
-
- /// Gets the list of export names created during summary linking.
- List<LinkedExportName> get linkedExportNames;
-
- /// Builds or retrieves an [Element] for the entity referred to by the given
- /// [exportName].
- Element buildExportName(LinkedExportName exportName);
-
- @override
- Namespace buildExportNamespace() {
- Namespace publicNamespace = library.publicNamespace;
- List<LinkedExportName> exportNames = linkedExportNames;
- Map<String, Element> definedNames = new HashMap<String, Element>();
- // Start by populating all the public names from [publicNamespace].
- publicNamespace.definedNames.forEach((String name, Element element) {
- definedNames[name] = element;
- });
- // Add all the names from [exportNames].
- for (LinkedExportName exportName in exportNames) {
- String name = exportName.name;
- if (!definedNames.containsKey(name)) {
- definedNames[name] = buildExportName(exportName);
- }
- }
- return new Namespace(definedNames);
- }
-
- @override
- Namespace buildPublicNamespace() =>
- new NamespaceBuilder().createPublicNamespaceForLibrary(library);
-}
-
-class RecursiveInstantiateToBounds {}
-
-/// Data structure used during resynthesis to record all the information that is
-/// known about how to resynthesize a single entry in [LinkedUnit.references]
-/// (and its associated entry in [UnlinkedUnit.references], if it exists).
-abstract class ReferenceInfo {
- /// The element referred to by this reference, or `null` if there is no
- /// associated element (e.g. because it is a reference to an undefined
- /// entity).
- Element get element;
-
- /// The enclosing [_ReferenceInfo], or `null` for top-level elements.
- ReferenceInfo get enclosing;
-
- /// Indicates whether the thing being referenced has at least one type
- /// parameter.
- bool get hasTypeParameters;
-
- /// The name of the entity referred to by this reference.
- String get name;
-
- /// If this reference refers to a non-generic type, the type it refers to.
- /// Otherwise `null`.
- DartType get type;
-}
-
-/**
- * Implementation of [ElementResynthesizer] used when resynthesizing an element
- * model from summaries.
- */
-abstract class SummaryResynthesizer extends ElementResynthesizer {
- /**
- * Source factory used to convert URIs to [Source] objects.
- */
- final SourceFactory sourceFactory;
-
- /**
- * Cache of [Source] objects that have already been converted from URIs.
- */
- final Map<String, Source> _sources = <String, Source>{};
-
- /**
- * The `dart:core` library for the context.
- */
- LibraryElementImpl _coreLibrary;
-
- /**
- * The `dart:async` library for the context.
- */
- LibraryElementImpl _asyncLibrary;
-
- /**
- * The [TypeProvider] used to obtain SDK types during resynthesis.
- */
- TypeProvider _typeProvider;
-
- /**
- * Map of compilation units resynthesized from summaries. The two map keys
- * are the first two elements of the element's location (the library URI and
- * the compilation unit URI).
- */
- final Map<String, Map<String, CompilationUnitElementImpl>>
- _resynthesizedUnits = <String, Map<String, CompilationUnitElementImpl>>{};
-
- /**
- * Map of top level elements resynthesized from summaries. The three map
- * keys are the first three elements of the element's location (the library
- * URI, the compilation unit URI, and the name of the top level declaration).
- */
- final Map<String, Map<String, Map<String, Element>>> _resynthesizedElements =
- <String, Map<String, Map<String, Element>>>{};
-
- /**
- * Map of libraries which have been resynthesized from summaries. The map
- * key is the library URI.
- */
- final Map<String, LibraryElement> _resynthesizedLibraries =
- <String, LibraryElement>{};
-
- SummaryResynthesizer(AnalysisContext context, AnalysisSession session,
- this.sourceFactory, bool _)
- : super(context, session) {
- _buildTypeProvider();
- }
-
- /**
- * Number of libraries that have been resynthesized so far.
- */
- int get resynthesisCount => _resynthesizedLibraries.length;
-
- /**
- * Indicates whether the summary should be resynthesized assuming strong mode
- * semantics.
- */
- @deprecated
- bool get strongMode => true;
-
- /**
- * The [TypeProvider] used to obtain SDK types during resynthesis.
- */
- TypeProvider get typeProvider => _typeProvider;
-
- /**
- * The [TypeSystem] used perform type operations.
- */
- TypeSystem get typeSystem => context.typeSystem;
-
- /**
- * The client installed this resynthesizer into the context, and set its
- * type provider, so it is not safe to access type provider to create
- * additional types.
- */
- void finishCoreAsyncLibraries() {
- _coreLibrary.createLoadLibraryFunction(_typeProvider);
- _asyncLibrary.createLoadLibraryFunction(_typeProvider);
- }
-
- @override
- Element getElement(ElementLocation location) {
- List<String> components = location.components;
- String libraryUri = components[0];
- // Resynthesize locally.
- if (components.length == 1) {
- return getLibraryElement(libraryUri);
- } else if (components.length == 2) {
- LibraryElement libraryElement = getLibraryElement(libraryUri);
- // Try to find the unit element.
- {
- Map<String, CompilationUnitElement> libraryMap =
- _resynthesizedUnits[libraryUri];
- assert(libraryMap != null);
- String unitUri = components[1];
- CompilationUnitElement unitElement = libraryMap[unitUri];
- if (unitElement != null) {
- return unitElement;
- }
- }
- // Try to find the prefix element.
- {
- String name = components[1];
- for (PrefixElement prefix in libraryElement.prefixes) {
- if (prefix.name == name) {
- return prefix;
- }
- }
- }
- // Fail.
- throw new Exception('The element not found in summary: $location');
- } else if (components.length == 3 || components.length == 4) {
- String unitUri = components[1];
- // Prepare elements-in-units in the library.
- Map<String, Map<String, Element>> unitsInLibrary =
- _resynthesizedElements[libraryUri];
- if (unitsInLibrary == null) {
- unitsInLibrary = new HashMap<String, Map<String, Element>>();
- _resynthesizedElements[libraryUri] = unitsInLibrary;
- }
- // Prepare elements in the unit.
- Map<String, Element> elementsInUnit = unitsInLibrary[unitUri];
- if (elementsInUnit == null) {
- // Prepare the CompilationUnitElementImpl.
- Map<String, CompilationUnitElementImpl> libraryMap =
- _resynthesizedUnits[libraryUri];
- if (libraryMap == null) {
- getLibraryElement(libraryUri);
- libraryMap = _resynthesizedUnits[libraryUri];
- if (libraryMap == null) {
- throw new StateError(
- 'Unable to find library `$libraryUri` in a summary file.');
- }
- }
- CompilationUnitElementImpl unitElement = libraryMap[unitUri];
- // Fill elements in the unit map.
- if (unitElement != null) {
- elementsInUnit = new HashMap<String, Element>();
- void putElement(Element e) {
- String id =
- e is PropertyAccessorElementImpl ? e.identifier : e.name;
- elementsInUnit[id] = e;
- }
-
- unitElement.accessors.forEach(putElement);
- unitElement.enums.forEach(putElement);
- unitElement.functions.forEach(putElement);
- unitElement.functionTypeAliases.forEach(putElement);
- unitElement.mixins.forEach(putElement);
- unitElement.topLevelVariables.forEach(putElement);
- unitElement.types.forEach(putElement);
- unitsInLibrary[unitUri] = elementsInUnit;
- }
- }
- // Get the element.
- Element element = elementsInUnit[components[2]];
- if (element != null && components.length == 4) {
- String name = components[3];
- Element parentElement = element;
- if (parentElement is ClassElement) {
- if (name.endsWith('?')) {
- element =
- parentElement.getGetter(name.substring(0, name.length - 1));
- } else if (name.endsWith('=')) {
- element =
- parentElement.getSetter(name.substring(0, name.length - 1));
- } else if (name.isEmpty) {
- element = parentElement.unnamedConstructor;
- } else {
- element = parentElement.getField(name) ??
- parentElement.getMethod(name) ??
- parentElement.getNamedConstructor(name);
- }
- } else {
- // The only elements that are currently retrieved using 4-component
- // locations are class members.
- throw new StateError(
- '4-element locations not supported for ${element.runtimeType}');
- }
- }
- if (element == null) {
- throw new Exception('Element not found in summary: $location');
- }
- return element;
- } else {
- throw new UnimplementedError(location.toString());
- }
- }
-
- /**
- * Get the [LibraryElement] for the given [uri], resynthesizing it if it
- * hasn't been resynthesized already.
- */
- LibraryElement getLibraryElement(String uri) {
- return _resynthesizedLibraries.putIfAbsent(uri, () {
- LinkedLibrary serializedLibrary = getLinkedSummary(uri);
- Source librarySource = _getSource(uri);
- if (serializedLibrary == null) {
- LibraryElementImpl libraryElement =
- new LibraryElementImpl(context, session, '', -1, 0, true);
- libraryElement.isSynthetic = true;
- CompilationUnitElementImpl unitElement =
- new CompilationUnitElementImpl();
- libraryElement.definingCompilationUnit = unitElement;
- unitElement.source = librarySource;
- unitElement.librarySource = librarySource;
- libraryElement.createLoadLibraryFunction(typeProvider);
- libraryElement.publicNamespace = new Namespace({});
- libraryElement.exportNamespace = new Namespace({});
- _resynthesizedUnits[uri] = {uri: unitElement};
- return libraryElement;
- }
- UnlinkedUnit unlinkedSummary = getUnlinkedSummary(uri);
- if (unlinkedSummary == null) {
- throw new StateError('Unable to find unlinked summary: $uri');
- }
- List<UnlinkedUnit> serializedUnits = <UnlinkedUnit>[unlinkedSummary];
- for (String part in serializedUnits[0].publicNamespace.parts) {
- Source partSource = sourceFactory.resolveUri(librarySource, part);
- UnlinkedUnit partUnlinkedUnit;
- if (partSource != null) {
- String partAbsUri = partSource.uri.toString();
- partUnlinkedUnit = getUnlinkedSummary(partAbsUri);
- }
- serializedUnits.add(partUnlinkedUnit ??
- new UnlinkedUnitBuilder(codeRange: new CodeRangeBuilder()));
- }
- _LibraryResynthesizer libraryResynthesizer = new _LibraryResynthesizer(
- this, serializedLibrary, serializedUnits, librarySource);
- LibraryElement library = libraryResynthesizer.buildLibrary();
- _resynthesizedUnits[uri] = libraryResynthesizer.resynthesizedUnits;
- return library;
- });
- }
-
- /**
- * Return the [LinkedLibrary] for the given [uri] or `null` if it could not
- * be found. Caller has already checked that `parent.hasLibrarySummary(uri)`
- * returns `false`.
- */
- LinkedLibrary getLinkedSummary(String uri);
-
- /**
- * Return the [UnlinkedUnit] for the given [uri] or `null` if it could not
- * be found. Caller has already checked that `parent.hasLibrarySummary(uri)`
- * returns `false`.
- */
- UnlinkedUnit getUnlinkedSummary(String uri);
-
- /**
- * Return `true` if this resynthesizer can provide summaries of the libraries
- * with the given [uri]. Caller has already checked that
- * `parent.hasLibrarySummary(uri)` returns `false`.
- */
- bool hasLibrarySummary(String uri);
-
- void _buildTypeProvider() {
- _coreLibrary = getLibraryElement('dart:core') as LibraryElementImpl;
- _asyncLibrary = getLibraryElement('dart:async') as LibraryElementImpl;
- _typeProvider = new TypeProviderImpl(_coreLibrary, _asyncLibrary);
- }
-
- /**
- * Get the [Source] object for the given [uri].
- */
- Source _getSource(String uri) {
- return _sources.putIfAbsent(uri, () => sourceFactory.forUri(uri));
- }
-}
-
-class SummaryResynthesizerContext implements ResynthesizerContext {
- final _UnitResynthesizer unitResynthesizer;
-
- SummaryResynthesizerContext(this.unitResynthesizer);
-
- @deprecated
- @override
- bool get isStrongMode => true;
-
- @override
- ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedExpr uc) {
- return unitResynthesizer.buildAnnotation(context, uc);
- }
-
- @override
- Expression buildExpression(ElementImpl context, UnlinkedExpr uc) {
- return unitResynthesizer._buildConstExpression(context, uc);
- }
-
- @override
- UnitExplicitTopLevelAccessors buildTopLevelAccessors() {
- return unitResynthesizer.buildUnitExplicitTopLevelAccessors();
- }
-
- @override
- UnitExplicitTopLevelVariables buildTopLevelVariables() {
- return unitResynthesizer.buildUnitExplicitTopLevelVariables();
- }
-
- @override
- TopLevelInferenceError getTypeInferenceError(int slot) {
- return unitResynthesizer.getTypeInferenceError(slot);
- }
-
- @override
- bool inheritsCovariant(int slot) {
- return unitResynthesizer.parametersInheritingCovariant.contains(slot);
- }
-
- @override
- bool isInConstCycle(int slot) {
- return unitResynthesizer.constCycles.contains(slot);
- }
-
- @override
- bool isSimplyBounded(int notSimplyBoundedSlot) {
- return !unitResynthesizer.linkedUnit.notSimplyBounded
- .contains(notSimplyBoundedSlot);
- }
-
- @override
- ConstructorElement resolveConstructorRef(
- ElementImpl context, EntityRef entry) {
- return unitResynthesizer._getConstructorForEntry(context, entry);
- }
-
- @override
- DartType resolveLinkedType(ElementImpl context, int slot) {
- return unitResynthesizer.buildLinkedType(context, slot);
- }
-
- @override
- DartType resolveTypeRef(ElementImpl context, EntityRef type,
- {bool defaultVoid: false,
- bool instantiateToBoundsAllowed: true,
- bool declaredType: false}) {
- return unitResynthesizer.buildType(context, type,
- defaultVoid: defaultVoid,
- instantiateToBoundsAllowed: instantiateToBoundsAllowed,
- declaredType: declaredType);
- }
-}
-
-/// An instance of [_UnitResynthesizer] is responsible for resynthesizing the
-/// elements in a single unit from that unit's summary.
-abstract class UnitResynthesizer {
- /// Gets the [LibraryElement] being resynthesized.
- LibraryElement get library;
-
- /// Gets the [TypeProvider], which may be used to create core types.
- TypeProvider get typeProvider;
-
- /// Gets the [TypeSystem], which may be used to create core types.
- TypeSystem get typeSystem;
-
- /// Builds a [DartType] object based on a [EntityRef]. This [DartType]
- /// may refer to elements in other libraries than the library being
- /// deserialized, so handles may be used to avoid having to deserialize other
- /// libraries in the process.
- DartType buildType(ElementImpl context, EntityRef type);
-
- /// Builds a [DartType] object based on [ReferenceInfo], which should refer to
- /// a class, by filling in the type arguments as appropriate, and performing
- /// instantiate to bounds if necessary.
- DartType buildTypeForClassInfo(ReferenceInfo info, int numTypeArguments,
- DartType getTypeArgument(int i));
-
- /// Returns the defining type for a [ConstructorElement] by applying
- /// [typeArgumentRefs] to the given linked [info]. Returns [DynamicTypeImpl]
- /// if the [info] is unresolved.
- DartType createConstructorDefiningType(ElementImpl context,
- ReferenceInfo info, List<EntityRef> typeArgumentRefs);
-
- /// Determines if the given [type] has implicit type arguments.
- bool doesTypeHaveImplicitArguments(ParameterizedType type);
-
- /// Returns the [ConstructorElement] corresponding to the given linked [info],
- /// using the [classType] which has already been computed (e.g. by
- /// [createConstructorDefiningType]). Both cases when [info] is a
- /// [ClassElement] and [ConstructorElement] are supported.
- ConstructorElement getConstructorForInfo(
- InterfaceType classType, ReferenceInfo info);
-
- /// Returns the [ReferenceInfo] with the given [index].
- ReferenceInfo getReferenceInfo(int index);
-}
-
-/// [UnitResynthesizerMixin] contains methods useful for implementing the
-/// [UnitResynthesizer] interface.
-mixin UnitResynthesizerMixin implements UnitResynthesizer {
- @override
- DartType createConstructorDefiningType(ElementImpl context,
- ReferenceInfo info, List<EntityRef> typeArgumentRefs) {
- bool isClass = info.element is ClassElement;
- ReferenceInfo classInfo = isClass ? info : info.enclosing;
- if (classInfo == null) {
- return DynamicTypeImpl.instance;
- }
- List<DartType> typeArguments =
- typeArgumentRefs.map((t) => buildType(context, t)).toList();
- return buildTypeForClassInfo(classInfo, typeArguments.length, (i) {
- if (i < typeArguments.length) {
- return typeArguments[i];
- } else {
- return DynamicTypeImpl.instance;
- }
- });
- }
-
- @override
- ConstructorElement getConstructorForInfo(
- InterfaceType classType, ReferenceInfo info) {
- ConstructorElement element;
- Element infoElement = info.element;
- if (infoElement is ConstructorElement) {
- element = infoElement;
- } else if (infoElement is ClassElement) {
- element = infoElement.unnamedConstructor;
- }
- if (element != null && info.hasTypeParameters) {
- return ConstructorMember.from(element, classType);
- }
- return element;
- }
-}
-
-/**
- * Local function element representing the initializer for a variable that has
- * been resynthesized from a summary. The actual element won't be constructed
- * until it is requested. But properties [context] and [enclosingElement] can
- * be used without creating the actual element.
- */
-class _DeferredInitializerElement extends FunctionElementHandle {
- /**
- * The variable element containing this element.
- */
- @override
- final VariableElement enclosingElement;
-
- _DeferredInitializerElement(this.enclosingElement) : super(null, null);
-
- @override
- FunctionElement get actualElement => enclosingElement.initializer;
-
- @override
- AnalysisContext get context => enclosingElement.context;
-
- @override
- ElementLocation get location => actualElement.location;
-
- @override
- AnalysisSession get session => enclosingElement.session;
-}
-
-/// Specialization of [LibraryResynthesizer] for resynthesis from linked
-/// summaries.
-class _LibraryResynthesizer extends LibraryResynthesizerMixin {
- /**
- * The [SummaryResynthesizer] which is being used to obtain summaries.
- */
- final SummaryResynthesizer summaryResynthesizer;
-
- /**
- * Linked summary of the library to be resynthesized.
- */
- final LinkedLibrary linkedLibrary;
-
- /**
- * Unlinked compilation units constituting the library to be resynthesized.
- */
- final List<UnlinkedUnit> unlinkedUnits;
-
- /**
- * [Source] object for the library to be resynthesized.
- */
- final Source librarySource;
-
- /**
- * The URI of [librarySource].
- */
- Uri libraryUri;
-
- /**
- * The URI of [librarySource].
- */
- String libraryUriStr;
-
- /**
- * Indicates whether [librarySource] is the `dart:core` library.
- */
- bool isCoreLibrary;
-
- /**
- * The resynthesized library.
- */
- LibraryElementImpl library;
-
- /**
- * Map of compilation unit elements that have been resynthesized so far. The
- * key is the URI of the compilation unit.
- */
- final Map<String, CompilationUnitElementImpl> resynthesizedUnits =
- <String, CompilationUnitElementImpl>{};
-
- _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary,
- this.unlinkedUnits, this.librarySource) {
- libraryUri = librarySource.uri;
- libraryUriStr = libraryUri.toString();
- isCoreLibrary = libraryUriStr == 'dart:core';
- }
-
- @override
- List<LinkedExportName> get linkedExportNames => linkedLibrary.exportNames;
-
- /**
- * Resynthesize a [NamespaceCombinator].
- */
- NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) {
- if (serializedCombinator.shows.isNotEmpty) {
- return new ShowElementCombinatorImpl.forSerialized(serializedCombinator);
- } else {
- return new HideElementCombinatorImpl.forSerialized(serializedCombinator);
- }
- }
-
- @override
- ElementHandle buildExportName(LinkedExportName exportName) {
- String name = exportName.name;
- if (exportName.kind == ReferenceKind.topLevelPropertyAccessor &&
- !name.endsWith('=')) {
- name += '?';
- }
- ElementLocationImpl location = new ElementLocationImpl.con3(
- getReferencedLocationComponents(
- exportName.dependency, exportName.unit, name));
- switch (exportName.kind) {
- case ReferenceKind.classOrEnum:
- return new ClassElementHandle(summaryResynthesizer, location);
- case ReferenceKind.typedef:
- return new FunctionTypeAliasElementHandle(
- summaryResynthesizer, location);
- case ReferenceKind.genericFunctionTypedef:
- return new GenericTypeAliasElementHandle(
- summaryResynthesizer, location);
- case ReferenceKind.topLevelFunction:
- return new FunctionElementHandle(summaryResynthesizer, location);
- case ReferenceKind.topLevelPropertyAccessor:
- return new PropertyAccessorElementHandle(
- summaryResynthesizer, location);
- case ReferenceKind.constructor:
- case ReferenceKind.function:
- case ReferenceKind.propertyAccessor:
- case ReferenceKind.method:
- case ReferenceKind.prefix:
- case ReferenceKind.unresolved:
- case ReferenceKind.variable:
- // Should never happen. Exported names never refer to import prefixes,
- // and they always refer to defined top-level entities.
- throw new StateError('Unexpected export name kind: ${exportName.kind}');
- }
- return null;
- }
-
- /**
- * Main entry point. Resynthesize the [LibraryElement] and return it.
- */
- LibraryElement buildLibrary() {
- // Create LibraryElementImpl.
- bool hasName = unlinkedUnits[0].libraryName.isNotEmpty;
- library = new LibraryElementImpl.forSerialized(
- summaryResynthesizer.context,
- summaryResynthesizer.session,
- unlinkedUnits[0].libraryName,
- hasName ? unlinkedUnits[0].libraryNameOffset : -1,
- unlinkedUnits[0].libraryNameLength,
- new _LibraryResynthesizerContext(this),
- unlinkedUnits[0]);
- // Create the defining unit.
- _UnitResynthesizer definingUnitResynthesizer =
- createUnitResynthesizer(0, librarySource, null);
- CompilationUnitElementImpl definingUnit = definingUnitResynthesizer.unit;
- library.definingCompilationUnit = definingUnit;
- definingUnit.source = librarySource;
- definingUnit.librarySource = librarySource;
- // Create parts.
- List<_UnitResynthesizer> partResynthesizers = <_UnitResynthesizer>[];
- UnlinkedUnit unlinkedDefiningUnit = unlinkedUnits[0];
- assert(unlinkedDefiningUnit.publicNamespace.parts.length + 1 ==
- linkedLibrary.units.length);
- for (int i = 1; i < linkedLibrary.units.length; i++) {
- _UnitResynthesizer partResynthesizer = buildPart(
- definingUnitResynthesizer,
- unlinkedDefiningUnit.publicNamespace.parts[i - 1],
- unlinkedDefiningUnit.parts[i - 1],
- i);
- if (partResynthesizer != null) {
- partResynthesizers.add(partResynthesizer);
- }
- }
- library.parts = partResynthesizers.map((r) => r.unit).toList();
- // Populate units.
- rememberUriToUnit(definingUnitResynthesizer);
- for (_UnitResynthesizer partResynthesizer in partResynthesizers) {
- rememberUriToUnit(partResynthesizer);
- }
- // Create the synthetic element for `loadLibrary`.
- // Until the client received dart:core and dart:async, we cannot do this,
- // because the TypeProvider is not fully initialized. So, it is up to the
- // Dart SDK client to initialize TypeProvider and finish the dart:core and
- // dart:async libraries creation.
- if (library.name != 'dart.core' && library.name != 'dart.async') {
- library.createLoadLibraryFunction(summaryResynthesizer.typeProvider);
- }
- // Done.
- return library;
- }
-
- /**
- * Create a [_UnitResynthesizer] that will resynthesize the part with the
- * given [uri]. Return `null` if the [uri] is invalid.
- */
- _UnitResynthesizer buildPart(_UnitResynthesizer definingUnitResynthesizer,
- String uri, UnlinkedPart partDecl, int unitNum) {
- Source unitSource =
- summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
- _UnitResynthesizer partResynthesizer =
- createUnitResynthesizer(unitNum, unitSource, partDecl);
- CompilationUnitElementImpl partUnit = partResynthesizer.unit;
- partUnit.uriOffset = partDecl.uriOffset;
- partUnit.uriEnd = partDecl.uriEnd;
- partUnit.source = unitSource;
- partUnit.librarySource = librarySource;
- partUnit.uri = uri;
- return partResynthesizer;
- }
-
- /**
- * Set up data structures for deserializing a compilation unit.
- */
- _UnitResynthesizer createUnitResynthesizer(
- int unitNum, Source unitSource, UnlinkedPart unlinkedPart) {
- LinkedUnit linkedUnit = linkedLibrary.units[unitNum];
- UnlinkedUnit unlinkedUnit = unlinkedUnits[unitNum];
- return new _UnitResynthesizer(
- this, unlinkedUnit, linkedUnit, unitSource, unlinkedPart);
- }
-
- /**
- * Build the components of an [ElementLocationImpl] for the entity in the
- * given [unit] of the dependency located at [dependencyIndex], and having
- * the given [name].
- */
- List<String> getReferencedLocationComponents(
- int dependencyIndex, int unit, String name) {
- if (dependencyIndex == 0) {
- String partUri;
- if (unit != 0) {
- String uri = unlinkedUnits[0].publicNamespace.parts[unit - 1];
- partUri = _resolveRelativeUri(uri);
- } else {
- partUri = libraryUriStr;
- }
- return <String>[libraryUriStr, partUri, name];
- }
-
- LinkedDependency dependency = linkedLibrary.dependencies[dependencyIndex];
- String referencedLibraryUri = _resolveRelativeUri(dependency.uri);
-
- String partUri;
- if (unit != 0) {
- String uri = dependency.parts[unit - 1];
- partUri = _resolveRelativeUri(uri);
- } else {
- partUri = referencedLibraryUri;
- }
- return <String>[referencedLibraryUri, partUri, name];
- }
-
- /**
- * Remember the absolute URI to the corresponding unit mapping.
- */
- void rememberUriToUnit(_UnitResynthesizer unitResynthesizer) {
- CompilationUnitElementImpl unit = unitResynthesizer.unit;
- Source source = unit.source;
- if (source != null) {
- String absoluteUri = source.uri.toString();
- resynthesizedUnits[absoluteUri] = unit;
- }
- }
-
- /**
- * Resolve the [relativeUriStr] against [libraryUri] using Dart rules.
- */
- String _resolveRelativeUri(String relativeUriStr) {
- Uri relativeUri = Uri.parse(relativeUriStr);
- Uri resolvedUri = resolveRelativeUri(libraryUri, relativeUri);
- return resolvedUri.toString();
- }
-}
-
-/**
- * Implementation of [LibraryResynthesizerContext] for [_LibraryResynthesizer].
- */
-class _LibraryResynthesizerContext extends LibraryResynthesizerContextMixin
- implements LibraryResynthesizerContext {
- final _LibraryResynthesizer resynthesizer;
-
- _LibraryResynthesizerContext(this.resynthesizer);
-
- @override
- LinkedLibrary get linkedLibrary => resynthesizer.linkedLibrary;
-
- @override
- LibraryElement buildExportedLibrary(String relativeUri) {
- return _getLibraryByRelativeUri(relativeUri);
- }
-
- @override
- LibraryElement buildImportedLibrary(int dependency) {
- String depUri = resynthesizer.linkedLibrary.dependencies[dependency].uri;
- return _getLibraryByRelativeUri(depUri);
- }
-
- @override
- FunctionElement findEntryPoint() {
- LibraryElementImpl library = resynthesizer.library;
- Element entryPoint =
- library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME);
- if (entryPoint is FunctionElement) {
- return entryPoint;
- }
- return null;
- }
-
- @override
- void patchTopLevelAccessors() {
- LibraryElementImpl library = resynthesizer.library;
- BuildLibraryElementUtils.patchTopLevelAccessors(library);
- }
-
- LibraryElementHandle _getLibraryByRelativeUri(String depUri) {
- Source source = resynthesizer.summaryResynthesizer.sourceFactory
- .resolveUri(resynthesizer.librarySource, depUri);
- if (source == null) {
- return null;
- }
- String absoluteUri = source.uri.toString();
- return new LibraryElementHandle(resynthesizer.summaryResynthesizer,
- new ElementLocationImpl.con3(<String>[absoluteUri]));
- }
-}
-
-/// Specialization of [ReferenceInfo] for resynthesis from linked summaries.
-class _ReferenceInfo extends ReferenceInfo {
- /**
- * The [_LibraryResynthesizer] which is being used to obtain summaries.
- */
- final _LibraryResynthesizer libraryResynthesizer;
-
- @override
- final _ReferenceInfo enclosing;
-
- @override
- final String name;
-
- /**
- * Is `true` if the [element] can be used as a declared type.
- */
- final bool isDeclarableType;
-
- @override
- final Element element;
-
- /**
- * If this reference refers to a non-generic type, the type it refers to.
- * Otherwise `null`.
- */
- DartType _type;
-
- /**
- * The number of type parameters accepted by the entity referred to by this
- * reference, or zero if it doesn't accept any type parameters.
- */
- final int numTypeParameters;
-
- bool _isBeingInstantiatedToBounds = false;
- bool _isRecursiveWhileInstantiateToBounds = false;
-
- /**
- * Create a new [_ReferenceInfo] object referring to an element called [name]
- * via the element handle [element], and having [numTypeParameters] type
- * parameters.
- *
- * For the special types `dynamic` and `void`, [specialType] should point to
- * the type itself. Otherwise, pass `null` and the type will be computed
- * when appropriate.
- */
- _ReferenceInfo(
- this.libraryResynthesizer,
- this.enclosing,
- this.name,
- this.isDeclarableType,
- this.element,
- DartType specialType,
- this.numTypeParameters) {
- if (specialType != null) {
- _type = specialType;
- }
- }
-
- @override
- bool get hasTypeParameters => numTypeParameters != 0;
-
- @override
- DartType get type {
- if (_type == null) {
- _type = _buildType(true, 0, (_) => DynamicTypeImpl.instance, const []);
- }
- return _type;
- }
-
- List<DartType> get _dynamicTypeArguments =>
- new List<DartType>.filled(numTypeParameters, DynamicTypeImpl.instance);
-
- /**
- * Build a [DartType] corresponding to the result of applying some type
- * arguments to the entity referred to by this [_ReferenceInfo]. The type
- * arguments are retrieved by calling [getTypeArgument].
- *
- * If [implicitFunctionTypeIndices] is not empty, a [DartType] should be
- * created which refers to a function type implicitly defined by one of the
- * element's parameters. [implicitFunctionTypeIndices] is interpreted as in
- * [EntityRef.implicitFunctionTypeIndices].
- *
- * If the entity referred to by this [_ReferenceInfo] is not a type, `null`
- * is returned.
- */
- DartType buildType(bool instantiateToBoundsAllowed, int numTypeArguments,
- DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
- DartType result =
- (numTypeParameters == 0 && implicitFunctionTypeIndices.isEmpty)
- ? type
- : _buildType(instantiateToBoundsAllowed, numTypeArguments,
- getTypeArgument, implicitFunctionTypeIndices);
- if (result == null) {
- return DynamicTypeImpl.instance;
- }
- return result;
- }
-
- /**
- * If this reference refers to a type, build a [DartType]. Otherwise return
- * `null`. If [numTypeArguments] is the same as the [numTypeParameters],
- * the type is instantiated with type arguments returned by [getTypeArgument],
- * otherwise it is instantiated with type parameter bounds (if strong mode),
- * or with `dynamic` type arguments.
- *
- * If [implicitFunctionTypeIndices] is not null, a [DartType] should be
- * created which refers to a function type implicitly defined by one of the
- * element's parameters. [implicitFunctionTypeIndices] is interpreted as in
- * [EntityRef.implicitFunctionTypeIndices].
- */
- DartType _buildType(bool instantiateToBoundsAllowed, int numTypeArguments,
- DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
- ElementHandle element = this.element; // To allow type promotion
- if (element is ClassElementHandle) {
- List<DartType> typeArguments = null;
- // If type arguments are specified, use them.
- // Otherwise, delay until they are requested.
- if (numTypeParameters == 0) {
- return element.type;
- } else if (numTypeArguments == numTypeParameters) {
- typeArguments = _buildTypeArguments(numTypeArguments, getTypeArgument);
- }
- InterfaceTypeImpl type =
- new InterfaceTypeImpl.elementWithNameAndArgs(element, name, () {
- if (typeArguments == null) {
- if (!_isBeingInstantiatedToBounds) {
- _isBeingInstantiatedToBounds = true;
- _isRecursiveWhileInstantiateToBounds = false;
- try {
- InterfaceType instantiatedToBounds = libraryResynthesizer
- .summaryResynthesizer.context.typeSystem
- .instantiateToBounds(element.type) as InterfaceType;
- if (_isRecursiveWhileInstantiateToBounds) {
- throw new RecursiveInstantiateToBounds();
- }
- return instantiatedToBounds.typeArguments;
- } finally {
- _isBeingInstantiatedToBounds = false;
- }
- } else {
- _isRecursiveWhileInstantiateToBounds = true;
- typeArguments = _dynamicTypeArguments;
- }
- }
- return typeArguments;
- });
- // Mark the type as having implicit type arguments, so that we don't
- // attempt to request them during constant expression resynthesizing.
- if (typeArguments == null) {
- _typesWithImplicitTypeArguments[type] = true;
- }
- // Done.
- return type;
- } else if (element is GenericTypeAliasElementHandle) {
- GenericTypeAliasElementImpl actualElement = element.actualElement;
- List<DartType> typeArguments;
- if (numTypeArguments == numTypeParameters) {
- typeArguments = _buildTypeArguments(numTypeArguments, getTypeArgument);
- } else if (instantiateToBoundsAllowed) {
- if (!_isBeingInstantiatedToBounds) {
- _isBeingInstantiatedToBounds = true;
- _isRecursiveWhileInstantiateToBounds = false;
- try {
- typeArguments = libraryResynthesizer
- .summaryResynthesizer.context.typeSystem
- .instantiateTypeFormalsToBounds(element.typeParameters);
- if (_isRecursiveWhileInstantiateToBounds) {
- typeArguments = _dynamicTypeArguments;
- }
- } finally {
- _isBeingInstantiatedToBounds = false;
- }
- } else {
- _isRecursiveWhileInstantiateToBounds = true;
- typeArguments = _dynamicTypeArguments;
- }
- } else {
- typeArguments = _dynamicTypeArguments;
- }
- return GenericTypeAliasElementImpl.typeAfterSubstitution(
- actualElement, typeArguments);
- } else if (element is FunctionTypedElement) {
- if (element is FunctionTypeAliasElementHandle) {
- List<DartType> typeArguments;
- if (numTypeArguments == numTypeParameters) {
- typeArguments =
- _buildTypeArguments(numTypeArguments, getTypeArgument);
- } else if (instantiateToBoundsAllowed) {
- if (!_isBeingInstantiatedToBounds) {
- _isBeingInstantiatedToBounds = true;
- _isRecursiveWhileInstantiateToBounds = false;
- try {
- FunctionType instantiatedToBounds = libraryResynthesizer
- .summaryResynthesizer.context.typeSystem
- .instantiateToBounds(element.type) as FunctionType;
- if (!_isRecursiveWhileInstantiateToBounds) {
- typeArguments = instantiatedToBounds.typeArguments;
- } else {
- typeArguments = _dynamicTypeArguments;
- }
- } finally {
- _isBeingInstantiatedToBounds = false;
- }
- } else {
- _isRecursiveWhileInstantiateToBounds = true;
- typeArguments = _dynamicTypeArguments;
- }
- } else {
- typeArguments = _dynamicTypeArguments;
- }
- return element.instantiate(typeArguments);
- } else {
- FunctionTypedElementComputer computer;
- if (implicitFunctionTypeIndices.isNotEmpty) {
- numTypeArguments = numTypeParameters;
- computer = () {
- FunctionTypedElement element = this.element;
- for (int index in implicitFunctionTypeIndices) {
- element = element.parameters[index].type.element;
- }
- return element;
- };
- } else {
- // For a type that refers to a generic executable, the type arguments are
- // not supposed to include the arguments to the executable itself.
- if (element is MethodElementHandle && !element.isStatic) {
- numTypeArguments = enclosing?.numTypeParameters ?? 0;
- } else {
- numTypeArguments = 0;
- }
- computer = () => this.element as FunctionTypedElement;
- }
- // TODO(paulberry): Is it a bug that we have to pass `false` for
- // isInstantiated?
- return new DeferredFunctionTypeImpl(computer, null,
- _buildTypeArguments(numTypeArguments, getTypeArgument), false);
- }
- } else {
- return null;
- }
- }
-
- /**
- * Build a list of type arguments having length [numTypeArguments] where each
- * type argument is obtained by calling [getTypeArgument].
- */
- List<DartType> _buildTypeArguments(
- int numTypeArguments, DartType getTypeArgument(int i)) {
- List<DartType> typeArguments = const <DartType>[];
- if (numTypeArguments != 0) {
- typeArguments = new List<DartType>(numTypeArguments);
- for (int i = 0; i < numTypeArguments; i++) {
- typeArguments[i] = getTypeArgument(i);
- }
- }
- return typeArguments;
- }
-}
-
-/// Specialization of [UnitResynthesizer] for resynthesis from linked summaries.
-class _UnitResynthesizer extends UnitResynthesizer with UnitResynthesizerMixin {
- /**
- * The [_LibraryResynthesizer] which is being used to obtain summaries.
- */
- final _LibraryResynthesizer libraryResynthesizer;
-
- /**
- * The [UnlinkedUnit] from which elements are currently being resynthesized.
- */
- final UnlinkedUnit unlinkedUnit;
-
- /**
- * The [LinkedUnit] from which elements are currently being resynthesized.
- */
- final LinkedUnit linkedUnit;
-
- /**
- * The [CompilationUnitElementImpl] for the compilation unit currently being
- * resynthesized.
- */
- CompilationUnitElementImpl unit;
-
- /**
- * Map from slot id to the corresponding [EntityRef] object for linked types
- * (i.e. propagated and inferred types).
- */
- final Map<int, EntityRef> linkedTypeMap = <int, EntityRef>{};
-
- /**
- * Set of slot ids corresponding to const constructors that are part of
- * cycles.
- */
- Set<int> constCycles;
-
- /**
- * Set of slot ids corresponding to parameters that inherit `@covariant`
- * behavior.
- */
- Set<int> parametersInheritingCovariant;
-
- int numLinkedReferences;
- int numUnlinkedReferences;
-
- /**
- * List of [_ReferenceInfo] objects describing the references in the current
- * compilation unit. This list is works as a lazily filled cache, use
- * [getReferenceInfo] to get the [_ReferenceInfo] for an index.
- */
- List<_ReferenceInfo> referenceInfos;
-
- /**
- * The [ResynthesizerContext] for this resynthesize session.
- */
- ResynthesizerContext _resynthesizerContext;
-
- _UnitResynthesizer(this.libraryResynthesizer, this.unlinkedUnit,
- this.linkedUnit, Source unitSource, UnlinkedPart unlinkedPart) {
- _resynthesizerContext = new SummaryResynthesizerContext(this);
- unit = new CompilationUnitElementImpl.forSerialized(
- libraryResynthesizer.library,
- _resynthesizerContext,
- unlinkedUnit,
- unlinkedPart);
-
- {
- List<int> lineStarts = unlinkedUnit.lineStarts;
- if (lineStarts.isEmpty) {
- lineStarts = const <int>[0];
- }
- unit.lineInfo = new LineInfo(lineStarts);
- }
-
- for (EntityRef t in linkedUnit.types) {
- linkedTypeMap[t.slot] = t;
- }
- constCycles = linkedUnit.constCycles.toSet();
- parametersInheritingCovariant =
- linkedUnit.parametersInheritingCovariant.toSet();
- numLinkedReferences = linkedUnit.references.length;
- numUnlinkedReferences = unlinkedUnit.references.length;
- referenceInfos = new List<_ReferenceInfo>(numLinkedReferences);
- }
-
- @override
- LibraryElement get library => libraryResynthesizer.library;
-
- SummaryResynthesizer get summaryResynthesizer =>
- libraryResynthesizer.summaryResynthesizer;
-
- @override
- TypeProvider get typeProvider => summaryResynthesizer.typeProvider;
-
- @override
- TypeSystem get typeSystem => summaryResynthesizer.typeSystem;
-
- /**
- * Build [ElementAnnotationImpl] for the given [UnlinkedExpr].
- */
- ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedExpr uc) {
- ElementAnnotationImpl elementAnnotation = new ElementAnnotationImpl(unit);
- Expression constExpr = _buildConstExpression(context, uc);
- if (constExpr == null) {
- // Invalid constant expression.
- } else if (constExpr is Identifier) {
- ArgumentList arguments = constExpr.getProperty(ExprBuilder.ARGUMENT_LIST);
- elementAnnotation.element = constExpr.staticElement;
- elementAnnotation.annotationAst =
- AstTestFactory.annotation2(constExpr, null, arguments);
- } else if (constExpr is InstanceCreationExpression) {
- var element = constExpr.staticElement;
- elementAnnotation.element = element;
- Identifier typeName = constExpr.constructorName.type.name;
- SimpleIdentifier constructorName = constExpr.constructorName.name;
- if (typeName is SimpleIdentifier && constructorName != null) {
- // E.g. `@cls.ctor()`. Since `cls.ctor` would have been parsed as
- // a PrefixedIdentifier, we need to resynthesize it as one.
- typeName = AstTestFactory.identifier(typeName, constructorName);
- constructorName = null;
- }
- elementAnnotation.annotationAst = AstTestFactory.annotation2(
- typeName, constructorName, constExpr.argumentList)
- ..element = constExpr.staticElement;
- } else if (constExpr is PropertyAccess) {
- var target = constExpr.target as Identifier;
- var propertyName = constExpr.propertyName;
- var propertyElement = propertyName.staticElement;
- ArgumentList arguments = constExpr.getProperty(ExprBuilder.ARGUMENT_LIST);
- elementAnnotation.element = propertyElement;
- elementAnnotation.annotationAst =
- AstTestFactory.annotation2(target, propertyName, arguments)
- ..element = propertyElement;
- } else {
- throw new StateError(
- 'Unexpected annotation type: ${constExpr.runtimeType}');
- }
- return elementAnnotation;
- }
-
- /**
- * Build an implicit getter for the given [property] and bind it to the
- * [property] and to its enclosing element.
- */
- PropertyAccessorElementImpl buildImplicitGetter(
- PropertyInducingElementImpl property) {
- PropertyAccessorElementImpl_ImplicitGetter getter =
- new PropertyAccessorElementImpl_ImplicitGetter(property);
- getter.enclosingElement = property.enclosingElement;
- return getter;
- }
-
- /**
- * Build an implicit setter for the given [property] and bind it to the
- * [property] and to its enclosing element.
- */
- PropertyAccessorElementImpl buildImplicitSetter(
- PropertyInducingElementImpl property) {
- PropertyAccessorElementImpl_ImplicitSetter setter =
- new PropertyAccessorElementImpl_ImplicitSetter(property);
- setter.enclosingElement = property.enclosingElement;
- return setter;
- }
-
- /**
- * Build the appropriate [DartType] object corresponding to a slot id in the
- * [LinkedUnit.types] table.
- */
- DartType buildLinkedType(ElementImpl context, int slot) {
- if (slot == 0) {
- // A slot id of 0 means there is no [DartType] object to build.
- return null;
- }
- EntityRef type = linkedTypeMap[slot];
- if (type == null) {
- // A missing entry in [LinkedUnit.types] means there is no [DartType]
- // stored in this slot.
- return null;
- }
- return buildType(context, type);
- }
-
- @override
- DartType buildType(ElementImpl context, EntityRef type,
- {bool defaultVoid: false,
- bool instantiateToBoundsAllowed: true,
- bool declaredType: false}) {
- if (type == null) {
- if (defaultVoid) {
- return VoidTypeImpl.instance;
- } else {
- return DynamicTypeImpl.instance;
- }
- }
- if (type.refinedSlot != 0) {
- var refinedType = linkedTypeMap[type.refinedSlot];
- if (refinedType != null) {
- type = refinedType;
- }
- }
- DartType result;
- if (type.paramReference != 0) {
- result = context.typeParameterContext
- .getTypeParameterType(type.paramReference);
- } else if (type.entityKind == EntityRefKind.genericFunctionType) {
- GenericFunctionTypeElement element =
- new GenericFunctionTypeElementImpl.forSerialized(context, type);
- result = element.type;
- } else if (type.syntheticReturnType != null) {
- FunctionElementImpl element =
- new FunctionElementImpl_forLUB(context, type);
- result = element.type;
- } else {
- DartType getTypeArgument(int i) {
- if (i < type.typeArguments.length) {
- return buildType(context, type.typeArguments[i],
- declaredType: declaredType);
- } else {
- return DynamicTypeImpl.instance;
- }
- }
-
- _ReferenceInfo referenceInfo = getReferenceInfo(type.reference);
- if (declaredType && !referenceInfo.isDeclarableType) {
- return DynamicTypeImpl.instance;
- }
-
- result = referenceInfo.buildType(
- instantiateToBoundsAllowed,
- type.typeArguments.length,
- getTypeArgument,
- type.implicitFunctionTypeIndices);
- }
- var nullabilitySuffix = decodeNullabilitySuffix(type.nullabilitySuffix);
- return (result as TypeImpl).withNullability(nullabilitySuffix);
- }
-
- @override
- DartType buildTypeForClassInfo(covariant _ReferenceInfo info,
- int numTypeArguments, DartType getTypeArgument(int i)) =>
- info.buildType(true, numTypeArguments, getTypeArgument, const <int>[]);
-
- UnitExplicitTopLevelAccessors buildUnitExplicitTopLevelAccessors() {
- Map<String, TopLevelVariableElementImpl> implicitVariables =
- new HashMap<String, TopLevelVariableElementImpl>();
- UnitExplicitTopLevelAccessors accessorsData =
- new UnitExplicitTopLevelAccessors();
- for (UnlinkedExecutable unlinkedExecutable in unlinkedUnit.executables) {
- UnlinkedExecutableKind kind = unlinkedExecutable.kind;
- if (kind == UnlinkedExecutableKind.getter ||
- kind == UnlinkedExecutableKind.setter) {
- // name
- String name = unlinkedExecutable.name;
- if (kind == UnlinkedExecutableKind.setter) {
- assert(name.endsWith('='));
- name = name.substring(0, name.length - 1);
- }
- // create
- PropertyAccessorElementImpl accessor =
- new PropertyAccessorElementImpl.forSerialized(
- unlinkedExecutable, unit);
- accessorsData.accessors.add(accessor);
- // implicit variable
- TopLevelVariableElementImpl variable = implicitVariables[name];
- if (variable == null) {
- variable = new TopLevelVariableElementImpl(name, -1);
- variable.enclosingElement = unit;
- implicitVariables[name] = variable;
- accessorsData.implicitVariables.add(variable);
- variable.isSynthetic = true;
- variable.isFinal = kind == UnlinkedExecutableKind.getter;
- } else {
- variable.isFinal = false;
- }
- accessor.variable = variable;
- // link
- if (kind == UnlinkedExecutableKind.getter) {
- variable.getter = accessor;
- } else {
- variable.setter = accessor;
- }
- }
- }
- return accessorsData;
- }
-
- UnitExplicitTopLevelVariables buildUnitExplicitTopLevelVariables() {
- List<UnlinkedVariable> unlinkedVariables = unlinkedUnit.variables;
- int numberOfVariables = unlinkedVariables.length;
- UnitExplicitTopLevelVariables variablesData =
- new UnitExplicitTopLevelVariables(numberOfVariables);
- for (int i = 0; i < numberOfVariables; i++) {
- UnlinkedVariable unlinkedVariable = unlinkedVariables[i];
- TopLevelVariableElementImpl element;
- if (unlinkedVariable.initializer?.bodyExpr != null &&
- unlinkedVariable.isConst) {
- element = new ConstTopLevelVariableElementImpl.forSerialized(
- unlinkedVariable, unit);
- } else {
- element = new TopLevelVariableElementImpl.forSerialized(
- unlinkedVariable, unit);
- }
- variablesData.variables[i] = element;
- // implicit accessors
- variablesData.implicitAccessors.add(buildImplicitGetter(element));
- if (!(element.isConst || element.isFinal)) {
- variablesData.implicitAccessors.add(buildImplicitSetter(element));
- }
- }
- return variablesData;
- }
-
- @override
- bool doesTypeHaveImplicitArguments(ParameterizedType type) =>
- _typesWithImplicitTypeArguments[type] != null;
-
- @override
- _ReferenceInfo getReferenceInfo(int index) {
- // We don't know how to reproduce this.
- // https://github.com/dart-lang/sdk/issues/35551
- // https://github.com/dart-lang/sdk/issues/34534
- // So, adding logging to gather more information.
- if (index >= referenceInfos.length) {
- var buffer = StringBuffer();
- buffer.writeln('librarySource: ${unit.librarySource}');
- buffer.writeln('unitSource: ${unit.source}');
- buffer.writeln('unlinkedUnit: ${unlinkedUnit.toJson()}');
- buffer.writeln('linkedUnit: ${linkedUnit.toJson()}');
- throw StateError(buffer.toString());
- }
-
- _ReferenceInfo result = referenceInfos[index];
- if (result == null) {
- LinkedReference linkedReference = linkedUnit.references[index];
- String name;
- int containingReference;
- if (index < numUnlinkedReferences) {
- name = unlinkedUnit.references[index].name;
- containingReference = unlinkedUnit.references[index].prefixReference;
- } else {
- name = linkedUnit.references[index].name;
- containingReference = linkedUnit.references[index].containingReference;
- }
- _ReferenceInfo enclosingInfo = containingReference != 0
- ? getReferenceInfo(containingReference)
- : null;
- Element element;
- DartType type;
- bool isDeclarableType = false;
- int numTypeParameters = linkedReference.numTypeParameters;
- if (linkedReference.kind == ReferenceKind.unresolved) {
- type = DynamicTypeImpl.instance;
- element = null;
- isDeclarableType = true;
- } else if (name == 'dynamic') {
- type = DynamicTypeImpl.instance;
- element = type.element;
- isDeclarableType = true;
- } else if (name == 'void') {
- type = VoidTypeImpl.instance;
- element = type.element;
- isDeclarableType = true;
- } else if (name == '*bottom*') {
- type = BottomTypeImpl.instance;
- element = null;
- isDeclarableType = true;
- } else {
- List<String> locationComponents;
- if (enclosingInfo != null && enclosingInfo.element is ClassElement) {
- String identifier = _getElementIdentifier(name, linkedReference.kind);
- locationComponents =
- enclosingInfo.element.location.components.toList();
- locationComponents.add(identifier);
- } else {
- String identifier = _getElementIdentifier(name, linkedReference.kind);
- locationComponents =
- libraryResynthesizer.getReferencedLocationComponents(
- linkedReference.dependency, linkedReference.unit, identifier);
- if (linkedReference.kind == ReferenceKind.prefix) {
- locationComponents = <String>[
- locationComponents[0],
- locationComponents[2]
- ];
- }
- }
- ElementLocation location =
- new ElementLocationImpl.con3(locationComponents);
- if (enclosingInfo != null) {
- numTypeParameters += enclosingInfo.numTypeParameters;
- }
- switch (linkedReference.kind) {
- case ReferenceKind.classOrEnum:
- if (locationComponents.length == 3 &&
- locationComponents[0] == 'dart:core' &&
- locationComponents[1] == 'dart:core' &&
- locationComponents[2] == 'Never') {
- element = NeverElementImpl.instance;
- type = BottomTypeImpl.instance;
- } else {
- element = new ClassElementHandle(summaryResynthesizer, location);
- }
- isDeclarableType = true;
- break;
- case ReferenceKind.constructor:
- assert(location.components.length == 4);
- element =
- new ConstructorElementHandle(summaryResynthesizer, location);
- break;
- case ReferenceKind.method:
- assert(location.components.length == 4);
- element = new MethodElementHandle(summaryResynthesizer, location);
- break;
- case ReferenceKind.propertyAccessor:
- assert(location.components.length == 4);
- element = new PropertyAccessorElementHandle(
- summaryResynthesizer, location);
- break;
- case ReferenceKind.topLevelFunction:
- assert(location.components.length == 3);
- element = new FunctionElementHandle(summaryResynthesizer, location);
- break;
- case ReferenceKind.topLevelPropertyAccessor:
- element = new PropertyAccessorElementHandle(
- summaryResynthesizer, location);
- break;
- case ReferenceKind.typedef:
- case ReferenceKind.genericFunctionTypedef:
- element = new GenericTypeAliasElementHandle(
- summaryResynthesizer, location);
- isDeclarableType = true;
- break;
- case ReferenceKind.function:
- Element enclosingElement = enclosingInfo.element;
- if (enclosingElement is VariableElement) {
- element = new _DeferredInitializerElement(enclosingElement);
- } else {
- throw new StateError('Unexpected element enclosing function:'
- ' ${enclosingElement.runtimeType}');
- }
- break;
- case ReferenceKind.prefix:
- element = new PrefixElementHandle(summaryResynthesizer, location);
- break;
- case ReferenceKind.variable:
- case ReferenceKind.unresolved:
- break;
- }
- }
- result = new _ReferenceInfo(libraryResynthesizer, enclosingInfo, name,
- isDeclarableType, element, type, numTypeParameters);
- referenceInfos[index] = result;
- }
- return result;
- }
-
- /**
- * Return the error reported during type inference for the given [slot],
- * or `null` if there were no error.
- */
- TopLevelInferenceError getTypeInferenceError(int slot) {
- if (slot == 0) {
- return null;
- }
- for (TopLevelInferenceError error in linkedUnit.topLevelInferenceErrors) {
- if (error.slot == slot) {
- return error;
- }
- }
- return null;
- }
-
- Expression _buildConstExpression(ElementImpl context, UnlinkedExpr uc) {
- return new ExprBuilder(this, context, uc).build();
- }
-
- /**
- * Return the [ConstructorElement] corresponding to the given [entry].
- */
- ConstructorElement _getConstructorForEntry(
- ElementImpl context, EntityRef entry) {
- _ReferenceInfo info = getReferenceInfo(entry.reference);
- DartType type =
- createConstructorDefiningType(context, info, entry.typeArguments);
- if (type is InterfaceType) {
- return getConstructorForInfo(type, info);
- }
- return null;
- }
-
- /**
- * If the given [kind] is a top-level or class member property accessor, and
- * the given [name] does not end with `=`, i.e. does not denote a setter,
- * return the getter identifier by appending `?`.
- */
- static String _getElementIdentifier(String name, ReferenceKind kind) {
- if (kind == ReferenceKind.topLevelPropertyAccessor ||
- kind == ReferenceKind.propertyAccessor) {
- if (!name.endsWith('=')) {
- return name + '?';
- }
- }
- return name;
- }
-}
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
deleted file mode 100644
index 401122b..0000000
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ /dev/null
@@ -1,1511 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
-import 'package:analyzer/src/summary/api_signature.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/public_namespace_computer.dart';
-import 'package:analyzer/src/summary/summarize_const_expr.dart';
-
-/// Serialize all the declarations in [compilationUnit] to an unlinked summary.
-///
-/// [serializeInferrableFields] indicates whether field initializers and closure
-/// bodies should be serialized to facilitate type inference.
-UnlinkedUnitBuilder serializeAstUnlinked(CompilationUnit compilationUnit,
- {bool serializeInferrableFields: true}) {
- return new _SummarizeAstVisitor(serializeInferrableFields,
- compilationUnit.featureSet.isEnabled(Feature.non_nullable))
- .serializeCompilationUnit(compilationUnit);
-}
-
-/// Instances of this class keep track of intermediate state during
-/// serialization of a single constant [Expression].
-class _ConstExprSerializer extends AbstractConstExprSerializer {
- final _SummarizeAstVisitor visitor;
-
- /// If the expression being serialized can contain closures, map whose
- /// keys are the offsets of local function nodes representing those closures,
- /// and whose values are indices of those local functions relative to their
- /// siblings.
- final Map<int, int> localClosureIndexMap;
-
- /// The names of local variables and parameters that are in scope.
- /// This is a list so that we can handle nesting by pushing and popping values
- /// at the end of it.
- final List<String> variableNames;
-
- _ConstExprSerializer(bool forConst, this.visitor, this.localClosureIndexMap,
- List<String> variableNames)
- : variableNames = variableNames ?? [],
- super(forConst);
-
- @override
- EntityRefNullabilitySuffix computeNullabilitySuffix(Token question) =>
- visitor.computeNullabilitySuffix(question);
-
- @override
- bool isParameterName(String name) {
- return variableNames?.contains(name) ?? false;
- }
-
- @override
- void popVariableNames(int count) {
- variableNames.length -= count;
- }
-
- @override
- void pushVariableName(String name) {
- variableNames.add(name);
- }
-
- @override
- void serialize(Expression expr) {
- int startingVariableCount = variableNames.length;
- super.serialize(expr);
- assert(startingVariableCount == variableNames.length);
- }
-
- @override
- void serializeAnnotation(Annotation annotation) {
- Identifier name = annotation.name;
- EntityRefBuilder constructor;
- if (name is PrefixedIdentifier && annotation.constructorName == null) {
- constructor = serializeConstructorRef(name.prefix, null, name.identifier);
- } else {
- constructor = serializeConstructorRef(
- annotation.name, null, annotation.constructorName);
- }
- if (annotation.arguments == null) {
- references.add(constructor);
- operations.add(UnlinkedExprOperation.pushReference);
- } else {
- serializeInstanceCreation(constructor, annotation.arguments, false);
- }
- }
-
- @override
- EntityRefBuilder serializeConstructorRef(Identifier typeName,
- TypeArgumentList typeArguments, SimpleIdentifier name) {
- EntityRefBuilder typeBuilder = serializeTypeName(
- typeName, typeArguments, EntityRefNullabilitySuffix.starOrIrrelevant);
- if (name == null) {
- return typeBuilder;
- } else {
- int nameRef =
- visitor.serializeReference(typeBuilder.reference, name.name);
- return new EntityRefBuilder(
- reference: nameRef, typeArguments: typeBuilder.typeArguments);
- }
- }
-
- @override
- List<int> serializeFunctionExpression(FunctionExpression functionExpression) {
- int localIndex;
- if (localClosureIndexMap == null) {
- return null;
- } else {
- localIndex = localClosureIndexMap[functionExpression.offset];
- assert(localIndex != null);
- return <int>[0, localIndex];
- }
- }
-
- @override
- EntityRefBuilder serializeGenericFunctionType(GenericFunctionType node) =>
- visitor.serializeGenericFunctionType(node);
-
- EntityRefBuilder serializeIdentifier(Identifier identifier) {
- EntityRefBuilder b =
- new EntityRefBuilder(nullabilitySuffix: computeNullabilitySuffix(null));
- if (identifier is SimpleIdentifier) {
- int index = visitor.serializeSimpleReference(identifier.name);
- if (index < 0) {
- b.paramReference = -index;
- } else {
- b.reference = index;
- }
- } else if (identifier is PrefixedIdentifier) {
- int prefix = visitor.serializeSimpleReference(identifier.prefix.name);
- if (prefix < 0) {
- throw new StateError('Invalid type parameter usage: $identifier}');
- }
- b.reference =
- visitor.serializeReference(prefix, identifier.identifier.name);
- } else {
- throw new StateError(
- 'Unexpected identifier type: ${identifier.runtimeType}');
- }
- return b;
- }
-
- @override
- EntityRefBuilder serializeIdentifierSequence(Expression expr) {
- if (expr is Identifier) {
- AstNode parent = expr.parent;
- if (parent is MethodInvocation &&
- parent.methodName == expr &&
- parent.target != null) {
- int targetId = serializeIdentifierSequence(parent.target).reference;
- int nameId = visitor.serializeReference(targetId, expr.name);
- return new EntityRefBuilder(reference: nameId);
- }
- return serializeIdentifier(expr);
- }
- if (expr is PropertyAccess) {
- int targetId = serializeIdentifierSequence(expr.target).reference;
- int nameId = visitor.serializeReference(targetId, expr.propertyName.name);
- return new EntityRefBuilder(reference: nameId);
- } else {
- throw new StateError('Unexpected node type: ${expr.runtimeType}');
- }
- }
-
- @override
- EntityRefBuilder serializeTypeName(
- Identifier name,
- TypeArgumentList arguments,
- EntityRefNullabilitySuffix nullabilitySuffix) {
- return visitor.serializeTypeName(name, arguments, nullabilitySuffix);
- }
-}
-
-/// A [_Scope] represents a set of name/value pairs defined locally within a
-/// limited span of a compilation unit. (Note that the spec also uses the term
-/// "scope" to refer to the set of names defined at top level within a
-/// compilation unit, but we do not use [_Scope] for that purpose).
-class _Scope {
- /// Names defined in this scope, and their meanings.
- Map<String, _ScopedEntity> _definedNames = <String, _ScopedEntity>{};
-
- /// Look up the meaning associated with the given [name], and return it. If
- /// [name] is not defined in this scope, return `null`.
- _ScopedEntity operator [](String name) => _definedNames[name];
-
- /// Let the given [name] refer to [entity] within this scope.
- void operator []=(String name, _ScopedEntity entity) {
- _definedNames[name] = entity;
- }
-}
-
-/// A [_ScopedClassMember] is a [_ScopedEntity] refers to a member of a class.
-class _ScopedClassMember extends _ScopedEntity {
- /// The name of the class.
- final String className;
-
- _ScopedClassMember(this.className);
-}
-
-/// Base class for entities that can live inside a scope.
-abstract class _ScopedEntity {}
-
-/// A [_ScopedTypeParameter] is a [_ScopedEntity] that refers to a type
-/// parameter of a class, typedef, or executable.
-class _ScopedTypeParameter extends _ScopedEntity {
- /// Index of the type parameter within this scope. Since summaries use De
- /// Bruijn indices to refer to type parameters, which count upwards from the
- /// innermost bound name, the last type parameter in the scope has an index of
- /// 1, and each preceding type parameter has the next higher index.
- final int index;
-
- _ScopedTypeParameter(this.index);
-}
-
-/// Visitor used to create a summary from an AST.
-class _SummarizeAstVisitor extends RecursiveAstVisitor {
- /// Indicates whether non-const field initializers and closure bodies should
- /// be serialized to facilitate type inference.
- ///
- /// For one-phase summary generation, the only field initializers that need to
- /// be serialized are those involved in constants, since type inference is
- /// performed using the AST representation.
- final bool _serializeInferrableFields;
-
- final bool _nnbd;
-
- /// List of objects which should be written to [UnlinkedUnit.classes].
- final List<UnlinkedClassBuilder> classes = <UnlinkedClassBuilder>[];
-
- /// List of objects which should be written to [UnlinkedUnit.enums].
- final List<UnlinkedEnumBuilder> enums = <UnlinkedEnumBuilder>[];
-
- /// List of objects which should be written to [UnlinkedUnit.executables],
- /// [UnlinkedClass.executables] or [UnlinkedExecutable.localFunctions].
- List<UnlinkedExecutableBuilder> executables = <UnlinkedExecutableBuilder>[];
-
- /// List of objects which should be written to [UnlinkedUnit.extensions].
- final List<UnlinkedExtensionBuilder> extensions =
- <UnlinkedExtensionBuilder>[];
-
- /// List of objects which should be written to [UnlinkedUnit.exports].
- final List<UnlinkedExportNonPublicBuilder> exports =
- <UnlinkedExportNonPublicBuilder>[];
-
- /// Whether the current class declaration has a `const` constructor.
- bool enclosingClassHasConstConstructor = false;
-
- /// List of objects which should be written to [UnlinkedUnit.mixins].
- final List<UnlinkedClassBuilder> mixins = <UnlinkedClassBuilder>[];
-
- /// List of names of methods, getters, setters, and operators that are
- /// super-invoked in the current mixin declaration.
- Set<String> mixinSuperInvokedNames;
-
- /// List of objects which should be written to [UnlinkedUnit.parts].
- final List<UnlinkedPartBuilder> parts = <UnlinkedPartBuilder>[];
-
- /// List of objects which should be written to [UnlinkedUnit.typedefs].
- final List<UnlinkedTypedefBuilder> typedefs = <UnlinkedTypedefBuilder>[];
-
- /// List of objects which should be written to [UnlinkedUnit.variables] or
- /// [UnlinkedClass.fields].
- List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[];
-
- /// The unlinked portion of the "imports table". This is the list of objects
- /// which should be written to [UnlinkedUnit.imports].
- final List<UnlinkedImportBuilder> unlinkedImports = <UnlinkedImportBuilder>[];
-
- /// The unlinked portion of the "references table". This is the list of
- /// objects which should be written to [UnlinkedUnit.references].
- final List<UnlinkedReferenceBuilder> unlinkedReferences =
- <UnlinkedReferenceBuilder>[new UnlinkedReferenceBuilder()];
-
- /// List of [_Scope]s currently in effect. This is used to resolve type names
- /// to type parameters within classes, typedefs, and executables, as well as
- /// references to class members.
- final List<_Scope> scopes = <_Scope>[];
-
- /// True if 'dart:core' has been explicitly imported.
- bool hasCoreBeenImported = false;
-
- /// Names referenced by this compilation unit. Structured as a map from
- /// prefix index to (map from name to reference table index), where "prefix
- /// index" means the index into [UnlinkedUnit.references] of the prefix (or
- /// `null` if there is no prefix), and "reference table index" means the index
- /// into [UnlinkedUnit.references] for the name itself.
- final Map<int, Map<String, int>> nameToReference = <int, Map<String, int>>{};
-
- /// True if the 'dart:core' library is been summarized.
- bool isCoreLibrary = false;
-
- /// True if the 'dart:core' library defining unit is been summarized.
- bool isCoreLibraryDefiningUnit = false;
-
- /// True is a [PartOfDirective] was found, so the unit is a part.
- bool isPartOf = false;
-
- /// If the library has a library directive, the library name derived from it.
- /// Otherwise `null`.
- String libraryName;
-
- /// If the library has a library directive, the offset of the library name.
- /// Otherwise `null`.
- int libraryNameOffset;
-
- /// If the library has a library directive, the length of the library name, as
- /// it appears in the source file. Otherwise `null`.
- int libraryNameLength;
-
- /// If the library has a library directive, the documentation comment for it
- /// (if any). Otherwise `null`.
- UnlinkedDocumentationCommentBuilder libraryDocumentationComment;
-
- /// If the library has a library directive, the annotations for it (if any).
- /// Otherwise `null`.
- List<UnlinkedExpr> libraryAnnotations = const <UnlinkedExprBuilder>[];
-
- /// The number of slot ids which have been assigned to this compilation unit.
- int numSlots = 0;
-
- /// The [Block] that is being visited now, or `null` for non-local contexts.
- Block enclosingBlock = null;
-
- /// If an expression is being serialized which can contain closures, map whose
- /// keys are the offsets of local function nodes representing those closures,
- /// and whose values are indices of those local functions relative to their
- /// siblings.
- Map<int, int> _localClosureIndexMap;
-
- /// Indicates whether closure function bodies should be serialized. This flag
- /// is set while visiting the bodies of initializer expressions that will be
- /// needed by type inference.
- bool _serializeClosureBodyExprs = false;
-
- /// The set of variable names which are currently in scope.
- List<String> _variableNames = [];
-
- /// Indicates whether parameters found during visitors might inherit
- /// covariance.
- bool _parametersMayInheritCovariance = false;
-
- _SummarizeAstVisitor(this._serializeInferrableFields, this._nnbd);
-
- /// Create a slot id for storing a propagated or inferred type or const cycle
- /// info.
- int assignSlot() => ++numSlots;
-
- /// Build a [_Scope] object containing the names defined within the body of a
- /// class declaration.
- _Scope buildClassMemberScope(
- String className, NodeList<ClassMember> members) {
- _Scope scope = new _Scope();
- for (ClassMember member in members) {
- if (member is MethodDeclaration) {
- if (member.isSetter || member.isOperator) {
- // We don't have to handle setters or operators because the only
- // things we look up are type names and identifiers.
- } else {
- scope[member.name.name] = new _ScopedClassMember(className);
- }
- } else if (member is FieldDeclaration) {
- for (VariableDeclaration field in member.fields.variables) {
- // A field declaration introduces two names, one with a trailing `=`.
- // We don't have to worry about the one with a trailing `=` because
- // the only things we look up are type names and identifiers.
- scope[field.name.name] = new _ScopedClassMember(className);
- }
- }
- }
- return scope;
- }
-
- EntityRefNullabilitySuffix computeNullabilitySuffix(Token question) {
- if (!_nnbd) return EntityRefNullabilitySuffix.starOrIrrelevant;
- if (question != null) return EntityRefNullabilitySuffix.question;
- return EntityRefNullabilitySuffix.none;
- }
-
- /// Serialize the given list of [annotations]. If there are no annotations,
- /// the empty list is returned.
- List<UnlinkedExprBuilder> serializeAnnotations(
- NodeList<Annotation> annotations) {
- if (annotations == null || annotations.isEmpty) {
- return const <UnlinkedExprBuilder>[];
- }
- return annotations.map((Annotation a) {
- // Closures can't appear inside annotations, so we don't need a
- // localClosureIndexMap.
- Map<int, int> localClosureIndexMap = null;
- _ConstExprSerializer serializer =
- new _ConstExprSerializer(true, this, localClosureIndexMap, null);
- try {
- serializer.serializeAnnotation(a);
- } on StateError {
- return new UnlinkedExprBuilder()..isValidConst = false;
- }
- return serializer.toBuilder(a.atSign.next, a.endToken);
- }).toList();
- }
-
- /// Serialize a [ClassDeclaration] or [ClassTypeAlias] into an [UnlinkedClass]
- /// and store the result in [classes].
- void serializeClass(
- AstNode node,
- Token abstractKeyword,
- String name,
- int nameOffset,
- TypeParameterList typeParameters,
- TypeName superclass,
- WithClause withClause,
- ImplementsClause implementsClause,
- NodeList<ClassMember> members,
- bool isMixinApplication,
- Comment documentationComment,
- NodeList<Annotation> annotations) {
- int oldScopesLength = scopes.length;
- enclosingClassHasConstConstructor = node is ClassDeclaration &&
- node.members
- .any((m) => m is ConstructorDeclaration && m.constKeyword != null);
- List<UnlinkedExecutableBuilder> oldExecutables = executables;
- executables = <UnlinkedExecutableBuilder>[];
- List<UnlinkedVariableBuilder> oldVariables = variables;
- variables = <UnlinkedVariableBuilder>[];
- _TypeParameterScope typeParameterScope = new _TypeParameterScope();
- scopes.add(typeParameterScope);
- UnlinkedClassBuilder b = new UnlinkedClassBuilder();
- b.name = name;
- b.nameOffset = nameOffset;
- b.isMixinApplication = isMixinApplication;
- b.typeParameters =
- serializeTypeParameters(typeParameters, typeParameterScope);
- if (_shouldAssignNotSimplyBoundedSlot(typeParameters)) {
- b.notSimplyBoundedSlot = assignSlot();
- }
- if (superclass != null) {
- b.supertype = serializeType(superclass);
- } else {
- b.hasNoSupertype = isCoreLibrary && name == 'Object';
- }
- if (withClause != null) {
- b.mixins = withClause.mixinTypes.map(serializeMixedInType).toList();
- }
- if (implementsClause != null) {
- b.interfaces = implementsClause.interfaces.map(serializeType).toList();
- }
- if (members != null) {
- scopes.add(buildClassMemberScope(name, members));
- for (ClassMember member in members) {
- member.accept(this);
- }
- scopes.removeLast();
- }
- b.executables = executables;
- b.fields = variables;
- b.isAbstract = abstractKeyword != null;
- b.documentationComment = serializeDocumentation(documentationComment);
- b.annotations = serializeAnnotations(annotations);
- b.codeRange = serializeCodeRange(node);
- classes.add(b);
- scopes.removeLast();
- assert(scopes.length == oldScopesLength);
- executables = oldExecutables;
- variables = oldVariables;
- }
-
- /// Create a [CodeRangeBuilder] for the given [node].
- CodeRangeBuilder serializeCodeRange(AstNode node) {
- return new CodeRangeBuilder(offset: node.offset, length: node.length);
- }
-
- /// Serialize a [Combinator] into an [UnlinkedCombinator].
- UnlinkedCombinatorBuilder serializeCombinator(Combinator combinator) {
- UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder();
- if (combinator is ShowCombinator) {
- b.shows =
- combinator.shownNames.map((SimpleIdentifier id) => id.name).toList();
- b.offset = combinator.offset;
- b.end = combinator.end;
- } else if (combinator is HideCombinator) {
- b.hides =
- combinator.hiddenNames.map((SimpleIdentifier id) => id.name).toList();
- } else {
- throw new StateError(
- 'Unexpected combinator type: ${combinator.runtimeType}');
- }
- return b;
- }
-
- /// Main entry point for serializing an AST.
- UnlinkedUnitBuilder serializeCompilationUnit(
- CompilationUnit compilationUnit) {
- compilationUnit.directives.accept(this);
- if (!hasCoreBeenImported) {
- unlinkedImports.add(new UnlinkedImportBuilder(isImplicit: true));
- }
- compilationUnit.declarations.accept(this);
- UnlinkedUnitBuilder b = new UnlinkedUnitBuilder(
- isNNBD: compilationUnit.featureSet.isEnabled(Feature.non_nullable));
- b.lineStarts = compilationUnit.lineInfo?.lineStarts;
- b.isPartOf = isPartOf;
- b.libraryName = libraryName;
- b.libraryNameOffset = libraryNameOffset;
- b.libraryNameLength = libraryNameLength;
- b.libraryDocumentationComment = libraryDocumentationComment;
- b.libraryAnnotations = libraryAnnotations;
- b.codeRange = serializeCodeRange(compilationUnit);
- b.classes = classes;
- b.enums = enums;
- b.executables = executables;
- b.extensions = extensions;
- b.exports = exports;
- b.imports = unlinkedImports;
- b.mixins = mixins;
- b.parts = parts;
- b.references = unlinkedReferences;
- b.typedefs = typedefs;
- b.variables = variables;
-
- b.publicNamespace = computePublicNamespace(compilationUnit);
- if (isCoreLibraryDefiningUnit) {
- b.publicNamespace.names.add(
- UnlinkedPublicNameBuilder(
- name: 'Never',
- kind: ReferenceKind.classOrEnum,
- ),
- );
- }
-
- _computeApiSignature(b);
- return b;
- }
-
- /// Serialize the given [expression], creating an [UnlinkedExprBuilder].
- UnlinkedExprBuilder serializeConstExpr(
- bool forConst, Map<int, int> localClosureIndexMap, Expression expression,
- [List<String> variableNames]) {
- _ConstExprSerializer serializer = new _ConstExprSerializer(
- forConst, this, localClosureIndexMap, variableNames);
- serializer.serialize(expression);
- return serializer.toBuilder(expression.beginToken, expression.endToken);
- }
-
- /// Serialize a [Comment] node into an [UnlinkedDocumentationComment] object.
- UnlinkedDocumentationCommentBuilder serializeDocumentation(
- Comment documentationComment) {
- if (documentationComment == null) {
- return null;
- }
- String text = documentationComment.tokens
- .map((Token t) => t.toString())
- .join('\n')
- .replaceAll('\r\n', '\n');
- return new UnlinkedDocumentationCommentBuilder(text: text);
- }
-
- /// Return an entity reference builder representing the type 'dynamic'.
- EntityRefBuilder serializeDynamic() {
- EntityRefBuilder builder = new EntityRefBuilder();
- builder.reference = serializeReference(null, 'dynamic');
- return builder;
- }
-
- /// Serialize an [EnumConstantDeclaration] into an [UnlinkedEnumValue].
- UnlinkedEnumValueBuilder serializeEnumConstantDeclaration(
- EnumConstantDeclaration node) {
- return new UnlinkedEnumValueBuilder(
- annotations: serializeAnnotations(node.metadata),
- documentationComment: serializeDocumentation(node.documentationComment),
- name: node.name.name,
- nameOffset: node.name.offset);
- }
-
- /// Serialize a [FunctionDeclaration] or [MethodDeclaration] into an
- /// [UnlinkedExecutable].
- ///
- /// If [serializeBodyExpr] is `true`, then the function definition is stored
- /// in [UnlinkedExecutableBuilder.bodyExpr].
- UnlinkedExecutableBuilder serializeExecutable(
- AstNode node,
- String name,
- int nameOffset,
- bool isGetter,
- bool isSetter,
- TypeAnnotation returnType,
- FormalParameterList formalParameters,
- FunctionBody body,
- bool isTopLevel,
- bool isDeclaredStatic,
- Comment documentationComment,
- NodeList<Annotation> annotations,
- TypeParameterList typeParameters,
- bool isExternal,
- bool serializeBodyExpr,
- bool serializeBody) {
- int oldScopesLength = scopes.length;
- _TypeParameterScope typeParameterScope = new _TypeParameterScope();
- scopes.add(typeParameterScope);
- UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
- String nameString = name;
- if (isGetter) {
- b.kind = UnlinkedExecutableKind.getter;
- } else if (isSetter) {
- b.kind = UnlinkedExecutableKind.setter;
- nameString = '$nameString=';
- } else {
- b.kind = UnlinkedExecutableKind.functionOrMethod;
- }
- b.isExternal = isExternal;
- b.isAbstract = !isExternal && body is EmptyFunctionBody;
- b.isAsynchronous = body.isAsynchronous;
- b.isGenerator = body.isGenerator;
- b.name = nameString;
- b.nameOffset = nameOffset;
- b.typeParameters =
- serializeTypeParameters(typeParameters, typeParameterScope);
- if (!isTopLevel) {
- b.isStatic = isDeclaredStatic;
- }
- b.returnType = serializeType(returnType);
- bool isSemanticallyStatic = isTopLevel || isDeclaredStatic;
- if (formalParameters != null) {
- bool oldMayInheritCovariance = _parametersMayInheritCovariance;
- _parametersMayInheritCovariance = !isTopLevel && !isDeclaredStatic;
- b.parameters = formalParameters.parameters
- .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
- .toList();
- _parametersMayInheritCovariance = oldMayInheritCovariance;
- if (!isSemanticallyStatic) {
- for (int i = 0; i < formalParameters.parameters.length; i++) {
- if (!b.parameters[i].isFunctionTyped &&
- b.parameters[i].type == null) {
- b.parameters[i].inferredTypeSlot = assignSlot();
- }
- }
- }
- }
- b.documentationComment = serializeDocumentation(documentationComment);
- b.annotations = serializeAnnotations(annotations);
- b.codeRange = serializeCodeRange(node);
- if (returnType == null && !isSemanticallyStatic) {
- b.inferredReturnTypeSlot = assignSlot();
- }
- b.visibleOffset = enclosingBlock?.offset;
- b.visibleLength = enclosingBlock?.length;
- int oldVariableNamesLength = _variableNames.length;
- if (formalParameters != null && formalParameters.parameters.isNotEmpty) {
- _variableNames.addAll(formalParameters.parameters
- .map((FormalParameter p) => p.identifier.name));
- }
- serializeFunctionBody(
- b, null, body, serializeBodyExpr, serializeBody, false);
-
- if (mixinSuperInvokedNames != null) {
- body?.accept(new MixinSuperInvokedNamesCollector(mixinSuperInvokedNames));
- }
-
- _variableNames.length = oldVariableNamesLength;
- scopes.removeLast();
- assert(scopes.length == oldScopesLength);
- return b;
- }
-
- /// Record local functions and variables into the given executable. The given
- /// [body] is usually an actual [FunctionBody], but may be an [Expression]
- /// when we process a synthetic variable initializer function.
- ///
- /// If [initializers] is non-`null`, closures occurring inside the
- /// initializers are serialized first.
- ///
- /// If [serializeBodyExpr] is `true`, then the function definition is stored
- /// in [UnlinkedExecutableBuilder.bodyExpr], and closures occurring inside
- /// [initializers] and [body] have their function bodies serialized as well.
- ///
- /// The return value is a map whose keys are the offsets of local function
- /// nodes representing closures inside [initializers] and [body], and whose
- /// values are the indices of those local functions relative to their
- /// siblings.
- Map<int, int> serializeFunctionBody(
- UnlinkedExecutableBuilder b,
- List<ConstructorInitializer> initializers,
- AstNode body,
- bool serializeBodyExpr,
- bool serializeBody,
- bool forConst) {
- if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
- for (UnlinkedParamBuilder parameter in b.parameters) {
- if (!parameter.isInitializingFormal) {
- parameter.visibleOffset = body.offset;
- parameter.visibleLength = body.length;
- }
- }
- }
- List<UnlinkedExecutableBuilder> oldExecutables = executables;
- Map<int, int> oldLocalClosureIndexMap = _localClosureIndexMap;
- bool oldSerializeClosureBodyExprs = _serializeClosureBodyExprs;
- executables = <UnlinkedExecutableBuilder>[];
- _localClosureIndexMap = <int, int>{};
- _serializeClosureBodyExprs =
- serializeBodyExpr && _serializeInferrableFields;
- if (initializers != null) {
- for (ConstructorInitializer initializer in initializers) {
- initializer.accept(this);
- }
- }
- if (serializeBody) {
- body.accept(this);
- }
- if (serializeBodyExpr) {
- if (body is Expression) {
- b.bodyExpr = serializeConstExpr(
- forConst, _localClosureIndexMap, body, _variableNames);
- } else if (body is ExpressionFunctionBody) {
- b.bodyExpr = serializeConstExpr(
- forConst, _localClosureIndexMap, body.expression, _variableNames);
- } else {
- // TODO(paulberry): serialize other types of function bodies.
- }
- }
- b.localFunctions = executables;
- Map<int, int> localClosureIndexMap = _localClosureIndexMap;
- executables = oldExecutables;
- _localClosureIndexMap = oldLocalClosureIndexMap;
- _serializeClosureBodyExprs = oldSerializeClosureBodyExprs;
- return localClosureIndexMap;
- }
-
- /// Serialize the return type and parameters of a function-typed formal
- /// parameter and store them in [b].
- void serializeFunctionTypedParameterDetails(UnlinkedParamBuilder b,
- TypeAnnotation returnType, FormalParameterList parameters) {
- EntityRefBuilder serializedReturnType = serializeType(returnType);
- if (serializedReturnType != null) {
- b.type = serializedReturnType;
- }
- bool oldMayInheritCovariance = _parametersMayInheritCovariance;
- _parametersMayInheritCovariance = false;
- b.parameters = parameters.parameters
- .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
- .toList();
- _parametersMayInheritCovariance = oldMayInheritCovariance;
- }
-
- /// Serialize a generic function type.
- EntityRefBuilder serializeGenericFunctionType(GenericFunctionType node) {
- _TypeParameterScope typeParameterScope = new _TypeParameterScope();
- scopes.add(typeParameterScope);
- EntityRefBuilder b = new EntityRefBuilder(
- nullabilitySuffix: computeNullabilitySuffix(node?.question));
- b.entityKind = EntityRefKind.genericFunctionType;
- b.typeParameters =
- serializeTypeParameters(node.typeParameters, typeParameterScope);
- b.syntheticReturnType = node.returnType == null
- ? serializeDynamic()
- : serializeType(node.returnType);
- b.syntheticParams = node.parameters.parameters
- .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
- .toList();
- scopes.removeLast();
- return b;
- }
-
- /// If the given [expression] is not `null`, serialize it as an
- /// [UnlinkedExecutableBuilder], otherwise return `null`.
- ///
- /// If [serializeBodyExpr] is `true`, then the initializer expression is
- /// stored in [UnlinkedExecutableBuilder.bodyExpr].
- UnlinkedExecutableBuilder serializeInitializerFunction(
- Expression expression, bool serializeBodyExpr, bool forConst) {
- if (expression == null) {
- return null;
- }
- UnlinkedExecutableBuilder initializer =
- new UnlinkedExecutableBuilder(nameOffset: expression.offset);
- serializeFunctionBody(
- initializer, null, expression, serializeBodyExpr, true, forConst);
- initializer.inferredReturnTypeSlot = assignSlot();
- return initializer;
- }
-
- /// Serialize a type name that appears in a "with" clause to an [EntityRef].
- EntityRefBuilder serializeMixedInType(TypeAnnotation node) {
- var builder = serializeType(node);
- if (builder != null && builder.typeArguments.isEmpty) {
- // Type arguments may get inferred so we need to assign a slot to hold the
- // complete inferred mixed in type.
- builder.refinedSlot = assignSlot();
- }
- return builder;
- }
-
- /// Serialize a [MixinDeclaration] into an [UnlinkedClass]
- /// and store the result in [mixins].
- void serializeMixin(
- AstNode node,
- String name,
- int nameOffset,
- TypeParameterList typeParameters,
- OnClause onClause,
- ImplementsClause implementsClause,
- NodeList<ClassMember> members,
- Comment documentationComment,
- NodeList<Annotation> annotations) {
- List<UnlinkedExecutableBuilder> oldExecutables = executables;
- executables = <UnlinkedExecutableBuilder>[];
-
- mixinSuperInvokedNames = new Set<String>();
-
- List<UnlinkedVariableBuilder> oldVariables = variables;
- variables = <UnlinkedVariableBuilder>[];
-
- int oldScopesLength = scopes.length;
- _TypeParameterScope typeParameterScope = new _TypeParameterScope();
- scopes.add(typeParameterScope);
-
- UnlinkedClassBuilder b = new UnlinkedClassBuilder();
- b.name = name;
- b.nameOffset = nameOffset;
- b.typeParameters =
- serializeTypeParameters(typeParameters, typeParameterScope);
- if (onClause != null) {
- b.superclassConstraints =
- onClause.superclassConstraints.map(serializeType).toList();
- }
- if (implementsClause != null) {
- b.interfaces = implementsClause.interfaces.map(serializeType).toList();
- }
- if (members != null) {
- scopes.add(buildClassMemberScope(name, members));
- for (ClassMember member in members) {
- member.accept(this);
- }
- scopes.removeLast();
- }
- b.executables = executables;
- b.fields = variables;
- b.superInvokedNames = mixinSuperInvokedNames.toList();
- b.documentationComment = serializeDocumentation(documentationComment);
- b.annotations = serializeAnnotations(annotations);
- b.codeRange = serializeCodeRange(node);
- mixins.add(b);
-
- scopes.removeLast();
- assert(scopes.length == oldScopesLength);
-
- executables = oldExecutables;
- mixinSuperInvokedNames = null;
- variables = oldVariables;
- }
-
- /// Serialize a [FieldFormalParameter], [FunctionTypedFormalParameter], or
- /// [SimpleFormalParameter] into an [UnlinkedParam].
- UnlinkedParamBuilder serializeParameter(NormalFormalParameter node) {
- UnlinkedParamBuilder b = new UnlinkedParamBuilder();
- b.name = node.identifier?.name;
- b.nameOffset = node.identifier?.offset;
- b.annotations = serializeAnnotations(node.metadata);
- b.codeRange = serializeCodeRange(node);
- b.isExplicitlyCovariant = node.covariantKeyword != null;
- b.isFinal = node.isFinal;
- if (_parametersMayInheritCovariance) {
- b.inheritsCovariantSlot = assignSlot();
- }
- if (node.isRequiredPositional) {
- b.kind = UnlinkedParamKind.requiredPositional;
- } else if (node.isRequiredNamed) {
- b.kind = UnlinkedParamKind.requiredNamed;
- } else if (node.isOptionalPositional) {
- b.kind = UnlinkedParamKind.optionalPositional;
- } else if (node.isOptionalNamed) {
- b.kind = UnlinkedParamKind.optionalNamed;
- } else {
- // ignore: deprecated_member_use_from_same_package
- throw new StateError('Unexpected parameter kind: ${node.kind}');
- }
- return b;
- }
-
- /// Serialize a reference to a top level name declared elsewhere, by adding an
- /// entry to the references table if necessary. If [prefixIndex] is not null,
- /// the reference is associated with the prefix having the given index in the
- /// references table.
- int serializeReference(int prefixIndex, String name) => nameToReference
- .putIfAbsent(prefixIndex, () => <String, int>{})
- .putIfAbsent(name, () {
- int index = unlinkedReferences.length;
- unlinkedReferences.add(new UnlinkedReferenceBuilder(
- prefixReference: prefixIndex, name: name));
- return index;
- });
-
- /// Serialize a reference to a name declared either at top level or in a
- /// nested scope.
- ///
- /// References to type parameters are returned as negative numbers.
- int serializeSimpleReference(String name) {
- int indexOffset = 0;
- for (int i = scopes.length - 1; i >= 0; i--) {
- _Scope scope = scopes[i];
- _ScopedEntity entity = scope[name];
- if (entity != null) {
- if (entity is _ScopedClassMember) {
- return serializeReference(
- serializeReference(null, entity.className), name);
- } else if (entity is _ScopedTypeParameter) {
- int paramReference = indexOffset + entity.index;
- return -paramReference;
- }
- }
- if (scope is _TypeParameterScope) {
- indexOffset += scope.length;
- }
- }
- return serializeReference(null, name);
- }
-
- /// Serialize a type name (which might be defined in a nested scope, at top
- /// level within this library, or at top level within an imported library) to
- /// a [EntityRef]. Note that this method does the right thing if the
- /// name doesn't refer to an entity other than a type (e.g. a class member).
- EntityRefBuilder serializeType(TypeAnnotation node) {
- var nullabilitySuffix = computeNullabilitySuffix(node?.question);
- if (node is TypeName) {
- return serializeTypeName(
- node?.name, node?.typeArguments, nullabilitySuffix);
- } else if (node is GenericFunctionType) {
- return serializeGenericFunctionType(node);
- } else if (node != null) {
- throw new ArgumentError('Cannot serialize a ${node.runtimeType}');
- }
- return null;
- }
-
- /// Serialize a type name (which might be defined in a nested scope, at top
- /// level within this library, or at top level within an imported library) to
- /// a [EntityRef]. Note that this method does the right thing if the
- /// name doesn't refer to an entity other than a type (e.g. a class member).
- EntityRefBuilder serializeTypeName(
- Identifier identifier,
- TypeArgumentList typeArguments,
- EntityRefNullabilitySuffix nullabilitySuffix) {
- if (identifier == null) {
- return null;
- } else {
- EntityRefBuilder b =
- new EntityRefBuilder(nullabilitySuffix: nullabilitySuffix);
- if (identifier is SimpleIdentifier) {
- String name = identifier.name;
- int indexOffset = 0;
- for (int i = scopes.length - 1; i >= 0; i--) {
- _Scope scope = scopes[i];
- _ScopedEntity entity = scope[name];
- if (entity != null) {
- if (entity is _ScopedTypeParameter) {
- b.paramReference = indexOffset + entity.index;
- return b;
- } else {
- // None of the other things that can be declared in local scopes
- // are types, so this is an error and should be treated as a
- // reference to `dynamic`.
- b.reference = serializeReference(null, 'dynamic');
- return b;
- }
- }
- if (scope is _TypeParameterScope) {
- indexOffset += scope.length;
- }
- }
- b.reference = serializeReference(null, name);
- } else if (identifier is PrefixedIdentifier) {
- int prefixIndex = serializeSimpleReference(identifier.prefix.name);
- if (prefixIndex < 0) {
- // Type parameters are not expected here, so this is an error and the
- // type should be treated as a reference to `dynamic`.
- b.reference = serializeReference(null, 'dynamic');
- return b;
- } else {
- b.reference =
- serializeReference(prefixIndex, identifier.identifier.name);
- }
- } else {
- throw new StateError(
- 'Unexpected identifier type: ${identifier.runtimeType}');
- }
- if (typeArguments != null) {
- b.typeArguments = typeArguments.arguments.map(serializeType).toList();
- }
- return b;
- }
- }
-
- /// Serialize the given [typeParameters] into a list of [UnlinkedTypeParam]s,
- /// and also store them in [typeParameterScope].
- List<UnlinkedTypeParamBuilder> serializeTypeParameters(
- TypeParameterList typeParameters,
- _TypeParameterScope typeParameterScope) {
- if (typeParameters != null) {
- for (int i = 0; i < typeParameters.typeParameters.length; i++) {
- TypeParameter typeParameter = typeParameters.typeParameters[i];
- typeParameterScope[typeParameter.name.name] =
- new _ScopedTypeParameter(typeParameters.typeParameters.length - i);
- }
- return typeParameters.typeParameters.map(visitTypeParameter).toList();
- }
- return const <UnlinkedTypeParamBuilder>[];
- }
-
- /// Serialize the given [variables] into [UnlinkedVariable]s, and store them
- /// in [this.variables].
- void serializeVariables(
- VariableDeclarationList variables,
- bool isDeclaredStatic,
- Comment documentationComment,
- NodeList<Annotation> annotations,
- bool isField) {
- bool isCovariant = isField
- ? (variables.parent as FieldDeclaration).covariantKeyword != null
- : false;
- for (int i = 0; i < variables.variables.length; i++) {
- VariableDeclaration variable = variables.variables[i];
- UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
- b.isConst = variables.isConst;
- b.isCovariant = isCovariant;
- b.isFinal = variables.isFinal;
- b.isLate = variable.isLate;
- b.isStatic = isDeclaredStatic;
- b.name = variable.name.name;
- b.nameOffset = variable.name.offset;
- b.type = serializeType(variables.type);
- b.documentationComment = serializeDocumentation(documentationComment);
- b.annotations = serializeAnnotations(annotations);
-
- {
- int offset = (i == 0 ? variables.parent : variable).offset;
- int length = variable.end - offset;
- b.codeRange = new CodeRangeBuilder(offset: offset, length: length);
- }
-
- bool serializeBodyExpr = variable.isConst ||
- _serializeInferrableFields && variables.type == null ||
- isField &&
- !isDeclaredStatic &&
- variables.isFinal &&
- enclosingClassHasConstConstructor;
- b.initializer = serializeInitializerFunction(
- variable.initializer, serializeBodyExpr, b.isConst);
- if (isField && !isDeclaredStatic && !variables.isFinal) {
- b.inheritsCovariantSlot = assignSlot();
- }
- if (variable.initializer != null &&
- (variables.isFinal || variables.isConst)) {
- b.propagatedTypeSlot = assignSlot();
- }
- bool isSemanticallyStatic = !isField || isDeclaredStatic;
- if (variables.type == null &&
- (variable.initializer != null || !isSemanticallyStatic)) {
- b.inferredTypeSlot = assignSlot();
- }
- this.variables.add(b);
- }
- }
-
- @override
- void visitBlock(Block node) {
- Block oldBlock = enclosingBlock;
- enclosingBlock = node;
- super.visitBlock(node);
- enclosingBlock = oldBlock;
- }
-
- @override
- void visitClassDeclaration(ClassDeclaration node) {
- TypeName superclass =
- node.extendsClause == null ? null : node.extendsClause.superclass;
- serializeClass(
- node,
- node.abstractKeyword,
- node.name.name,
- node.name.offset,
- node.typeParameters,
- superclass,
- node.withClause,
- node.implementsClause,
- node.members,
- false,
- node.documentationComment,
- node.metadata);
- }
-
- @override
- void visitClassTypeAlias(ClassTypeAlias node) {
- serializeClass(
- node,
- node.abstractKeyword,
- node.name.name,
- node.name.offset,
- node.typeParameters,
- node.superclass,
- node.withClause,
- node.implementsClause,
- null,
- true,
- node.documentationComment,
- node.metadata);
- }
-
- @override
- void visitConstructorDeclaration(ConstructorDeclaration node) {
- UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
- if (node.name != null) {
- b.name = node.name.name;
- b.nameOffset = node.name.offset;
- b.periodOffset = node.period.offset;
- b.nameEnd = node.name.end;
- } else {
- b.nameOffset = node.returnType.offset;
- }
- b.parameters = node.parameters.parameters
- .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
- .toList();
- b.kind = UnlinkedExecutableKind.constructor;
- if (node.factoryKeyword != null) {
- b.isFactory = true;
- if (node.redirectedConstructor != null) {
- b.isRedirectedConstructor = true;
- TypeName typeName = node.redirectedConstructor.type;
- // Closures can't appear inside factory constructor redirections, so we
- // don't need a localClosureIndexMap.
- Map<int, int> localClosureIndexMap = null;
- b.redirectedConstructor =
- new _ConstExprSerializer(true, this, localClosureIndexMap, null)
- .serializeConstructorRef(typeName.name, typeName.typeArguments,
- node.redirectedConstructor.name);
- }
- } else {
- for (ConstructorInitializer initializer in node.initializers) {
- if (initializer is RedirectingConstructorInvocation) {
- b.isRedirectedConstructor = true;
- b.redirectedConstructorName = initializer.constructorName?.name;
- }
- }
- }
- if (node.constKeyword != null) {
- b.isConst = true;
- b.constCycleSlot = assignSlot();
- }
- b.isExternal =
- node.externalKeyword != null || node.body is NativeFunctionBody;
- b.documentationComment = serializeDocumentation(node.documentationComment);
- b.annotations = serializeAnnotations(node.metadata);
- b.codeRange = serializeCodeRange(node);
- Map<int, int> localClosureIndexMap = serializeFunctionBody(b,
- node.initializers, node.body, node.constKeyword != null, false, false);
- if (node.constKeyword != null) {
- List<String> constructorParameterNames =
- node.parameters.parameters.map((p) => p.identifier.name).toList();
- b.constantInitializers = node.initializers
- .map((ConstructorInitializer initializer) =>
- serializeConstructorInitializer(initializer, (Expression expr) {
- return serializeConstExpr(true, localClosureIndexMap, expr,
- constructorParameterNames);
- }))
- .toList();
- }
- executables.add(b);
- }
-
- @override
- UnlinkedParamBuilder visitDefaultFormalParameter(
- DefaultFormalParameter node) {
- UnlinkedParamBuilder b =
- node.parameter.accept(this) as UnlinkedParamBuilder;
- b.initializer = serializeInitializerFunction(node.defaultValue, true, true);
- if (node.defaultValue != null) {
- b.defaultValueCode = node.defaultValue.toSource();
- }
- b.codeRange = serializeCodeRange(node);
- return b;
- }
-
- @override
- void visitEnumDeclaration(EnumDeclaration node) {
- UnlinkedEnumBuilder b = new UnlinkedEnumBuilder();
- b.name = node.name.name;
- b.nameOffset = node.name.offset;
- b.values = node.constants.map(serializeEnumConstantDeclaration).toList();
- b.documentationComment = serializeDocumentation(node.documentationComment);
- b.annotations = serializeAnnotations(node.metadata);
- b.codeRange = serializeCodeRange(node);
- enums.add(b);
- }
-
- @override
- void visitExportDirective(ExportDirective node) {
- UnlinkedExportNonPublicBuilder b = new UnlinkedExportNonPublicBuilder(
- uriOffset: node.uri.offset, uriEnd: node.uri.end, offset: node.offset);
- b.annotations = serializeAnnotations(node.metadata);
- exports.add(b);
- }
-
- @override
- visitExtensionDeclaration(ExtensionDeclaration node) {
- int oldScopesLength = scopes.length;
- enclosingClassHasConstConstructor = false;
- List<UnlinkedExecutableBuilder> oldExecutables = executables;
- executables = <UnlinkedExecutableBuilder>[];
- List<UnlinkedVariableBuilder> oldVariables = variables;
- variables = <UnlinkedVariableBuilder>[];
- _TypeParameterScope typeParameterScope = new _TypeParameterScope();
- scopes.add(typeParameterScope);
-
- UnlinkedExtensionBuilder b = UnlinkedExtensionBuilder();
- b.name = node.name?.name;
- b.nameOffset = node.name?.offset ?? 0;
- b.typeParameters =
- serializeTypeParameters(node.typeParameters, typeParameterScope);
- b.extendedType = serializeType(node.extendedType);
- if (node.members != null) {
- scopes.add(buildClassMemberScope(node.name?.name, node.members));
- for (ClassMember member in node.members) {
- member.accept(this);
- }
- scopes.removeLast();
- }
- b.executables = executables;
- b.fields = variables;
- b.documentationComment = serializeDocumentation(node.documentationComment);
- b.annotations = serializeAnnotations(node.metadata);
- b.codeRange = serializeCodeRange(node);
- extensions.add(b);
-
- scopes.removeLast();
- assert(scopes.length == oldScopesLength);
- executables = oldExecutables;
- variables = oldVariables;
- }
-
- @override
- void visitFieldDeclaration(FieldDeclaration node) {
- serializeVariables(node.fields, node.staticKeyword != null,
- node.documentationComment, node.metadata, true);
- }
-
- @override
- UnlinkedParamBuilder visitFieldFormalParameter(FieldFormalParameter node) {
- UnlinkedParamBuilder b = serializeParameter(node);
- b.isInitializingFormal = true;
- if (node.type != null || node.parameters != null) {
- b.isFunctionTyped = node.parameters != null;
- if (node.parameters != null) {
- serializeFunctionTypedParameterDetails(b, node.type, node.parameters);
- } else {
- b.type = serializeType(node.type);
- }
- }
- return b;
- }
-
- @override
- void visitFunctionDeclaration(FunctionDeclaration node) {
- executables.add(serializeExecutable(
- node,
- node.name.name,
- node.name.offset,
- node.isGetter,
- node.isSetter,
- node.returnType,
- node.functionExpression.parameters,
- node.functionExpression.body,
- true,
- false,
- node.documentationComment,
- node.metadata,
- node.functionExpression.typeParameters,
- node.externalKeyword != null ||
- node.functionExpression.body is NativeFunctionBody,
- false,
- node.parent is FunctionDeclarationStatement));
- }
-
- @override
- void visitFunctionExpression(FunctionExpression node) {
- if (node.parent is! FunctionDeclaration) {
- if (_localClosureIndexMap != null) {
- _localClosureIndexMap[node.offset] = executables.length;
- }
- executables.add(serializeExecutable(
- node,
- null,
- node.offset,
- false,
- false,
- null,
- node.parameters,
- node.body,
- false,
- false,
- null,
- null,
- node.typeParameters,
- false,
- _serializeClosureBodyExprs,
- true));
- }
- }
-
- @override
- void visitFunctionTypeAlias(FunctionTypeAlias node) {
- int oldScopesLength = scopes.length;
- _TypeParameterScope typeParameterScope = new _TypeParameterScope();
- scopes.add(typeParameterScope);
- UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder();
- b.name = node.name.name;
- b.nameOffset = node.name.offset;
- b.typeParameters =
- serializeTypeParameters(node.typeParameters, typeParameterScope);
- b.notSimplyBoundedSlot = assignSlot();
- EntityRefBuilder serializedReturnType = serializeType(node.returnType);
- if (serializedReturnType != null) {
- b.returnType = serializedReturnType;
- }
- b.parameters = node.parameters.parameters
- .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
- .toList();
- b.documentationComment = serializeDocumentation(node.documentationComment);
- b.annotations = serializeAnnotations(node.metadata);
- b.codeRange = serializeCodeRange(node);
- typedefs.add(b);
-
- scopes.removeLast();
- assert(scopes.length == oldScopesLength);
- }
-
- @override
- UnlinkedParamBuilder visitFunctionTypedFormalParameter(
- FunctionTypedFormalParameter node) {
- UnlinkedParamBuilder b = serializeParameter(node);
- b.isFunctionTyped = true;
- serializeFunctionTypedParameterDetails(b, node.returnType, node.parameters);
- return b;
- }
-
- @override
- void visitGenericTypeAlias(GenericTypeAlias node) {
- int oldScopesLength = scopes.length;
- _TypeParameterScope typeParameterScope = new _TypeParameterScope();
- scopes.add(typeParameterScope);
- UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder();
- b.style = TypedefStyle.genericFunctionType;
- b.name = node.name.name;
- b.nameOffset = node.name.offset;
- b.typeParameters =
- serializeTypeParameters(node.typeParameters, typeParameterScope);
- b.notSimplyBoundedSlot = assignSlot();
- GenericFunctionType functionType = node.functionType;
- EntityRefBuilder serializedType = functionType == null
- ? null
- : serializeGenericFunctionType(functionType);
- if (serializedType != null) {
- b.returnType = serializedType;
- }
- b.documentationComment = serializeDocumentation(node.documentationComment);
- b.annotations = serializeAnnotations(node.metadata);
- b.codeRange = serializeCodeRange(node);
- typedefs.add(b);
- scopes.removeLast();
- assert(scopes.length == oldScopesLength);
- }
-
- @override
- void visitImportDirective(ImportDirective node) {
- UnlinkedImportBuilder b = new UnlinkedImportBuilder();
- b.annotations = serializeAnnotations(node.metadata);
- if (node.uri.stringValue == 'dart:core') {
- hasCoreBeenImported = true;
- }
- b.offset = node.offset;
- b.combinators = node.combinators.map(serializeCombinator).toList();
- b.configurations = node.configurations.map(serializeConfiguration).toList();
- if (node.prefix != null) {
- b.prefixReference = serializeReference(null, node.prefix.name);
- b.prefixOffset = node.prefix.offset;
- }
- b.isDeferred = node.deferredKeyword != null;
- b.uri = node.uri.stringValue;
- b.uriOffset = node.uri.offset;
- b.uriEnd = node.uri.end;
- unlinkedImports.add(b);
- }
-
- @override
- void visitLibraryDirective(LibraryDirective node) {
- libraryName =
- node.name.components.map((SimpleIdentifier id) => id.name).join('.');
- libraryNameOffset = node.name.offset;
- libraryNameLength = node.name.length;
- isCoreLibrary = libraryName == 'dart.core';
- isCoreLibraryDefiningUnit = isCoreLibrary;
- libraryDocumentationComment =
- serializeDocumentation(node.documentationComment);
- libraryAnnotations = serializeAnnotations(node.metadata);
- }
-
- @override
- void visitMethodDeclaration(MethodDeclaration node) {
- executables.add(serializeExecutable(
- node,
- node.name.name,
- node.name.offset,
- node.isGetter,
- node.isSetter,
- node.returnType,
- node.parameters,
- node.body,
- false,
- node.isStatic,
- node.documentationComment,
- node.metadata,
- node.typeParameters,
- node.externalKeyword != null || node.body is NativeFunctionBody,
- false,
- false));
- }
-
- @override
- visitMixinDeclaration(MixinDeclaration node) {
- serializeMixin(
- node,
- node.name.name,
- node.name.offset,
- node.typeParameters,
- node.onClause,
- node.implementsClause,
- node.members,
- node.documentationComment,
- node.metadata);
- }
-
- @override
- void visitPartDirective(PartDirective node) {
- parts.add(new UnlinkedPartBuilder(
- uriOffset: node.uri.offset,
- uriEnd: node.uri.end,
- annotations: serializeAnnotations(node.metadata)));
- }
-
- @override
- void visitPartOfDirective(PartOfDirective node) {
- isCoreLibrary = node.libraryName?.name == 'dart.core' ||
- node.uri?.stringValue == 'core.dart';
- isPartOf = true;
- }
-
- @override
- UnlinkedParamBuilder visitSimpleFormalParameter(SimpleFormalParameter node) {
- UnlinkedParamBuilder b = serializeParameter(node);
- b.type = serializeType(node.type);
- return b;
- }
-
- @override
- void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- serializeVariables(
- node.variables, false, node.documentationComment, node.metadata, false);
- }
-
- @override
- UnlinkedTypeParamBuilder visitTypeParameter(TypeParameter node) {
- UnlinkedTypeParamBuilder b = new UnlinkedTypeParamBuilder();
- b.name = node.name.name;
- b.nameOffset = node.name.offset;
- if (node.bound != null) {
- b.bound = serializeType(node.bound);
- }
- b.annotations = serializeAnnotations(node.metadata);
- b.codeRange = serializeCodeRange(node);
- return b;
- }
-
- @override
- void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
- // TODO(scheglov) Remove when we stop serializing local functions.
- }
-
- /// Determines whether a class declaration with the given [typeParameters]
- /// needs to be assigned a slot to indicate whether it is simply bounded.
- bool _shouldAssignNotSimplyBoundedSlot(TypeParameterList typeParameters) {
- if (typeParameters == null) return false;
- for (var typeParameter in typeParameters.typeParameters) {
- if (typeParameter.bound != null) return true;
- }
- return false;
- }
-
- /// Compute the API signature of the unit and record it.
- static void _computeApiSignature(UnlinkedUnitBuilder b) {
- ApiSignature apiSignature = new ApiSignature();
- b.collectApiSignature(apiSignature);
- b.apiSignature = apiSignature.toByteList();
- }
-}
-
-/// A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s.
-class _TypeParameterScope extends _Scope {
- /// Get the number of [_ScopedTypeParameter]s defined in this
- /// [_TypeParameterScope].
- int get length => _definedNames.length;
-}
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
deleted file mode 100644
index 6a931fa..0000000
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ /dev/null
@@ -1,808 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
-
-/// Serialize the given constructor initializer [node].
-UnlinkedConstructorInitializerBuilder serializeConstructorInitializer(
- ConstructorInitializer node,
- UnlinkedExprBuilder serializeConstExpr(Expression expr)) {
- if (node is ConstructorFieldInitializer) {
- return new UnlinkedConstructorInitializerBuilder(
- kind: UnlinkedConstructorInitializerKind.field,
- name: node.fieldName.name,
- expression: serializeConstExpr(node.expression));
- }
-
- List<UnlinkedExprBuilder> arguments = <UnlinkedExprBuilder>[];
- List<String> argumentNames = <String>[];
- void serializeArguments(List<Expression> args) {
- for (Expression arg in args) {
- if (arg is NamedExpression) {
- NamedExpression namedExpression = arg;
- argumentNames.add(namedExpression.name.label.name);
- arg = namedExpression.expression;
- }
- arguments.add(serializeConstExpr(arg));
- }
- }
-
- if (node is AssertInitializer) {
- serializeArguments(node.message != null
- ? [node.condition, node.message]
- : [node.condition]);
- return new UnlinkedConstructorInitializerBuilder(
- kind: UnlinkedConstructorInitializerKind.assertInvocation,
- arguments: arguments);
- }
- if (node is RedirectingConstructorInvocation) {
- serializeArguments(node.argumentList.arguments);
- return new UnlinkedConstructorInitializerBuilder(
- kind: UnlinkedConstructorInitializerKind.thisInvocation,
- name: node?.constructorName?.name,
- arguments: arguments,
- argumentNames: argumentNames);
- }
- if (node is SuperConstructorInvocation) {
- serializeArguments(node.argumentList.arguments);
- return new UnlinkedConstructorInitializerBuilder(
- kind: UnlinkedConstructorInitializerKind.superInvocation,
- name: node?.constructorName?.name,
- arguments: arguments,
- argumentNames: argumentNames);
- }
- throw new StateError('Unexpected initializer type ${node.runtimeType}');
-}
-
-/// Converts all the tokens between [startToken] and [endToken] (inclusive) into
-/// a string which, when scanned, will yield the same tokens back.
-String tokensToString(Token startToken, Token endToken) {
- var buffer = StringBuffer();
- var token = startToken;
- var spaceNeeded = false;
- while (true) {
- if (token.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
- buffer.write(token.lexeme);
- buffer.write(tokensToString(token.next, token.endGroup));
- spaceNeeded = false;
- token = token.endGroup;
- } else if (token.type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
- buffer.write(token.lexeme);
- buffer.write(token.next.lexeme);
- spaceNeeded = false;
- token = token.next;
- } else {
- if (spaceNeeded) buffer.write(' ');
- buffer.write(token.lexeme);
- spaceNeeded = true;
- }
- if (identical(token, endToken)) break;
- token = token.next;
- }
- return buffer.toString();
-}
-
-/// Instances of this class keep track of intermediate state during
-/// serialization of a single constant [Expression].
-abstract class AbstractConstExprSerializer {
- /// Whether an expression that should be a constant is being serialized.
- ///
- /// For constants we need to store more than we need just for type inference,
- /// because we need to be able to restore these AST to evaluate actual values
- /// of constants. So, we need to store constructor arguments, elements for
- /// list and map literals even if these literals are typed.
- final bool forConst;
-
- /// See [UnlinkedExprBuilder.isValidConst].
- bool isValidConst = true;
-
- /// See [UnlinkedExprBuilder.name].
- String name = null;
-
- /// See [UnlinkedExprBuilder.operations].
- final List<UnlinkedExprOperation> operations = <UnlinkedExprOperation>[];
-
- /// See [UnlinkedExprBuilder.assignmentOperators].
- final List<UnlinkedExprAssignOperator> assignmentOperators =
- <UnlinkedExprAssignOperator>[];
-
- /// See [UnlinkedExprBuilder.ints].
- final List<int> ints = <int>[];
-
- /// See [UnlinkedExprBuilder.doubles].
- final List<double> doubles = <double>[];
-
- /// See [UnlinkedExprBuilder.strings].
- final List<String> strings = <String>[];
-
- /// See [UnlinkedExprBuilder.references].
- final List<EntityRefBuilder> references = <EntityRefBuilder>[];
-
- AbstractConstExprSerializer(this.forConst);
-
- /// Return `true` if the given [name] is a parameter reference.
- bool isParameterName(String name);
-
- /// Removes the [count] variables that were most recently added to the scope
- /// by [pushVariableName].
- void popVariableNames(int count);
-
- /// Pushes a variable with the given [name] onto the current scope.
- void pushVariableName(String name);
-
- /// Serialize the given [expr] expression into this serializer state.
- void serialize(Expression expr) {
- try {
- if (expr is NamedExpression) {
- NamedExpression namedExpression = expr;
- name = namedExpression.name.label.name;
- expr = namedExpression.expression;
- }
- _serialize(expr);
- } on StateError {
- isValidConst = false;
- operations.clear();
- assignmentOperators.clear();
- ints.clear();
- doubles.clear();
- strings.clear();
- references.clear();
- }
- }
-
- /// Serialize the given [annotation] into this serializer state.
- void serializeAnnotation(Annotation annotation);
-
- /// Return [EntityRefBuilder] that corresponds to the constructor having name
- /// [name] in the class identified by [typeName].
- EntityRefBuilder serializeConstructorRef(Identifier typeName,
- TypeArgumentList typeArguments, SimpleIdentifier name);
-
- /// Return a pair of ints showing how the given [functionExpression] is nested
- /// within the constant currently being serialized. The first int indicates
- /// how many levels of function nesting must be popped in order to reach the
- /// parent of the [functionExpression]. The second int is the index of the
- /// [functionExpression] within its parent element.
- ///
- /// If the constant being summarized is in a context where local function
- /// references are not allowed, return `null`.
- List<int> serializeFunctionExpression(FunctionExpression functionExpression);
-
- /// Return [EntityRefBuilder] that corresponds to the [type], which is defined
- /// using generic function type syntax. These may appear as the type arguments
- /// of a const list, etc.
- EntityRefBuilder serializeGenericFunctionType(GenericFunctionType type);
-
- /// Return [EntityRefBuilder] that corresponds to the given [identifier].
- EntityRefBuilder serializeIdentifier(Identifier identifier);
-
- /// Return [EntityRefBuilder] that corresponds to the given [expr], which
- /// must be a sequence of identifiers.
- EntityRefBuilder serializeIdentifierSequence(Expression expr);
-
- void serializeInstanceCreation(EntityRefBuilder constructor,
- ArgumentList argumentList, bool typeArgumentsProvided) {
- _serializeArguments(argumentList, typeArgumentsProvided);
- references.add(constructor);
- operations.add(UnlinkedExprOperation.invokeConstructor);
- }
-
- /// Return [EntityRefBuilder] that corresponds to the given [type].
- EntityRefBuilder serializeType(TypeAnnotation type) {
- if (type is TypeName) {
- return serializeTypeName(type?.name, type?.typeArguments,
- computeNullabilitySuffix(type.question));
- }
- if (type is GenericFunctionType) {
- return serializeGenericFunctionType(type);
- }
- throw new ArgumentError(
- 'Cannot serialize an instance of ${type.runtimeType}');
- }
-
- /// Return [EntityRefBuilder] that corresponds to the type with the given
- /// [name] and [arguments].
- EntityRefBuilder serializeTypeName(Identifier name,
- TypeArgumentList arguments, EntityRefNullabilitySuffix nullabilitySuffix);
-
- /// Return the [UnlinkedExprBuilder] that corresponds to the state of this
- /// serializer.
- UnlinkedExprBuilder toBuilder(Token startToken, Token endToken) {
- return new UnlinkedExprBuilder(
- isValidConst: isValidConst,
- operations: operations,
- assignmentOperators: assignmentOperators,
- ints: ints,
- doubles: doubles,
- strings: strings,
- references: references,
- sourceRepresentation: tokensToString(startToken, endToken));
- }
-
- /// Return `true` if the given [expr] is a sequence of identifiers.
- bool _isIdentifierSequence(Expression expr) {
- while (expr != null) {
- if (expr is SimpleIdentifier) {
- AstNode parent = expr.parent;
- if (parent is MethodInvocation && parent.methodName == expr) {
- if (parent.isCascaded) {
- return false;
- }
- return parent.target == null || _isIdentifierSequence(parent.target);
- }
- if (isParameterName(expr.name)) {
- return false;
- }
- return true;
- } else if (expr is PrefixedIdentifier) {
- expr = (expr as PrefixedIdentifier).prefix;
- } else if (expr is PropertyAccess) {
- expr = (expr as PropertyAccess).target;
- } else {
- return false;
- }
- }
- return false;
- }
-
- /// Push the operation for the given assignable [expr].
- void _pushAssignable(Expression expr) {
- if (_isIdentifierSequence(expr)) {
- EntityRefBuilder ref = serializeIdentifierSequence(expr);
- references.add(ref);
- operations.add(UnlinkedExprOperation.assignToRef);
- } else if (expr is SimpleIdentifier && isParameterName(expr.name)) {
- strings.add(expr.name);
- operations.add(UnlinkedExprOperation.assignToParameter);
- } else if (expr is PropertyAccess) {
- if (!expr.isCascaded) {
- _serialize(expr.target);
- }
- strings.add(expr.propertyName.name);
- operations.add(UnlinkedExprOperation.assignToProperty);
- } else if (expr is IndexExpression) {
- if (!expr.isCascaded) {
- _serialize(expr.target);
- }
- _serialize(expr.index);
- operations.add(UnlinkedExprOperation.assignToIndex);
- } else if (expr is PrefixedIdentifier) {
- strings.add(expr.prefix.name);
- operations.add(UnlinkedExprOperation.pushParameter);
- strings.add(expr.identifier.name);
- operations.add(UnlinkedExprOperation.assignToProperty);
- } else {
- throw new StateError('Unsupported assignable: $expr');
- }
- }
-
- void _pushInt(int value) {
- value ??= 0;
- assert(value >= 0);
- if (value >= 0x100000000) {
- int numOfComponents = 0;
- ints.add(numOfComponents);
- void pushComponents(int value) {
- if (value >= 0x100000000) {
- pushComponents(value ~/ 0x100000000);
- }
- numOfComponents++;
- ints.add(value & 0xFFFFFFFF);
- }
-
- pushComponents(value);
- ints[ints.length - 1 - numOfComponents] = numOfComponents;
- operations.add(UnlinkedExprOperation.pushLongInt);
- } else {
- operations.add(UnlinkedExprOperation.pushInt);
- ints.add(value);
- }
- }
-
- /// Serialize the given [expr] expression into this serializer state.
- void _serialize(Expression expr, {bool emptyExpressionPermitted: false}) {
- if (emptyExpressionPermitted && expr == null) {
- operations.add(UnlinkedExprOperation.pushEmptyExpression);
- } else if (expr is IntegerLiteral) {
- int value = expr.value ?? 0;
- if (value >= 0) {
- _pushInt(value);
- } else {
- _pushInt(-value);
- operations.add(UnlinkedExprOperation.negate);
- }
- } else if (expr is DoubleLiteral) {
- operations.add(UnlinkedExprOperation.pushDouble);
- doubles.add(expr.value);
- } else if (expr is BooleanLiteral) {
- if (expr.value) {
- operations.add(UnlinkedExprOperation.pushTrue);
- } else {
- operations.add(UnlinkedExprOperation.pushFalse);
- }
- } else if (expr is StringLiteral) {
- _serializeString(expr);
- } else if (expr is SymbolLiteral) {
- strings.add(expr.components.map((token) => token.lexeme).join('.'));
- operations.add(UnlinkedExprOperation.makeSymbol);
- } else if (expr is NullLiteral) {
- operations.add(UnlinkedExprOperation.pushNull);
- } else if (expr is Identifier) {
- if (expr is SimpleIdentifier && isParameterName(expr.name)) {
- strings.add(expr.name);
- operations.add(UnlinkedExprOperation.pushParameter);
- } else if (expr is PrefixedIdentifier &&
- isParameterName(expr.prefix.name)) {
- strings.add(expr.prefix.name);
- operations.add(UnlinkedExprOperation.pushParameter);
- strings.add(expr.identifier.name);
- operations.add(UnlinkedExprOperation.extractProperty);
- } else {
- references.add(serializeIdentifier(expr));
- operations.add(UnlinkedExprOperation.pushReference);
- }
- } else if (expr is InstanceCreationExpression) {
- if (!expr.isConst) {
- isValidConst = false;
- }
- TypeName typeName = expr.constructorName.type;
- serializeInstanceCreation(
- serializeConstructorRef(
- typeName.name, typeName.typeArguments, expr.constructorName.name),
- expr.argumentList,
- typeName.typeArguments != null);
- } else if (expr is ListLiteral) {
- _serializeListLiteral(expr);
- } else if (expr is SetOrMapLiteral) {
- _serializeSetOrMapLiteral(expr);
- } else if (expr is MethodInvocation) {
- _serializeMethodInvocation(expr);
- } else if (expr is BinaryExpression) {
- _serializeBinaryExpression(expr);
- } else if (expr is ConditionalExpression) {
- _serialize(expr.condition);
- _serialize(expr.thenExpression);
- _serialize(expr.elseExpression);
- operations.add(UnlinkedExprOperation.conditional);
- } else if (expr is PrefixExpression) {
- _serializePrefixExpression(expr);
- } else if (expr is PostfixExpression) {
- _serializePostfixExpression(expr);
- } else if (expr is PropertyAccess) {
- _serializePropertyAccess(expr);
- } else if (expr is ParenthesizedExpression) {
- _serialize(expr.expression);
- } else if (expr is IndexExpression) {
- isValidConst = false;
- _serialize(expr.target);
- _serialize(expr.index);
- operations.add(UnlinkedExprOperation.extractIndex);
- } else if (expr is AssignmentExpression) {
- _serializeAssignment(expr);
- } else if (expr is CascadeExpression) {
- isValidConst = false;
- _serialize(expr.target);
- } else if (expr is FunctionExpression) {
- isValidConst = false;
- List<int> indices = serializeFunctionExpression(expr);
- if (indices != null) {
- ints.addAll(serializeFunctionExpression(expr));
- operations.add(UnlinkedExprOperation.pushLocalFunctionReference);
- } else {
- // Invalid expression; just push null.
- operations.add(UnlinkedExprOperation.pushNull);
- }
- } else if (expr is FunctionExpressionInvocation) {
- isValidConst = false;
- _serialize(expr.function);
- _serializeArguments(expr.argumentList, expr.typeArguments != null);
- strings.add('call');
- _serializeTypeArguments(expr.typeArguments);
- operations.add(UnlinkedExprOperation.invokeMethod);
- } else if (expr is AsExpression) {
- isValidConst = false;
- _serialize(expr.expression);
- references.add(serializeType(expr.type));
- operations.add(UnlinkedExprOperation.typeCast);
- } else if (expr is IsExpression) {
- isValidConst = false;
- _serialize(expr.expression);
- references.add(serializeType(expr.type));
- operations.add(UnlinkedExprOperation.typeCheck);
- if (expr.notOperator != null) {
- operations.add(UnlinkedExprOperation.not);
- }
- } else if (expr is SuperExpression) {
- operations.add(UnlinkedExprOperation.pushSuper);
- } else if (expr is ThisExpression) {
- operations.add(UnlinkedExprOperation.pushThis);
- } else if (expr is ThrowExpression) {
- isValidConst = false;
- _serialize(expr.expression);
- operations.add(UnlinkedExprOperation.throwException);
- } else if (expr is AwaitExpression) {
- isValidConst = false;
- _serialize(expr.expression);
- operations.add(UnlinkedExprOperation.await);
- } else {
- throw new StateError('Unknown expression type: $expr');
- }
- }
-
- void _serializeArguments(
- ArgumentList argumentList, bool typeArgumentsProvided) {
- if (forConst || !typeArgumentsProvided) {
- List<Expression> arguments = argumentList.arguments;
- // Serialize the arguments.
- List<String> argumentNames = <String>[];
- arguments.forEach((arg) {
- if (arg is NamedExpression) {
- argumentNames.add(arg.name.label.name);
- _serialize(arg.expression);
- } else {
- _serialize(arg);
- }
- });
- // Add numbers of named and positional arguments, and the op-code.
- ints.add(argumentNames.length);
- strings.addAll(argumentNames);
- ints.add(arguments.length - argumentNames.length);
- } else {
- ints.add(0);
- ints.add(0);
- }
- }
-
- void _serializeAssignment(AssignmentExpression expr) {
- isValidConst = false;
- // Push the value.
- _serialize(expr.rightHandSide);
- // Push the assignment operator.
- TokenType operator = expr.operator.type;
- UnlinkedExprAssignOperator assignmentOperator;
- if (operator == TokenType.EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.assign;
- } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.ifNull;
- } else if (operator == TokenType.STAR_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.multiply;
- } else if (operator == TokenType.SLASH_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.divide;
- } else if (operator == TokenType.TILDE_SLASH_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.floorDivide;
- } else if (operator == TokenType.PERCENT_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.modulo;
- } else if (operator == TokenType.PLUS_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.plus;
- } else if (operator == TokenType.MINUS_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.minus;
- } else if (operator == TokenType.LT_LT_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.shiftLeft;
- } else if (operator == TokenType.GT_GT_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.shiftRight;
- } else if (operator == TokenType.AMPERSAND_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.bitAnd;
- } else if (operator == TokenType.CARET_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.bitXor;
- } else if (operator == TokenType.BAR_EQ) {
- assignmentOperator = UnlinkedExprAssignOperator.bitOr;
- } else {
- throw new StateError('Unknown assignment operator: $operator');
- }
- assignmentOperators.add(assignmentOperator);
- // Push the assignment to the LHS.
- _pushAssignable(expr.leftHandSide);
- }
-
- void _serializeBinaryExpression(BinaryExpression expr) {
- _serialize(expr.leftOperand);
- _serialize(expr.rightOperand);
- TokenType operator = expr.operator.type;
- if (operator == TokenType.EQ_EQ) {
- operations.add(UnlinkedExprOperation.equal);
- } else if (operator == TokenType.BANG_EQ) {
- operations.add(UnlinkedExprOperation.notEqual);
- } else if (operator == TokenType.AMPERSAND_AMPERSAND) {
- operations.add(UnlinkedExprOperation.and);
- } else if (operator == TokenType.BAR_BAR) {
- operations.add(UnlinkedExprOperation.or);
- } else if (operator == TokenType.CARET) {
- operations.add(UnlinkedExprOperation.bitXor);
- } else if (operator == TokenType.AMPERSAND) {
- operations.add(UnlinkedExprOperation.bitAnd);
- } else if (operator == TokenType.BAR) {
- operations.add(UnlinkedExprOperation.bitOr);
- } else if (operator == TokenType.GT_GT) {
- operations.add(UnlinkedExprOperation.bitShiftRight);
- } else if (operator == TokenType.GT_GT_GT) {
- operations.add(UnlinkedExprOperation.bitShiftRightLogical);
- } else if (operator == TokenType.LT_LT) {
- operations.add(UnlinkedExprOperation.bitShiftLeft);
- } else if (operator == TokenType.PLUS) {
- operations.add(UnlinkedExprOperation.add);
- } else if (operator == TokenType.MINUS) {
- operations.add(UnlinkedExprOperation.subtract);
- } else if (operator == TokenType.STAR) {
- operations.add(UnlinkedExprOperation.multiply);
- } else if (operator == TokenType.SLASH) {
- operations.add(UnlinkedExprOperation.divide);
- } else if (operator == TokenType.TILDE_SLASH) {
- operations.add(UnlinkedExprOperation.floorDivide);
- } else if (operator == TokenType.GT) {
- operations.add(UnlinkedExprOperation.greater);
- } else if (operator == TokenType.LT) {
- operations.add(UnlinkedExprOperation.less);
- } else if (operator == TokenType.GT_EQ) {
- operations.add(UnlinkedExprOperation.greaterEqual);
- } else if (operator == TokenType.LT_EQ) {
- operations.add(UnlinkedExprOperation.lessEqual);
- } else if (operator == TokenType.PERCENT) {
- operations.add(UnlinkedExprOperation.modulo);
- } else if (operator == TokenType.QUESTION_QUESTION) {
- operations.add(UnlinkedExprOperation.ifNull);
- } else {
- throw new StateError('Unknown operator: $operator');
- }
- }
-
- void _serializeCollectionElement(CollectionElement element) {
- if (element is Expression) {
- _serialize(element);
- } else if (element is MapLiteralEntry) {
- _serialize(element.key);
- _serialize(element.value);
- operations.add(UnlinkedExprOperation.makeMapLiteralEntry);
- } else if (element is SpreadElement) {
- _serialize(element.expression);
- bool isNullAware = element.spreadOperator.type ==
- TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
- operations.add(isNullAware
- ? UnlinkedExprOperation.nullAwareSpreadElement
- : UnlinkedExprOperation.spreadElement);
- } else if (element is IfElement) {
- _serialize(element.condition);
- _serializeCollectionElement(element.thenElement);
- var elseElement = element.elseElement;
- if (elseElement == null) {
- operations.add(UnlinkedExprOperation.ifElement);
- } else {
- _serializeCollectionElement(elseElement);
- operations.add(UnlinkedExprOperation.ifElseElement);
- }
- } else if (element is ForElement) {
- isValidConst = false;
- var parts = element.forLoopParts;
- int numVariablesToPop = 0;
- if (parts is ForParts) {
- if (parts is ForPartsWithExpression) {
- _serialize(parts.initialization, emptyExpressionPermitted: true);
- } else if (parts is ForPartsWithDeclarations) {
- for (var variable in parts.variables.variables) {
- operations.add(UnlinkedExprOperation.variableDeclarationStart);
- var name = variable.name.name;
- strings.add(name);
- pushVariableName(name);
- ++numVariablesToPop;
- _serialize(variable.initializer, emptyExpressionPermitted: true);
- operations.add(UnlinkedExprOperation.variableDeclaration);
- ints.add(0);
- }
- var type = parts.variables.type;
- if (type == null) {
- operations
- .add(UnlinkedExprOperation.forInitializerDeclarationsUntyped);
- } else {
- references.add(serializeType(type));
- operations
- .add(UnlinkedExprOperation.forInitializerDeclarationsTyped);
- }
- ints.add(parts.variables.variables.length);
- } else {
- throw StateError('Unrecognized for parts');
- }
- _serialize(parts.condition, emptyExpressionPermitted: true);
- for (var updater in parts.updaters) {
- _serialize(updater);
- }
- operations.add(UnlinkedExprOperation.forParts);
- ints.add(parts.updaters.length);
- } else if (parts is ForEachParts) {
- if (parts is ForEachPartsWithIdentifier) {
- _serialize(parts.identifier);
- _serialize(parts.iterable);
- operations.add(UnlinkedExprOperation.forEachPartsWithIdentifier);
- } else if (parts is ForEachPartsWithDeclaration) {
- _serialize(parts.iterable);
- var type = parts.loopVariable.type;
- if (type == null) {
- operations
- .add(UnlinkedExprOperation.forEachPartsWithUntypedDeclaration);
- } else {
- references.add(serializeType(type));
- operations
- .add(UnlinkedExprOperation.forEachPartsWithTypedDeclaration);
- }
- var name = parts.loopVariable.identifier.name;
- strings.add(name);
- pushVariableName(name);
- ++numVariablesToPop;
- } else {
- throw StateError('Unrecognized for parts');
- }
- } else {
- throw StateError('Unrecognized for parts');
- }
- _serializeCollectionElement(element.body);
- popVariableNames(numVariablesToPop);
- operations.add(element.awaitKeyword == null
- ? UnlinkedExprOperation.forElement
- : UnlinkedExprOperation.forElementWithAwait);
- } else {
- throw new StateError('Unsupported CollectionElement: $element');
- }
- }
-
- void _serializeListLiteral(ListLiteral expr) {
- if (forConst || expr.typeArguments == null) {
- List<CollectionElement> elements = expr.elements;
- elements.forEach(_serializeCollectionElement);
- ints.add(elements.length);
- } else {
- ints.add(0);
- }
- if (expr.typeArguments != null &&
- expr.typeArguments.arguments.length == 1) {
- references.add(serializeType(expr.typeArguments.arguments[0]));
- operations.add(UnlinkedExprOperation.makeTypedList);
- } else {
- operations.add(UnlinkedExprOperation.makeUntypedList);
- }
- }
-
- void _serializeMethodInvocation(MethodInvocation invocation) {
- Expression target = invocation.target;
- SimpleIdentifier methodName = invocation.methodName;
- ArgumentList argumentList = invocation.argumentList;
- if (_isIdentifierSequence(methodName)) {
- EntityRefBuilder ref = serializeIdentifierSequence(methodName);
- _serializeArguments(argumentList, invocation.typeArguments != null);
- references.add(ref);
- _serializeTypeArguments(invocation.typeArguments);
- operations.add(UnlinkedExprOperation.invokeMethodRef);
- } else {
- if (!invocation.isCascaded) {
- _serialize(target);
- }
- _serializeArguments(argumentList, invocation.typeArguments != null);
- strings.add(methodName.name);
- _serializeTypeArguments(invocation.typeArguments);
- operations.add(UnlinkedExprOperation.invokeMethod);
- }
- }
-
- void _serializePostfixExpression(PostfixExpression expr) {
- TokenType operator = expr.operator.type;
- Expression operand = expr.operand;
- if (operator == TokenType.PLUS_PLUS) {
- _serializePrefixPostfixIncDec(
- operand, UnlinkedExprAssignOperator.postfixIncrement);
- } else if (operator == TokenType.MINUS_MINUS) {
- _serializePrefixPostfixIncDec(
- operand, UnlinkedExprAssignOperator.postfixDecrement);
- } else {
- throw new StateError('Unknown operator: $operator');
- }
- }
-
- void _serializePrefixExpression(PrefixExpression expr) {
- TokenType operator = expr.operator.type;
- Expression operand = expr.operand;
- if (operator == TokenType.BANG) {
- _serialize(operand);
- operations.add(UnlinkedExprOperation.not);
- } else if (operator == TokenType.MINUS) {
- _serialize(operand);
- operations.add(UnlinkedExprOperation.negate);
- } else if (operator == TokenType.TILDE) {
- _serialize(operand);
- operations.add(UnlinkedExprOperation.complement);
- } else if (operator == TokenType.PLUS_PLUS) {
- _serializePrefixPostfixIncDec(
- operand, UnlinkedExprAssignOperator.prefixIncrement);
- } else if (operator == TokenType.MINUS_MINUS) {
- _serializePrefixPostfixIncDec(
- operand, UnlinkedExprAssignOperator.prefixDecrement);
- } else {
- throw new StateError('Unknown operator: $operator');
- }
- }
-
- void _serializePrefixPostfixIncDec(
- Expression operand, UnlinkedExprAssignOperator operator) {
- isValidConst = false;
- assignmentOperators.add(operator);
- _pushAssignable(operand);
- }
-
- void _serializePropertyAccess(PropertyAccess expr) {
- if (_isIdentifierSequence(expr)) {
- EntityRefBuilder ref = serializeIdentifierSequence(expr);
- references.add(ref);
- operations.add(UnlinkedExprOperation.pushReference);
- } else {
- if (!expr.isCascaded) {
- _serialize(expr.target);
- }
- strings.add(expr.propertyName.name);
- operations.add(UnlinkedExprOperation.extractProperty);
- }
- }
-
- void _serializeSetOrMapLiteral(SetOrMapLiteral expr) {
- if (forConst || expr.typeArguments == null) {
- for (CollectionElement element in expr.elements) {
- _serializeCollectionElement(element);
- }
- ints.add(expr.elements.length);
- } else {
- ints.add(0);
- }
-
- List<TypeAnnotation> typeArguments = expr.typeArguments?.arguments;
- if (typeArguments != null && typeArguments.length == 2) {
- references.add(serializeType(typeArguments[0]));
- references.add(serializeType(typeArguments[1]));
- operations.add(UnlinkedExprOperation.makeTypedMap2);
- } else if (typeArguments != null && typeArguments.length == 1) {
- references.add(serializeType(typeArguments[0]));
- operations.add(UnlinkedExprOperation.makeTypedSet);
- } else {
- operations.add(UnlinkedExprOperation.makeUntypedSetOrMap);
- }
- }
-
- void _serializeString(StringLiteral expr) {
- if (expr is AdjacentStrings) {
- if (expr.strings.every((string) => string is SimpleStringLiteral)) {
- operations.add(UnlinkedExprOperation.pushString);
- strings.add(expr.stringValue);
- } else {
- expr.strings.forEach(_serializeString);
- operations.add(UnlinkedExprOperation.concatenate);
- ints.add(expr.strings.length);
- }
- } else if (expr is SimpleStringLiteral) {
- operations.add(UnlinkedExprOperation.pushString);
- strings.add(expr.value);
- } else {
- StringInterpolation interpolation = expr as StringInterpolation;
- for (InterpolationElement element in interpolation.elements) {
- if (element is InterpolationString) {
- operations.add(UnlinkedExprOperation.pushString);
- strings.add(element.value);
- } else {
- _serialize((element as InterpolationExpression).expression);
- }
- }
- operations.add(UnlinkedExprOperation.concatenate);
- ints.add(interpolation.elements.length);
- }
- }
-
- void _serializeTypeArguments(TypeArgumentList typeArguments) {
- if (typeArguments == null) {
- ints.add(0);
- } else {
- ints.add(typeArguments.arguments.length);
- for (TypeAnnotation type in typeArguments.arguments) {
- references.add(serializeType(type));
- }
- }
- }
-
- EntityRefNullabilitySuffix computeNullabilitySuffix(Token question);
-}
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index 9068bfd..b42a5a4 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -4,14 +4,12 @@
import 'dart:collection';
-import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
@@ -19,10 +17,6 @@
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/link.dart';
-import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'package:analyzer/src/summary2/link.dart' as summary2;
import 'package:analyzer/src/summary2/linked_element_factory.dart' as summary2;
@@ -76,7 +70,6 @@
final Iterable<Source> librarySources;
final Set<String> libraryUris = new Set<String>();
- final Map<String, UnlinkedUnit> unlinkedMap = <String, UnlinkedUnit>{};
final List<summary2.LinkInputLibrary> inputLibraries = [];
final PackageBundleAssembler bundleAssembler = new PackageBundleAssembler();
@@ -89,24 +82,14 @@
List<int> build() {
librarySources.forEach(_addLibrary);
- var useSummary2 = AnalysisDriver.useSummary2;
- try {
- AnalysisDriver.useSummary2 = false;
- Map<String, LinkedLibraryBuilder> map = link(libraryUris, (uri) {
- throw new StateError('Unexpected call to GetDependencyCallback($uri).');
- }, (uri) {
- UnlinkedUnit unlinked = unlinkedMap[uri];
- if (unlinked == null) {
- throw new StateError('Unable to find unresolved unit $uri.');
- }
- return unlinked;
- }, DeclaredVariables(), context.analysisOptions);
- map.forEach(bundleAssembler.addLinkedLibrary);
- } finally {
- AnalysisDriver.useSummary2 = useSummary2;
- }
+ var elementFactory = summary2.LinkedElementFactory(
+ context,
+ null,
+ summary2.Reference.root(),
+ );
- _link2();
+ var linkResult = summary2.link(elementFactory, inputLibraries);
+ bundleAssembler.setBundle2(linkResult.bundle);
return bundleAssembler.assemble().toBuffer();
}
@@ -120,7 +103,6 @@
var inputUnits = <summary2.LinkInputUnit>[];
CompilationUnit definingUnit = _parse(source);
- _addUnlinked(source, definingUnit);
inputUnits.add(
summary2.LinkInputUnit(null, source, false, definingUnit),
);
@@ -134,7 +116,6 @@
String partUri = directive.uri.stringValue;
Source partSource = context.sourceFactory.resolveUri(source, partUri);
CompilationUnit partUnit = _parse(partSource);
- _addUnlinked(partSource, partUnit);
inputUnits.add(
summary2.LinkInputUnit(partUri, partSource, false, partUnit),
);
@@ -146,24 +127,6 @@
);
}
- void _addUnlinked(Source source, CompilationUnit unit) {
- String uriStr = source.uri.toString();
- UnlinkedUnitBuilder unlinked = serializeAstUnlinked(unit);
- unlinkedMap[uriStr] = unlinked;
- bundleAssembler.addUnlinkedUnit(source, unlinked);
- }
-
- void _link2() {
- var elementFactory = summary2.LinkedElementFactory(
- context,
- null,
- summary2.Reference.root(),
- );
-
- var linkResult = summary2.link(elementFactory, inputLibraries);
- bundleAssembler.setBundle2(linkResult.bundle);
- }
-
CompilationUnit _parse(Source source) {
AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
String code = source.contents.data;
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 6e15f41..ef725a0 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -20,6 +20,7 @@
import 'package:analyzer/src/summary2/lazy_ast.dart';
import 'package:analyzer/src/summary2/linked_bundle_context.dart';
import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/type_builder.dart';
/// The context of a unit - the context of the bundle, and the unit tokens.
class LinkedUnitContext {
@@ -238,7 +239,12 @@
}
DartType getDefaultType(TypeParameter node) {
- return LazyTypeParameter.getDefaultType(_astReader, node);
+ var type = LazyTypeParameter.getDefaultType(_astReader, node);
+ if (type is TypeBuilder) {
+ type = (type as TypeBuilder).build();
+ LazyAst.setDefaultType(node, type);
+ }
+ return type;
}
String getDefaultValueCode(AstNode node) {
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index f4273a7..2cef609 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -40,6 +40,7 @@
final Linker linker;
LibraryElement _library;
+ bool _enclosingClassHasConstConstructor = false;
Scope _scope;
ConstantInitializersResolver(this.linker);
@@ -59,11 +60,15 @@
}
void _resolveClassFields(ClassElement class_) {
+ _enclosingClassHasConstConstructor =
+ class_.constructors.any((c) => c.isConst);
+
var node = _getLinkedNode(class_);
_scope = LinkingNodeContext.get(node).scope;
for (var element in class_.fields) {
_resolveVariable(element);
}
+ _enclosingClassHasConstConstructor = false;
}
void _resolveExtensionFields(ExtensionElement extension_) {
@@ -82,15 +87,18 @@
VariableDeclarationList declarationList = variable.parent;
var typeNode = declarationList.type;
- if (declarationList.isConst && typeNode != null) {
- var holder = ElementHolder();
- variable.initializer.accept(LocalElementBuilder(holder, null));
- (element as VariableElementImpl).encloseElements(holder.functions);
+ if (typeNode != null) {
+ if (declarationList.isConst ||
+ declarationList.isFinal && _enclosingClassHasConstConstructor) {
+ var holder = ElementHolder();
+ variable.initializer.accept(LocalElementBuilder(holder, null));
+ (element as VariableElementImpl).encloseElements(holder.functions);
- InferenceContext.setType(variable.initializer, typeNode.type);
- var astResolver = AstResolver(linker, _library, _scope);
- astResolver.rewriteAst(variable.initializer);
- astResolver.resolve(variable.initializer);
+ InferenceContext.setType(variable.initializer, typeNode.type);
+ var astResolver = AstResolver(linker, _library, _scope);
+ astResolver.rewriteAst(variable.initializer);
+ astResolver.resolve(variable.initializer);
+ }
}
}
}
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index 21fcc0a..d0e19d8 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -14,8 +14,6 @@
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/link.dart'
- show FieldElementForLink_ClassField, ParameterElementForLink;
import 'package:analyzer/src/summary2/lazy_ast.dart';
/**
@@ -177,9 +175,6 @@
kind: TopLevelInferenceErrorKind.overrideConflictParameterType,
),
);
- } else if (parameter is ParameterElementForLink) {
- parameter.setInferenceError(new TopLevelInferenceErrorBuilder(
- kind: TopLevelInferenceErrorKind.overrideConflictParameterType));
}
return typeProvider.dynamicType;
}
@@ -428,9 +423,6 @@
kind: TopLevelInferenceErrorKind.overrideConflictFieldType,
),
);
- } else if (field is FieldElementForLink_ClassField) {
- field.setInferenceError(new TopLevelInferenceErrorBuilder(
- kind: TopLevelInferenceErrorKind.overrideConflictFieldType));
}
return;
}
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index a1a5220..a4345eb 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.38.4
+version: 0.38.5-dev
author: Dart Team <misc@dartlang.org>
description: This package provides a library that performs static analysis of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
diff --git a/pkg/analyzer/test/file_system/physical_resource_provider_watch_test.dart b/pkg/analyzer/test/file_system/physical_resource_provider_watch_test.dart
index 6f68a1e..bac4ad2 100644
--- a/pkg/analyzer/test/file_system/physical_resource_provider_watch_test.dart
+++ b/pkg/analyzer/test/file_system/physical_resource_provider_watch_test.dart
@@ -7,7 +7,7 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:path/path.dart' as pathLib;
+import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:watcher/watcher.dart';
@@ -25,10 +25,10 @@
@reflectiveTest
class PhysicalResourceProviderWatchTest extends BaseTest {
test_watchFile_delete() {
- var path = pathLib.join(tempPath, 'foo');
- var file = new io.File(path);
+ var filePath = path.join(tempPath, 'foo');
+ var file = new io.File(filePath);
file.writeAsStringSync('contents 1');
- return _watchingFile(path, (changesReceived) {
+ return _watchingFile(filePath, (changesReceived) {
expect(changesReceived, hasLength(0));
file.deleteSync();
return _delayed(() {
@@ -43,22 +43,22 @@
} else {
expect(changesReceived[0].type, equals(ChangeType.REMOVE));
}
- expect(changesReceived[0].path, equals(path));
+ expect(changesReceived[0].path, equals(filePath));
});
});
}
test_watchFile_modify() {
- var path = pathLib.join(tempPath, 'foo');
- var file = new io.File(path);
+ var filePath = path.join(tempPath, 'foo');
+ var file = new io.File(filePath);
file.writeAsStringSync('contents 1');
- return _watchingFile(path, (changesReceived) {
+ return _watchingFile(filePath, (changesReceived) {
expect(changesReceived, hasLength(0));
file.writeAsStringSync('contents 2');
return _delayed(() {
expect(changesReceived, hasLength(1));
expect(changesReceived[0].type, equals(ChangeType.MODIFY));
- expect(changesReceived[0].path, equals(path));
+ expect(changesReceived[0].path, equals(filePath));
});
});
}
@@ -66,26 +66,26 @@
test_watchFolder_createFile() {
return _watchingFolder(tempPath, (changesReceived) {
expect(changesReceived, hasLength(0));
- var path = pathLib.join(tempPath, 'foo');
- new io.File(path).writeAsStringSync('contents');
+ var filePath = path.join(tempPath, 'foo');
+ new io.File(filePath).writeAsStringSync('contents');
return _delayed(() {
// There should be an "add" event indicating that the file was added.
// Depending on how long it took to write the contents, it may be
// followed by "modify" events.
expect(changesReceived, isNotEmpty);
expect(changesReceived[0].type, equals(ChangeType.ADD));
- expect(changesReceived[0].path, equals(path));
+ expect(changesReceived[0].path, equals(filePath));
for (int i = 1; i < changesReceived.length; i++) {
expect(changesReceived[i].type, equals(ChangeType.MODIFY));
- expect(changesReceived[i].path, equals(path));
+ expect(changesReceived[i].path, equals(filePath));
}
});
});
}
test_watchFolder_deleteFile() {
- var path = pathLib.join(tempPath, 'foo');
- var file = new io.File(path);
+ var filePath = path.join(tempPath, 'foo');
+ var file = new io.File(filePath);
file.writeAsStringSync('contents 1');
return _watchingFolder(tempPath, (changesReceived) {
expect(changesReceived, hasLength(0));
@@ -93,14 +93,14 @@
return _delayed(() {
expect(changesReceived, hasLength(1));
expect(changesReceived[0].type, equals(ChangeType.REMOVE));
- expect(changesReceived[0].path, equals(path));
+ expect(changesReceived[0].path, equals(filePath));
});
});
}
test_watchFolder_modifyFile() {
- var path = pathLib.join(tempPath, 'foo');
- var file = new io.File(path);
+ var filePath = path.join(tempPath, 'foo');
+ var file = new io.File(filePath);
file.writeAsStringSync('contents 1');
return _watchingFolder(tempPath, (changesReceived) {
expect(changesReceived, hasLength(0));
@@ -108,16 +108,16 @@
return _delayed(() {
expect(changesReceived, hasLength(1));
expect(changesReceived[0].type, equals(ChangeType.MODIFY));
- expect(changesReceived[0].path, equals(path));
+ expect(changesReceived[0].path, equals(filePath));
});
});
}
test_watchFolder_modifyFile_inSubDir() {
- var fooPath = pathLib.join(tempPath, 'foo');
+ var fooPath = path.join(tempPath, 'foo');
new io.Directory(fooPath).createSync();
- var path = pathLib.join(tempPath, 'bar');
- var file = new io.File(path);
+ var barPath = path.join(tempPath, 'bar');
+ var file = new io.File(barPath);
file.writeAsStringSync('contents 1');
return _watchingFolder(tempPath, (changesReceived) {
expect(changesReceived, hasLength(0));
@@ -125,7 +125,7 @@
return _delayed(() {
expect(changesReceived, anyOf(hasLength(1), hasLength(2)));
expect(changesReceived[0].type, equals(ChangeType.MODIFY));
- expect(changesReceived[0].path, equals(path));
+ expect(changesReceived[0].path, equals(barPath));
});
});
}
@@ -137,13 +137,13 @@
return new Future.delayed(new Duration(seconds: 1), computation);
}
- _watchingFile(String path, test(List<WatchEvent> changesReceived)) {
+ _watchingFile(String filePath, test(List<WatchEvent> changesReceived)) {
// Delay before we start watching the file. This is necessary
// because on MacOS, file modifications that occur just before we
// start watching are sometimes misclassified as happening just after
// we start watching.
return _delayed(() {
- File file = PhysicalResourceProvider.INSTANCE.getResource(path);
+ File file = PhysicalResourceProvider.INSTANCE.getResource(filePath);
var changesReceived = <WatchEvent>[];
var subscription = file.changes.listen(changesReceived.add);
// Delay running the rest of the test to allow file.changes propagate.
@@ -153,13 +153,13 @@
});
}
- _watchingFolder(String path, test(List<WatchEvent> changesReceived)) {
+ _watchingFolder(String filePath, test(List<WatchEvent> changesReceived)) {
// Delay before we start watching the folder. This is necessary
// because on MacOS, file modifications that occur just before we
// start watching are sometimes misclassified as happening just after
// we start watching.
return _delayed(() {
- Folder folder = PhysicalResourceProvider.INSTANCE.getResource(path);
+ Folder folder = PhysicalResourceProvider.INSTANCE.getResource(filePath);
var changesReceived = <WatchEvent>[];
var subscription = folder.changes.listen(changesReceived.add);
// Delay running the rest of the test to allow folder.changes to
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index 49b349f..8a60f47 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -6,7 +6,6 @@
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
@@ -1679,20 +1678,7 @@
var code = '''
void g(T f<T>(T x)) {}
''';
- if (AnalysisDriver.useSummary2) {
- await assertNoErrorsInCode(code);
- } else {
- // Once dartbug.com/28515 is fixed, this syntax should no longer generate an
- // error.
- await assertErrorsInCode(code, [
- // Due to dartbug.com/28515, some additional errors appear when using the
- // new analysis driver.
- error(CompileTimeErrorCode.UNDEFINED_CLASS, 7, 1),
- error(CompileTimeErrorCode.GENERIC_FUNCTION_TYPED_PARAM_UNSUPPORTED, 7,
- 11),
- error(CompileTimeErrorCode.UNDEFINED_CLASS, 14, 1),
- ]);
- }
+ await assertNoErrorsInCode(code);
}
test_implementsDeferredClass() async {
@@ -4786,18 +4772,10 @@
}
test_typeAliasCannotReferenceItself_generic() async {
- List<ExpectedError> expectedErrors;
- if (AnalysisDriver.useSummary2) {
- expectedErrors = [
- error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 37),
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 101, 1),
- ];
- } else {
- expectedErrors = [
- error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 37),
- error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 38, 37),
- ];
- }
+ List<ExpectedError> expectedErrors = [
+ error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 37),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 101, 1),
+ ];
await assertErrorsInCode(r'''
typedef F = void Function(List<G> l);
typedef G = void Function(List<F> l);
diff --git a/pkg/analyzer/test/generated/invalid_code_test.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
index 6659778..e97dbde 100644
--- a/pkg/analyzer/test/generated/invalid_code_test.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -5,7 +5,6 @@
import 'dart:async';
import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -13,23 +12,11 @@
main() {
defineReflectiveSuite(() {
- if (AnalysisDriver.useSummary2) {
- defineReflectiveTests(InvalidCodeSummary2Test);
- } else {
- defineReflectiveTests(InvalidCodeTest);
- }
+ defineReflectiveTests(InvalidCodeTest);
defineReflectiveTests(InvalidCodeWithExtensionMethodsTest);
});
}
-@reflectiveTest
-class InvalidCodeSummary2Test extends InvalidCodeTest {
- @failingTest
- test_fuzz_12() {
- return test_fuzz_12();
- }
-}
-
/// Tests for various end-to-end cases when invalid code caused exceptions
/// in one or another Analyzer subsystem. We are not interested not in specific
/// errors generated, but we want to make sure that there is at least one,
@@ -159,6 +146,7 @@
''');
}
+ @failingTest
test_fuzz_12() async {
// This code crashed with summary2 because usually AST reader is lazy,
// so we did not read metadata `@b` for `c`. But default values must be
diff --git a/pkg/analyzer/test/generated/issues_test.dart b/pkg/analyzer/test/generated/issues_test.dart
new file mode 100644
index 0000000..93b97b9
--- /dev/null
+++ b/pkg/analyzer/test/generated/issues_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2019, 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:test_reflective_loader/test_reflective_loader.dart';
+
+import '../src/dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(IssuesTest);
+ });
+}
+
+/// Tests for various end-to-end cases reported as user issues, where it is
+/// not obvious where to put the test otherwise.
+@reflectiveTest
+class IssuesTest extends DriverResolutionTest {
+ /// https://github.com/dart-lang/sdk/issues/38589
+ test_issue38589() async {
+ await resolveTestCode('''
+mixin M {}
+
+class A implements M {}
+
+class B implements M {}
+
+var b = true;
+var c = b ? A() : B();
+''');
+ assertElementTypeString(findElement.topVar('c').type, 'M');
+ }
+}
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index f3145f8..203d6db 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -1152,9 +1152,10 @@
}
@override
- void endTypeVariable(Token token, int index, Token extendsOrSuper) {
+ void endTypeVariable(
+ Token token, int index, Token extendsOrSuper, Token variance) {
end('TypeVariable');
- super.endTypeVariable(token, index, extendsOrSuper);
+ super.endTypeVariable(token, index, extendsOrSuper, variance);
}
@override
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 1a16278..c92e79d 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -3037,6 +3037,103 @@
expect(target.operand.toSource(), 'obj');
}
+ void test_nullCheckOnIndex3() {
+ // https://github.com/dart-lang/sdk/issues/37708
+ var unit = parseCompilationUnit('f() { foo.bar![arg]; }');
+ var funct = unit.declarations[0] as FunctionDeclaration;
+ var body = funct.functionExpression.body as BlockFunctionBody;
+ var statement = body.block.statements[0] as ExpressionStatement;
+ var expression = statement.expression as IndexExpression;
+ expect(expression.index.toSource(), 'arg');
+ var target = expression.target as PostfixExpression;
+ expect(target.operand.toSource(), 'foo.bar');
+ expect(target.operator.lexeme, '!');
+ }
+
+ void test_nullCheckOnIndex4() {
+ // https://github.com/dart-lang/sdk/issues/37708
+ var unit = parseCompilationUnit('f() { foo!.bar![arg]; }');
+ var funct = unit.declarations[0] as FunctionDeclaration;
+ var body = funct.functionExpression.body as BlockFunctionBody;
+ var statement = body.block.statements[0] as ExpressionStatement;
+ var expression = statement.expression as IndexExpression;
+ var fooBarTarget = expression.target as PostfixExpression;
+ expect(fooBarTarget.toSource(), "foo!.bar!");
+ var propertyAccess = fooBarTarget.operand as PropertyAccess;
+ var targetFoo = propertyAccess.target as PostfixExpression;
+ expect(targetFoo.operand.toSource(), "foo");
+ expect(targetFoo.operator.lexeme, "!");
+ expect(propertyAccess.propertyName.toSource(), "bar");
+ expect(fooBarTarget.operator.lexeme, '!');
+ expect(expression.index.toSource(), 'arg');
+ }
+
+ void test_nullCheckOnIndex5() {
+ // https://github.com/dart-lang/sdk/issues/37708
+ var unit = parseCompilationUnit('f() { foo.bar![arg]![arg2]; }');
+ var funct = unit.declarations[0] as FunctionDeclaration;
+ var body = funct.functionExpression.body as BlockFunctionBody;
+ var statement = body.block.statements[0] as ExpressionStatement;
+ var expression = statement.expression as IndexExpression;
+ expect(expression.index.toSource(), 'arg2');
+ var target = expression.target as PostfixExpression;
+ expect(target.operator.lexeme, '!');
+ expression = target.operand as IndexExpression;
+ expect(expression.index.toSource(), 'arg');
+ target = expression.target as PostfixExpression;
+ expect(target.operator.lexeme, '!');
+ expect(target.operand.toSource(), 'foo.bar');
+ }
+
+ void test_nullCheckOnIndex6() {
+ // https://github.com/dart-lang/sdk/issues/37708
+ var unit = parseCompilationUnit('f() { foo!.bar![arg]![arg2]; }');
+ var funct = unit.declarations[0] as FunctionDeclaration;
+ var body = funct.functionExpression.body as BlockFunctionBody;
+ var statement = body.block.statements[0] as ExpressionStatement;
+
+ // expression is "foo!.bar![arg]![arg2]"
+ var expression = statement.expression as IndexExpression;
+ expect(expression.index.toSource(), 'arg2');
+
+ // target is "foo!.bar![arg]!"
+ var target = expression.target as PostfixExpression;
+ expect(target.operator.lexeme, '!');
+
+ // expression is "foo!.bar![arg]"
+ expression = target.operand as IndexExpression;
+ expect(expression.index.toSource(), 'arg');
+
+ // target is "foo!.bar!"
+ target = expression.target as PostfixExpression;
+ expect(target.operator.lexeme, '!');
+
+ // propertyAccess is "foo!.bar"
+ PropertyAccess propertyAccess = target.operand as PropertyAccess;
+ expect(propertyAccess.propertyName.toSource(), "bar");
+
+ // target is "foo!"
+ target = propertyAccess.target as PostfixExpression;
+ expect(target.operator.lexeme, '!');
+
+ expect(target.operand.toSource(), "foo");
+ }
+
+ void test_nullCheckBeforeIndex() {
+ // https://github.com/dart-lang/sdk/issues/37708
+ var unit = parseCompilationUnit('f() { foo.bar!.baz[arg]; }');
+ var funct = unit.declarations[0] as FunctionDeclaration;
+ var body = funct.functionExpression.body as BlockFunctionBody;
+ var statement = body.block.statements[0] as ExpressionStatement;
+ var expression = statement.expression as IndexExpression;
+ expect(expression.index.toSource(), 'arg');
+ var propertyAccess = expression.target as PropertyAccess;
+ expect(propertyAccess.propertyName.toSource(), 'baz');
+ var target = propertyAccess.target as PostfixExpression;
+ expect(target.operand.toSource(), 'foo.bar');
+ expect(target.operator.lexeme, '!');
+ }
+
void test_nullCheckOnLiteral_disabled() {
parseCompilationUnit('f() { var x = 0!; }',
errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)],
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index c49393b..f7c425f 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -1085,7 +1085,7 @@
_listener.assertNoErrors();
}
- void setUp({bool shouldSetElementSupertypes: false}) {
+ void setUp() {
_listener = new GatheringErrorListener();
AnalysisContext context = TestAnalysisContext();
Source librarySource = new FileSource(getFile("/lib.dart"));
@@ -1102,9 +1102,7 @@
libraryScope = new LibraryScope(element);
_visitor = new TypeResolverVisitor(
element, librarySource, _typeProvider, _listener,
- featureSet: featureSet,
- nameScope: libraryScope,
- shouldSetElementSupertypes: shouldSetElementSupertypes);
+ featureSet: featureSet, nameScope: libraryScope);
}
test_modeApi() async {
@@ -1550,57 +1548,6 @@
_listener.assertNoErrors();
}
- test_visitClassDeclaration() async {
- // class A extends B with C implements D {}
- // class B {}
- // class C {}
- // class D {}
- setUp(shouldSetElementSupertypes: true);
- ClassElement elementA = ElementFactory.classElement2("A");
- ClassElement elementB = ElementFactory.classElement2("B");
- ClassElement elementC = ElementFactory.classElement2("C");
- ClassElement elementD = ElementFactory.classElement2("D");
- ExtendsClause extendsClause =
- AstTestFactory.extendsClause(AstTestFactory.typeName(elementB));
- WithClause withClause =
- AstTestFactory.withClause([AstTestFactory.typeName(elementC)]);
- ImplementsClause implementsClause =
- AstTestFactory.implementsClause([AstTestFactory.typeName(elementD)]);
- ClassDeclaration declaration = AstTestFactory.classDeclaration(
- null, "A", null, extendsClause, withClause, implementsClause);
- declaration.name.staticElement = elementA;
- _resolveNode(declaration, [elementA, elementB, elementC, elementD]);
- expect(elementA.supertype, interfaceType(elementB));
- List<InterfaceType> mixins = elementA.mixins;
- expect(mixins, hasLength(1));
- expect(mixins[0], interfaceType(elementC));
- List<InterfaceType> interfaces = elementA.interfaces;
- expect(interfaces, hasLength(1));
- expect(interfaces[0], interfaceType(elementD));
- _listener.assertNoErrors();
- }
-
- test_visitClassDeclaration_instanceMemberCollidesWithClass() async {
- // class A {}
- // class B extends A {
- // void A() {}
- // }
- setUp(shouldSetElementSupertypes: true);
- ClassElementImpl elementA = ElementFactory.classElement2("A");
- ClassElementImpl elementB = ElementFactory.classElement2("B");
- elementB.methods = <MethodElement>[
- ElementFactory.methodElement("A", VoidTypeImpl.instance)
- ];
- ExtendsClause extendsClause =
- AstTestFactory.extendsClause(AstTestFactory.typeName(elementA));
- ClassDeclaration declaration = AstTestFactory.classDeclaration(
- null, "B", null, extendsClause, null, null);
- declaration.name.staticElement = elementB;
- _resolveNode(declaration, [elementA, elementB]);
- expect(elementB.supertype, interfaceType(elementA));
- _listener.assertNoErrors();
- }
-
test_visitFieldFormalParameter_functionType() async {
InterfaceType intType = _typeProvider.intType;
TypeName intTypeName = AstTestFactory.typeName4('int');
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index b9c570d..59ffc3d 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -1063,7 +1063,7 @@
]);
}
- test_typeParameterSupertypeOfItsBound() async {
+ test_typeParameterSupertypeOfItsBound_1of1() async {
await assertErrorsInCode(r'''
class A<T extends T> {
}
@@ -1072,6 +1072,17 @@
]);
}
+ test_typeParameterSupertypeOfItsBound_2of3() async {
+ await assertErrorsInCode(r'''
+class A<T1 extends T3, T2, T3 extends T1> {
+}
+''', [
+ error(StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND, 8, 13),
+ error(
+ StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND, 27, 13),
+ ]);
+ }
+
test_typePromotion_booleanAnd_useInRight_accessedInClosureRight_mutated() async {
await assertErrorsInCode(r'''
callMe(f()) { f(); }
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 8557eb0..7f1e8fe 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -9,7 +9,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -2700,12 +2699,8 @@
for (ExpressionStatement stmt in stmts) {
MethodInvocation invoke = stmt.expression;
FunctionType fType = invoke.staticInvokeType;
- if (AnalysisDriver.useSummary2) {
- expect('$fType',
- 'void Function(T Function(T), int Function(T, T), T Function(T))');
- } else {
- expect(fType.typeArguments[0].toString(), 'T');
- }
+ expect('$fType',
+ 'void Function(T Function(T), int Function(T, T), T Function(T))');
}
}
@@ -2732,11 +2727,7 @@
for (ExpressionStatement stmt in stmts) {
MethodInvocation invoke = stmt.expression;
FunctionType fType = invoke.staticInvokeType;
- if (AnalysisDriver.useSummary2) {
- expect('$fType', 'void Function(List<T>, int Function(T, T), List<T>)');
- } else {
- expect(fType.typeArguments[0].toString(), 'T');
- }
+ expect('$fType', 'void Function(List<T>, int Function(T, T), List<T>)');
}
}
@@ -2763,11 +2754,7 @@
for (ExpressionStatement stmt in stmts) {
MethodInvocation invoke = stmt.expression;
FunctionType fType = invoke.staticInvokeType;
- if (AnalysisDriver.useSummary2) {
- expect('$fType', 'void Function(T, int Function(T, T), T)');
- } else {
- expect(fType.typeArguments[0].toString(), 'T');
- }
+ expect('$fType', 'void Function(T, int Function(T, T), T)');
}
}
@@ -4218,9 +4205,6 @@
}
test_genericFunction_parameter() async {
- // TODO(paulberry): remove when dartbug.com/28515 fixed.
- if (!AnalysisDriver.useSummary2) return;
-
await assertNoErrorsInCode(r'''
void g(T f<T>(T x)) {}
''');
@@ -4385,9 +4369,6 @@
}
test_genericMethod_functionExpressionInvocation_functionTypedParameter_explicit() async {
- // TODO(paulberry): remove when dartbug.com/28515 fixed.
- if (!AnalysisDriver.useSummary2) return;
-
await assertNoErrorsInCode(r'''
void test<S>(T pf<T>(T e)) {
var paramCall = (pf)<int>(3);
@@ -4397,9 +4378,6 @@
}
test_genericMethod_functionExpressionInvocation_functionTypedParameter_inferred() async {
- // TODO(paulberry): remove when dartbug.com/28515 fixed.
- if (!AnalysisDriver.useSummary2) return;
-
await assertNoErrorsInCode(r'''
void test<S>(T pf<T>(T e)) {
var paramCall = (pf)(3);
@@ -4409,9 +4387,6 @@
}
test_genericMethod_functionExpressionInvocation_inferred() async {
- // TODO(paulberry): remove when dartbug.com/28515 fixed.
- if (!AnalysisDriver.useSummary2) return;
-
await assertNoErrorsInCode(r'''
class C<E> {
T f<T>(T e) => null;
@@ -4477,9 +4452,6 @@
}
test_genericMethod_functionInvocation_functionTypedParameter_explicit() async {
- // TODO(paulberry): remove when dartbug.com/28515 fixed.
- if (!AnalysisDriver.useSummary2) return;
-
await assertNoErrorsInCode(r'''
void test<S>(T pf<T>(T e)) {
var paramCall = pf<int>(3);
@@ -4489,9 +4461,6 @@
}
test_genericMethod_functionInvocation_functionTypedParameter_inferred() async {
- // TODO(paulberry): remove when dartbug.com/28515 fixed.
- if (!AnalysisDriver.useSummary2) return;
-
await assertNoErrorsInCode(r'''
void test<S>(T pf<T>(T e)) {
var paramCall = pf(3);
@@ -4554,9 +4523,6 @@
}
test_genericMethod_functionTypedParameter_tearoff() async {
- // TODO(paulberry): remove when dartbug.com/28515 fixed.
- if (!AnalysisDriver.useSummary2) return;
-
await assertNoErrorsInCode(r'''
void test<S>(T pf<T>(T e)) {
var paramTearOff = pf;
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index f4d11a7..8f0cb6f 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -16,6 +16,7 @@
import 'error_suppression_test.dart' as error_suppression;
import 'inheritance_manager_test.dart' as inheritance_manager_test;
import 'invalid_code_test.dart' as invalid_code;
+import 'issues_test.dart' as issues;
import 'java_core_test.dart' as java_core_test;
import 'java_io_test.dart' as java_io_test;
import 'non_error_resolver_test.dart' as non_error_resolver;
@@ -47,6 +48,7 @@
error_suppression.main();
inheritance_manager_test.main();
invalid_code.main();
+ issues.main();
java_core_test.main();
java_io_test.main();
non_error_resolver.main();
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index d5f31a8..b1a5532 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -3659,6 +3659,7 @@
void test_equals() {
SourceRange r = new SourceRange(10, 1);
expect(r == null, isFalse);
+ // ignore: unrelated_type_equality_checks
expect(r == this, isFalse);
expect(r == new SourceRange(20, 2), isFalse);
expect(r == new SourceRange(10, 1), isTrue);
diff --git a/pkg/analyzer/test/id_tests/constant_test.dart b/pkg/analyzer/test/id_tests/constant_test.dart
index d2d5509..bf88745 100644
--- a/pkg/analyzer/test/id_tests/constant_test.dart
+++ b/pkg/analyzer/test/id_tests/constant_test.dart
@@ -88,7 +88,7 @@
}
} else if (type is FunctionType) {
var element = value.toFunctionValue();
- return 'Function(${element.name})';
+ return 'Function(${element.name},type=${value.type})';
}
throw UnimplementedError('_stringify for type $type');
}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 35828ff..8746dc1 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -10,7 +10,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
@@ -4784,11 +4783,6 @@
var gType = findNode.typeName('Consumer<T>');
var gTypeType = gType.type as FunctionType;
- if (!AnalysisDriver.useSummary2) {
- var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
- expect(gTypeTypeArgument.element, same(tElement));
- }
-
var gTypeParameterType =
gTypeType.namedParameterTypes['u'] as TypeParameterType;
expect(gTypeParameterType.element, same(tElement));
@@ -4817,11 +4811,6 @@
var gType = findNode.typeName('Consumer<T>');
var gTypeType = gType.type as FunctionType;
- if (!AnalysisDriver.useSummary2) {
- var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
- expect(gTypeTypeArgument.element, same(tElement));
- }
-
var gTypeParameterType =
gTypeType.normalParameterTypes[0] as TypeParameterType;
expect(gTypeParameterType.element, same(tElement));
@@ -4850,11 +4839,6 @@
var gType = findNode.typeName('Consumer<T>');
var gTypeType = gType.type as FunctionType;
- if (!AnalysisDriver.useSummary2) {
- var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
- expect(gTypeTypeArgument.element, same(tElement));
- }
-
var gTypeParameterType =
gTypeType.optionalParameterTypes[0] as TypeParameterType;
expect(gTypeParameterType.element, same(tElement));
@@ -4883,11 +4867,6 @@
var gType = findNode.typeName('Producer<T>');
var gTypeType = gType.type as FunctionType;
- if (!AnalysisDriver.useSummary2) {
- var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
- expect(gTypeTypeArgument.element, same(tElement));
- }
-
var gTypeReturnType = gTypeType.returnType as TypeParameterType;
expect(gTypeReturnType.element, same(tElement));
@@ -5453,8 +5432,7 @@
}
test_methodInvocation_instanceMethod_genericClass_genericMethod() async {
- try {
- addTestFile(r'''
+ addTestFile(r'''
main() {
new C<int>().m(1, 2.3);
}
@@ -5462,41 +5440,22 @@
Map<T, U> m<U>(T a, U b) => null;
}
''');
- await resolveTestFile();
- MethodElement mElement = findElement.method('m');
+ await resolveTestFile();
+ MethodElement mElement = findElement.method('m');
- {
- var invocation = findNode.methodInvocation('m(1, 2.3)');
- List<Expression> arguments = invocation.argumentList.arguments;
+ {
+ var invocation = findNode.methodInvocation('m(1, 2.3)');
+ List<Expression> arguments = invocation.argumentList.arguments;
- var invokeTypeStr = 'Map<int, double> Function(int, double)';
- assertType(invocation, 'Map<int, double>');
- assertInvokeType(invocation, invokeTypeStr);
+ var invokeTypeStr = 'Map<int, double> Function(int, double)';
+ assertType(invocation, 'Map<int, double>');
+ assertInvokeType(invocation, invokeTypeStr);
- assertMember(invocation.methodName, mElement, {'T': 'int'});
- assertType(invocation.methodName, 'Map<int, U> Function<U>(int, U)');
+ assertMember(invocation.methodName, mElement, {'T': 'int'});
+ assertType(invocation.methodName, 'Map<int, U> Function<U>(int, U)');
- if (AnalysisDriver.useSummary2) {
- _assertArgumentToParameter2(arguments[0], 'int');
- _assertArgumentToParameter2(arguments[1], 'double');
- } else {
- _assertArgumentToParameter(arguments[0], mElement.parameters[0]);
- _assertArgumentToParameter(arguments[1], mElement.parameters[1]);
- }
- }
- if (!AnalysisDriver.useSummary2) {
- throw 'Test passed - expected to fail.';
- }
- } on String {
- rethrow;
- } catch (_) {
- // This test started failing in summary1, because we assign
- // corresponding parameter elements from FunctionType, which became
- // structural, and does not know its element anymore.
- // We should fix this up by using MethodMember parameters instead.
- if (AnalysisDriver.useSummary2) {
- rethrow;
- }
+ _assertArgumentToParameter2(arguments[0], 'int');
+ _assertArgumentToParameter2(arguments[1], 'double');
}
}
@@ -5597,9 +5556,6 @@
''');
await resolveTestFile();
- FunctionTypeAlias funDeclaration = result.unit.declarations[0];
- FunctionTypeAliasElement funElement = funDeclaration.declaredElement;
-
ClassDeclaration cDeclaration = result.unit.declarations[1];
MethodDeclaration fDeclaration = cDeclaration.members[0];
@@ -5617,13 +5573,8 @@
expect(invocation.staticType, typeProvider.stringType);
List<Expression> arguments = invocation.argumentList.arguments;
- if (AnalysisDriver.useSummary2) {
- _assertArgumentToParameter2(arguments[0], 'int');
- _assertArgumentToParameter2(arguments[1], 'int');
- } else {
- _assertArgumentToParameter(arguments[0], funElement.parameters[0]);
- _assertArgumentToParameter(arguments[1], funElement.parameters[1]);
- }
+ _assertArgumentToParameter2(arguments[0], 'int');
+ _assertArgumentToParameter2(arguments[1], 'int');
}
test_methodInvocation_notFunction_local_dynamic() async {
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index ef0509e..276fc93 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -23,7 +23,6 @@
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:test/test.dart';
@@ -37,9 +36,6 @@
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisDriverSchedulerTest);
defineReflectiveTests(AnalysisDriverTest);
- if (!AnalysisDriver.useSummary2) {
- defineReflectiveTests(AnalysisDriverSummary1Test);
- }
defineReflectiveTests(CacheAllAnalysisDriverTest);
});
}
@@ -346,374 +342,6 @@
}
}
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
-@reflectiveTest
-class AnalysisDriverSummary1Test extends BaseAnalysisDriverTest {
- test_externalSummaries() async {
- var a = convertPath('/a.dart');
- var b = convertPath('/b.dart');
- newFile(a, content: r'''
-class A {}
-''');
- newFile(b, content: r'''
-import 'a.dart';
-var a = new A();
-''');
-
- // Prepare the store with a.dart and everything it needs.
- SummaryDataStore summaryStore =
- await createAnalysisDriver().test.getSummaryStore(a);
-
- // There are at least a.dart and dart:core libraries.
- String aUri = toUriStr(a);
- expect(summaryStore.unlinkedMap.keys, contains(aUri));
- expect(summaryStore.linkedMap.keys, contains(aUri));
- expect(summaryStore.unlinkedMap.keys, contains('dart:core'));
- expect(summaryStore.linkedMap.keys, contains('dart:core'));
-
- // Remove a.dart from the file system.
- deleteFile(a);
-
- // We don't need a.dart file when we analyze with the summary store.
- // Still no analysis errors.
- AnalysisDriver driver =
- createAnalysisDriver(externalSummaries: summaryStore);
- ResolvedUnitResult result = await driver.getResult(b);
- expect(result.errors, isEmpty);
- }
-
- test_externalSummaries_partReuse() async {
- var a = convertPath('/a.dart');
- var b = convertPath('/b.dart');
- var c = convertPath('/c.dart');
- newFile(a, content: r'''
-library a;
-part 'b.dart';
-class A {}
-''');
- newFile(b, content: r'''
-part of a;
-class _B {}
-''');
- newFile(c, content: r'''
-library a;
-import 'a.dart';
-part 'b.dart';
-var a = new A();
-var b = new _B();
-''');
-
- // Prepare the store with a.dart and everything it needs.
- SummaryDataStore summaryStore =
- await createAnalysisDriver().test.getSummaryStore(a);
-
- String aUri = toUriStr(a);
- String bUri = toUriStr(b);
- // There are unlinked units for a.dart and b.dart files.
- expect(summaryStore.hasUnlinkedUnit(aUri), isTrue);
- expect(summaryStore.hasUnlinkedUnit(bUri), isTrue);
- // Only a.dart is linked, because b.dart is not a library.
- expect(summaryStore.hasLinkedLibrary(aUri), isTrue);
- expect(summaryStore.hasLinkedLibrary(bUri), isFalse);
-
- // Remove a.dart from the file system.
- // Keep b.dart, because we (re)use it as a part.
- deleteFile(a);
-
- // We don't need a.dart file when we analyze with the summary store.
- // We can instantiate the class A the library a.dart.
- // We can instantiate the class _A the part b.dart.
- AnalysisDriver driver =
- createAnalysisDriver(externalSummaries: summaryStore);
- ResolvedUnitResult result = await driver.getResult(c);
- expect(result.errors, isEmpty);
- }
-
- test_getLibraryByUri_external() async {
- var a = convertPath('/test/lib/a.dart');
- var b = convertPath('/test/lib/b.dart');
-
- String aUriStr = 'package:test/a.dart';
- String bUriStr = 'package:test/b.dart';
-
- newFile(a, content: r'''
-part 'b.dart';
-
-class A {}
-''');
-
- newFile(b, content: r'''
-part of 'a.dart';
-
-class B {}
-''');
-
- // Prepare the store with package:test/test.dart URI.
- var store = await createAnalysisDriver().test.getSummaryStore(a);
-
- // package:test/test.dart is in the store.
- expect(store.unlinkedMap.keys, contains(aUriStr));
- expect(store.unlinkedMap.keys, contains(bUriStr));
- expect(store.linkedMap.keys, contains(aUriStr));
- expect(store.linkedMap.keys, isNot(contains(bUriStr)));
-
- // Remove the files from the file system.
- deleteFile(a);
- deleteFile(b);
-
- // We can resynthesize the library from the store.
- var driver = createAnalysisDriver(externalSummaries: store);
-
- // Ask by URI, so we get the "external" FileState.
- var aUri = Uri.parse(aUriStr);
- var aFile = driver.fsState.getFileForUri(aUri);
- expect(aFile.uri, aUri);
- expect(aFile.path, isNull);
-
- // We still can resynthesize the library.
- // The URI is known to be external, so we don't talk to the file.
- var library = await driver.getLibraryByUri(aUriStr);
- expect(library.getType('A'), isNotNull);
- expect(library.getType('B'), isNotNull);
-
- // It is an error to ask for a library when we know that it is a part.
- expect(() async {
- await driver.getLibraryByUri(bUriStr);
- }, throwsArgumentError);
- }
-
- test_getLibraryByUri_sdk_analyze() async {
- LibraryElement coreLibrary = await driver.getLibraryByUri('dart:core');
- expect(coreLibrary, isNotNull);
- expect(coreLibrary.getType('Object'), isNotNull);
- expect(coreLibrary.getType('int'), isNotNull);
- }
-
- test_getLibraryByUri_sdk_resynthesize() async {
- String corePath = sdk.mapDartUri('dart:core').fullName;
- String asyncPath = sdk.mapDartUri('dart:async').fullName;
- var sdkStore = await createAnalysisDriver().test.getSummaryStore(corePath);
-
- // There are dart:core and dart:async in the store.
- expect(sdkStore.unlinkedMap.keys, contains('dart:core'));
- expect(sdkStore.unlinkedMap.keys, contains('dart:async'));
- expect(sdkStore.linkedMap.keys, contains('dart:core'));
- expect(sdkStore.linkedMap.keys, contains('dart:async'));
-
- // Remove dart:core and dart:async.
- // So, the new driver below cannot parse and summarize them.
- deleteFile(corePath);
- deleteFile(asyncPath);
-
- // We still get get dart:core library element.
- AnalysisDriver driver = createAnalysisDriver(externalSummaries: sdkStore);
- LibraryElement coreLibrary = await driver.getLibraryByUri('dart:core');
- expect(coreLibrary, isNotNull);
- expect(coreLibrary.getType('Object'), isNotNull);
- }
-
- test_getParsedLibrary_external() async {
- var a1 = convertPath('/aaa/lib/a1.dart');
- var a2 = convertPath('/aaa/lib/a2.dart');
-
- var a1UriStr = 'package:aaa/a1.dart';
- var a2UriStr = 'package:aaa/a2.dart';
-
- newFile(a1, content: "part 'a2.dart'; class A {}");
- newFile(a2, content: "part of 'a1.dart';");
-
- // Build the store with the library.
- var store = await createAnalysisDriver().test.getSummaryStore(a1);
- expect(store.unlinkedMap.keys, contains(a1UriStr));
- expect(store.unlinkedMap.keys, contains(a2UriStr));
- expect(store.linkedMap.keys, contains(a1UriStr));
-
- var driver = createAnalysisDriver(externalSummaries: store);
- var libraryElement = await driver.getLibraryByUri(a1UriStr);
- var classA = libraryElement.library.getType('A');
-
- var parsedLibrary = driver.getParsedLibrary(a1);
- expect(parsedLibrary, isNotNull);
- expect(parsedLibrary.state, ResultState.NOT_A_FILE);
- expect(() {
- parsedLibrary.getElementDeclaration(classA);
- }, throwsStateError);
-
- // It is an error to ask for a library when we know that it is a part.
- expect(() {
- driver.getParsedLibrary(a2);
- }, throwsArgumentError);
- }
-
- test_getParsedLibraryByUri_external() async {
- var a1 = convertPath('/aaa/lib/a1.dart');
- var a2 = convertPath('/aaa/lib/a2.dart');
-
- var a1UriStr = 'package:aaa/a1.dart';
- var a2UriStr = 'package:aaa/a2.dart';
-
- var a1Uri = Uri.parse(a1UriStr);
- var a2Uri = Uri.parse(a2UriStr);
-
- newFile(a1, content: "part 'a2.dart'; class A {}");
- newFile(a2, content: "part of 'a1.dart';");
-
- // Build the store with the library.
- var store = await createAnalysisDriver().test.getSummaryStore(a1);
- expect(store.unlinkedMap.keys, contains(a1UriStr));
- expect(store.unlinkedMap.keys, contains(a2UriStr));
- expect(store.linkedMap.keys, contains(a1UriStr));
-
- var driver = createAnalysisDriver(externalSummaries: store);
- var libraryElement = await driver.getLibraryByUri(a1UriStr);
- var classA = libraryElement.library.getType('A');
-
- {
- var parsedLibrary = driver.getParsedLibraryByUri(a1Uri);
- expect(parsedLibrary, isNotNull);
- expect(parsedLibrary.state, ResultState.NOT_A_FILE);
- expect(() {
- parsedLibrary.getElementDeclaration(classA);
- }, throwsStateError);
- }
-
- // We can also get the result from the session.
- {
- var session = driver.currentSession;
- var parsedLibrary = session.getParsedLibraryByElement(libraryElement);
- expect(parsedLibrary, isNotNull);
- expect(parsedLibrary.state, ResultState.NOT_A_FILE);
- expect(() {
- parsedLibrary.getElementDeclaration(classA);
- }, throwsStateError);
- }
-
- // It is an error to ask for a library when we know that it is a part.
- expect(() {
- driver.getParsedLibraryByUri(a2Uri);
- }, throwsArgumentError);
- }
-
- test_getResolvedLibrary_external() async {
- var a1 = convertPath('/aaa/lib/a1.dart');
- var a2 = convertPath('/aaa/lib/a2.dart');
-
- var a1UriStr = 'package:aaa/a1.dart';
- var a2UriStr = 'package:aaa/a2.dart';
-
- newFile(a1, content: "part 'a2.dart'; class A {}");
- newFile(a2, content: "part of 'a1.dart';");
-
- // Build the store with the library.
- var store = await createAnalysisDriver().test.getSummaryStore(a1);
- expect(store.unlinkedMap.keys, contains(a1UriStr));
- expect(store.unlinkedMap.keys, contains(a2UriStr));
- expect(store.linkedMap.keys, contains(a1UriStr));
-
- var driver = createAnalysisDriver(externalSummaries: store);
- var libraryElement = await driver.getLibraryByUri(a1UriStr);
- var classA = libraryElement.library.getType('A');
-
- var resolvedLibrary = await driver.getResolvedLibrary(a1);
- expect(resolvedLibrary, isNotNull);
- expect(resolvedLibrary.state, ResultState.NOT_A_FILE);
- expect(() {
- resolvedLibrary.getElementDeclaration(classA);
- }, throwsStateError);
-
- // It is an error to ask for a library when we know that it is a part.
- expect(() async {
- await driver.getResolvedLibrary(a2);
- }, throwsArgumentError);
- }
-
- test_getResolvedLibraryByUri_external() async {
- var a1 = convertPath('/aaa/lib/a1.dart');
- var a2 = convertPath('/aaa/lib/a2.dart');
-
- var a1UriStr = 'package:aaa/a1.dart';
- var a2UriStr = 'package:aaa/a2.dart';
-
- var a1Uri = Uri.parse(a1UriStr);
- var a2Uri = Uri.parse(a2UriStr);
-
- newFile(a1, content: "part 'a2.dart'; class A {}");
- newFile(a2, content: "part of 'a1.dart';");
-
- // Build the store with the library.
- var store = await createAnalysisDriver().test.getSummaryStore(a1);
- expect(store.unlinkedMap.keys, contains(a1UriStr));
- expect(store.unlinkedMap.keys, contains(a2UriStr));
- expect(store.linkedMap.keys, contains(a1UriStr));
-
- var driver = createAnalysisDriver(externalSummaries: store);
- var libraryElement = await driver.getLibraryByUri(a1UriStr);
- var classA = libraryElement.library.getType('A');
-
- {
- var resolvedLibrary = await driver.getResolvedLibraryByUri(a1Uri);
- expect(resolvedLibrary, isNotNull);
- expect(resolvedLibrary.state, ResultState.NOT_A_FILE);
- expect(() {
- resolvedLibrary.getElementDeclaration(classA);
- }, throwsStateError);
- }
-
- // We can also get the result from the session.
- {
- var session = driver.currentSession;
- var resolvedLibrary =
- await session.getResolvedLibraryByElement(libraryElement);
- expect(resolvedLibrary, isNotNull);
- expect(resolvedLibrary.state, ResultState.NOT_A_FILE);
- expect(() {
- resolvedLibrary.getElementDeclaration(classA);
- }, throwsStateError);
- }
-
- // It is an error to ask for a library when we know that it is a part.
- expect(() async {
- await driver.getResolvedLibraryByUri(a2Uri);
- }, throwsArgumentError);
- }
-
- test_isLibraryByUri() async {
- var a1 = '/aaa/lib/a1.dart';
- var a2 = '/aaa/lib/a2.dart';
- var b1 = '/bbb/lib/b1.dart';
- var b2 = '/bbb/lib/b2.dart';
-
- String a1UriStr = 'package:aaa/a1.dart';
- String a2UriStr = 'package:aaa/a2.dart';
- String b1UriStr = 'package:bbb/b1.dart';
- String b2UriStr = 'package:bbb/b2.dart';
-
- newFile(a1, content: "part 'a2.dart';");
- newFile(a2, content: "part of 'a1.dart';");
- newFile(b1, content: "part 'b2.dart';");
- newFile(b2, content: "part of 'b1.dart';");
-
- // Build the store with the library.
- var store =
- await createAnalysisDriver().test.getSummaryStore(convertPath(a1));
- expect(store.unlinkedMap.keys, contains(a1UriStr));
- expect(store.unlinkedMap.keys, contains(a2UriStr));
- expect(store.linkedMap.keys, contains(a1UriStr));
-
- // Remove the stored files from the file system.
- deleteFile(a1);
- deleteFile(a2);
-
- // We can ask isLibraryByUri() for both external and local units.
- AnalysisDriver driver = createAnalysisDriver(externalSummaries: store);
- expect(driver.isLibraryByUri(Uri.parse(a1UriStr)), isTrue);
- expect(driver.isLibraryByUri(Uri.parse(a2UriStr)), isFalse);
- expect(driver.isLibraryByUri(Uri.parse(b1UriStr)), isTrue);
- expect(driver.isLibraryByUri(Uri.parse(b2UriStr)), isFalse);
- }
-}
-
@reflectiveTest
class AnalysisDriverTest extends BaseAnalysisDriverTest {
test_addedFiles() async {
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index af25455..c0c347e 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -7,7 +7,6 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/library_graph.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
@@ -119,13 +118,8 @@
expect(_excludeSdk(file.directReferencedFiles), isEmpty);
expect(file.isPart, isFalse);
expect(file.library, isNull);
- if (AnalysisDriver.useSummary2) {
- expect(file.unlinked2, isNotNull);
- expect(file.unlinked2.exports, isEmpty);
- } else {
- expect(file.unlinked, isNotNull);
- expect(file.unlinked.classes, isEmpty);
- }
+ expect(file.unlinked2, isNotNull);
+ expect(file.unlinked2.exports, isEmpty);
}
test_getFileForPath_emptyUri() {
@@ -215,13 +209,7 @@
expect(file.isPart, isFalse);
expect(file.library, isNull);
- if (AnalysisDriver.useSummary2) {
- expect(file.unlinked2, isNotNull);
- } else {
- expect(file.unlinked, isNotNull);
- expect(file.unlinked.classes, hasLength(1));
- expect(file.unlinked.classes[0].name, 'A1');
- }
+ expect(file.unlinked2, isNotNull);
expect(_excludeSdk(file.importedFiles), hasLength(2));
expect(file.importedFiles[0].path, a2);
@@ -292,13 +280,7 @@
expect(file_a2.path, a2);
expect(file_a2.uri, Uri.parse('package:aaa/a2.dart'));
- if (AnalysisDriver.useSummary2) {
- expect(file_a2.unlinked2, isNotNull);
- } else {
- expect(file_a2.unlinked, isNotNull);
- expect(file_a2.unlinked.classes, hasLength(1));
- expect(file_a2.unlinked.classes[0].name, 'A2');
- }
+ expect(file_a2.unlinked2, isNotNull);
expect(_excludeSdk(file_a2.importedFiles), isEmpty);
expect(file_a2.exportedFiles, isEmpty);
@@ -515,11 +497,7 @@
class A {}
''');
FileState file = fileSystemState.getFileForPath(path);
- if (AnalysisDriver.useSummary2) {
- expect(file.definedTopLevelNames, contains('A'));
- } else {
- expect(file.unlinked.classes[0].name, 'A');
- }
+ expect(file.definedTopLevelNames, contains('A'));
List<int> signature = file.apiSignature;
// Update the resource and refresh the file state.
@@ -529,11 +507,7 @@
bool apiSignatureChanged = file.refresh();
expect(apiSignatureChanged, isTrue);
- if (AnalysisDriver.useSummary2) {
- expect(file.definedTopLevelNames, contains('B'));
- } else {
- expect(file.unlinked.classes[0].name, 'B');
- }
+ expect(file.definedTopLevelNames, contains('B'));
expect(file.apiSignature, isNot(signature));
}
@@ -569,22 +543,14 @@
// Get the file, prepare unlinked.
FileState file = fileSystemState.getFileForPath(path);
- if (AnalysisDriver.useSummary2) {
- expect(file.unlinked2, isNotNull);
- } else {
- expect(file.unlinked, isNotNull);
- }
+ expect(file.unlinked2, isNotNull);
// Make the unlinked unit in the byte store zero-length, damaged.
byteStore.put(file.test.unlinkedKey, <int>[]);
// Refresh should not fail, zero bytes in the store are ignored.
file.refresh();
- if (AnalysisDriver.useSummary2) {
- expect(file.unlinked2, isNotNull);
- } else {
- expect(file.unlinked, isNotNull);
- }
+ expect(file.unlinked2, isNotNull);
}
test_subtypedNames() {
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index f0489be..9d5b46d 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -959,7 +959,9 @@
);
classElement.fields = <FieldElement>[field];
expect(field == field, isTrue);
+ // ignore: unrelated_type_equality_checks
expect(field == field.getter, isFalse);
+ // ignore: unrelated_type_equality_checks
expect(field == field.setter, isFalse);
expect(field.getter == field.setter, isFalse);
}
@@ -1077,6 +1079,7 @@
void test_equals_notEqual_notLocation() {
ElementLocationImpl first = new ElementLocationImpl.con2("a;b;c");
+ // ignore: unrelated_type_equality_checks
expect(first == "a;b;d", isFalse);
}
@@ -3529,7 +3532,9 @@
PropertyAccessorElementHandle handle =
new PropertyAccessorElementHandle(null, element.location);
expect(element.hashCode, handle.hashCode);
+ // ignore: unrelated_type_equality_checks
expect(element == handle, isTrue);
+ // ignore: unrelated_type_equality_checks
expect(handle == element, isTrue);
}
@@ -3544,7 +3549,9 @@
PropertyAccessorElementHandle handle =
new PropertyAccessorElementHandle(null, element.location);
expect(element.hashCode, handle.hashCode);
+ // ignore: unrelated_type_equality_checks
expect(element == handle, isTrue);
+ // ignore: unrelated_type_equality_checks
expect(handle == element, isTrue);
}
}
diff --git a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
index 17352e4..c364469 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
@@ -20,6 +21,7 @@
defineReflectiveTests(SubstituteFromPairsTest);
defineReflectiveTests(SubstituteFromUpperAndLowerBoundsTest);
defineReflectiveTests(SubstituteTest);
+ defineReflectiveTests(SubstituteWithNullabilityTest);
});
}
@@ -276,19 +278,57 @@
var result = substitute(type, substitution);
expect(result, same(type));
}
+}
- void _assertSubstitution(
- DartType type,
- Map<TypeParameterElement, DartType> substitution,
- String expected,
- ) {
- var result = substitute(type, substitution);
- assertElementTypeString(result, expected);
+@reflectiveTest
+class SubstituteWithNullabilityTest extends _Base {
+ SubstituteWithNullabilityTest() : super(useNnbd: true);
+
+ test_interface_none() async {
+ // class A<T> {}
+ var T = typeParameter('T');
+ var A = class_(name: 'A', typeParameters: [T]);
+
+ var U = typeParameter('U');
+ var type = interfaceType(A,
+ typeArguments: [typeParameterType(U)],
+ nullabilitySuffix: NullabilitySuffix.none);
+ _assertSubstitution(type, {U: intType}, 'A<int>');
+ }
+
+ test_interface_question() async {
+ // class A<T> {}
+ var T = typeParameter('T');
+ var A = class_(name: 'A', typeParameters: [T]);
+
+ var U = typeParameter('U');
+ var type = interfaceType(A,
+ typeArguments: [typeParameterType(U)],
+ nullabilitySuffix: NullabilitySuffix.question);
+ _assertSubstitution(type, {U: intType}, 'A<int>?');
+ }
+
+ test_interface_star() async {
+ // class A<T> {}
+ var T = typeParameter('T');
+ var A = class_(name: 'A', typeParameters: [T]);
+
+ var U = typeParameter('U');
+ var type = interfaceType(A,
+ typeArguments: [typeParameterType(U)],
+ nullabilitySuffix: NullabilitySuffix.star);
+ _assertSubstitution(type, {U: intType}, 'A<int>*');
}
}
class _Base with ElementsTypesMixin {
- final typeProvider = TestTypeProvider();
+ final TestTypeProvider typeProvider;
+
+ final bool useNnbd;
+
+ _Base({this.useNnbd = false})
+ : typeProvider = TestTypeProvider(null, null,
+ useNnbd ? NullabilitySuffix.none : NullabilitySuffix.question);
InterfaceType get boolType => typeProvider.boolType;
@@ -297,11 +337,20 @@
InterfaceType get intType => typeProvider.intType;
/// Whether `DartType.toString()` with nullability should be asked.
- bool get typeToStringWithNullability => false;
+ bool get typeToStringWithNullability => useNnbd;
void assertElementTypeString(DartType type, String expected) {
TypeImpl typeImpl = type;
expect(typeImpl.toString(withNullability: typeToStringWithNullability),
expected);
}
+
+ void _assertSubstitution(
+ DartType type,
+ Map<TypeParameterElement, DartType> substitution,
+ String expected,
+ ) {
+ var result = substitute(type, substitution);
+ assertElementTypeString(result, expected);
+ }
}
diff --git a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
index 5fbe1d7..cdb8590 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -3,11 +3,8 @@
// 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/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'driver_resolution.dart';
@@ -164,12 +161,8 @@
}
ImportElement _importOfA() {
- if (AnalysisDriver.useSummary2) {
- var importOfB = findElement.import('package:test/b.dart');
- return importOfB.importedLibrary.imports[0];
- } else {
- return null;
- }
+ var importOfB = findElement.import('package:test/b.dart');
+ return importOfB.importedLibrary.imports[0];
}
Future<InstanceCreationExpression> _resolveImplicitConst(String expr,
@@ -207,10 +200,6 @@
var v = vg.variable as ConstVariableElement;
InstanceCreationExpression creation = v.constantInitializer;
- if (!AnalysisDriver.useSummary2) {
- expect(creation.keyword.keyword, Keyword.CONST);
- }
-
return creation;
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart b/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart
index 263cebb..f8fe9c5 100644
--- a/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart
@@ -60,6 +60,38 @@
''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 12, 9)]);
}
+ test_classInstanceMethod_overriding() async {
+ await assertNoErrorsInCode(r'''
+class C {
+ int f() => 7;
+}
+
+class D extends C {
+ f() => 9;
+}
+
+class E implements C {
+ f() => 9;
+}
+
+class F with C {
+ f() => 9;
+}
+
+mixin M on C {
+ f() => 9;
+}
+
+mixin N {
+ int g() => 7;
+}
+
+class G with N {
+ g() => 9;
+}
+''');
+ }
+
test_classInstanceMethod_withReturnType() async {
await assertNoErrorsInCode(r'''
class C {
@@ -77,11 +109,11 @@
}
test_classInstanceSetter() async {
- await assertErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
class C {
set f(int x) => print(x);
}
-''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 12, 25)]);
+''');
}
test_classStaticMethod() async {
@@ -124,6 +156,22 @@
''');
}
+ test_genericFunctionType() async {
+ await assertErrorsInCode(r'''
+Function(int) f = (int n) {
+ print(n);
+};
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 0, 13)]);
+ }
+
+ test_genericFunctionType_withReturnType() async {
+ await assertNoErrorsInCode(r'''
+void Function(int) f = (int n) {
+ print(n);
+};
+''');
+ }
+
test_localFunction() async {
await assertNoErrorsInCode(r'''
class C {
@@ -169,4 +217,28 @@
dynamic f() => 7;
''');
}
+
+ test_typedef_classic() async {
+ await assertErrorsInCode(r'''
+typedef Callback(int i);
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 0, 24)]);
+ }
+
+ test_typedef_classic_withReturnType() async {
+ await assertNoErrorsInCode(r'''
+typedef void Callback(int i);
+''');
+ }
+
+ test_typedef_modern() async {
+ await assertErrorsInCode(r'''
+typedef Callback = Function(int i);
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 0, 35)]);
+ }
+
+ test_typedef_modern_withReturnType() async {
+ await assertNoErrorsInCode(r'''
+typedef Callback = void Function(int i);
+''');
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart b/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
index bbc42ec..de01ca4 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/test_utilities/package_mixin.dart';
@@ -165,10 +164,15 @@
assertTestErrorsWithCodes([HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS]);
}
+ @FailingTest(reason: r'''
+MISSING_REQUIRED_PARAM cannot be reported here with summary2, because
+the return type of `C.m` is a structural FunctionType, which does
+not know its elements, and does not know that there was a parameter
+marked `@required`. There is exactly one such typedef in Flutter.
+''')
test_typedef_functionParam() async {
addMetaPackage();
- try {
- await assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
String test(C c) => c.m()();
@@ -179,17 +183,8 @@
F m() => ({@required String x}) => null;
}
''', [
- error(HintCode.MISSING_REQUIRED_PARAM, 54, 7),
- ]);
- } catch (_) {
- // MISSING_REQUIRED_PARAM cannot be reported here with summary2, because
- // the return type of `C.m` is a structural FunctionType, which does
- // not know its elements, and does not know that there was a parameter
- // marked `@required`. There is exactly one such typedef in Flutter.
- if (!AnalysisDriver.useSummary2) {
- rethrow;
- }
- }
+ error(HintCode.MISSING_REQUIRED_PARAM, 54, 7),
+ ]);
}
/// Resolve the test file at [path].
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/forEach_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/for_each_statement_test.dart
similarity index 100%
rename from pkg/analyzer/test/src/fasta/recovery/partial_code/forEach_statement_test.dart
rename to pkg/analyzer/test/src/fasta/recovery/partial_code/for_each_statement_test.dart
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/test_all.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/test_all.dart
index 0b20072..06c1d0f 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/test_all.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/test_all.dart
@@ -15,7 +15,7 @@
import 'export_directive_test.dart' as export_directive;
import 'extension_declaration_test.dart' as extension_declaration;
import 'field_declaration_test.dart' as field_declaration;
-import 'forEach_statement_test.dart' as forEach_statement;
+import 'for_each_statement_test.dart' as for_each_statement;
import 'for_statement_test.dart' as for_statement;
import 'if_statement_test.dart' as if_statement;
import 'import_directive_test.dart' as import_directive;
@@ -50,7 +50,7 @@
extension_declaration.main();
field_declaration.main();
for_statement.main();
- forEach_statement.main();
+ for_each_statement.main();
if_statement.main();
import_directive.main();
index_expression.main();
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index d0ffbb9..6831be1 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -15,6 +15,8 @@
import 'package:analyzer/src/summary/idl.dart';
import 'package:test/test.dart';
+import 'resolved_ast_printer.dart';
+
/**
* Set this path to automatically replace expectations in invocations of
* [checkElementText] with the new actual texts.
@@ -53,19 +55,24 @@
* taking into account the specified 'withX' options. Then compare the
* actual text with the given [expected] one.
*/
-void checkElementText(LibraryElement library, String expected,
- {bool withCodeRanges: false,
- bool withConstElements: true,
- bool withExportScope: false,
- bool withOffsets: false,
- bool withSyntheticAccessors: false,
- bool withSyntheticFields: false,
- bool withTypes: false,
- bool annotateNullability: false}) {
+void checkElementText(
+ LibraryElement library,
+ String expected, {
+ bool withCodeRanges: false,
+ bool withConstElements: true,
+ bool withExportScope: false,
+ bool withFullyResolvedAst: false,
+ bool withOffsets: false,
+ bool withSyntheticAccessors: false,
+ bool withSyntheticFields: false,
+ bool withTypes: false,
+ bool annotateNullability: false,
+}) {
var writer = new _ElementWriter(
withCodeRanges: withCodeRanges,
withConstElements: withConstElements,
withExportScope: withExportScope,
+ withFullyResolvedAst: withFullyResolvedAst,
withOffsets: withOffsets,
withSyntheticAccessors: withSyntheticAccessors,
withSyntheticFields: withSyntheticFields,
@@ -133,6 +140,7 @@
class _ElementWriter {
final bool withCodeRanges;
final bool withExportScope;
+ final bool withFullyResolvedAst;
final bool withOffsets;
final bool withConstElements;
final bool withSyntheticAccessors;
@@ -145,6 +153,7 @@
{this.withCodeRanges,
this.withConstElements: true,
this.withExportScope: false,
+ this.withFullyResolvedAst: false,
this.withOffsets: false,
this.withSyntheticAccessors: false,
this.withSyntheticFields: false,
@@ -531,7 +540,14 @@
}
}
- void writeNode(AstNode e, [Expression enclosing]) {
+ void writeNode(AstNode e, {String indent: '', Expression enclosing}) {
+ if (withFullyResolvedAst) {
+ buffer.writeln();
+ var printer = ResolvedAstPrinter(buffer, indent);
+ e.accept(printer);
+ return;
+ }
+
bool needsParenthesis = e is Expression &&
enclosing != null &&
e.precedence < enclosing.precedence;
@@ -568,11 +584,11 @@
}
buffer.write(')');
} else if (e is BinaryExpression) {
- writeNode(e.leftOperand, e);
+ writeNode(e.leftOperand, enclosing: e);
buffer.write(' ');
buffer.write(e.operator.lexeme);
buffer.write(' ');
- writeNode(e.rightOperand, e);
+ writeNode(e.rightOperand, enclosing: e);
} else if (e is BooleanLiteral) {
buffer.write(e.value);
} else if (e is ConditionalExpression) {
@@ -673,16 +689,16 @@
} else if (e is NullLiteral) {
buffer.write('null');
} else if (e is ParenthesizedExpression) {
- writeNode(e.expression, e);
+ writeNode(e.expression, enclosing: e);
} else if (e is PrefixExpression) {
buffer.write(e.operator.lexeme);
- writeNode(e.operand, e);
+ writeNode(e.operand, enclosing: e);
} else if (e is PrefixedIdentifier) {
writeNode(e.prefix);
buffer.write('.');
writeNode(e.identifier);
} else if (e is PropertyAccess) {
- writeNode(e.target, e);
+ writeNode(e.target, enclosing: e);
buffer.write('.');
writeNode(e.propertyName);
} else if (e is RedirectingConstructorInvocation) {
@@ -949,7 +965,13 @@
Expression initializer = (e as ConstVariableElement).constantInitializer;
if (initializer != null) {
buffer.write(' = ');
- writeNode(initializer);
+ writeNode(
+ initializer,
+ indent: ' ' * (e is FieldElement ? 4 : 2),
+ );
+ if (withFullyResolvedAst) {
+ return;
+ }
}
}
diff --git a/pkg/analyzer/test/src/summary/expr_builder_test.dart b/pkg/analyzer/test/src/summary/expr_builder_test.dart
deleted file mode 100644
index c73bee8..0000000
--- a/pkg/analyzer/test/src/summary/expr_builder_test.dart
+++ /dev/null
@@ -1,895 +0,0 @@
-// Copyright (c) 2018, 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/analysis/features.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/scanner/reader.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/string_source.dart';
-import 'package:analyzer/src/summary/expr_builder.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/resynthesize.dart';
-import 'package:analyzer/src/summary/summarize_const_expr.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'resynthesize_common.dart';
-import 'test_strategies.dart';
-
-main() {
- if (AnalysisDriver.useSummary2) {
- test('fake', () {});
- return;
- }
- defineReflectiveSuite(() {
- defineReflectiveTests(ExprBuilderTest);
- defineReflectiveTests(ExprBuilderWithConstantUpdateTest);
- defineReflectiveTests(TokensToStringTest);
- });
-}
-
-@reflectiveTest
-class ExprBuilderTest extends ResynthesizeTestStrategyTwoPhase
- with ExprBuilderTestCases, ExprBuilderTestHelpers {}
-
-/// Mixin containing test cases exercising the [ExprBuilder]. Intended to be
-/// applied to a class implementing [ResynthesizeTestStrategy], along with the
-/// mixin [ExprBuilderTestHelpers].
-mixin ExprBuilderTestCases implements ExprBuilderTestHelpers {
- void test_add() {
- checkSimpleExpression('0 + 1');
- }
-
- void test_and() {
- checkSimpleExpression('false && true');
- }
-
- void test_assignToIndex() {
- checkSimpleExpression('items[0] = 1',
- extraDeclarations: 'var items = [0, 1, 2]');
- }
-
- void test_assignToIndex_compound_multiply() {
- checkSimpleExpression('items[0] *= 1',
- extraDeclarations: 'var items = [0, 1, 2]');
- }
-
- void test_assignToProperty() {
- checkSimpleExpression('new A().f = 1', extraDeclarations: r'''
-class A {
- int f = 0;
-}
-''');
- }
-
- void test_assignToProperty_compound_plus() {
- checkSimpleExpression('new A().f += 1', extraDeclarations: r'''
-class A {
- int f = 0;
-}
-''');
- }
-
- void test_assignToProperty_compound_suffixIncrement() {
- checkSimpleExpression('new A().f++', extraDeclarations: r'''
-class A {
- int f = 0;
-}
-''');
- }
-
- void test_assignToRef() {
- checkSimpleExpression('y = 0', extraDeclarations: 'var y;');
- }
-
- void test_await() {
- checkSimpleExpression('() async => await 0');
- }
-
- void test_bitAnd() {
- checkSimpleExpression('0 & 1');
- }
-
- void test_bitOr() {
- checkSimpleExpression('0 | 1');
- }
-
- void test_bitShiftLeft() {
- checkSimpleExpression('0 << 1');
- }
-
- void test_bitShiftRight() {
- checkSimpleExpression('0 >> 1');
- }
-
- void test_bitXor() {
- checkSimpleExpression('0 ^ 1');
- }
-
- void test_cascade() {
- // Cascade sections don't matter for type inference.
- // The type of a cascade is the type of the target.
- checkSimpleExpression('new C()..f1 = 1..m(2, 3)..f2 = 4',
- extraDeclarations: r'''
-class C {
- int f1;
- int f2;
- int m(int a, int b) => 0;
-}
-''',
- expectedText: 'new C()');
- }
-
- void test_closure_invalid_const() {
- checkInvalidConst('() => 0');
- }
-
- void test_complement() {
- checkSimpleExpression('~0');
- }
-
- void test_compoundAssignment_bitAnd() {
- checkCompoundAssignment('y &= 0');
- }
-
- void test_compoundAssignment_bitOr() {
- checkCompoundAssignment('y |= 0');
- }
-
- void test_compoundAssignment_bitXor() {
- checkCompoundAssignment('y ^= 0');
- }
-
- void test_compoundAssignment_divide() {
- checkCompoundAssignment('y /= 0');
- }
-
- void test_compoundAssignment_floorDivide() {
- checkCompoundAssignment('y ~/= 0');
- }
-
- void test_compoundAssignment_ifNull() {
- checkCompoundAssignment('y ??= 0');
- }
-
- void test_compoundAssignment_minus() {
- checkCompoundAssignment('y -= 0');
- }
-
- void test_compoundAssignment_modulo() {
- checkCompoundAssignment('y %= 0');
- }
-
- void test_compoundAssignment_multiply() {
- checkCompoundAssignment('y *= 0');
- }
-
- void test_compoundAssignment_plus() {
- checkCompoundAssignment('y += 0');
- }
-
- void test_compoundAssignment_postfixDecrement() {
- checkCompoundAssignment('y--');
- }
-
- void test_compoundAssignment_postfixIncrement() {
- checkCompoundAssignment('y++');
- }
-
- void test_compoundAssignment_prefixDecrement() {
- checkCompoundAssignment('--y');
- }
-
- void test_compoundAssignment_prefixIncrement() {
- checkCompoundAssignment('++y');
- }
-
- void test_compoundAssignment_shiftLeft() {
- checkCompoundAssignment('y <<= 0');
- }
-
- void test_compoundAssignment_shiftRight() {
- checkCompoundAssignment('y >>= 0');
- }
-
- void test_concatenate() {
- var expr = buildTopLevelVariable(r'var x = "${0}";') as StringInterpolation;
- expect(expr.elements, hasLength(3));
- expect((expr.elements[0] as InterpolationString).value, '');
- expect((expr.elements[1] as InterpolationExpression).expression.toString(),
- '0');
- expect((expr.elements[2] as InterpolationString).value, '');
- }
-
- void test_conditional() {
- checkSimpleExpression('false ? 0 : 1');
- }
-
- void test_divide() {
- checkSimpleExpression('0 / 1');
- }
-
- void test_equal() {
- checkSimpleExpression('0 == 1');
- }
-
- void test_extractIndex() {
- checkSimpleExpression('items[0]',
- extraDeclarations: 'var items = [0, 1, 2]');
- }
-
- void test_extractProperty() {
- checkSimpleExpression("'x'.length");
- }
-
- void test_floorDivide() {
- checkSimpleExpression('0 ~/ 1');
- }
-
- void test_greater() {
- checkSimpleExpression('0 > 1');
- }
-
- void test_greaterEqual() {
- checkSimpleExpression('0 >= 1');
- }
-
- void test_ifNull() {
- checkSimpleExpression('0 ?? 1');
- }
-
- void test_invokeConstructor_const() {
- checkSimpleExpression('const C()',
- extraDeclarations: '''
-class C {
- const C();
-}
-''',
- requireValidConst: true);
- }
-
- void test_invokeConstructor_generic_hasTypeArguments() {
- checkSimpleExpression('new Map<int, List<String>>()');
- }
-
- void test_invokeConstructor_generic_noTypeArguments() {
- checkSimpleExpression('new Map()');
- }
-
- void test_invokeMethod() {
- checkSimpleExpression('new C().foo(1, 2)', extraDeclarations: r'''
-class C {
- int foo(int a, int b) => 0;
-}
-''');
- }
-
- void test_invokeMethod_namedArguments() {
- checkSimpleExpression('new C().foo(a: 1, c: 3)', extraDeclarations: r'''
-class C {
- int foo({int a, int b, int c}) => 0;
-}
-''');
- }
-
- void test_invokeMethod_typeArguments() {
- checkSimpleExpression('new C().foo<int, double>(1, 2.3)',
- extraDeclarations: r'''
-class C {
- int foo<T, U>(T a, U b) => 0;
-}
-''',
- expectedText: 'new C().foo<int, double>()');
- }
-
- void test_invokeMethodRef() {
- checkSimpleExpression('identical(0, 0)');
- }
-
- void test_less() {
- checkSimpleExpression('0 < 1');
- }
-
- void test_lessEqual() {
- checkSimpleExpression('0 <= 1');
- }
-
- void test_list_for() {
- var sourceText = '[for (i = 0; i < 10; i++) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- checkSimpleExpression(sourceText,
- expectedText: expectedText, extraDeclarations: 'int i;');
- }
-
- void test_list_for_each_with_declaration_typed() {
- var sourceText = '[for (int i in const []) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- var list = checkSimpleExpression(sourceText, expectedText: expectedText)
- as ListLiteral;
- var forElement = list.elements[0] as ForElement;
- var loopParts = forElement.forLoopParts as ForEachPartsWithDeclaration;
- var iElement = loopParts.loopVariable.identifier.staticElement;
- var iRef = forElement.body as SimpleIdentifier;
- expect(iRef.staticElement, same(iElement));
- }
-
- void test_list_for_each_with_declaration_untyped() {
- var sourceText = '[for (var i in const []) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- var list = checkSimpleExpression(sourceText, expectedText: expectedText)
- as ListLiteral;
- var forElement = list.elements[0] as ForElement;
- var loopParts = forElement.forLoopParts as ForEachPartsWithDeclaration;
- var iElement = loopParts.loopVariable.identifier.staticElement;
- var iRef = forElement.body as SimpleIdentifier;
- expect(iRef.staticElement, same(iElement));
- }
-
- void test_list_for_each_with_identifier() {
- var sourceText = '[for (i in const []) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- checkSimpleExpression(sourceText,
- expectedText: expectedText, extraDeclarations: 'int i;');
- }
-
- void test_list_for_each_with_identifier_await() {
- var sourceText = '[await for (i in const []) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- checkSimpleExpression(sourceText,
- expectedText: expectedText, extraDeclarations: 'int i;');
- }
-
- void test_list_for_empty_condition() {
- var sourceText = '[for (i = 0;; i++) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- checkSimpleExpression(sourceText,
- expectedText: expectedText, extraDeclarations: 'int i;');
- }
-
- void test_list_for_empty_initializer() {
- var sourceText = '[for (; i < 10; i++) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- checkSimpleExpression(sourceText,
- expectedText: expectedText, extraDeclarations: 'int i;');
- }
-
- void test_list_for_two_updaters() {
- var sourceText = '[for (i = 0; i < 10; i++, j++) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- checkSimpleExpression(sourceText,
- expectedText: expectedText, extraDeclarations: 'int i; int j;');
- }
-
- void test_list_for_with_one_declaration_typed() {
- var sourceText = '[for (int i = 0; i < 10; i++) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- var list = checkSimpleExpression(sourceText, expectedText: expectedText)
- as ListLiteral;
- var forElement = list.elements[0] as ForElement;
- var loopParts = forElement.forLoopParts as ForPartsWithDeclarations;
- var iElement = loopParts.variables.variables[0].name.staticElement;
- var condition = loopParts.condition as BinaryExpression;
- var iRef1 = condition.leftOperand as SimpleIdentifier;
- expect(iRef1.staticElement, same(iElement));
- var updater = loopParts.updaters[0] as PostfixExpression;
- var iRef2 = updater.operand as SimpleIdentifier;
- expect(iRef2.staticElement, same(iElement));
- var iRef3 = forElement.body as SimpleIdentifier;
- expect(iRef3.staticElement, same(iElement));
- }
-
- void test_list_for_with_one_declaration_untyped() {
- var sourceText = '[for (var i = 0; i < 10; i++) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- var list = checkSimpleExpression(sourceText, expectedText: expectedText)
- as ListLiteral;
- var forElement = list.elements[0] as ForElement;
- var loopParts = forElement.forLoopParts as ForPartsWithDeclarations;
- var iElement = loopParts.variables.variables[0].name.staticElement;
- var condition = loopParts.condition as BinaryExpression;
- var iRef1 = condition.leftOperand as SimpleIdentifier;
- expect(iRef1.staticElement, same(iElement));
- var updater = loopParts.updaters[0] as PostfixExpression;
- var iRef2 = updater.operand as SimpleIdentifier;
- expect(iRef2.staticElement, same(iElement));
- var iRef3 = forElement.body as SimpleIdentifier;
- expect(iRef3.staticElement, same(iElement));
- }
-
- void test_list_for_with_two_declarations_untyped() {
- var sourceText = '[for (var i = 0, j = 0; i < 10; j++) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- var list = checkSimpleExpression(sourceText, expectedText: expectedText)
- as ListLiteral;
- var forElement = list.elements[0] as ForElement;
- var loopParts = forElement.forLoopParts as ForPartsWithDeclarations;
- var iElement = loopParts.variables.variables[0].name.staticElement;
- var jElement = loopParts.variables.variables[1].name.staticElement;
- var condition = loopParts.condition as BinaryExpression;
- var iRef1 = condition.leftOperand as SimpleIdentifier;
- expect(iRef1.staticElement, same(iElement));
- var updater = loopParts.updaters[0] as PostfixExpression;
- var jRef = updater.operand as SimpleIdentifier;
- expect(jRef.staticElement, same(jElement));
- var iRef2 = forElement.body as SimpleIdentifier;
- expect(iRef2.staticElement, same(iElement));
- }
-
- void test_list_for_with_uninitialized_declaration_untyped() {
- var sourceText = '[for (var i; i < 10; i++) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- var list = checkSimpleExpression(sourceText, expectedText: expectedText)
- as ListLiteral;
- var forElement = list.elements[0] as ForElement;
- var loopParts = forElement.forLoopParts as ForPartsWithDeclarations;
- var iElement = loopParts.variables.variables[0].name.staticElement;
- var condition = loopParts.condition as BinaryExpression;
- var iRef1 = condition.leftOperand as SimpleIdentifier;
- expect(iRef1.staticElement, same(iElement));
- var updater = loopParts.updaters[0] as PostfixExpression;
- var iRef2 = updater.operand as SimpleIdentifier;
- expect(iRef2.staticElement, same(iElement));
- var iRef3 = forElement.body as SimpleIdentifier;
- expect(iRef3.staticElement, same(iElement));
- }
-
- void test_list_for_zero_updaters() {
- var sourceText = '[for (i = 0; i < 10;) i]';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- checkSimpleExpression(sourceText,
- expectedText: expectedText, extraDeclarations: 'int i;');
- }
-
- void test_makeSymbol() {
- checkSimpleExpression('#foo');
- }
-
- void test_makeTypedList_const() {
- checkSimpleExpression('const <int>[]');
- }
-
- void test_makeTypedMap_const() {
- checkSimpleExpression('const <int, bool>{}');
- }
-
- void test_makeUntypedList_const() {
- checkSimpleExpression('const [0]');
- }
-
- void test_makeUntypedMap_const() {
- checkSimpleExpression('const {0 : false}');
- }
-
- void test_map_for() {
- var sourceText = '{1 : 2, for (i = 0; i < 10; i++) i : i}';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- checkSimpleExpression(sourceText,
- expectedText: expectedText, extraDeclarations: 'int i;');
- }
-
- void test_modulo() {
- checkSimpleExpression('0 % 1');
- }
-
- void test_multiply() {
- checkSimpleExpression('0 * 1');
- }
-
- void test_negate() {
- checkSimpleExpression('-1');
- }
-
- void test_not() {
- checkSimpleExpression('!true');
- }
-
- void test_notEqual() {
- checkSimpleExpression('0 != 1');
- }
-
- void test_or() {
- checkSimpleExpression('false || true');
- }
-
- void test_pushDouble() {
- checkSimpleExpression('0.5');
- }
-
- void test_pushFalse() {
- checkSimpleExpression('false');
- }
-
- void test_pushInt() {
- checkSimpleExpression('0');
- }
-
- void test_pushLocalFunctionReference() {
- checkSimpleExpression('() => 0');
- }
-
- void test_pushLocalFunctionReference_async() {
- checkSimpleExpression('() async => 0');
- }
-
- void test_pushLocalFunctionReference_block() {
- checkSimpleExpression('() {}');
- }
-
- void test_pushLocalFunctionReference_namedParam_untyped() {
- checkSimpleExpression('({x}) => 0');
- }
-
- @failingTest
- void test_pushLocalFunctionReference_nested() {
- var expr =
- checkSimpleExpression('(x) => (y) => x + y') as FunctionExpression;
- var outerFunctionElement = expr.declaredElement;
- var xElement = outerFunctionElement.parameters[0];
- var x = expr.parameters.parameters[0];
- expect(x.declaredElement, same(xElement));
- var outerBody = expr.body as ExpressionFunctionBody;
- var outerBodyExpr = outerBody.expression as FunctionExpression;
- var innerFunctionElement = outerBodyExpr.declaredElement;
- var yElement = innerFunctionElement.parameters[0];
- var y = outerBodyExpr.parameters.parameters[0];
- expect(y.declaredElement, same(yElement));
- var innerBody = outerBodyExpr.body as ExpressionFunctionBody;
- var innerBodyExpr = innerBody.expression as BinaryExpression;
- var xRef = innerBodyExpr.leftOperand as SimpleIdentifier;
- var yRef = innerBodyExpr.rightOperand as SimpleIdentifier;
- expect(xRef.staticElement, same(xElement));
- expect(yRef.staticElement, same(yElement));
- }
-
- @failingTest
- void test_pushLocalFunctionReference_paramReference() {
- var expr = checkSimpleExpression('(x, y) => x + y') as FunctionExpression;
- var localFunctionElement = expr.declaredElement;
- var xElement = localFunctionElement.parameters[0];
- var yElement = localFunctionElement.parameters[1];
- var x = expr.parameters.parameters[0];
- var y = expr.parameters.parameters[1];
- expect(x.declaredElement, same(xElement));
- expect(y.declaredElement, same(yElement));
- var body = expr.body as ExpressionFunctionBody;
- var bodyExpr = body.expression as BinaryExpression;
- var xRef = bodyExpr.leftOperand as SimpleIdentifier;
- var yRef = bodyExpr.rightOperand as SimpleIdentifier;
- expect(xRef.staticElement, same(xElement));
- expect(yRef.staticElement, same(yElement));
- }
-
- void test_pushLocalFunctionReference_positionalParam_untyped() {
- checkSimpleExpression('([x]) => 0');
- }
-
- void test_pushLocalFunctionReference_requiredParam_typed() {
- var expr = checkSimpleExpression('(int x) => 0', expectedText: '(x) => 0')
- as FunctionExpression;
- var functionElement = expr.declaredElement;
- var xElement = functionElement.parameters[0] as ParameterElementImpl;
- expect(xElement.type.toString(), 'int');
- }
-
- void test_pushLocalFunctionReference_requiredParam_untyped() {
- checkSimpleExpression('(x) => 0');
- }
-
- void test_pushLongInt() {
- checkSimpleExpression('4294967296');
- }
-
- void test_pushNull() {
- checkSimpleExpression('null');
- }
-
- void test_pushParameter() {
- checkConstructorInitializer('''
-class C {
- int x;
- const C(int p) : x = p;
-}
-''', 'p');
- }
-
- void test_pushReference() {
- checkSimpleExpression('int');
- }
-
- void test_pushReference_sequence() {
- checkSimpleExpression('a.b.f', extraDeclarations: r'''
-var a = new A();
-class A {
- B b = new B();
-}
-class B {
- int f = 0;
-}
-''');
- }
-
- void test_pushString() {
- checkSimpleExpression("'foo'");
- }
-
- void test_pushTrue() {
- checkSimpleExpression('true');
- }
-
- void test_set_for() {
- var sourceText = '{1, for (i = 0; i < 10; i++) i}';
- // Resynthesis inserts synthetic "const" tokens; work around that.
- var expectedText = 'const $sourceText';
- checkSimpleExpression(sourceText,
- expectedText: expectedText, extraDeclarations: 'int i;');
- }
-
- void test_subtract() {
- checkSimpleExpression('0 - 1');
- }
-
- void test_throwException() {
- checkSimpleExpression('throw 0');
- }
-
- void test_typeCast() {
- checkSimpleExpression('0 as num');
- }
-
- void test_typeCheck() {
- checkSimpleExpression('0 is num');
- }
-
- void test_typeCheck_negated() {
- checkSimpleExpression('0 is! num', expectedText: '!(0 is num)');
- }
-}
-
-/// Mixin containing helper methods for testing the [ExprBuilder]. Intended to
-/// be applied to a class implementing [ResynthesizeTestStrategy].
-mixin ExprBuilderTestHelpers implements ResynthesizeTestStrategy {
- Expression buildConstructorInitializer(String sourceText,
- {String className: 'C',
- String initializerName: 'x',
- bool requireValidConst: false}) {
- var resynthesizer = encodeSource(sourceText);
- var library = resynthesizer.getLibraryElement(testSource.uri.toString());
- var c = library.getType(className);
- var constructor = c.unnamedConstructor as ConstructorElementImpl;
- var serializedExecutable = constructor.serializedExecutable;
- var x = serializedExecutable.constantInitializers
- .singleWhere((i) => i.name == initializerName);
- return buildExpression(resynthesizer, constructor, x.expression,
- serializedExecutable.localFunctions,
- requireValidConst: requireValidConst);
- }
-
- Expression buildExpression(
- TestSummaryResynthesizer resynthesizer,
- ElementImpl context,
- UnlinkedExpr unlinkedExpr,
- List<UnlinkedExecutable> localFunctions,
- {bool requireValidConst: false}) {
- var library = resynthesizer.getLibraryElement(testSource.uri.toString());
- var unit = library.definingCompilationUnit as CompilationUnitElementImpl;
- var unitResynthesizerContext =
- unit.resynthesizerContext as SummaryResynthesizerContext;
- var unitResynthesizer = unitResynthesizerContext.unitResynthesizer;
- var exprBuilder = new ExprBuilder(unitResynthesizer, context, unlinkedExpr,
- requireValidConst: requireValidConst, localFunctions: localFunctions);
- return exprBuilder.build();
- }
-
- Expression buildTopLevelVariable(String sourceText,
- {String variableName: 'x', bool requireValidConst: false}) {
- var resynthesizer = encodeSource(sourceText);
- var library = resynthesizer.getLibraryElement(testSource.uri.toString());
- var unit = library.definingCompilationUnit as CompilationUnitElementImpl;
- TopLevelVariableElementImpl x =
- unit.topLevelVariables.singleWhere((e) => e.name == variableName);
- return buildExpression(
- resynthesizer,
- x,
- x.unlinkedVariableForTesting.initializer.bodyExpr,
- x.unlinkedVariableForTesting.initializer.localFunctions,
- requireValidConst: requireValidConst);
- }
-
- void checkCompoundAssignment(String exprText) {
- checkSimpleExpression(exprText, extraDeclarations: 'var y;');
- }
-
- void checkConstructorInitializer(String sourceText, String expectedText,
- {String className: 'C',
- String initializerName: 'x',
- bool requireValidConst: false}) {
- Expression expr = buildConstructorInitializer(sourceText,
- className: className,
- initializerName: initializerName,
- requireValidConst: requireValidConst);
- expect(expr.toString(), expectedText);
- }
-
- void checkInvalidConst(String expressionText) {
- checkTopLevelVariable('var x = $expressionText;', 'null',
- requireValidConst: true);
- }
-
- Expression checkSimpleExpression(String expressionText,
- {String expectedText,
- String extraDeclarations: '',
- bool requireValidConst: false}) {
- return checkTopLevelVariable('var x = $expressionText;\n$extraDeclarations',
- expectedText ?? expressionText,
- requireValidConst: requireValidConst);
- }
-
- Expression checkTopLevelVariable(String sourceText, String expectedText,
- {String variableName: 'x', bool requireValidConst: false}) {
- Expression expr = buildTopLevelVariable(sourceText,
- variableName: variableName, requireValidConst: requireValidConst);
- expect(expr.toString(), expectedText);
- return expr;
- }
-
- TestSummaryResynthesizer encodeSource(String text) {
- var source = addTestSource(text);
- return encodeLibrary(source);
- }
-}
-
-@reflectiveTest
-class ExprBuilderWithConstantUpdateTest extends ResynthesizeTestStrategyTwoPhase
- with ExprBuilderTestHelpers {
- @override
- FeatureSet get featureSet => new FeatureSet.forTesting(
- sdkVersion: '2.2.2',
- additionalFeatures: [Feature.constant_update_2018, Feature.triple_shift]);
-
- void test_bitShiftRightLogical() {
- checkSimpleExpression('0 >>> 1');
- }
-}
-
-@reflectiveTest
-class TokensToStringTest {
- final featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
-
- void test_empty_list_no_space() {
- // This is an interesting test case because "[]" is scanned as a single
- // token, but the parser splits it into two.
- _check('[]');
- }
-
- void test_empty_list_with_space() {
- _check('[ ]');
- }
-
- void test_gt_gt_gt_in_type() {
- // This is an interesting test case because ">>>" is scanned as a single
- // token, but the parser splits it into three.
- _check('A<B<C>>>[]');
- }
-
- void test_gt_gt_gt_in_type_split_both() {
- _check('A<B<C> > >[]');
- }
-
- void test_gt_gt_gt_in_type_split_left() {
- _check('A<B<C> >>[]');
- }
-
- void test_gt_gt_gt_in_type_split_right() {
- _check('A<B<C>> >[]');
- }
-
- void test_gt_gt_in_type() {
- // This is an interesting test case because ">>" is scanned as a single
- // token, but the parser splits it into two.
- _check('<A<B>>[]');
- }
-
- void test_gt_gt_in_type_split() {
- _check('A<B> >[]');
- }
-
- void test_identifier() {
- _check('foo');
- }
-
- void test_interpolation_expr_at_end_of_string() {
- _check(r'"foo${bar}"');
- }
-
- void test_interpolation_expr_at_start_of_string() {
- _check(r'"${foo}bar"');
- }
-
- void test_interpolation_expr_inside_string() {
- _check(r'"foo${bar}baz"');
- }
-
- void test_interpolation_var_at_end_of_string() {
- _check(r'"foo$bar"');
- }
-
- void test_interpolation_var_at_start_of_string() {
- _check(r'"$foo bar"');
- }
-
- void test_interpolation_var_inside_string() {
- _check(r'"foo$bar baz"');
- }
-
- void test_simple_string() {
- _check('"foo"');
- }
-
- void _check(String originalString) {
- var expression = _parseExpression(originalString);
- var originalTokens =
- _extractTokenList(expression.beginToken, expression.endToken);
- var newString = tokensToString(expression.beginToken, expression.endToken);
- var errorListener = AnalysisErrorListener.NULL_LISTENER;
- var reader = new CharSequenceReader(newString);
- var stringSource = new StringSource(newString, null);
- var scanner = new Scanner(stringSource, reader, errorListener)
- ..configureFeatures(featureSet);
- var startToken = scanner.tokenize();
- var newTokens = _extractTokenList(startToken);
- expect(newTokens, originalTokens);
- }
-
- List<String> _extractTokenList(Token startToken, [Token endToken]) {
- var result = <String>[];
- while (!startToken.isEof) {
- if (!startToken.isSynthetic) result.add(startToken.lexeme);
- if (identical(startToken, endToken)) break;
- startToken = startToken.next;
- }
- return result;
- }
-
- Expression _parseExpression(String expressionString) {
- // Note: to normalize the token string it's not sufficient to tokenize it
- // and then pass the tokens to `tokensToString`; we also need to parse it
- // because parsing modifies the token stream (splitting up `[]`, `>>`, and
- // `>>>` tokens when circumstances warrant).
- //
- // We wrap the expression in "f() async => ...;" to ensure that the await
- // keyword is properly parsed.
- var sourceText = 'f() async => $expressionString;';
- var errorListener = AnalysisErrorListener.NULL_LISTENER;
- var reader = new CharSequenceReader(sourceText);
- var stringSource = new StringSource(sourceText, null);
- var scanner = new Scanner(stringSource, reader, errorListener)
- ..configureFeatures(featureSet);
- var startToken = scanner.tokenize();
- var parser =
- new Parser(stringSource, errorListener, featureSet: featureSet);
- var compilationUnit = parser.parseCompilationUnit(startToken);
- var f = compilationUnit.declarations[0] as FunctionDeclaration;
- var body = f.functionExpression.body as ExpressionFunctionBody;
- return body.expression;
- }
-}
diff --git a/pkg/analyzer/test/src/summary/linker_test.dart b/pkg/analyzer/test/src/summary/linker_test.dart
deleted file mode 100644
index bb34cbd..0000000
--- a/pkg/analyzer/test/src/summary/linker_test.dart
+++ /dev/null
@@ -1,1031 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/link.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'test_strategies.dart';
-
-main() {
- if (AnalysisDriver.useSummary2) {
- test('fake', () {});
- return;
- }
- defineReflectiveSuite(() {
- defineReflectiveTests(LinkerUnitTest);
- });
-}
-
-@reflectiveTest
-class LinkerUnitTest extends SummaryLinkerTestStrategyTwoPhase
- with LinkerUnitTestCases {}
-
-/// Test cases that exercise the summary linker in a white-box fashion.
-///
-/// These test cases may be mixed into any class derived from
-/// [SummaryLinkerTestStrategy], allowing the linker to be unit-tested in a
-/// variety of ways.
-mixin LinkerUnitTestCases implements SummaryLinkerTestStrategy {
- Matcher get isUndefined => const TypeMatcher<UndefinedElementForLink>();
-
- LibraryElementForLink getLibrary(String uri) {
- return linker.getLibrary(Uri.parse(uri));
- }
-
- void test_baseClass_genericWithAccessor() {
- createLinker('''
-class B<T> {
- int get i => null;
-}
-class C<U> extends B<U> {
- var j;
-}
- ''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- // No assertions--just make sure it doesn't crash.
- }
-
- void test_baseClass_genericWithField() {
- createLinker('''
-class B<T> {
- int i = 0;
-}
-class C<T> extends B<T> {
- void f() {}
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- // No assertions--just make sure it doesn't crash.
- }
-
- void test_baseClass_genericWithFunctionTypedParameter() {
- createLinker('''
-class B<T> {
- void f(void g(T t));
-}
-class C<U> extends B<U> {
- void f(g) {}
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- // No assertions--just make sure it doesn't crash.
- }
-
- void test_baseClass_genericWithGenericMethod() {
- createLinker('''
-class B<T> {
- List<U> f<U>(U u) => null;
-}
-class C<V> extends B<V> {
- var j;
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- // No assertions--just make sure it doesn't crash.
- }
-
- void test_baseClass_genericWithGenericMethod_returnsGenericFuture() {
- createLinker('''
-import 'dart:async';
-class B<T> {
- Future<T> f() => null;
-}
-class C<T> extends B<T> {
- Future<T> f() => null;
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- // No assertions--just make sure it doesn't crash.
- }
-
- void test_baseClass_genericWithStaticFinal() {
- createLinker('''
-class B<T> {
- static final int i = 0;
-}
-class C<T> extends B<T> {
- void f() {}
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- }
-
- void test_baseClass_withPrivateField() {
- createLinker('''
-class B {
- var _b;
-}
-class C extends B {
- var c;
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- // No assertions--just make sure it doesn't crash.
- }
-
- void test_bundle_refers_to_bundle() {
- var bundle1 = createPackageBundle('''
-var x = 0;
-''', path: '/a.dart');
- addBundle('/a.ds', bundle1);
- var bundle2 = createPackageBundle('''
-import "a.dart";
-var y = x;
-''', path: '/b.dart');
- addBundle('/a.ds', bundle1);
- addBundle('/b.ds', bundle2);
- createLinker('''
-import "b.dart";
-var z = y;
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- expect(_getVariable(library.getContainedName('z')).inferredType.toString(),
- 'int');
- }
-
- void test_constCycle_viaLength() {
- createLinker('''
-class C {
- final y;
- const C() : y = x.length;
-}
-const x = [const C()];
-''');
- testLibrary.libraryCycleForLink.ensureLinked();
- ClassElementForLink classC = testLibrary.getContainedName('C');
- expect(classC.unnamedConstructor.isCycleFree, false);
- }
-
- void test_covariance() {
- createLinker('''
-class A<T> {
- void f(covariant T t) {}
-}
-class B<T> extends A<T> {
- void f(T t) {}
-}
-''');
- testLibrary.libraryCycleForLink.ensureLinked();
- ClassElementForLink classA = testLibrary.getContainedName('A');
- MethodElementForLink methodAF = classA.getContainedName('f');
- ParameterElementForLink parameterAFT = methodAF.parameters[0];
- expect(parameterAFT.isCovariant, isTrue);
- expect(parameterAFT.inheritsCovariant, isFalse);
- ClassElementForLink classB = testLibrary.getContainedName('B');
- MethodElementForLink methodBF = classB.getContainedName('f');
- ParameterElementForLink parameterBFT = methodBF.parameters[0];
- expect(parameterAFT.isCovariant, isTrue);
- expect(parameterBFT.inheritsCovariant, isTrue);
- }
-
- void test_createPackageBundle_withPackageUri() {
- PackageBundle bundle = createPackageBundle('''
-class B {
- void f(int i) {}
-}
-class C extends B {
- f(i) {} // Inferred param type: int
-}
-''', uri: 'package:foo/bar.dart');
- UnlinkedExecutable cf = bundle.unlinkedUnits[0].classes[1].executables[0];
- UnlinkedParam cfi = cf.parameters[0];
- expect(cfi.inferredTypeSlot, isNot(0));
- EntityRef typeRef = _lookupInferredType(
- bundle.linkedLibraries[0].units[0], cfi.inferredTypeSlot);
- expect(typeRef, isNotNull);
- expect(bundle.unlinkedUnits[0].references[typeRef.reference].name, 'int');
- }
-
- void test_genericTypeAlias_fromBundle() {
- var bundle = createPackageBundle('''
-typedef F<S> = S Function(num);
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
-
- createLinker('''
-import 'a.dart';
-class A {
- F<int> f;
-}
-class B implements A {
- F<int> f;
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
-
- ClassElementForLink_Class B = library.getContainedName('B');
- expect(B.fields, hasLength(1));
- FieldElementForLink f = B.fields[0];
- expect(f.type.toString(), 'int Function(num)');
- }
-
- void test_getContainedName_nonStaticField() {
- createLinker('class C { var f; }');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- ClassElementForLink_Class c = library.getContainedName('C');
- expect(c.getContainedName('f'), isNot(isUndefined));
- }
-
- void test_getContainedName_nonStaticGetter() {
- createLinker('class C { get g => null; }');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- ClassElementForLink_Class c = library.getContainedName('C');
- expect(c.getContainedName('g'), isNot(isUndefined));
- }
-
- void test_getContainedName_nonStaticMethod() {
- createLinker('class C { m() {} }');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- ClassElementForLink_Class c = library.getContainedName('C');
- expect(c.getContainedName('m'), isNot(isUndefined));
- }
-
- void test_getContainedName_nonStaticSetter() {
- createLinker('class C { void set s(value) {} }');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- ClassElementForLink_Class c = library.getContainedName('C');
- expect(c.getContainedName('s='), isNot(isUndefined));
- }
-
- void test_inferredType_closure_fromBundle() {
- var bundle = createPackageBundle('''
-var x = () {};
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-var y = x;
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- expect(_getVariable(library.getContainedName('y')).inferredType.toString(),
- 'Null Function()');
- }
-
- void test_inferredType_closure_fromBundle_identifierSequence() {
- var bundle = createPackageBundle('''
-class C {
- static final x = (D d) => d.e;
-}
-class D {
- E e;
-}
-class E {}
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-var y = C.x;
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- expect(_getVariable(library.getContainedName('y')).inferredType.toString(),
- 'E Function(D)');
- }
-
- void test_inferredType_implicitFunctionTypeIndices() {
- var bundle = createPackageBundle('''
-class A {
- void foo(void bar(int arg)) {}
-}
-class B extends A {
- void foo(bar) {}
-}
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-class C extends B {
- void foo(bar) {}
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class cls = library.getContainedName('C');
- expect(cls.methods, hasLength(1));
- MethodElementForLink foo = cls.methods[0];
- expect(foo.parameters, hasLength(1));
- FunctionType barType = foo.parameters[0].type;
- expect(barType.parameters[0].type.toString(), 'int');
- }
-
- void test_inferredType_instanceField_conditional_genericFunctions() {
- createLinker('''
-class C {
- final f = true ? <T>(T t) => 0 : <T>(T t) => 1;
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class cls = library.getContainedName('C');
- expect(cls.fields, hasLength(1));
- var field = cls.fields[0];
- expect(field.type.toString(), 'int Function<T>(T)');
- }
-
- void test_inferredType_instanceField_dynamic() {
- createLinker('''
-var x;
-class C {
- var f = x; // Inferred type: dynamic
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class cls = library.getContainedName('C');
- expect(cls.fields, hasLength(1));
- var field = cls.fields[0];
- expect(field.type.toString(), 'dynamic');
- }
-
- void test_inferredType_methodParamType_dynamic() {
- createLinker('''
-clas B {
- void f(dynamic x) {}
-}
-class C extends B {
- f(x) {} // Inferred param type: dynamic
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class cls = library.getContainedName('C');
- expect(cls.methods, hasLength(1));
- var method = cls.methods[0];
- expect(method.parameters, hasLength(1));
- expect(method.parameters[0].type.toString(), 'dynamic');
- }
-
- void test_inferredType_methodParamType_genericFunction() {
- createLinker('''
-class A {
- void m(Map<T, List<U>> Function<T, U>(T, U) p) {}
-}
-class B<V> extends A {
- void m(p) {}
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class cls = library.getContainedName('B');
- expect(cls.methods, hasLength(1));
- var method = cls.methods[0];
- expect(method.parameters, hasLength(1));
- var pType = method.parameters[0].type;
- expect(pType.toString(), 'Map<T, List<U>> Function<T,U>(T, U)');
- }
-
- void test_inferredType_methodReturnType_dynamic() {
- createLinker('''
-class B {
- dynamic f() {}
-}
-class C extends B {
- f() {} // Inferred return type: dynamic
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class cls = library.getContainedName('C');
- expect(cls.methods, hasLength(1));
- expect(cls.methods[0].returnType.toString(), 'dynamic');
- }
-
- void test_inferredType_methodReturnType_void() {
- createLinker('''
-class B {
- void f() {}
-}
-class C extends B {
- f() {}
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class cls = library.getContainedName('C');
- expect(cls.methods, hasLength(1));
- expect(cls.methods[0].returnType.toString(), 'void');
- }
-
- void test_inferredType_parameter_genericFunctionType() {
- var bundle = createPackageBundle('''
-class A<T> {
- A<R> map<R>(R Function(T) f) => null;
-}
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-class C extends A<int> {
- map<R2>(f) => null;
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class c = library.getContainedName('C');
- expect(c.methods, hasLength(1));
- MethodElementForLink map = c.methods[0];
- expect(map.parameters, hasLength(1));
- FunctionType fType = map.parameters[0].type;
- expect(fType.returnType.toString(), 'R2');
- expect(fType.parameters[0].type.toString(), 'int');
- }
-
- void test_inferredType_parameter_genericFunctionType_asTypeArgument() {
- var bundle = createPackageBundle('''
-class A<T> {
- A<R> map<R>(List<R Function(T)> fs) => null;
-}
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-class C extends A<int> {
- map<R2>(fs) => null;
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class c = library.getContainedName('C');
- expect(c.methods, hasLength(1));
- MethodElementForLink map = c.methods[0];
- expect(map.parameters, hasLength(1));
- InterfaceType iType = map.parameters[0].type;
- expect(iType.typeArguments, hasLength(1));
- FunctionType fType = iType.typeArguments[0];
- expect(fType.returnType.toString(), 'R2');
- expect(fType.parameters[0].type.toString(), 'int');
- }
-
- void test_inferredType_staticField_dynamic() {
- createLinker('''
-dynamic x = null;
-class C {
- static var y = x;
-}
-''');
- expect(
- _getVariable(linker
- .getLibrary(testDartUri)
- .getContainedName('C')
- .getContainedName('y'))
- .inferredType
- .toString(),
- 'dynamic');
- }
-
- void test_inferredType_topLevelVariable_dynamic() {
- createLinker('''
-dynamic x = null;
-var y = x;
-''');
- expect(
- _getVariable(linker.getLibrary(testDartUri).getContainedName('y'))
- .inferredType
- .toString(),
- 'dynamic');
- }
-
- void test_inferredTypeFromOutsideBuildUnit_dynamic() {
- var bundle = createPackageBundle('''
-var x;
-var y = x; // Inferred type: dynamic
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-var z = y; // Inferred type: dynamic
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- expect(_getVariable(library.getContainedName('z')).inferredType.toString(),
- 'dynamic');
- }
-
- void test_inferredTypeFromOutsideBuildUnit_instanceField() {
- var bundle = createPackageBundle('''
-class C {
- var f = 0; // Inferred type: int
-}
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-var x = new C().f; // Inferred type: int
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- expect(_getVariable(library.getContainedName('x')).inferredType.toString(),
- 'dynamic');
- }
-
- void test_inferredTypeFromOutsideBuildUnit_instanceField_toInstanceField() {
- var bundle = createPackageBundle('''
-class C {
- var f = 0; // Inferred type: int
-}
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-class D {
- var g = new C().f; // Inferred type: int
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- ClassElementForLink_Class classD = library.getContainedName('D');
- expect(classD.fields[0].inferredType.toString(), 'dynamic');
- }
-
- void test_inferredTypeFromOutsideBuildUnit_methodParamType_viaInheritance() {
- var bundle = createPackageBundle('''
-class B {
- void f(int i) {}
-}
-class C extends B {
- f(i) {} // Inferred param type: int
-}
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-class D extends C {
- f(i) {} // Inferred param type: int
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class cls = library.getContainedName('D');
- expect(cls.methods, hasLength(1));
- var method = cls.methods[0];
- expect(method.parameters, hasLength(1));
- expect(method.parameters[0].type.toString(), 'int');
- }
-
- void test_inferredTypeFromOutsideBuildUnit_methodReturnType_viaCall() {
- var bundle = createPackageBundle('''
-class B {
- int f() => 0;
-}
-class C extends B {
- f() => 1; // Inferred return type: int
-}
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-var x = new C().f(); // Inferred type: int
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- expect(_getVariable(library.getContainedName('x')).inferredType.toString(),
- 'int');
- }
-
- void test_inferredTypeFromOutsideBuildUnit_methodReturnType_viaInheritance() {
- var bundle = createPackageBundle('''
-class B {
- int f() => 0;
-}
-class C extends B {
- f() => 1; // Inferred return type: int
-}
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('''
-import 'a.dart';
-class D extends C {
- f() => 2; //Inferred return type: int
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- ClassElementForLink_Class cls = library.getContainedName('D');
- expect(cls.methods, hasLength(1));
- expect(cls.methods[0].returnType.toString(), 'int');
- }
-
- void test_inferredTypeFromOutsideBuildUnit_staticField() {
- var bundle =
- createPackageBundle('class C { static var f = 0; }', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('import "a.dart"; var x = C.f;', path: '/b.dart');
- expect(
- _getVariable(linker.getLibrary(testDartUri).getContainedName('x'))
- .inferredType
- .toString(),
- 'int');
- }
-
- void test_inferredTypeFromOutsideBuildUnit_topLevelVariable() {
- var bundle = createPackageBundle('var a = 0;', path: '/a.dart');
- addBundle('/a.ds', bundle);
- createLinker('import "a.dart"; var b = a;', path: '/b.dart');
- expect(
- _getVariable(linker.getLibrary(testDartUri).getContainedName('b'))
- .inferredType
- .toString(),
- 'int');
- }
-
- void test_inheritsCovariant_fromBundle() {
- var bundle = createPackageBundle('''
-class X1 {}
-class X2 extends X1 {}
-class A {
- void foo(covariant X1 x) {}
-}
-class B extends A {
- void foo(X2 x) {}
-}
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
-
- // C.foo.x must inherit covariance from B.foo.x, even though it is
- // resynthesized from the bundle.
- createLinker('''
-import 'a.dart';
-class C extends B {
- void foo(X2 x) {}
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
-
- ClassElementForLink_Class C = library.getContainedName('C');
- expect(C.methods, hasLength(1));
- MethodElementForLink foo = C.methods[0];
- expect(foo.parameters, hasLength(1));
- expect(foo.parameters[0].isCovariant, isTrue);
- }
-
- void test_instantiate_param_of_param_to_bounds() {
- createLinker('''
-class C<T> {}
-class D<T extends num> {}
-final x = new C<D>();
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- PropertyAccessorElementForLink_Variable x = library.getContainedName('x');
- ParameterizedType type1 = x.returnType;
- expect(type1.element.name, 'C');
- expect(type1.typeArguments, hasLength(1));
- ParameterizedType type2 = type1.typeArguments[0];
- expect(type2.element.name, 'D');
- expect(type2.typeArguments, hasLength(1));
- DartType type3 = type2.typeArguments[0];
- expect(type3.toString(), 'num');
- }
-
- void test_instantiate_param_to_bounds_class() {
- createLinker('''
-class C<T extends num> {}
-final x = new C();
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- PropertyAccessorElementForLink_Variable x = library.getContainedName('x');
- ParameterizedType type1 = x.returnType;
- expect(type1.element.name, 'C');
- expect(type1.typeArguments, hasLength(1));
- DartType type2 = type1.typeArguments[0];
- expect(type2.toString(), 'num');
- }
-
- void test_instantiate_param_to_bounds_typedef() {
- createLinker('''
-typedef T F<T extends num>();
-final x = new List<F>();
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- PropertyAccessorElementForLink_Variable x = library.getContainedName('x');
- ParameterizedType type1 = x.returnType;
- expect(type1.element.name, 'List');
- expect(type1.typeArguments, hasLength(1));
- FunctionType type2 = type1.typeArguments[0];
- expect(type2.element.name, 'F');
- expect(type2.returnType.toString(), 'num');
- }
-
- void test_isSimplyBounded_class_in_other_bundle() {
- var bundle = createPackageBundle('''
-class C<T extends C> {} // Not simply bounded
-class D<T extends D<Null>> {} // Simply bounded
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
-
- createLinker('''
-import 'a.dart';
-class A<T extends C> {} // Not simply bounded
-class B<T extends D> {} // Simply bounded
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
-
- expect(library.getContainedName('A').isSimplyBounded, false);
- expect(library.getContainedName('B').isSimplyBounded, true);
- }
-
- void test_isSimplyBounded_new_typedef_in_other_bundle() {
- var bundle = createPackageBundle('''
-typedef C<T extends C> = void Function(T x); // Not simply bounded
-typedef D<T extends D<Null>> = void Function(T x); // Simply bounded
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
-
- createLinker('''
-import 'a.dart';
-class A<T extends C> {} // Not simply bounded
-class B<T extends D> {} // Simply bounded
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
-
- expect(library.getContainedName('A').isSimplyBounded, false);
- expect(library.getContainedName('B').isSimplyBounded, true);
- }
-
- void test_isSimplyBounded_old_typedef_in_other_bundle() {
- var bundle = createPackageBundle('''
-typedef void C<T extends C>(T x); // Not simply bounded
-typedef void D<T extends D<Null>>(T x); // Simply bounded
-''', path: '/a.dart');
- addBundle('/a.ds', bundle);
-
- createLinker('''
-import 'a.dart';
-class A<T extends C> {} // Not simply bounded
-class B<T extends D> {} // Simply bounded
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
-
- expect(library.getContainedName('A').isSimplyBounded, false);
- expect(library.getContainedName('B').isSimplyBounded, true);
- }
-
- void test_leastUpperBound_functionAndClass() {
- createLinker('''
-class C {}
-void f() {}
-var x = {
- 'C': C,
- 'f': f
-};
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- // No assertions--just make sure it doesn't crash.
- }
-
- void test_libraryCycle_ignoresDependenciesOutsideBuildUnit() {
- createLinker('import "dart:async";');
- LibraryCycleForLink libraryCycle = testLibrary.libraryCycleForLink;
- expect(libraryCycle.dependencies, isEmpty);
- expect(libraryCycle.libraries, [testLibrary]);
- }
-
- void test_libraryCycle_linkEnsuresDependenciesLinked() {
- addNamedSource('/a.dart', 'import "b.dart";');
- addNamedSource('/b.dart', '');
- addNamedSource('/c.dart', '');
- createLinker('import "a.dart"; import "c.dart";');
- LibraryElementForLink libA = getLibrary('file:///a.dart');
- LibraryElementForLink libB = getLibrary('file:///b.dart');
- LibraryElementForLink libC = getLibrary('file:///c.dart');
- expect(libA.libraryCycleForLink.node.isEvaluated, isFalse);
- expect(libB.libraryCycleForLink.node.isEvaluated, isFalse);
- expect(libC.libraryCycleForLink.node.isEvaluated, isFalse);
- libA.libraryCycleForLink.ensureLinked();
- expect(libA.libraryCycleForLink.node.isEvaluated, isTrue);
- expect(libB.libraryCycleForLink.node.isEvaluated, isTrue);
- expect(libC.libraryCycleForLink.node.isEvaluated, isFalse);
- }
-
- void test_libraryCycle_nontrivial() {
- addNamedSource('/a.dart', 'import "b.dart";');
- addNamedSource('/b.dart', 'import "a.dart";');
- createLinker('');
- LibraryElementForLink libA = getLibrary('file:///a.dart');
- LibraryElementForLink libB = getLibrary('file:///b.dart');
- LibraryCycleForLink libraryCycle = libA.libraryCycleForLink;
- expect(libB.libraryCycleForLink, same(libraryCycle));
- expect(libraryCycle.dependencies, isEmpty);
- expect(libraryCycle.libraries, unorderedEquals([libA, libB]));
- }
-
- void test_libraryCycle_nontrivial_dependencies() {
- addNamedSource('/a.dart', '');
- addNamedSource('/b.dart', '');
- addNamedSource('/c.dart', 'import "a.dart"; import "d.dart";');
- addNamedSource('/d.dart', 'import "b.dart"; import "c.dart";');
- createLinker('');
- LibraryElementForLink libA = getLibrary('file:///a.dart');
- LibraryElementForLink libB = getLibrary('file:///b.dart');
- LibraryElementForLink libC = getLibrary('file:///c.dart');
- LibraryElementForLink libD = getLibrary('file:///d.dart');
- LibraryCycleForLink libraryCycle = libC.libraryCycleForLink;
- expect(libD.libraryCycleForLink, same(libraryCycle));
- expect(libraryCycle.dependencies,
- unorderedEquals([libA.libraryCycleForLink, libB.libraryCycleForLink]));
- expect(libraryCycle.libraries, unorderedEquals([libC, libD]));
- }
-
- void test_libraryCycle_nontrivial_via_export() {
- addNamedSource('/a.dart', 'export "b.dart";');
- addNamedSource('/b.dart', 'export "a.dart";');
- createLinker('');
- LibraryElementForLink libA = getLibrary('file:///a.dart');
- LibraryElementForLink libB = getLibrary('file:///b.dart');
- LibraryCycleForLink libraryCycle = libA.libraryCycleForLink;
- expect(libB.libraryCycleForLink, same(libraryCycle));
- expect(libraryCycle.dependencies, isEmpty);
- expect(libraryCycle.libraries, unorderedEquals([libA, libB]));
- }
-
- void test_libraryCycle_trivial() {
- createLinker('');
- LibraryCycleForLink libraryCycle = testLibrary.libraryCycleForLink;
- expect(libraryCycle.dependencies, isEmpty);
- expect(libraryCycle.libraries, [testLibrary]);
- }
-
- void test_libraryCycle_trivial_dependencies() {
- addNamedSource('/a.dart', '');
- addNamedSource('/b.dart', '');
- createLinker('import "a.dart"; import "b.dart";');
- LibraryElementForLink libA = getLibrary('file:///a.dart');
- LibraryElementForLink libB = getLibrary('file:///b.dart');
- LibraryCycleForLink libraryCycle = testLibrary.libraryCycleForLink;
- expect(libraryCycle.dependencies,
- unorderedEquals([libA.libraryCycleForLink, libB.libraryCycleForLink]));
- expect(libraryCycle.libraries, [testLibrary]);
- }
-
- void test_multiplyInheritedExecutable_differentSignatures() {
- createLinker('''
-class B {
- void f() {}
-}
-abstract class I {
- f();
-}
-class C extends B with I {}
-class D extends C {
- void f() {}
-}
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- library.libraryCycleForLink.ensureLinked();
- // No assertions--just make sure it doesn't crash.
- }
-
- void test_parameterParentElementForLink_implicitFunctionTypeIndices() {
- createLinker('void f(a, void g(b, c, d, void h())) {}');
- TopLevelFunctionElementForLink f = testLibrary.getContainedName('f');
- expect(f.implicitFunctionTypeIndices, []);
- ParameterElementForLink g = f.parameters[1];
- FunctionType gType = g.type;
- FunctionElementForLink_FunctionTypedParam gTypeElement = gType.element;
- expect(gTypeElement.implicitFunctionTypeIndices, [1]);
- ParameterElementForLink h = gTypeElement.parameters[3];
- FunctionType hType = h.type;
- FunctionElementForLink_FunctionTypedParam hTypeElement = hType.element;
- expect(hTypeElement.implicitFunctionTypeIndices, [1, 3]);
- }
-
- void test_parameterParentElementForLink_innermostExecutable() {
- createLinker('void f(void g(void h())) {}');
- TopLevelFunctionElementForLink f = testLibrary.getContainedName('f');
- expect(f.typeParameterContext, same(f));
- ParameterElementForLink g = f.parameters[0];
- FunctionType gType = g.type;
- FunctionElementForLink_FunctionTypedParam gTypeElement = gType.element;
- expect(gTypeElement.typeParameterContext, same(f));
- ParameterElementForLink h = gTypeElement.parameters[0];
- FunctionType hType = h.type;
- FunctionElementForLink_FunctionTypedParam hTypeElement = hType.element;
- expect(hTypeElement.typeParameterContext, same(f));
- }
-
- void test_topLevelFunction_isStatic() {
- createLinker('f() {}');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- TopLevelFunctionElementForLink f = library.getContainedName('f');
- expect(f.isStatic, true);
- }
-
- void test_topLevelGetter_isStatic() {
- createLinker('get x => null;');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- PropertyAccessorElementForLink_Executable x = library.getContainedName('x');
- expect(x.isStatic, true);
- }
-
- void test_topLevelSetter_isStatic() {
- createLinker('void set x(value) {}');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- PropertyAccessorElementForLink_Executable x =
- library.getContainedName('x=');
- expect(x.isStatic, true);
- }
-
- void test_topLevelVariable_isStatic() {
- createLinker('var x;');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- PropertyAccessorElementForLink_Variable x = library.getContainedName('x');
- expect(x.isStatic, true);
- expect(x.variable.isStatic, true);
- }
-
- void test_typeParameter_computeDeBruijnIndex_direct() {
- createLinker('class C<T, U> {}');
- ClassElementForLink_Class c = testLibrary.getContainedName('C');
- TypeParameterElementImpl t = c.typeParameters[0];
- TypeParameterElementImpl u = c.typeParameters[1];
- expect(c.computeDeBruijnIndex(t), 2);
- expect(c.computeDeBruijnIndex(u), 1);
- }
-
- void test_typeParameter_computeDeBruijnIndex_indirect() {
- createLinker('class C<T, U> { f<V, W>() {} }');
- ClassElementForLink_Class c = testLibrary.getContainedName('C');
- MethodElementForLink f = c.methods[0];
- TypeParameterElementImpl t = c.typeParameters[0];
- TypeParameterElementImpl u = c.typeParameters[1];
- expect(f.computeDeBruijnIndex(t), 4);
- expect(f.computeDeBruijnIndex(u), 3);
- }
-
- void test_typeParameter_computeDeBruijnIndex_reversed() {
- createLinker('class C<T, U> { f<V, W>() {} }');
- ClassElementForLink_Class c = testLibrary.getContainedName('C');
- MethodElementForLink f = c.methods[0];
- TypeParameterElementImpl v = f.typeParameters[0];
- TypeParameterElementImpl w = f.typeParameters[1];
- expect(c.computeDeBruijnIndex(v), isNull);
- expect(c.computeDeBruijnIndex(w), isNull);
- }
-
- void test_typeParameter_computeDeBruijnIndex_unrelated() {
- createLinker('class C<T, U> {} class D<V, W> {}');
- ClassElementForLink_Class c = testLibrary.getContainedName('C');
- ClassElementForLink_Class d = testLibrary.getContainedName('D');
- TypeParameterElementImpl t = c.typeParameters[0];
- TypeParameterElementImpl u = c.typeParameters[1];
- TypeParameterElementImpl v = d.typeParameters[0];
- TypeParameterElementImpl w = d.typeParameters[1];
- expect(c.computeDeBruijnIndex(v), isNull);
- expect(c.computeDeBruijnIndex(w), isNull);
- expect(d.computeDeBruijnIndex(t), isNull);
- expect(d.computeDeBruijnIndex(u), isNull);
- }
-
- void test_variable_initializer_presence() {
- // Any variable declaration with an initializer should have a non-null value
- // for `initializer`, regardless of whether it is constant and regardless of
- // whether it has an explicit type.
- createLinker('''
-const int c = 0;
-int i = 0;
-int j;
-var v = 0;
-''');
- LibraryElementForLink library = linker.getLibrary(testDartUri);
- PropertyAccessorElementForLink_Variable c = library.getContainedName('c');
- expect(c.variable.initializer, isNotNull);
- PropertyAccessorElementForLink_Variable i = library.getContainedName('i');
- expect(i.variable.initializer, isNotNull);
- PropertyAccessorElementForLink_Variable j = library.getContainedName('j');
- expect(j.variable.initializer, isNull);
- PropertyAccessorElementForLink_Variable v = library.getContainedName('v');
- expect(v.variable.initializer, isNotNull);
- }
-
- VariableElementForLink _getVariable(ReferenceableElementForLink element) {
- return (element as PropertyAccessorElementForLink_Variable).variable;
- }
-
- /**
- * Finds the first inferred type stored in [unit] whose slot matches [slot].
- */
- EntityRef _lookupInferredType(LinkedUnit unit, int slot) {
- for (EntityRef ref in unit.types) {
- if (ref.slot == slot) {
- return ref;
- }
- }
- return null;
- }
-}
diff --git a/pkg/analyzer/test/src/summary/prelinker_test.dart b/pkg/analyzer/test/src/summary/prelinker_test.dart
deleted file mode 100644
index aa47aaaa..0000000
--- a/pkg/analyzer/test/src/summary/prelinker_test.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'summary_common.dart';
-import 'test_strategies.dart';
-
-main() {
- if (AnalysisDriver.useSummary2) {
- test('fake', () {});
- return;
- }
- defineReflectiveSuite(() {
- defineReflectiveTests(PrelinkerTest);
- });
-}
-
-/// Tests for the pre-linker which exercise it using the old (two-phase) summary
-/// generation strategy.
-///
-/// TODO(paulberry): eliminate these tests once we have transitioned over to
-/// one-step summary generation.
-@reflectiveTest
-class PrelinkerTest extends SummaryBlackBoxTestStrategyPrelink
- with SummaryTestCases {}
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
new file mode 100644
index 0000000..551cad1
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2019, 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/visitor.dart';
+
+/// Prints AST as a tree, with properties and children.
+class ResolvedAstPrinter extends ThrowingAstVisitor<void> {
+ StringSink _sink;
+ String _indent = '';
+
+ ResolvedAstPrinter(StringSink sink, String indent)
+ : _sink = sink,
+ _indent = indent;
+
+ @override
+ void visitCompilationUnit(CompilationUnit node) {
+ super.visitCompilationUnit(node);
+ }
+
+ @override
+ void visitIntegerLiteral(IntegerLiteral node) {
+ _writeln('IntegerLiteral(${node.literal.lexeme})');
+ _withIndent(() {
+ _writeln2('staticType: ', node.staticType);
+ });
+ }
+
+ @override
+ void visitListLiteral(ListLiteral node) {
+ _writeln('ListLiteral');
+ _withIndent(() {
+ _writeln2('isConst: ', node.isConst);
+ _writeln2('staticType: ', node.staticType);
+ _writeTypeArgumentList('typeArguments', node.typeArguments);
+ _writeNodeList('elements', node.elements);
+ });
+ }
+
+ void _withIndent(void Function() f) {
+ var indent = _indent;
+ _indent = '$_indent ';
+ f();
+ _indent = indent;
+ }
+
+ void _writeln(String line) {
+ _sink.write('$_indent');
+ _sink.writeln(line);
+ }
+
+ void _writeln2(String prefix, Object o) {
+ _sink.write('$_indent');
+ _sink.write(prefix);
+ _sink.writeln(o);
+ }
+
+ void _writeNodeList(String name, NodeList nodeList) {
+ if (nodeList.isNotEmpty) {
+ _writeln(name);
+ _withIndent(() {
+ nodeList.accept(this);
+ });
+ }
+ }
+
+ void _writeTypeArgumentList(String name, TypeArgumentList node) {
+ if (node != null) {
+ _writeln(name);
+ _withIndent(() {
+ node.arguments?.accept(this);
+ });
+ }
+ }
+}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
deleted file mode 100644
index 190954b..0000000
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'element_text.dart';
-import 'resynthesize_common.dart';
-import 'test_strategies.dart';
-
-main() {
- if (AnalysisDriver.useSummary2) {
- test('fake', () {});
- return;
- }
- defineReflectiveSuite(() {
- defineReflectiveTests(ApplyCheckElementTextReplacements);
- defineReflectiveTests(ResynthesizeAstStrongTest);
- });
-}
-
-@reflectiveTest
-class ApplyCheckElementTextReplacements {
- test_applyReplacements() {
- applyCheckElementTextReplacements();
- }
-}
-
-@reflectiveTest
-class ResynthesizeAstStrongTest extends ResynthesizeTestStrategyTwoPhase
- with ResynthesizeTestCases, GetElementTestCases, ResynthesizeTestHelpers {
- @override
- @failingTest
- test_class_constructor_field_formal_functionTyped_withReturnType_generic() async {
- await super
- .test_class_constructor_field_formal_functionTyped_withReturnType_generic();
- }
-
- @failingTest // See dartbug.com/32290
- test_const_constructor_inferred_args() =>
- super.test_const_constructor_inferred_args();
-
- @failingTest // See dartbug.com/33441
- test_const_list_inferredType() => super.test_const_list_inferredType();
-
- @failingTest // See dartbug.com/33441
- test_const_map_inferredType() => super.test_const_map_inferredType();
-
- @FailingTest(
- reason: "NoSuchMethodError: Class 'ExtensionElementForLink' has no "
- "instance method 'getGetter' with matching arguments.")
- test_const_reference_staticMethod_ofExtension() async {
- await super.test_const_reference_staticMethod_ofExtension();
- }
-
- @failingTest // See dartbug.com/33441
- test_const_set_inferredType() => super.test_const_set_inferredType();
-
- @override
- @failingTest
- test_defaultValue_refersToExtension_method_inside() async {
- await super.test_defaultValue_refersToExtension_method_inside();
- }
-
- @override
- @failingTest
- test_defaultValue_refersToGenericClass() async {
- await super.test_defaultValue_refersToGenericClass();
- }
-
- @FailingTest(
- reason: 'Inference for extension fields is not implemented in summary1.',
- )
- test_duplicateDeclaration_extension() async {
- await super.test_duplicateDeclaration_extension();
- }
-
- @FailingTest(
- reason: 'Inference for extension fields is not implemented in summary1.',
- )
- test_extension_field_inferredType_const() async {
- await super.test_extension_field_inferredType_const();
- }
-
- @override
- @failingTest
- test_infer_generic_typedef_complex() async {
- await super.test_infer_generic_typedef_complex();
- }
-
- @override
- @failingTest
- test_syntheticFunctionType_inGenericClass() async {
- await super.test_syntheticFunctionType_inGenericClass();
- }
-}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index d3e4e8a..86a1ada 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -11,17 +11,13 @@
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/resynthesize.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:test/test.dart';
-import '../../util/element_type_matchers.dart';
import 'element_text.dart';
import 'test_strategies.dart';
@@ -81,126 +77,6 @@
testSource = addSource(testFile, code);
return testSource;
}
-
- /**
- * Verify that the [resynthesizer] didn't do any unnecessary work when
- * resynthesizing the library with the [expectedLibraryUri].
- */
- void checkMinimalResynthesisWork(TestSummaryResynthesizer resynthesizer,
- Uri expectedLibraryUri, List<Uri> expectedUnitUriList) {
- // Check that no other summaries needed to be resynthesized to resynthesize
- // the library element.
- expect(resynthesizer.resynthesisCount, 3);
- // Check that the only linked summary consulted was that for [uri].
- expect(resynthesizer.linkedSummariesRequested, hasLength(1));
- expect(resynthesizer.linkedSummariesRequested.first,
- expectedLibraryUri.toString());
- // Check that the only unlinked summaries consulted were those for the
- // library in question.
- var expectedUnitUriStrSet =
- expectedUnitUriList.map((uri) => uri.toString()).toSet();
- for (String requestedUri in resynthesizer.unlinkedSummariesRequested) {
- expect(expectedUnitUriStrSet, contains(requestedUri));
- }
- }
-}
-
-/// Mixin containing test cases exercising summary resynthesis. Intended to be
-/// applied to a class implementing [ResynthesizeTestStrategy], along with the
-/// mixin [ResynthesizeTestHelpers].
-mixin GetElementTestCases implements ResynthesizeTestHelpers {
- test_getElement_class() async {
- var resynthesized = _validateGetElement(
- 'class C { m() {} }',
- ['C'],
- );
- expect(resynthesized, isClassElement);
- }
-
- test_getElement_constructor_named() async {
- var resynthesized = _validateGetElement(
- 'class C { C.named(); }',
- ['C', 'named'],
- );
- expect(resynthesized, isConstructorElement);
- }
-
- test_getElement_constructor_unnamed() async {
- var resynthesized = _validateGetElement(
- 'class C { C(); }',
- ['C', ''],
- );
- expect(resynthesized, isConstructorElement);
- }
-
- test_getElement_field() async {
- var resynthesized = _validateGetElement(
- 'class C { var f; }',
- ['C', 'f'],
- );
- expect(resynthesized, isFieldElement);
- }
-
- test_getElement_getter() async {
- var resynthesized = _validateGetElement(
- 'class C { get f => null; }',
- ['C', 'f?'],
- );
- expect(resynthesized, isPropertyAccessorElement);
- }
-
- test_getElement_method() async {
- var resynthesized = _validateGetElement(
- 'class C { m() {} }',
- ['C', 'm'],
- );
- expect(resynthesized, isMethodElement);
- }
-
- test_getElement_operator() async {
- var resynthesized = _validateGetElement(
- 'class C { operator+(x) => null; }',
- ['C', '+'],
- );
- expect(resynthesized, isMethodElement);
- }
-
- test_getElement_setter() async {
- var resynthesized = _validateGetElement(
- 'class C { void set f(value) {} }',
- ['C', 'f='],
- );
- expect(resynthesized, isPropertyAccessorElement);
- }
-
- test_getElement_unit() async {
- var resynthesized = _validateGetElement('class C {}', []);
- expect(resynthesized, isCompilationUnitElement);
- }
-
- /**
- * Encode the library [text] into a summary and then use
- * [TestSummaryResynthesizer.getElement] to retrieve just the element with
- * the specified [names] from the resynthesized summary.
- */
- Element _validateGetElement(String text, List<String> names) {
- Source source = addTestSource(text);
- SummaryResynthesizer resynthesizer = encodeLibrary(source);
-
- var locationComponents = [
- source.uri.toString(),
- source.uri.toString(),
- ]..addAll(names);
- var location = ElementLocationImpl.con3(locationComponents);
-
- Element result = resynthesizer.getElement(location);
- checkMinimalResynthesisWork(resynthesizer, source.uri, [source.uri]);
- // Check that no other summaries needed to be resynthesized to resynthesize
- // the library element.
- expect(resynthesizer.resynthesisCount, 3);
- expect(result.location, location);
- return result;
- }
}
/// Mixin containing test cases exercising summary resynthesis. Intended to be
@@ -6540,6 +6416,35 @@
''');
}
+ test_finalField_hasConstConstructor() async {
+ var library = await checkLibrary(r'''
+class C1 {
+ final List<int> f1 = const [];
+ const C1();
+}
+class C2 {
+ final List<int> f2 = const [];
+ C2();
+}
+''');
+ checkElementText(
+ library,
+ r'''
+class C1 {
+ final List<int> f1 =
+ ListLiteral
+ isConst: true
+ staticType: List<int>
+ const C1();
+}
+class C2 {
+ final List<int> f2;
+ C2();
+}
+''',
+ withFullyResolvedAst: true);
+ }
+
test_function_async() async {
var library = await checkLibrary(r'''
import 'dart:async';
@@ -8029,6 +7934,22 @@
''');
}
+ test_instantiateToBounds_issue38498() async {
+ var library = await checkLibrary('''
+class A<R extends B> {
+ final values = <B>[];
+}
+class B<T extends num> {}
+''');
+ checkElementText(library, r'''
+class A<R extends B<num>> {
+ final List<B<num>> values;
+}
+class B<T extends num> {
+}
+''');
+ }
+
test_instantiateToBounds_simple() async {
var library = await checkLibrary('''
class C<T extends num> {}
@@ -11509,60 +11430,9 @@
mixin ResynthesizeTestHelpers implements ResynthesizeTestStrategy {
Future<LibraryElementImpl> checkLibrary(String text,
{bool allowErrors: false, bool dumpSummaries: false}) async {
- Source source = addTestSource(text);
- SummaryResynthesizer resynthesizer = encodeLibrary(source);
- return resynthesizer.getLibraryElement(source.uri.toString());
- }
-}
-
-class TestSummaryResynthesizer extends SummaryResynthesizer {
- final Map<String, UnlinkedUnit> unlinkedSummaries;
- final Map<String, LinkedLibrary> linkedSummaries;
- final bool allowMissingFiles;
-
- /**
- * The set of uris for which unlinked summaries have been requested using
- * [getUnlinkedSummary].
- */
- final Set<String> unlinkedSummariesRequested = new Set<String>();
-
- /**
- * The set of uris for which linked summaries have been requested using
- * [getLinkedSummary].
- */
- final Set<String> linkedSummariesRequested = new Set<String>();
-
- TestSummaryResynthesizer(AnalysisContextImpl context, this.unlinkedSummaries,
- this.linkedSummaries, this.allowMissingFiles)
- : super(context, null, context.sourceFactory, true) {
- // Clear after resynthesizing TypeProvider in super().
- unlinkedSummariesRequested.clear();
- linkedSummariesRequested.clear();
- context.typeProvider = typeProvider;
- }
-
- @override
- LinkedLibrary getLinkedSummary(String uri) {
- linkedSummariesRequested.add(uri);
- LinkedLibrary serializedLibrary = linkedSummaries[uri];
- if (serializedLibrary == null && !allowMissingFiles) {
- fail('Unexpectedly tried to get linked summary for $uri');
- }
- return serializedLibrary;
- }
-
- @override
- UnlinkedUnit getUnlinkedSummary(String uri) {
- unlinkedSummariesRequested.add(uri);
- UnlinkedUnit serializedUnit = unlinkedSummaries[uri];
- if (serializedUnit == null && !allowMissingFiles) {
- fail('Unexpectedly tried to get unlinked summary for $uri');
- }
- return serializedUnit;
- }
-
- @override
- bool hasLibrarySummary(String uri) {
- return true;
+ throw 42;
+// Source source = addTestSource(text);
+// SummaryResynthesizer resynthesizer = encodeLibrary(source);
+// return resynthesizer.getLibraryElement(source.uri.toString());
}
}
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_strong_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_strong_test.dart
deleted file mode 100644
index c6d4b8d..0000000
--- a/pkg/analyzer/test/src/summary/summarize_ast_strong_test.dart
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'summary_common.dart';
-import 'test_strategies.dart';
-
-main() {
- if (AnalysisDriver.useSummary2) {
- test('fake', () {});
- return;
- }
- defineReflectiveSuite(() {
- defineReflectiveTests(LinkedSummarizeAstStrongTest);
- });
-}
-
-@reflectiveTest
-class LinkedSummarizeAstStrongTest extends SummaryBlackBoxTestStrategyTwoPhase
- with SummaryTestCases {
- @override
- @failingTest
- test_closure_executable_with_imported_return_type() {
- super.test_closure_executable_with_imported_return_type();
- }
-
- @override
- @failingTest
- test_closure_executable_with_return_type_from_closure() {
- super.test_closure_executable_with_return_type_from_closure();
- }
-
- @override
- @failingTest
- test_closure_executable_with_unimported_return_type() {
- super.test_closure_executable_with_unimported_return_type();
- }
-
- @override
- @failingTest
- test_initializer_executable_with_bottom_return_type() {
- super.test_initializer_executable_with_bottom_return_type();
- }
-
- @override
- @failingTest
- test_initializer_executable_with_imported_return_type() {
- super.test_initializer_executable_with_imported_return_type();
- }
-
- @override
- @failingTest
- test_initializer_executable_with_return_type_from_closure() {
- super.test_initializer_executable_with_return_type_from_closure();
- }
-
- @override
- @failingTest
- test_initializer_executable_with_return_type_from_closure_field() {
- super.test_initializer_executable_with_return_type_from_closure_field();
- }
-
- @override
- @failingTest
- test_initializer_executable_with_unimported_return_type() {
- super.test_initializer_executable_with_unimported_return_type();
- }
-
- @override
- @failingTest
- test_syntheticFunctionType_genericClosure() {
- super.test_syntheticFunctionType_genericClosure();
- }
-
- @override
- @failingTest
- test_syntheticFunctionType_inGenericClass() {
- super.test_syntheticFunctionType_inGenericClass();
- }
-}
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
deleted file mode 100644
index 10f6ccd..0000000
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ /dev/null
@@ -1,11856 +0,0 @@
-// Copyright (c) 2015, 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/analysis/features.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/scanner/reader.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/string_source.dart';
-import 'package:analyzer/src/summary/base.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/public_namespace_computer.dart'
- as public_namespace;
-import 'package:analyzer/src/summary/summarize_const_expr.dart';
-import 'package:test/test.dart';
-
-import 'test_strategies.dart';
-
-/// Convert a summary object (or a portion of one) into a canonical form that
-/// can be easily compared using [expect]. If [orderByName] is true, and the
-/// object is a [List], it is sorted by the `name` field of its elements.
-Object canonicalize(Object obj, {bool orderByName: false}) {
- if (obj is SummaryClass) {
- Map<String, Object> result = <String, Object>{};
- obj.toMap().forEach((String key, Object value) {
- bool orderByName = false;
- if (obj is UnlinkedPublicNamespace && key == 'names' ||
- obj is UnlinkedPublicName && key == 'members') {
- orderByName = true;
- }
- result[key] = canonicalize(value, orderByName: orderByName);
- });
- return result;
- } else if (obj is List) {
- List<Object> result = <Object>[];
- for (Object item in obj) {
- result.add(canonicalize(item));
- }
- if (orderByName) {
- result.sort((Object a, Object b) {
- if (a is Map && b is Map) {
- return Comparable.compare(a['name'], b['name']);
- } else {
- return 0;
- }
- });
- }
- return result;
- } else if (obj is String || obj is num || obj is bool) {
- return obj;
- } else {
- return obj.toString();
- }
-}
-
-UnlinkedPublicNamespace computePublicNamespaceFromText(
- String text, Source source, FeatureSet featureSet) {
- CharacterReader reader = new CharSequenceReader(text);
- Scanner scanner =
- new Scanner(source, reader, AnalysisErrorListener.NULL_LISTENER)
- ..configureFeatures(featureSet);
- Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
- featureSet: featureSet);
- CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
- UnlinkedPublicNamespace namespace = new UnlinkedPublicNamespace.fromBuffer(
- public_namespace.computePublicNamespace(unit).toBuffer());
- return namespace;
-}
-
-/// Type of a function that validates an [EntityRef].
-typedef void _EntityRefValidator(EntityRef entityRef);
-
-/// Test cases that exercise summary generation in a black-box fashion.
-///
-/// These test cases may be mixed into any class derived from
-/// [SummaryBlackBoxTestStrategy], allowing summary generation to be unit-tested
-/// in a variety of ways.
-mixin SummaryTestCases implements SummaryBlackBoxTestStrategy {
- /// Get access to the linked defining compilation unit.
- LinkedUnit get definingUnit => linked.units[0];
-
- FeatureSet get disableNnbd => FeatureSet.forTesting(sdkVersion: '2.2.2');
-
- FeatureSet get enableNnbd =>
- FeatureSet.forTesting(additionalFeatures: [Feature.non_nullable]);
-
- /// TODO(scheglov) rename "Const" to "Expr" everywhere
- void assertUnlinkedConst(UnlinkedExpr constExpr, String sourceRepresentation,
- {bool isValidConst: true,
- List<UnlinkedExprOperation> operators: const <UnlinkedExprOperation>[],
- List<UnlinkedExprAssignOperator> assignmentOperators:
- const <UnlinkedExprAssignOperator>[],
- List<int> ints: const <int>[],
- List<double> doubles: const <double>[],
- List<String> strings: const <String>[],
- List<_EntityRefValidator> referenceValidators:
- const <_EntityRefValidator>[],
- bool forTypeInferenceOnly: false}) {
- if (forTypeInferenceOnly && !containsNonConstExprs) {
- expect(constExpr, isNull);
- return;
- }
- expect(constExpr, isNotNull);
- expect(constExpr.sourceRepresentation,
- _normalizeTokenString(sourceRepresentation));
- expect(constExpr.isValidConst, isValidConst);
- expect(constExpr.operations, operators);
- expect(constExpr.ints, ints);
- expect(constExpr.doubles, doubles);
- expect(constExpr.strings, strings);
- expect(constExpr.assignmentOperators, assignmentOperators);
- expect(constExpr.references, hasLength(referenceValidators.length));
- for (int i = 0; i < referenceValidators.length; i++) {
- referenceValidators[i](constExpr.references[i]);
- }
- }
-
- /// Check that [annotations] contains a single entry which is a reference to
- /// a top level variable called `a` in the current library.
- void checkAnnotationA(List<UnlinkedExpr> annotations) {
- expect(annotations, hasLength(1));
- assertUnlinkedConst(annotations[0], 'a', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- void checkConstCycle(String className,
- {String name: '', bool hasCycle: true}) {
- UnlinkedClass cls = findClass(className);
- int constCycleSlot =
- findExecutable(name, executables: cls.executables).constCycleSlot;
- expect(constCycleSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(
- definingUnit.constCycles,
- hasCycle
- ? contains(constCycleSlot)
- : isNot(contains(constCycleSlot)));
- }
- }
-
- /// Verify that the [dependency]th element of the dependency table represents
- /// a file reachable via the given [absoluteUri].
- void checkDependency(int dependency, String absoluteUri) {
- expect(dependency, new TypeMatcher<int>());
- expect(linked.dependencies[dependency].uri, absoluteUri);
- }
-
- /// Verify that the given [dependency] lists the given
- /// [relativeUris] as its parts.
- void checkDependencyParts(
- LinkedDependency dependency, List<String> relativeUris) {
- expect(dependency.parts, relativeUris);
- }
-
- /// Check that the given [documentationComment] matches the first
- /// Javadoc-style comment found in [text].
- ///
- /// Note that the algorithm for finding the Javadoc-style comment in [text] is
- /// a simple-minded text search; it is easily confused by corner cases such as
- /// strings containing comments, nested comments, etc.
- void checkDocumentationComment(
- UnlinkedDocumentationComment documentationComment, String text) {
- expect(documentationComment, isNotNull);
- int commentStart = text.indexOf('/*');
- expect(commentStart, isNot(-1));
- int commentEnd = text.indexOf('*/');
- expect(commentEnd, isNot(-1));
- commentEnd += 2;
- String expectedCommentText =
- text.substring(commentStart, commentEnd).replaceAll('\r\n', '\n');
- expect(documentationComment.text, expectedCommentText);
- }
-
- /// Verify that the given [typeRef] represents the type `dynamic`.
- void checkDynamicTypeRef(EntityRef typeRef) {
- checkTypeRef(typeRef, null, 'dynamic');
- }
-
- /// Verify that the given [exportName] represents a reference to an entity
- /// declared in a file reachable via [absoluteUri], having name [expectedName].
- /// [expectedKind] is the kind of object referenced. [expectedTargetUnit] is
- /// the index of the compilation unit in which the target of the [exportName]
- /// is expected to appear; if not specified it is assumed to be the defining
- /// compilation unit.
- void checkExportName(LinkedExportName exportName, String absoluteUri,
- String expectedName, ReferenceKind expectedKind,
- {int expectedTargetUnit: 0}) {
- expect(exportName, new TypeMatcher<LinkedExportName>());
- // Exported names must come from other libraries.
- expect(exportName.dependency, isNot(0));
- checkDependency(exportName.dependency, absoluteUri);
- expect(exportName.name, expectedName);
- expect(exportName.kind, expectedKind);
- expect(exportName.unit, expectedTargetUnit);
- }
-
- /// Verify that the dependency table contains an entry for a file reachable
- /// via the given [relativeUri]. If [fullyLinked] is
- /// `true`, then the dependency should be a fully-linked dependency; otherwise
- /// it should be a prelinked dependency.
- ///
- /// The index of the [LinkedDependency] is returned.
- int checkHasDependency(String relativeUri, {bool fullyLinked: false}) {
- List<String> found = <String>[];
- for (int i = 0; i < linked.dependencies.length; i++) {
- LinkedDependency dep = linked.dependencies[i];
- if (dep.uri == relativeUri) {
- if (fullyLinked) {
- expect(i, greaterThanOrEqualTo(linked.numPrelinkedDependencies));
- } else {
- expect(i, lessThan(linked.numPrelinkedDependencies));
- }
- return i;
- }
- found.add(dep.uri);
- }
- fail('Did not find dependency $relativeUri. Found: $found');
- }
-
- /// Test an inferred type. If [onlyInStrongMode] is `true` (the default) and
- /// strong mode is disabled, verify that the given [slotId] exists and has no
- /// associated type. Otherwise, behave as in [checkLinkedTypeSlot].
- void checkInferredTypeSlot(
- int slotId, String absoluteUri, String expectedName,
- {int numTypeArguments: 0,
- ReferenceKind expectedKind: ReferenceKind.classOrEnum,
- int expectedTargetUnit: 0,
- LinkedUnit linkedSourceUnit,
- UnlinkedUnit unlinkedSourceUnit,
- int numTypeParameters: 0,
- bool onlyInStrongMode: true}) {
- checkLinkedTypeSlot(slotId, absoluteUri, expectedName,
- numTypeArguments: numTypeArguments,
- expectedKind: expectedKind,
- expectedTargetUnit: expectedTargetUnit,
- linkedSourceUnit: linkedSourceUnit,
- unlinkedSourceUnit: unlinkedSourceUnit,
- numTypeParameters: numTypeParameters);
- }
-
- /// Verify that the dependency table *does not* contain any entries for a file
- /// reachable via the given [relativeUri].
- void checkLacksDependency(String relativeUri) {
- for (LinkedDependency dep in linked.dependencies) {
- if (dep.uri == relativeUri) {
- fail('Unexpected dependency found: $relativeUri');
- }
- }
- }
-
- /// Verify that the given [typeRef] represents the type `dynamic`.
- void checkLinkedDynamicTypeRef(EntityRef typeRef) {
- checkLinkedTypeRef(typeRef, null, 'dynamic');
- }
-
- /// Verify that the given [typeRef] represents a reference to a type declared
- /// in a file reachable via [absoluteUri], having name [expectedName]. Verify
- /// that the number of type arguments is equal to [numTypeArguments].
- /// [expectedKind] is the kind of object referenced. [linkedSourceUnit] and
- /// [unlinkedSourceUnit] refer to the compilation unit within which the
- /// [typeRef] appears; if not specified they are assumed to refer to the
- /// defining compilation unit. [expectedTargetUnit] is the index of the
- /// compilation unit in which the target of the [typeRef] is expected to
- /// appear; if not specified it is assumed to be the defining compilation unit.
- /// [numTypeParameters] is the number of type parameters of the thing being
- /// referred to.
- void checkLinkedTypeRef(
- EntityRef typeRef, String absoluteUri, String expectedName,
- {int numTypeArguments: 0,
- ReferenceKind expectedKind: ReferenceKind.classOrEnum,
- int expectedTargetUnit: 0,
- LinkedUnit linkedSourceUnit,
- UnlinkedUnit unlinkedSourceUnit,
- int numTypeParameters: 0}) {
- linkedSourceUnit ??= definingUnit;
- expect(typeRef, isNotNull,
- reason: 'No entry in linkedSourceUnit.types matching slotId');
- expect(typeRef.paramReference, 0);
- int index = typeRef.reference;
- expect(typeRef.typeArguments, hasLength(numTypeArguments));
- checkReferenceIndex(index, absoluteUri, expectedName,
- expectedKind: expectedKind,
- expectedTargetUnit: expectedTargetUnit,
- linkedSourceUnit: linkedSourceUnit,
- unlinkedSourceUnit: unlinkedSourceUnit,
- numTypeParameters: numTypeParameters);
- }
-
- /// Verify that the given [slotId] represents a reference to a type declared
- /// in a file reachable via [absoluteUri], having name [expectedName]. Verify
- /// that the number of type arguments is equal to [numTypeArguments].
- /// [expectedKind] is the kind of object referenced. [linkedSourceUnit] and
- /// [unlinkedSourceUnit] refer to the compilation unit within which the
- /// [typeRef] appears; if not specified they are assumed to refer to the
- /// defining compilation unit. [expectedTargetUnit] is the index of the
- /// compilation unit in which the target of the [typeRef] is expected to
- /// appear; if not specified it is assumed to be the defining compilation unit.
- /// [numTypeParameters] is the number of type parameters of the thing being
- /// referred to.
- void checkLinkedTypeSlot(int slotId, String absoluteUri, String expectedName,
- {int numTypeArguments: 0,
- ReferenceKind expectedKind: ReferenceKind.classOrEnum,
- int expectedTargetUnit: 0,
- LinkedUnit linkedSourceUnit,
- UnlinkedUnit unlinkedSourceUnit,
- int numTypeParameters: 0}) {
- // Slot ids should be nonzero, since zero means "no associated slot".
- expect(slotId, isNot(0));
- if (skipFullyLinkedData) {
- return;
- }
- linkedSourceUnit ??= definingUnit;
- checkLinkedTypeRef(
- getTypeRefForSlot(slotId, linkedSourceUnit: linkedSourceUnit),
- absoluteUri,
- expectedName,
- numTypeArguments: numTypeArguments,
- expectedKind: expectedKind,
- expectedTargetUnit: expectedTargetUnit,
- linkedSourceUnit: linkedSourceUnit,
- unlinkedSourceUnit: unlinkedSourceUnit,
- numTypeParameters: numTypeParameters);
- }
-
- /// Verify that the given [typeRef] represents a reference to a type parameter
- /// having the given [deBruijnIndex].
- void checkParamTypeRef(EntityRef typeRef, int deBruijnIndex) {
- expect(typeRef, new TypeMatcher<EntityRef>());
- expect(typeRef.reference, 0);
- expect(typeRef.typeArguments, isEmpty);
- expect(typeRef.paramReference, deBruijnIndex);
- }
-
- /// Verify that [prefixReference] is a valid reference to a prefix having the
- /// given [name].
- void checkPrefix(int prefixReference, String name) {
- expect(prefixReference, isNot(0));
- expect(unlinkedUnits[0].references[prefixReference].prefixReference, 0);
- expect(unlinkedUnits[0].references[prefixReference].name, name);
- expect(definingUnit.references[prefixReference].dependency, 0);
- expect(definingUnit.references[prefixReference].kind, ReferenceKind.prefix);
- expect(definingUnit.references[prefixReference].unit, 0);
- }
-
- /// Check the data structures that are reachable from an index in the
- /// references table. If the reference in question is an explicit
- /// reference, return the [UnlinkedReference] that is used to make the
- /// explicit reference. If the type reference in question is an implicit
- /// reference, return `null`.
- UnlinkedReference checkReferenceIndex(
- int referenceIndex, String absoluteUri, String expectedName,
- {ReferenceKind expectedKind: ReferenceKind.classOrEnum,
- int expectedTargetUnit: 0,
- LinkedUnit linkedSourceUnit,
- UnlinkedUnit unlinkedSourceUnit,
- int numTypeParameters: 0,
- bool unresolvedHasName: false}) {
- linkedSourceUnit ??= definingUnit;
- unlinkedSourceUnit ??= unlinkedUnits[0];
- LinkedReference referenceResolution =
- linkedSourceUnit.references[referenceIndex];
- String name;
- UnlinkedReference reference;
- if (referenceIndex < unlinkedSourceUnit.references.length) {
- // This is an explicit reference, so its name and prefix should be in
- // [UnlinkedUnit.references].
- expect(referenceResolution.name, isEmpty);
- reference = unlinkedSourceUnit.references[referenceIndex];
- name = reference.name;
- if (reference.prefixReference != 0) {
- // Prefixes should appear in the references table before any reference
- // that uses them.
- expect(reference.prefixReference, lessThan(referenceIndex));
- }
- } else {
- // This is an implicit reference, so its name should be in
- // [LinkedUnit.references].
- name = referenceResolution.name;
- }
- // Index 0 is reserved.
- expect(referenceIndex, isNot(0));
- if (absoluteUri == null) {
- expect(referenceResolution.dependency, 0);
- } else {
- checkDependency(referenceResolution.dependency, absoluteUri);
- }
- if (expectedName == null) {
- expect(name, isEmpty);
- } else {
- expect(name, expectedName);
- }
- expect(referenceResolution.kind, expectedKind);
- expect(referenceResolution.unit, expectedTargetUnit);
- expect(referenceResolution.numTypeParameters, numTypeParameters);
- return reference;
- }
-
- /// Verify that the given [typeRef] represents a reference to a type declared
- /// in a file reachable via [absoluteUri], having name [expectedName].
- /// If [expectedPrefix] is supplied, verify that the type is reached via the
- /// given prefix. Verify that the number of type arguments is equal to
- /// [numTypeArguments]. [expectedKind] is the kind of object referenced.
- /// [linkedSourceUnit] and [unlinkedSourceUnit] refer to the compilation unit
- /// within which the [typeRef] appears; if not specified they are assumed to
- /// refer to the defining compilation unit. [expectedTargetUnit] is the index
- /// of the compilation unit in which the target of the [typeRef] is expected
- /// to appear; if not specified it is assumed to be the defining compilation
- /// unit. [numTypeParameters] is the number of type parameters of the thing
- /// being referred to.
- void checkTypeRef(EntityRef typeRef, String absoluteUri, String expectedName,
- {String expectedPrefix,
- List<_PrefixExpectation> prefixExpectations,
- int numTypeArguments: 0,
- ReferenceKind expectedKind: ReferenceKind.classOrEnum,
- EntityRefKind entityKind: null,
- int expectedTargetUnit: 0,
- LinkedUnit linkedSourceUnit,
- UnlinkedUnit unlinkedSourceUnit,
- int numTypeParameters: 0,
- bool unresolvedHasName: false,
- EntityRefNullabilitySuffix nullabilitySuffix:
- EntityRefNullabilitySuffix.starOrIrrelevant}) {
- linkedSourceUnit ??= definingUnit;
- expect(typeRef, new TypeMatcher<EntityRef>());
- expect(typeRef.paramReference, 0);
- int index = typeRef.reference;
- expect(typeRef.typeArguments, hasLength(numTypeArguments));
- expect(typeRef.nullabilitySuffix, nullabilitySuffix);
-
- if (entityKind == EntityRefKind.genericFunctionType) {
- // [GenericFunctionType]s don't have references to check.
- return;
- }
-
- UnlinkedReference reference = checkReferenceIndex(
- index, absoluteUri, expectedName,
- expectedKind: expectedKind,
- expectedTargetUnit: expectedTargetUnit,
- linkedSourceUnit: linkedSourceUnit,
- unlinkedSourceUnit: unlinkedSourceUnit,
- numTypeParameters: numTypeParameters,
- unresolvedHasName: unresolvedHasName);
- expect(reference, isNotNull,
- reason: 'Unlinked type refs must refer to an explicit reference');
- if (expectedPrefix != null) {
- checkPrefix(reference.prefixReference, expectedPrefix);
- } else if (prefixExpectations != null) {
- for (_PrefixExpectation expectation in prefixExpectations) {
- expect(reference.prefixReference, isNot(0));
- reference = checkReferenceIndex(reference.prefixReference,
- expectation.absoluteUri, expectation.name,
- expectedKind: expectation.kind,
- expectedTargetUnit: expectedTargetUnit,
- linkedSourceUnit: linkedSourceUnit,
- unlinkedSourceUnit: unlinkedSourceUnit,
- numTypeParameters: expectation.numTypeParameters);
- }
- expect(reference.prefixReference, 0);
- } else {
- expect(reference.prefixReference, 0);
- }
- }
-
- /// Verify that the given [typeRef] represents a reference to an unresolved
- /// type.
- void checkUnresolvedTypeRef(
- EntityRef typeRef, String expectedPrefix, String expectedName,
- {LinkedUnit linkedSourceUnit, UnlinkedUnit unlinkedSourceUnit}) {
- // When serializing from the element model, unresolved type refs lose their
- // name.
- checkTypeRef(typeRef, null, expectedName,
- expectedPrefix: expectedPrefix,
- expectedKind: ReferenceKind.unresolved,
- linkedSourceUnit: linkedSourceUnit,
- unlinkedSourceUnit: unlinkedSourceUnit);
- }
-
- /// Verify that the given [typeRef] represents the type `void`.
- void checkVoidTypeRef(EntityRef typeRef) {
- checkTypeRef(typeRef, null, 'void');
- }
-
- fail_invalid_prefix_dynamic() {
-// if (checkAstDerivedData) {
-// // TODO(paulberry): get this to work properly.
-// return;
-// }
- var t = serializeTypeText('dynamic.T', allowErrors: true);
- checkUnresolvedTypeRef(t, 'dynamic', 'T');
- }
-
- fail_invalid_prefix_type_parameter() {
-// if (checkAstDerivedData) {
-// // TODO(paulberry): get this to work properly.
-// return;
-// }
- checkUnresolvedTypeRef(
- serializeClassText('class C<T> { T.U x; }', allowErrors: true)
- .fields[0]
- .type,
- 'T',
- 'U');
- }
-
- fail_invalid_prefix_void() {
-// if (checkAstDerivedData) {
-// // TODO(paulberry): get this to work properly.
-// return;
-// }
- checkUnresolvedTypeRef(
- serializeTypeText('void.T', allowErrors: true), 'void', 'T');
- }
-
- /// Find the class with the given [className] in the summary, and return its
- /// [UnlinkedClass] data structure. If [unit] is not given, the class is
- /// looked for in the defining compilation unit.
- UnlinkedClass findClass(String className,
- {bool failIfAbsent: false, UnlinkedUnit unit}) {
- unit ??= unlinkedUnits[0];
- UnlinkedClass result;
- for (UnlinkedClass cls in unit.classes) {
- if (cls.name == className) {
- if (result != null) {
- fail('Duplicate class $className');
- }
- result = cls;
- }
- }
- if (result == null && failIfAbsent) {
- fail('Class $className not found in serialized output');
- }
- return result;
- }
-
- /// Find the enum with the given [enumName] in the summary, and return its
- /// [UnlinkedEnum] data structure. If [unit] is not given, the enum is looked
- /// for in the defining compilation unit.
- UnlinkedEnum findEnum(String enumName,
- {bool failIfAbsent: false, UnlinkedUnit unit}) {
- unit ??= unlinkedUnits[0];
- UnlinkedEnum result;
- for (UnlinkedEnum e in unit.enums) {
- if (e.name == enumName) {
- if (result != null) {
- fail('Duplicate enum $enumName');
- }
- result = e;
- }
- }
- if (result == null && failIfAbsent) {
- fail('Enum $enumName not found in serialized output');
- }
- return result;
- }
-
- /// Find the executable with the given [executableName] in the summary, and
- /// return its [UnlinkedExecutable] data structure. If [executables] is not
- /// given, then the executable is searched for in the defining compilation
- /// unit.
- UnlinkedExecutable findExecutable(String executableName,
- {List<UnlinkedExecutable> executables, bool failIfAbsent: false}) {
- executables ??= unlinkedUnits[0].executables;
- UnlinkedExecutable result;
- for (UnlinkedExecutable executable in executables) {
- if (executable.name == executableName) {
- if (result != null) {
- fail('Duplicate executable $executableName');
- }
- result = executable;
- }
- }
- if (result == null && failIfAbsent) {
- fail('Executable $executableName not found in serialized output');
- }
- return result;
- }
-
- /// Find the mixin with the given [name] in the summary, and return its
- /// [UnlinkedClass] data structure.
- UnlinkedClass findMixin(String name) {
- UnlinkedClass result;
- for (UnlinkedClass mixin in unlinkedUnits[0].mixins) {
- if (mixin.name == name) {
- if (result != null) {
- fail('Duplicate mixin $name');
- }
- result = mixin;
- }
- }
- if (result == null) {
- fail('Mixin $name not found in serialized output.');
- }
- return result;
- }
-
- /// Find the parameter with the given [name] in [parameters].
- UnlinkedParam findParameter(List<UnlinkedParam> parameters, String name) {
- UnlinkedParam result;
- for (UnlinkedParam parameter in parameters) {
- if (parameter.name == name) {
- if (result != null) {
- fail('Duplicate parameter $name');
- }
- result = parameter;
- }
- }
- if (result == null) {
- fail('Parameter $name not found');
- }
- return result;
- }
-
- /// Find the typedef with the given [typedefName] in the summary, and return
- /// its [UnlinkedTypedef] data structure. If [unit] is not given, the typedef
- /// is looked for in the defining compilation unit.
- UnlinkedTypedef findTypedef(String typedefName,
- {bool failIfAbsent: false, UnlinkedUnit unit}) {
- unit ??= unlinkedUnits[0];
- UnlinkedTypedef result;
- for (UnlinkedTypedef type in unit.typedefs) {
- if (type.name == typedefName) {
- if (result != null) {
- fail('Duplicate typedef $typedefName');
- }
- result = type;
- }
- }
- if (result == null && failIfAbsent) {
- fail('Typedef $typedefName not found in serialized output');
- }
- return result;
- }
-
- /// Find the top level variable with the given [variableName] in the summary,
- /// and return its [UnlinkedVariable] data structure. If [variables] is not
- /// specified, the variable is looked for in the defining compilation unit.
- UnlinkedVariable findVariable(String variableName,
- {List<UnlinkedVariable> variables, bool failIfAbsent: false}) {
- variables ??= unlinkedUnits[0].variables;
- UnlinkedVariable result;
- for (UnlinkedVariable variable in variables) {
- if (variable.name == variableName) {
- if (result != null) {
- fail('Duplicate variable $variableName');
- }
- result = variable;
- }
- }
- if (result == null && failIfAbsent) {
- fail('Variable $variableName not found in serialized output');
- }
- return result;
- }
-
- /// Find the entry in [linkedSourceUnit.types] matching [slotId].
- EntityRef getTypeRefForSlot(int slotId, {LinkedUnit linkedSourceUnit}) {
- linkedSourceUnit ??= definingUnit;
- for (EntityRef typeRef in linkedSourceUnit.types) {
- if (typeRef.slot == slotId) {
- return typeRef;
- }
- }
- return null;
- }
-
- /// Serialize the given library [text] and return the summary of the class
- /// with the given [className].
- UnlinkedClass serializeClassText(String text,
- {String className: 'C', bool allowErrors: false}) {
- serializeLibraryText(text, allowErrors: allowErrors);
- return findClass(className, failIfAbsent: true);
- }
-
- /// Serialize the given library [text] and return the summary of the enum with
- /// the given [enumName].
- UnlinkedEnum serializeEnumText(String text, [String enumName = 'E']) {
- serializeLibraryText(text);
- return findEnum(enumName, failIfAbsent: true);
- }
-
- /// Serialize the given library [text] and return the summary of the
- /// executable with the given [executableName].
- UnlinkedExecutable serializeExecutableText(String text,
- {String executableName: 'f', bool allowErrors: false}) {
- serializeLibraryText(text, allowErrors: allowErrors);
- return findExecutable(executableName, failIfAbsent: true);
- }
-
- /// Serialize the given method [text] and return the summary of the executable
- /// with the given [executableName].
- UnlinkedExecutable serializeMethodText(String text,
- [String executableName = 'f']) {
- serializeLibraryText('class C { $text }');
- return findExecutable(executableName,
- executables: findClass('C', failIfAbsent: true).executables,
- failIfAbsent: true);
- }
-
- /// Serialize the given library [text] and return the summary of the mixin
- /// with the given [name].
- UnlinkedClass serializeMixinText(String text,
- {String name: 'M', bool allowErrors: false}) {
- serializeLibraryText(text, allowErrors: allowErrors);
- return findMixin(name);
- }
-
- /// Serialize the given library [text] and return the summary of the typedef
- /// with the given [typedefName].
- UnlinkedTypedef serializeTypedefText(String text,
- [String typedefName = 'F']) {
- serializeLibraryText(text);
- return findTypedef(typedefName, failIfAbsent: true);
- }
-
- /// Serialize a type declaration using the given [text] as a type name, and
- /// return a summary of the corresponding [EntityRef]. If the type
- /// declaration needs to refer to types that are not available in core, those
- /// types may be declared in [otherDeclarations].
- EntityRef serializeTypeText(String text,
- {String otherDeclarations: '', bool allowErrors: false}) {
- return serializeVariableText('$otherDeclarations\n$text v;',
- allowErrors: allowErrors)
- .type;
- }
-
- /// Serialize the given library [text] and return the summary of the variable
- /// with the given [variableName].
- UnlinkedVariable serializeVariableText(String text,
- {String variableName: 'v', bool allowErrors: false, imports: ''}) {
- if (imports.isNotEmpty && !imports.endsWith('\n')) {
- imports += '\n';
- }
- serializeLibraryText('$imports$text', allowErrors: allowErrors);
- return findVariable(variableName, failIfAbsent: true);
- }
-
- test_apiSignature() {
- List<int> signature1;
- List<int> signature2;
- List<int> signature3;
- {
- serializeLibraryText('class A {}');
- signature1 = unlinkedUnits[0].apiSignature;
- }
- {
- serializeLibraryText('class A { }');
- signature2 = unlinkedUnits[0].apiSignature;
- }
- {
- serializeLibraryText('class B {}');
- signature3 = unlinkedUnits[0].apiSignature;
- }
- expect(signature2, signature1);
- expect(signature3, isNot(signature1));
- }
-
- test_apiSignature_excludeBody_constructor() {
- List<int> signature1;
- List<int> signature2;
- List<int> signature3;
- {
- serializeLibraryText(r'''
-class A {
- A() {
- }
-}
-''');
- signature1 = unlinkedUnits[0].apiSignature;
- }
- {
- serializeLibraryText(r'''
-class A {
- A() {
- int v1;
- f() {
- double v2;
- }
- }
-}
-''');
- signature2 = unlinkedUnits[0].apiSignature;
- }
- {
- serializeLibraryText(r'''
-class A {
- A(int p) {
- }
-}
-''');
- }
- expect(signature2, signature1);
- expect(signature3, isNot(signature1));
- }
-
- test_apiSignature_excludeBody_method() {
- List<int> signature1;
- List<int> signature2;
- List<int> signature3;
- {
- serializeLibraryText(r'''
-class A {
- m() {
- }
-}
-''');
- signature1 = unlinkedUnits[0].apiSignature;
- }
- {
- serializeLibraryText(r'''
-class A {
- m() {
- int v1;
- f() {
- double v2;
- }
- }
-}
-''');
- signature2 = unlinkedUnits[0].apiSignature;
- }
- {
- serializeLibraryText(r'''
-class A {
- m(p) {
- }
-}
-''');
- }
- expect(signature2, signature1);
- expect(signature3, isNot(signature1));
- }
-
- test_apiSignature_excludeBody_topLevelFunction() {
- List<int> signature1;
- List<int> signature2;
- List<int> signature3;
- {
- serializeLibraryText('main() {}');
- signature1 = unlinkedUnits[0].apiSignature;
- }
- {
- serializeLibraryText(r'''
-main() {
- int v1 = 1;
- f() {
- int v2 = 2;
- }
-}
-''');
- signature2 = unlinkedUnits[0].apiSignature;
- }
- {
- serializeLibraryText('main(p) {}');
- signature3 = unlinkedUnits[0].apiSignature;
- }
- expect(signature2, signature1);
- expect(signature3, isNot(signature1));
- }
-
- test_bottom_reference_shared() {
- if (skipFullyLinkedData) {
- return;
- }
- // The synthetic executables for both `x` and `y` have type `() => `Bottom`.
- // Verify that they both use the same reference to `Bottom`.
- serializeLibraryText('var x = throw null; var y = throw null;');
- EntityRef xInitializerReturnType =
- getTypeRefForSlot(findVariable('x').initializer.inferredReturnTypeSlot);
- EntityRef yInitializerReturnType =
- getTypeRefForSlot(findVariable('y').initializer.inferredReturnTypeSlot);
- checkLinkedTypeRef(xInitializerReturnType, null, '*bottom*');
- checkLinkedTypeRef(yInitializerReturnType, null, '*bottom*');
- expect(xInitializerReturnType.reference, yInitializerReturnType.reference);
- }
-
- test_cascaded_export_hide_hide() {
- addNamedSource('/lib1.dart', 'export "lib2.dart" hide C hide B, C;');
- addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
- serializeLibraryText('''
-import 'lib1.dart';
-A a;
-B b;
-C c;
- ''', allowErrors: true);
- checkTypeRef(findVariable('a').type, absUri('/lib2.dart'), 'A');
- checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
- checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
- }
-
- test_cascaded_export_hide_show() {
- addNamedSource('/lib1.dart', 'export "lib2.dart" hide C show A, C;');
- addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
- serializeLibraryText('''
-import 'lib1.dart';
-A a;
-B b;
-C c;
- ''', allowErrors: true);
- checkTypeRef(findVariable('a').type, absUri('/lib2.dart'), 'A');
- checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
- checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
- }
-
- test_cascaded_export_show_hide() {
- addNamedSource('/lib1.dart', 'export "lib2.dart" show A, B hide B, C;');
- addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
- serializeLibraryText('''
-import 'lib1.dart';
-A a;
-B b;
-C c;
- ''', allowErrors: true);
- checkTypeRef(findVariable('a').type, absUri('/lib2.dart'), 'A');
- checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
- checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
- }
-
- test_cascaded_export_show_show() {
- addNamedSource('/lib1.dart', 'export "lib2.dart" show A, B show A, C;');
- addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
- serializeLibraryText('''
-import 'lib1.dart';
-A a;
-B b;
-C c;
- ''', allowErrors: true);
- checkTypeRef(findVariable('a').type, absUri('/lib2.dart'), 'A');
- checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
- checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
- }
-
- test_cascaded_import_hide_hide() {
- addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
- serializeLibraryText('''
-import 'lib.dart' hide C hide B, C;
-A a;
-B b;
-C c;
- ''', allowErrors: true);
- checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'A');
- checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
- checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
- }
-
- test_cascaded_import_hide_show() {
- addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
- serializeLibraryText('''
-import 'lib.dart' hide C show A, C;
-A a;
-B b;
-C c;
- ''', allowErrors: true);
- checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'A');
- checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
- checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
- }
-
- test_cascaded_import_show_hide() {
- addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
- serializeLibraryText('''
-import 'lib.dart' show A, B hide B, C;
-A a;
-B b;
-C c;
- ''', allowErrors: true);
- checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'A');
- checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
- checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
- }
-
- test_cascaded_import_show_show() {
- addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
- serializeLibraryText('''
-import 'lib.dart' show A, B show A, C;
-A a;
-B b;
-C c;
- ''', allowErrors: true);
- checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'A');
- checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
- checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
- }
-
- test_class_abstract() {
- UnlinkedClass cls = serializeClassText('abstract class C {}');
- expect(cls.isAbstract, true);
- }
-
- test_class_alias_abstract() {
- UnlinkedClass cls = serializeClassText(
- 'abstract class C = D with E; class D {} class E {}');
- expect(cls.isAbstract, true);
- }
-
- test_class_alias_concrete() {
- UnlinkedClass cls =
- serializeClassText('class C = _D with _E; class _D {} class _E {}');
- expect(cls.isAbstract, false);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].kind,
- ReferenceKind.classOrEnum);
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
- expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
- }
-
- test_class_alias_documented() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-class C = D with E;
-
-class D {}
-class E {}''';
- UnlinkedClass cls = serializeClassText(text);
- expect(cls.documentationComment, isNotNull);
- checkDocumentationComment(cls.documentationComment, text);
- }
-
- test_class_alias_flag() {
- UnlinkedClass cls =
- serializeClassText('class C = D with E; class D {} class E {}');
- expect(cls.isMixinApplication, true);
- }
-
- test_class_alias_generic() {
- serializeClassText('class C<A, B> = _D with _E; class _D {} class _E {}');
- expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 2);
- }
-
- test_class_alias_mixin_order() {
- UnlinkedClass cls = serializeClassText('''
-class C = D with E, F;
-class D {}
-class E {}
-class F {}
-''');
- expect(cls.mixins, hasLength(2));
- checkTypeRef(cls.mixins[0], null, 'E');
- checkTypeRef(cls.mixins[1], null, 'F');
- }
-
- test_class_alias_no_implicit_constructors() {
- UnlinkedClass cls = serializeClassText('''
-class C = D with E;
-class D {
- D.foo();
- D.bar();
-}
-class E {}
-''');
- expect(cls.executables, isEmpty);
- }
-
- test_class_alias_notSimplyBoundedSlot() {
- var cls = serializeClassText(
- 'class C<T extends C> = D with E; class D {} class E {}');
- expect(cls.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(
- linked.units[0].notSimplyBounded, contains(cls.notSimplyBoundedSlot));
- }
- }
-
- test_class_alias_notSimplyBoundedSlot_simple_because_non_generic() {
- // If no type parameters are specified, then the class is simply bounded, so
- // there is no reason to assign it a slot.
- var cls = serializeClassText('class C = D with E; class D {} class E {}');
- expect(cls.notSimplyBoundedSlot, 0);
- }
-
- test_class_alias_notSimplyBoundedSlot_simple_by_syntax() {
- // If no bounds are specified, then the class is simply bounded by sintax
- // alone, so there is no reason to assign it a slot.
- var cls =
- serializeClassText('class C<T> = D with E; class D {} class E {}');
- expect(cls.notSimplyBoundedSlot, 0);
- }
-
- test_class_alias_private() {
- serializeClassText('class _C = _D with _E; class _D {} class _E {}',
- className: '_C');
- expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
- }
-
- test_class_alias_reference_generic() {
- EntityRef typeRef = serializeTypeText('C',
- otherDeclarations: 'class C<D, E> = F with G; class F {} class G {}');
- checkTypeRef(typeRef, null, 'C', numTypeParameters: 2);
- }
-
- test_class_alias_reference_generic_imported() {
- addNamedSource(
- '/lib.dart', 'class C<D, E> = F with G; class F {} class G {}');
- EntityRef typeRef =
- serializeTypeText('C', otherDeclarations: 'import "lib.dart";');
- checkTypeRef(typeRef, absUri('/lib.dart'), 'C', numTypeParameters: 2);
- }
-
- test_class_alias_supertype() {
- UnlinkedClass cls =
- serializeClassText('class C = D with E; class D {} class E {}');
- checkTypeRef(cls.supertype, null, 'D');
- expect(cls.hasNoSupertype, isFalse);
- }
-
- test_class_codeRange() {
- UnlinkedClass cls = serializeClassText(' class C {}');
- _assertCodeRange(cls.codeRange, 1, 10);
- }
-
- test_class_concrete() {
- UnlinkedClass cls = serializeClassText('class C {}');
- expect(cls.isAbstract, false);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].kind,
- ReferenceKind.classOrEnum);
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
- expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
- }
-
- test_class_constMembers() {
- UnlinkedClass cls = serializeClassText('''
-class C {
- int fieldInstance = 0;
- final int fieldInstanceFinal = 0;
- static int fieldStatic = 0;
- static final int fieldStaticFinal = 0;
- static const int fieldStaticConst = 0;
- static const int _fieldStaticConstPrivate = 0;
- static void methodStaticPublic() {}
- static void _methodStaticPrivate() {}
- void methodInstancePublic() {}
- C operator+(C c) => null;
-}
-''');
- expect(cls.isAbstract, false);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- UnlinkedPublicName className = unlinkedUnits[0].publicNamespace.names[0];
- expect(className.kind, ReferenceKind.classOrEnum);
- expect(className.name, 'C');
- expect(className.numTypeParameters, 0);
- // executables
- Map<String, UnlinkedPublicName> executablesMap =
- <String, UnlinkedPublicName>{};
- className.members.forEach((e) => executablesMap[e.name] = e);
- expect(executablesMap, hasLength(4));
- Map<String, ReferenceKind> expectedExecutableKinds =
- <String, ReferenceKind>{
- 'fieldStaticConst': ReferenceKind.propertyAccessor,
- 'fieldStaticFinal': ReferenceKind.propertyAccessor,
- 'fieldStatic': ReferenceKind.propertyAccessor,
- 'methodStaticPublic': ReferenceKind.method,
- };
- expectedExecutableKinds.forEach((String name, ReferenceKind expectedKind) {
- UnlinkedPublicName executable = executablesMap[name];
- expect(executable.kind, expectedKind);
- expect(executable.members, isEmpty);
- });
- }
-
- test_class_constMembers_constructors() {
- UnlinkedClass cls = serializeClassText('''
-class C {
- const C();
- const C.constructorNamedPublicConst();
- C.constructorNamedPublic();
- C._constructorNamedPrivate();
-}
-''');
- expect(cls.isAbstract, false);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- UnlinkedPublicName className = unlinkedUnits[0].publicNamespace.names[0];
- expect(className.kind, ReferenceKind.classOrEnum);
- expect(className.name, 'C');
- expect(className.numTypeParameters, 0);
- // executables
- Map<String, UnlinkedPublicName> executablesMap =
- <String, UnlinkedPublicName>{};
- className.members.forEach((e) => executablesMap[e.name] = e);
- expect(executablesMap, hasLength(2));
- {
- UnlinkedPublicName executable =
- executablesMap['constructorNamedPublicConst'];
- expect(executable.kind, ReferenceKind.constructor);
- expect(executable.members, isEmpty);
- }
- {
- UnlinkedPublicName executable = executablesMap['constructorNamedPublic'];
- expect(executable.kind, ReferenceKind.constructor);
- expect(executable.members, isEmpty);
- }
- }
-
- test_class_documented() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-class C {}''';
- UnlinkedClass cls = serializeClassText(text);
- expect(cls.documentationComment, isNotNull);
- checkDocumentationComment(cls.documentationComment, text);
- }
-
- test_class_documented_tripleSlash() {
- String text = '''
-/// aaa
-/// bbbb
-/// cc
-class C {}''';
- UnlinkedClass cls = serializeClassText(text);
- UnlinkedDocumentationComment comment = cls.documentationComment;
- expect(comment, isNotNull);
- expect(comment.text, '/// aaa\n/// bbbb\n/// cc');
- }
-
- test_class_documented_with_references() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs referring to [D] and [E]
- */
-class C {}
-
-class D {}
-class E {}''';
- UnlinkedClass cls = serializeClassText(text);
- expect(cls.documentationComment, isNotNull);
- checkDocumentationComment(cls.documentationComment, text);
- }
-
- test_class_documented_with_with_windows_line_endings() {
- String text = '/**\r\n * Docs\r\n */\r\nclass C {}';
- UnlinkedClass cls = serializeClassText(text);
- expect(cls.documentationComment, isNotNull);
- checkDocumentationComment(cls.documentationComment, text);
- }
-
- test_class_interface() {
- UnlinkedClass cls = serializeClassText('''
-class C implements D {}
-class D {}
-''');
- expect(cls.interfaces, hasLength(1));
- checkTypeRef(cls.interfaces[0], null, 'D');
- }
-
- test_class_interface_order() {
- UnlinkedClass cls = serializeClassText('''
-class C implements D, E {}
-class D {}
-class E {}
-''');
- expect(cls.interfaces, hasLength(2));
- checkTypeRef(cls.interfaces[0], null, 'D');
- checkTypeRef(cls.interfaces[1], null, 'E');
- }
-
- test_class_mixin() {
- UnlinkedClass cls = serializeClassText('''
-class C extends Object with D {}
-class D {}
-''');
- expect(cls.mixins, hasLength(1));
- checkTypeRef(cls.mixins[0], null, 'D');
- }
-
- test_class_mixin_order() {
- UnlinkedClass cls = serializeClassText('''
-class C extends Object with D, E {}
-class D {}
-class E {}
-''');
- expect(cls.mixins, hasLength(2));
- checkTypeRef(cls.mixins[0], null, 'D');
- checkTypeRef(cls.mixins[1], null, 'E');
- }
-
- test_class_name() {
- var classText = 'class C {}';
- UnlinkedClass cls = serializeClassText(classText);
- expect(cls.name, 'C');
- expect(cls.nameOffset, classText.indexOf('C'));
- }
-
- test_class_no_flags() {
- UnlinkedClass cls = serializeClassText('class C {}');
- expect(cls.isAbstract, false);
- expect(cls.isMixinApplication, false);
- }
-
- test_class_no_interface() {
- UnlinkedClass cls = serializeClassText('class C {}');
- expect(cls.interfaces, isEmpty);
- }
-
- test_class_no_mixins() {
- UnlinkedClass cls = serializeClassText('class C {}');
- expect(cls.mixins, isEmpty);
- }
-
- test_class_no_superclass() {
- UnlinkedClass cls = serializeClassText('part of dart.core; class Object {}',
- className: 'Object');
- expect(cls.supertype, isNull);
- expect(cls.hasNoSupertype, isTrue);
- }
-
- test_class_no_type_param() {
- UnlinkedClass cls = serializeClassText('class C {}');
- expect(cls.typeParameters, isEmpty);
- }
-
- test_class_non_alias_flag() {
- UnlinkedClass cls = serializeClassText('class C {}');
- expect(cls.isMixinApplication, false);
- }
-
- test_class_notSimplyBounded_circularity_via_typedef() {
- // C's type parameter T is not simply bounded because its bound, F, expands
- // to `dynamic F(C)`, which refers to C.
- UnlinkedClass cls =
- serializeClassText('class C<T extends F> {} typedef F(C value);');
- expect(cls.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(
- linked.units[0].notSimplyBounded, contains(cls.notSimplyBoundedSlot));
- }
- }
-
- test_class_notSimplyBounded_circularity_with_type_params() {
- // C's type parameter T is simply bounded because even though it refers to
- // C, it specifies a bound.
- UnlinkedClass cls = serializeClassText('class C<T extends C<dynamic>> {}');
- expect(cls.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- isNot(contains(cls.notSimplyBoundedSlot)));
- }
- }
-
- test_class_notSimplyBounded_dependency_with_type_params() {
- // C's type parameter T is simply bounded because even though it refers to
- // non-simply-bounded type D, it specifies a bound.
- UnlinkedClass cls = serializeClassText(
- 'class C<T extends D<dynamic>> {} class D<T extends D<T>> {}');
- expect(cls.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- isNot(contains(cls.notSimplyBoundedSlot)));
- }
- }
-
- test_class_notSimplyBounded_function_typed_bound_complex_via_parameter_type() {
- UnlinkedClass cls =
- serializeClassText('class C<T extends void Function(T)> {}');
- expect(cls.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(
- linked.units[0].notSimplyBounded, contains(cls.notSimplyBoundedSlot));
- }
- }
-
- test_class_notSimplyBounded_function_typed_bound_complex_via_return_type() {
- UnlinkedClass cls =
- serializeClassText('class C<T extends T Function()> {}');
- expect(cls.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(
- linked.units[0].notSimplyBounded, contains(cls.notSimplyBoundedSlot));
- }
- }
-
- test_class_notSimplyBounded_function_typed_bound_simple() {
- UnlinkedClass cls =
- serializeClassText('class C<T extends void Function()> {}');
- expect(cls.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- isNot(contains(cls.notSimplyBoundedSlot)));
- }
- }
-
- test_class_notSimplyBounded_refers_to_circular_typedef() {
- // C's type parameter T has a bound of F, which is a circular typedef. This
- // is illegal in Dart, but we need to make sure it doesn't lead to a crash
- // or infinite loop.
- UnlinkedClass cls = serializeClassText(
- 'class C<T extends F> {} typedef F(G value); typedef G(F value);');
- expect(cls.notSimplyBoundedSlot, isNot(0));
- }
-
- test_class_notSimplyBoundedSlot() {
- var cls = serializeClassText('class C<T extends C> {}');
- expect(cls.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(
- linked.units[0].notSimplyBounded, contains(cls.notSimplyBoundedSlot));
- }
- }
-
- test_class_notSimplyBoundedSlot_complex_by_cycle() {
- var cls =
- serializeClassText('class C<T extends D> {} class D<T extends C> {}');
- if (!skipFullyLinkedData) {
- expect(
- linked.units[0].notSimplyBounded, contains(cls.notSimplyBoundedSlot));
- }
- }
-
- test_class_notSimplyBoundedSlot_complex_by_reference_to_cycle() {
- var cls =
- serializeClassText('class C<T extends D> {} class D<T extends D> {}');
- if (!skipFullyLinkedData) {
- expect(
- linked.units[0].notSimplyBounded, contains(cls.notSimplyBoundedSlot));
- }
- }
-
- test_class_notSimplyBoundedSlot_complex_by_use_of_parameter() {
- var cls = serializeClassText('class C<T extends D<T>> {} class D<T> {}');
- if (!skipFullyLinkedData) {
- expect(
- linked.units[0].notSimplyBounded, contains(cls.notSimplyBoundedSlot));
- }
- }
-
- test_class_notSimplyBoundedSlot_simple_because_non_generic() {
- // If no type parameters are specified, then the class is simply bounded, so
- // there is no reason to assign it a slot.
- var cls = serializeClassText('class C {}');
- expect(cls.notSimplyBoundedSlot, 0);
- }
-
- test_class_notSimplyBoundedSlot_simple_by_lack_of_cycles() {
- var cls = serializeClassText('class C<T extends D> {} class D<T> {}');
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- isNot(contains(cls.notSimplyBoundedSlot)));
- }
- }
-
- test_class_notSimplyBoundedSlot_simple_by_syntax() {
- // If no bounds are specified, then the class is simply bounded by syntax
- // alone, so there is no reason to assign it a slot.
- var cls = serializeClassText('class C<T> {}');
- expect(cls.notSimplyBoundedSlot, 0);
- }
-
- test_class_private() {
- serializeClassText('class _C {}', className: '_C');
- expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
- }
-
- test_class_reference_generic() {
- EntityRef typeRef =
- serializeTypeText('C', otherDeclarations: 'class C<D, E> {}');
- checkTypeRef(typeRef, null, 'C', numTypeParameters: 2);
- }
-
- test_class_reference_generic_imported() {
- addNamedSource('/lib.dart', 'class C<D, E> {}');
- EntityRef typeRef =
- serializeTypeText('C', otherDeclarations: 'import "lib.dart";');
- checkTypeRef(typeRef, absUri('/lib.dart'), 'C', numTypeParameters: 2);
- }
-
- test_class_superclass() {
- UnlinkedClass cls = serializeClassText('class C {}');
- expect(cls.supertype, isNull);
- expect(cls.hasNoSupertype, isFalse);
- }
-
- test_class_superclass_explicit() {
- UnlinkedClass cls = serializeClassText('class C extends D {} class D {}');
- expect(cls.supertype, isNotNull);
- checkTypeRef(cls.supertype, null, 'D');
- expect(cls.hasNoSupertype, isFalse);
- }
-
- test_class_type_param_bound() {
- UnlinkedClass cls = serializeClassText('class C<T extends List> {}');
- expect(cls.typeParameters, hasLength(1));
- {
- UnlinkedTypeParam typeParameter = cls.typeParameters[0];
- expect(typeParameter.name, 'T');
- expect(typeParameter.bound, isNotNull);
- checkTypeRef(typeParameter.bound, 'dart:core', 'List',
- numTypeParameters: 1);
- }
- }
-
- test_class_type_param_f_bound() {
- UnlinkedClass cls = serializeClassText('class C<T, U extends List<T>> {}');
- EntityRef typeArgument = cls.typeParameters[1].bound.typeArguments[0];
- checkParamTypeRef(typeArgument, 2);
- }
-
- test_class_type_param_f_bound_self_ref() {
- UnlinkedClass cls = serializeClassText('class C<T, U extends List<U>> {}');
- EntityRef typeArgument = cls.typeParameters[1].bound.typeArguments[0];
- checkParamTypeRef(typeArgument, 1);
- }
-
- test_class_type_param_no_bound() {
- String text = 'class C<T> {}';
- UnlinkedClass cls = serializeClassText(text);
- expect(cls.typeParameters, hasLength(1));
- expect(cls.typeParameters[0].name, 'T');
- expect(cls.typeParameters[0].nameOffset, text.indexOf('T'));
- expect(cls.typeParameters[0].bound, isNull);
- expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
- }
-
- test_closure_executable_with_bottom_return_type() {
- UnlinkedVariable variable = serializeVariableText('var v = (() => null);');
- UnlinkedExecutable closure;
- {
- UnlinkedExecutable executable = variable.initializer;
- expect(executable.localFunctions, hasLength(1));
- expect(executable.localFunctions[0].returnType, isNull);
- closure = executable.localFunctions[0];
- }
- // Strong mode infers a type for the closure of `() => Null`.
- checkInferredTypeSlot(closure.inferredReturnTypeSlot, 'dart:core', 'Null');
- }
-
- test_closure_executable_with_imported_return_type() {
- addNamedSource('/a.dart', 'class C { D d; } class D {}');
- // The closure has type `() => D`; `D` is defined in a library that is
- // imported.
- UnlinkedExecutable executable = serializeVariableText(r'''
-import "a.dart";
-var v = (() {
- print((() => new C().d)());
-});
-''').initializer.localFunctions[0];
- expect(executable.localFunctions, hasLength(1));
- expect(executable.localFunctions[0].returnType, isNull);
- checkInferredTypeSlot(executable.localFunctions[0].inferredReturnTypeSlot,
- absUri('/a.dart'), 'D',
- onlyInStrongMode: false);
- checkHasDependency(absUri('/a.dart'), fullyLinked: false);
- }
-
- test_closure_executable_with_return_type_from_closure() {
- if (skipFullyLinkedData) {
- return;
- }
- // The closure has type `() => () => int`, where the `() => int` part refers
- // to the nested closure.
- UnlinkedExecutable executable = serializeExecutableText('''
-f() {
- print(() {}); // force the closure below to have index 1
- print(() => () => 0);
-}
-''');
- expect(executable.localFunctions, hasLength(2));
- EntityRef closureType =
- getTypeRefForSlot(executable.localFunctions[1].inferredReturnTypeSlot);
- checkLinkedTypeRef(closureType, null, '',
- expectedKind: ReferenceKind.function);
- int outerClosureIndex =
- definingUnit.references[closureType.reference].containingReference;
- checkReferenceIndex(outerClosureIndex, null, '',
- expectedKind: ReferenceKind.function);
- int topLevelFunctionIndex =
- definingUnit.references[outerClosureIndex].containingReference;
- checkReferenceIndex(topLevelFunctionIndex, null, 'f',
- expectedKind: ReferenceKind.topLevelFunction);
- expect(
- definingUnit.references[topLevelFunctionIndex].containingReference, 0);
- }
-
- test_closure_executable_with_unimported_return_type() {
- addNamedSource('/a.dart', 'import "b.dart"; class C { D d; }');
- addNamedSource('/b.dart', 'class D {}');
- // The closure has type `() => D`; `D` is defined in a library that is not
- // imported.
- UnlinkedExecutable executable = serializeVariableText(r'''
-import "a.dart";
-var v = (() {
- print((() => new C().d)());
-});
-''').initializer.localFunctions[0];
- expect(executable.localFunctions, hasLength(1));
- expect(executable.localFunctions[0].returnType, isNull);
- checkInferredTypeSlot(executable.localFunctions[0].inferredReturnTypeSlot,
- absUri('/b.dart'), 'D',
- onlyInStrongMode: false);
- if (!skipFullyLinkedData) {
- checkHasDependency('b.dart', fullyLinked: true);
- }
- }
-
- test_compilationUnit_nnbd_disabled_via_dart_directive() {
- featureSet = enableNnbd;
- serializeLibraryText('''
-// @dart=2.2
-''');
- expect(unlinkedUnits[0].isNNBD, false);
- }
-
- test_compilationUnit_nnbd_disabled_via_feature_set() {
- featureSet = disableNnbd;
- serializeLibraryText('');
- expect(unlinkedUnits[0].isNNBD, false);
- }
-
- test_compilationUnit_nnbd_enabled() {
- featureSet = enableNnbd;
- serializeLibraryText('');
- expect(unlinkedUnits[0].isNNBD, true);
- }
-
- test_constExpr_binary_add() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 + 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 + 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.add
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_and() {
- UnlinkedVariable variable =
- serializeVariableText('const v = true && false;');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'true && false',
- operators: [
- UnlinkedExprOperation.pushTrue,
- UnlinkedExprOperation.pushFalse,
- UnlinkedExprOperation.and
- ]);
- }
-
- test_constExpr_binary_bitAnd() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 & 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 & 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.bitAnd
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_bitOr() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 | 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 | 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.bitOr
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_bitShiftLeft() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 << 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 << 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.bitShiftLeft
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_bitShiftRight() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 >> 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 >> 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.bitShiftRight
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_bitShiftRightLogical() {
- featureSet = FeatureSet.forTesting(
- sdkVersion: '2.2.2',
- additionalFeatures: [
- Feature.constant_update_2018,
- Feature.triple_shift
- ]);
- UnlinkedVariable variable = serializeVariableText('const v = 1 >>> 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 >>> 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.bitShiftRightLogical
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_bitXor() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 ^ 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 ^ 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.bitXor
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_divide() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 / 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 / 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.divide
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_equal() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 == 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 == 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.equal
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_equal_not() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 != 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 != 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.notEqual
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_floorDivide() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 ~/ 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 ~/ 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.floorDivide
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_greater() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 > 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 > 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.greater
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_greaterEqual() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 >= 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 >= 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.greaterEqual
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_less() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 < 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 < 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_lessEqual() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 <= 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 <= 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.lessEqual
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_modulo() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 % 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 % 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.modulo
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_multiply() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 * 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 * 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.multiply
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_or() {
- UnlinkedVariable variable =
- serializeVariableText('const v = false || true;');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'false || true',
- operators: [
- UnlinkedExprOperation.pushFalse,
- UnlinkedExprOperation.pushTrue,
- UnlinkedExprOperation.or
- ]);
- }
-
- test_constExpr_binary_qq() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 ?? 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 ?? 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.ifNull
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_binary_subtract() {
- UnlinkedVariable variable = serializeVariableText('const v = 1 - 2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 - 2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.subtract
- ], ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_classMember_shadows_typeParam() {
- // Although it is an error for a class member to have the same name as a
- // type parameter, the spec makes it clear that the class member scope is
- // nested inside the type parameter scope. So go ahead and verify that
- // the class member shadows the type parameter.
- String text = '''
-class C<T> {
- static const T = null;
- final x;
- const C() : x = T;
-}
-''';
- UnlinkedClass cls = serializeClassText(text, allowErrors: true);
- assertUnlinkedConst(
- cls.executables[0].constantInitializers[0].expression, 'T',
- operators: [
- UnlinkedExprOperation.pushReference
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'T',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- numTypeParameters: 1)
- ])
- ]);
- }
-
- test_constExpr_conditional() {
- UnlinkedVariable variable =
- serializeVariableText('const v = true ? 1 : 2;', allowErrors: true);
- assertUnlinkedConst(variable.initializer.bodyExpr, 'true ? 1 : 2',
- operators: [
- UnlinkedExprOperation.pushTrue,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.conditional
- ],
- ints: [
- 1,
- 2
- ]);
- }
-
- test_constExpr_constructorParam_shadows_classMember() {
- UnlinkedClass cls = serializeClassText('''
-class C {
- static const a = null;
- final b;
- const C(a) : b = a;
-}
-''');
- assertUnlinkedConst(
- cls.executables[0].constantInitializers[0].expression, 'a',
- operators: [UnlinkedExprOperation.pushParameter], strings: ['a']);
- }
-
- test_constExpr_constructorParam_shadows_typeParam() {
- UnlinkedClass cls = serializeClassText('''
-class C<T> {
- final x;
- const C(T) : x = T;
-}
-''');
- assertUnlinkedConst(
- cls.executables[0].constantInitializers[0].expression, 'T',
- operators: [UnlinkedExprOperation.pushParameter], strings: ['T']);
- }
-
- test_constExpr_function_type_arg_nullability_suffix_none() {
- featureSet = enableNnbd;
- var variable =
- serializeVariableText('const v = const <void Function()>[];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const <void Function()>[]', operators: [
- UnlinkedExprOperation.makeTypedList
- ], ints: [
- 0
- ], referenceValidators: [
- (EntityRef r) =>
- expect(r.nullabilitySuffix, EntityRefNullabilitySuffix.none)
- ]);
- }
-
- test_constExpr_function_type_arg_nullability_suffix_question() {
- featureSet = enableNnbd;
- var variable =
- serializeVariableText('const v = const <void Function()?>[];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const <void Function()?>[]',
- operators: [
- UnlinkedExprOperation.makeTypedList
- ],
- ints: [
- 0
- ],
- referenceValidators: [
- (EntityRef r) =>
- expect(r.nullabilitySuffix, EntityRefNullabilitySuffix.question)
- ]);
- }
-
- test_constExpr_function_type_arg_nullability_suffix_star() {
- featureSet = disableNnbd;
- var variable =
- serializeVariableText('const v = const <void Function()>[];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const <void Function()>[]',
- operators: [
- UnlinkedExprOperation.makeTypedList
- ],
- ints: [
- 0
- ],
- referenceValidators: [
- (EntityRef r) => expect(
- r.nullabilitySuffix, EntityRefNullabilitySuffix.starOrIrrelevant)
- ]);
- }
-
- test_constExpr_functionExpression() {
- UnlinkedVariable variable = serializeVariableText('''
-import 'dart:async';
-var v = (f) async => await f;
-''');
- assertUnlinkedConst(
- variable.initializer.localFunctions[0].bodyExpr, 'await f',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.await
- ],
- strings: ['f'],
- ints: [],
- forTypeInferenceOnly: true);
- }
-
- test_constExpr_functionExpression_asArgument() {
- // Even though function expressions are not allowed in constant
- // declarations, they might occur due to erroneous code, so make sure they
- // function correctly.
- UnlinkedVariable variable = serializeVariableText('''
-const v = foo(5, () => 42);
-foo(a, b) {}
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'foo(5, () => 42)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushLocalFunctionReference,
- UnlinkedExprOperation.invokeMethodRef
- ],
- ints: [
- 5,
- 0,
- 0,
- 0,
- 2,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.topLevelFunction)
- ]);
- }
-
- test_constExpr_functionExpression_asArgument_multiple() {
- // Even though function expressions are not allowed in constant
- // declarations, they might occur due to erroneous code, so make sure they
- // function correctly.
- UnlinkedVariable variable = serializeVariableText('''
-const v = foo(5, () => 42, () => 43);
-foo(a, b, c) {}
-''');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'foo(5, () => 42, () => 43)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushLocalFunctionReference,
- UnlinkedExprOperation.pushLocalFunctionReference,
- UnlinkedExprOperation.invokeMethodRef
- ],
- ints: [
- 5,
- 0,
- 0,
- 0,
- 1,
- 0,
- 3,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.topLevelFunction)
- ]);
- }
-
- test_constExpr_functionExpression_inConstructorInitializers() {
- // Even though function expressions are not allowed in constant
- // declarations, they might occur due to erroneous code, so make sure they
- // function correctly.
- UnlinkedExecutable executable = serializeClassText('''
-class C {
- final x, y;
- const C() : x = (() => 42), y = (() => 43);
-}
-''').executables[0];
- expect(executable.localFunctions, hasLength(2));
- assertUnlinkedConst(
- executable.constantInitializers[0].expression, '(() => 42)',
- isValidConst: false,
- operators: [UnlinkedExprOperation.pushLocalFunctionReference],
- ints: [0, 0]);
- assertUnlinkedConst(
- executable.constantInitializers[1].expression, '(() => 43)',
- isValidConst: false,
- operators: [UnlinkedExprOperation.pushLocalFunctionReference],
- ints: [0, 1]);
- }
-
- test_constExpr_invokeConstructor_generic_named() {
- UnlinkedVariable variable = serializeVariableText('''
-class C<K, V> {
- const C.named();
-}
-const v = const C<int, String>.named();
-''');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const C<int, String>.named()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) {
- checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- numTypeParameters: 2)
- ],
- numTypeArguments: 2);
- checkTypeRef(r.typeArguments[0], 'dart:core', 'int');
- checkTypeRef(r.typeArguments[1], 'dart:core', 'String');
- }
- ]);
- }
-
- test_constExpr_invokeConstructor_generic_named_imported() {
- addNamedSource('/a.dart', '''
-class C<K, V> {
- const C.named();
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = const C<int, String>.named();
-''');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const C<int, String>.named()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) {
- checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart'), numTypeParameters: 2)
- ],
- numTypeArguments: 2);
- checkTypeRef(r.typeArguments[0], 'dart:core', 'int');
- checkTypeRef(r.typeArguments[1], 'dart:core', 'String');
- }
- ]);
- }
-
- test_constExpr_invokeConstructor_generic_named_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-class C<K, V> {
- const C.named();
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = const p.C<int, String>.named();
-''');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const p.C<int, String>.named()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) {
- checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart'), numTypeParameters: 2),
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ],
- numTypeArguments: 2);
- checkTypeRef(r.typeArguments[0], 'dart:core', 'int');
- checkTypeRef(r.typeArguments[1], 'dart:core', 'String');
- }
- ]);
- }
-
- test_constExpr_invokeConstructor_generic_unnamed() {
- UnlinkedVariable variable = serializeVariableText('''
-class C<K, V> {
- const C();
-}
-const v = const C<int, String>();
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const C<int, String>()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) {
- checkTypeRef(r, null, 'C',
- expectedKind: ReferenceKind.classOrEnum,
- numTypeParameters: 2,
- numTypeArguments: 2);
- checkTypeRef(r.typeArguments[0], 'dart:core', 'int');
- checkTypeRef(r.typeArguments[1], 'dart:core', 'String');
- }
- ]);
- }
-
- test_constExpr_invokeConstructor_generic_unnamed_imported() {
- addNamedSource('/a.dart', '''
-class C<K, V> {
- const C();
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = const C<int, String>();
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const C<int, String>()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) {
- checkTypeRef(r, absUri('/a.dart'), 'C',
- expectedKind: ReferenceKind.classOrEnum,
- numTypeParameters: 2,
- numTypeArguments: 2);
- checkTypeRef(r.typeArguments[0], 'dart:core', 'int');
- checkTypeRef(r.typeArguments[1], 'dart:core', 'String');
- }
- ]);
- }
-
- test_constExpr_invokeConstructor_generic_unnamed_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-class C<K, V> {
- const C();
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = const p.C<int, String>();
-''');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const p.C<int, String>()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) {
- checkTypeRef(r, absUri('/a.dart'), 'C',
- expectedKind: ReferenceKind.classOrEnum,
- numTypeParameters: 2,
- numTypeArguments: 2,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ]);
- checkTypeRef(r.typeArguments[0], 'dart:core', 'int');
- checkTypeRef(r.typeArguments[1], 'dart:core', 'String');
- }
- ]);
- }
-
- test_constExpr_invokeConstructor_named() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- const C.named();
-}
-const v = const C.named();
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const C.named()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_invokeConstructor_named_imported() {
- addNamedSource('/a.dart', '''
-class C {
- const C.named();
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = const C.named();
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const C.named()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart'))
- ])
- ]);
- }
-
- test_constExpr_invokeConstructor_named_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-class C {
- const C.named();
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = const p.C.named();
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const p.C.named()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart')),
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ]);
- }
-
- test_constExpr_invokeConstructor_unnamed() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- const C(a, b, c, d, {e, f, g});
-}
-const v = const C(11, 22, 3.3, '444', e: 55, g: '777', f: 66);
-''');
- // Stack: 11 22 3.3 '444' 55 '777' 66 ^head
- // Ints: ^pointer 3 4
- // Doubles: ^pointer
- // Strings: ^pointer 'e' 'g' 'f' ''
- assertUnlinkedConst(variable.initializer.bodyExpr,
- "const C(11, 22, 3.3, '444', e: 55, g: '777', f: 66)",
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushDouble,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 11,
- 22,
- 55,
- 66,
- 3,
- 4,
- ],
- doubles: [
- 3.3
- ],
- strings: [
- '444',
- '777',
- 'e',
- 'g',
- 'f'
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'C',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_invokeConstructor_unnamed_imported() {
- addNamedSource('/a.dart', '''
-class C {
- const C();
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = const C();
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const C()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'C',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_invokeConstructor_unnamed_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-class C {
- const C();
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = const p.C();
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const p.C()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'C',
- expectedKind: ReferenceKind.classOrEnum,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ]);
- }
-
- test_constExpr_invokeConstructor_unresolved_named() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {}
-const v = const C.foo();
-''', allowErrors: true);
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const C.foo()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_invokeConstructor_unresolved_named2() {
- UnlinkedVariable variable = serializeVariableText('''
-const v = const C.foo();
-''', allowErrors: true);
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const C.foo()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.unresolved, 'C')
- ])
- ]);
- }
-
- test_constExpr_invokeConstructor_unresolved_named_prefixed() {
- addNamedSource('/a.dart', '''
-class C {
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = const p.C.foo();
-''', allowErrors: true);
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const p.C.foo()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart')),
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ]);
- }
-
- test_constExpr_invokeConstructor_unresolved_named_prefixed2() {
- addNamedSource('/a.dart', '');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = const p.C.foo();
-''', allowErrors: true);
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const p.C.foo()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.unresolved, 'C'),
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ]);
- }
-
- test_constExpr_invokeConstructor_unresolved_unnamed() {
- UnlinkedVariable variable = serializeVariableText('''
-const v = const Foo();
-''', allowErrors: true);
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const Foo()',
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- ints: [
- 0,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'Foo',
- expectedKind: ReferenceKind.unresolved)
- ]);
- }
-
- test_constExpr_invokeMethodRef_identical() {
- UnlinkedVariable variable =
- serializeVariableText('const v = identical(42, null);');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'identical(42, null)',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushNull,
- UnlinkedExprOperation.invokeMethodRef
- ],
- ints: [
- 42,
- 0,
- 2,
- 0
- ],
- referenceValidators: [
- (EntityRef r) {
- checkTypeRef(r, 'dart:core', 'identical',
- expectedKind: ReferenceKind.topLevelFunction);
- }
- ]);
- }
-
- test_constExpr_length_classConstField() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- static const int length = 0;
-}
-const int v = C.length;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.length', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'length',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_length_classConstField_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-class C {
- static const int length = 0;
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const int v = p.C.length;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'p.C.length',
- operators: [
- UnlinkedExprOperation.pushReference
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'length',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart')),
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ]);
- }
-
- test_constExpr_length_identifierTarget() {
- UnlinkedVariable variable = serializeVariableText('''
-const String a = 'aaa';
-const int v = a.length;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'a.length', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'length',
- expectedKind: ReferenceKind.unresolved,
- unresolvedHasName: true,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.topLevelPropertyAccessor, 'a')
- ])
- ]);
- }
-
- test_constExpr_length_identifierTarget_classConstField() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- static const String F = '';
-}
-const int v = C.F.length;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.F.length',
- operators: [
- UnlinkedExprOperation.pushReference
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'length',
- expectedKind: ReferenceKind.unresolved,
- unresolvedHasName: true,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.propertyAccessor, 'F'),
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C'),
- ])
- ]);
- }
-
- test_constExpr_length_identifierTarget_imported() {
- addNamedSource('/a.dart', '''
-const String a = 'aaa';
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const int v = a.length;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'a.length', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'length',
- expectedKind: ReferenceKind.unresolved,
- unresolvedHasName: true,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.topLevelPropertyAccessor, 'a',
- absoluteUri: absUri('/a.dart'))
- ])
- ]);
- }
-
- test_constExpr_length_identifierTarget_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-const String a = 'aaa';
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const int v = p.a.length;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'p.a.length',
- operators: [
- UnlinkedExprOperation.pushReference
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'length',
- expectedKind: ReferenceKind.unresolved,
- unresolvedHasName: true,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.topLevelPropertyAccessor, 'a',
- absoluteUri: absUri('/a.dart')),
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ]);
- }
-
- test_constExpr_length_parenthesizedBinaryTarget() {
- UnlinkedVariable variable =
- serializeVariableText('const v = ("abc" + "edf").length;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '("abc" + "edf").length',
- operators: [
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.add,
- UnlinkedExprOperation.extractProperty
- ],
- strings: [
- 'abc',
- 'edf',
- 'length'
- ]);
- }
-
- test_constExpr_length_parenthesizedStringTarget() {
- UnlinkedVariable variable =
- serializeVariableText('const v = ("abc").length;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '("abc").length',
- operators: [
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.extractProperty
- ],
- strings: [
- 'abc',
- 'length'
- ]);
- }
-
- test_constExpr_length_stringLiteralTarget() {
- UnlinkedVariable variable =
- serializeVariableText('const v = "abc".length;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '"abc".length',
- operators: [
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.extractProperty
- ],
- strings: [
- 'abc',
- 'length'
- ]);
- }
-
- test_constExpr_list_if() {
- UnlinkedVariable variable =
- serializeVariableText('const v = [if (true) 1];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '[if (true) 1]',
- operators: [
- UnlinkedExprOperation.pushTrue,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.ifElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- ints: [
- 1,
- 1
- ]);
- }
-
- test_constExpr_list_if_else() {
- UnlinkedVariable variable =
- serializeVariableText('const v = [if (true) 1 else 2];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '[if (true) 1 else 2]',
- operators: [
- UnlinkedExprOperation.pushTrue,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.ifElseElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- ints: [
- 1,
- 2,
- 1
- ]);
- }
-
- test_constExpr_list_spread() {
- UnlinkedVariable variable = serializeVariableText('const v = [...[]];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '[...[]]', operators: [
- UnlinkedExprOperation.makeUntypedList,
- UnlinkedExprOperation.spreadElement,
- UnlinkedExprOperation.makeUntypedList
- ], ints: [
- 0,
- 1
- ]);
- }
-
- test_constExpr_list_spread_null_aware() {
- UnlinkedVariable variable = serializeVariableText('const v = [...?[]];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '[...?[]]', operators: [
- UnlinkedExprOperation.makeUntypedList,
- UnlinkedExprOperation.nullAwareSpreadElement,
- UnlinkedExprOperation.makeUntypedList
- ], ints: [
- 0,
- 1
- ]);
- }
-
- test_constExpr_makeSymbol() {
- UnlinkedVariable variable = serializeVariableText('const v = #a.bb.ccc;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '#a.bb.ccc',
- operators: [UnlinkedExprOperation.makeSymbol], strings: ['a.bb.ccc']);
- }
-
- test_constExpr_makeTypedList() {
- UnlinkedVariable variable =
- serializeVariableText('const v = const <int>[11, 22, 33];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const <int>[11, 22, 33]',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeTypedList
- ],
- ints: [
- 11,
- 22,
- 33,
- 3
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_makeTypedList_dynamic() {
- UnlinkedVariable variable =
- serializeVariableText('const v = const <dynamic>[11, 22, 33];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const <dynamic>[11, 22, 33]',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeTypedList
- ],
- ints: [
- 11,
- 22,
- 33,
- 3
- ],
- referenceValidators: [
- (EntityRef r) => checkDynamicTypeRef(r)
- ]);
- }
-
- test_constExpr_makeTypedList_functionType() {
- UnlinkedVariable variable =
- serializeVariableText('final v = <void Function(int)>[];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '<void Function(int)>[]',
- operators: [UnlinkedExprOperation.makeTypedList],
- ints: [
- 0 // Size of the list
- ],
- referenceValidators: [
- (EntityRef reference) {
- expect(reference, new TypeMatcher<EntityRef>());
- expect(reference.entityKind, EntityRefKind.genericFunctionType);
- expect(reference.syntheticParams, hasLength(1));
- {
- final param = reference.syntheticParams[0];
- expect(param.name, ''); // no name for generic type parameters
- checkTypeRef(param.type, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum);
- }
- expect(reference.paramReference, 0);
- expect(reference.typeParameters, hasLength(0));
- // TODO(mfairhurst) check this references void
- expect(reference.syntheticReturnType, isNotNull);
- }
- ],
- forTypeInferenceOnly: true);
- }
-
- test_constExpr_makeTypedList_functionType_withTypeParameters() {
- UnlinkedVariable variable = serializeVariableText(
- 'final v = <void Function<T>(Function<Q>(T, Q))>[];');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- '<void Function<T>(Function<Q>(T, Q))>[]',
- operators: [UnlinkedExprOperation.makeTypedList],
- ints: [
- 0 // Size of the list
- ],
- referenceValidators: [
- (EntityRef reference) {
- expect(reference, new TypeMatcher<EntityRef>());
- expect(reference.entityKind, EntityRefKind.genericFunctionType);
- expect(reference.syntheticParams, hasLength(1));
- {
- final param = reference.syntheticParams[0];
- expect(param.type, new TypeMatcher<EntityRef>());
- expect(param.type.entityKind, EntityRefKind.genericFunctionType);
- expect(param.type.syntheticParams, hasLength(2));
- {
- final subparam = param.type.syntheticParams[0];
- expect(
- subparam.name, ''); // no name for generic type parameters
- expect(subparam.type, new TypeMatcher<EntityRef>());
- expect(subparam.type.paramReference, 2);
- }
- {
- final subparam = param.type.syntheticParams[1];
- expect(
- subparam.name, ''); // no name for generic type parameters
- expect(subparam.type, new TypeMatcher<EntityRef>());
- expect(subparam.type.paramReference, 1);
- }
- }
- expect(reference.paramReference, 0);
- expect(reference.typeParameters, hasLength(1));
- // TODO(mfairhurst) check this references void
- expect(reference.syntheticReturnType, isNotNull);
- }
- ],
- forTypeInferenceOnly: true);
- }
-
- test_constExpr_makeTypedMap() {
- UnlinkedVariable variable = serializeVariableText(
- 'const v = const <int, String>{11: "aaa", 22: "bbb", 33: "ccc"};');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- 'const <int, String>{11: "aaa", 22: "bbb", 33: "ccc"}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.makeTypedMap2
- ],
- ints: [
- 11,
- 22,
- 33,
- 3
- ],
- strings: [
- 'aaa',
- 'bbb',
- 'ccc'
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_makeTypedMap_dynamic() {
- UnlinkedVariable variable = serializeVariableText(
- 'const v = const <dynamic, dynamic>{11: "aaa", 22: "bbb", 33: "ccc"};');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- 'const <dynamic, dynamic>{11: "aaa", 22: "bbb", 33: "ccc"}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.makeTypedMap2
- ],
- ints: [
- 11,
- 22,
- 33,
- 3
- ],
- strings: [
- 'aaa',
- 'bbb',
- 'ccc'
- ],
- referenceValidators: [
- (EntityRef r) => checkDynamicTypeRef(r),
- (EntityRef r) => checkDynamicTypeRef(r)
- ]);
- }
-
- test_constExpr_makeTypedSet() {
- UnlinkedVariable variable =
- serializeVariableText('const v = const <int>{11, 22, 33};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr,
- 'const <int>{11, 22, 33}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeTypedSet
- ],
- ints: [11, 22, 33, 3],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- );
- }
-
- test_constExpr_makeTypedSet_dynamic() {
- UnlinkedVariable variable =
- serializeVariableText('const v = const <dynamic>{11, 22, 33};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr,
- 'const <dynamic>{11, 22, 33}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeTypedSet
- ],
- ints: [11, 22, 33, 3],
- referenceValidators: [(EntityRef r) => checkDynamicTypeRef(r)],
- );
- }
-
- test_constExpr_makeTypedSet_functionType() {
- UnlinkedVariable variable =
- serializeVariableText('final v = <void Function(int)>{};');
- assertUnlinkedConst(variable.initializer.bodyExpr, '<void Function(int)>{}',
- operators: [UnlinkedExprOperation.makeTypedSet],
- ints: [
- 0 // Size of the list
- ],
- referenceValidators: [
- (EntityRef reference) {
- expect(reference, new TypeMatcher<EntityRef>());
- expect(reference.entityKind, EntityRefKind.genericFunctionType);
- expect(reference.syntheticParams, hasLength(1));
- {
- final param = reference.syntheticParams[0];
- expect(param.name, ''); // no name for generic type parameters
- checkTypeRef(param.type, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum);
- }
- expect(reference.paramReference, 0);
- expect(reference.typeParameters, hasLength(0));
- // TODO(mfairhurst) check this references void
- expect(reference.syntheticReturnType, isNotNull);
- }
- ],
- forTypeInferenceOnly: true);
- }
-
- test_constExpr_makeTypedSet_functionType_withTypeParameters() {
- UnlinkedVariable variable = serializeVariableText(
- 'final v = <void Function<T>(Function<Q>(T, Q))>{};');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- '<void Function<T>(Function<Q>(T, Q))>{}',
- operators: [UnlinkedExprOperation.makeTypedSet],
- ints: [
- 0 // Size of the list
- ],
- referenceValidators: [
- (EntityRef reference) {
- expect(reference, new TypeMatcher<EntityRef>());
- expect(reference.entityKind, EntityRefKind.genericFunctionType);
- expect(reference.syntheticParams, hasLength(1));
- {
- final param = reference.syntheticParams[0];
- expect(param.type, new TypeMatcher<EntityRef>());
- expect(param.type.entityKind, EntityRefKind.genericFunctionType);
- expect(param.type.syntheticParams, hasLength(2));
- {
- final subparam = param.type.syntheticParams[0];
- expect(
- subparam.name, ''); // no name for generic type parameters
- expect(subparam.type, new TypeMatcher<EntityRef>());
- expect(subparam.type.paramReference, 2);
- }
- {
- final subparam = param.type.syntheticParams[1];
- expect(
- subparam.name, ''); // no name for generic type parameters
- expect(subparam.type, new TypeMatcher<EntityRef>());
- expect(subparam.type.paramReference, 1);
- }
- }
- expect(reference.paramReference, 0);
- expect(reference.typeParameters, hasLength(1));
- // TODO(mfairhurst) check this references void
- expect(reference.syntheticReturnType, isNotNull);
- }
- ],
- forTypeInferenceOnly: true);
- }
-
- test_constExpr_makeUntypedList() {
- UnlinkedVariable variable =
- serializeVariableText('const v = const [11, 22, 33];');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const [11, 22, 33]',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeUntypedList
- ],
- ints: [
- 11,
- 22,
- 33,
- 3
- ]);
- }
-
- test_constExpr_makeUntypedMap() {
- UnlinkedVariable variable = serializeVariableText(
- 'const v = const {11: "aaa", 22: "bbb", 33: "ccc"};');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- 'const {11: "aaa", 22: "bbb", 33: "ccc"}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.makeUntypedSetOrMap
- ],
- ints: [
- 11,
- 22,
- 33,
- 3
- ],
- strings: [
- 'aaa',
- 'bbb',
- 'ccc'
- ]);
- }
-
- test_constExpr_makeUntypedSet() {
- UnlinkedVariable variable =
- serializeVariableText('const v = const {11, 22, 33};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr,
- 'const {11, 22, 33}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeUntypedSetOrMap
- ],
- ints: [11, 22, 33, 3],
- );
- }
-
- test_constExpr_map_if() {
- UnlinkedVariable variable =
- serializeVariableText('const v = <int, int>{if (true) 1 : 2};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '<int, int>{if (true) 1 : 2}',
- operators: [
- UnlinkedExprOperation.pushTrue,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.ifElement,
- UnlinkedExprOperation.makeTypedMap2
- ],
- ints: [
- 1,
- 2,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_map_if_else() {
- UnlinkedVariable variable = serializeVariableText(
- 'const v = <int, int>{if (true) 1 : 2 else 3 : 4};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '<int, int>{if (true) 1 : 2 else 3 : 4}',
- operators: [
- UnlinkedExprOperation.pushTrue,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.ifElseElement,
- UnlinkedExprOperation.makeTypedMap2
- ],
- ints: [
- 1,
- 2,
- 3,
- 4,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_map_spread() {
- UnlinkedVariable variable =
- serializeVariableText('const v = <int, String>{...<int, String>{}};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '<int, String>{...<int, String>{}}',
- operators: [
- UnlinkedExprOperation.makeTypedMap2,
- UnlinkedExprOperation.spreadElement,
- UnlinkedExprOperation.makeTypedMap2
- ],
- ints: [
- 0,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_map_spread_null_aware() {
- UnlinkedVariable variable =
- serializeVariableText('const v = <int, String>{...?<int, String>{}};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '<int, String>{...?<int, String>{}}',
- operators: [
- UnlinkedExprOperation.makeTypedMap2,
- UnlinkedExprOperation.nullAwareSpreadElement,
- UnlinkedExprOperation.makeTypedMap2
- ],
- ints: [
- 0,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_parenthesized() {
- UnlinkedVariable variable = serializeVariableText('const v = (1 + 2) * 3;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '(1 + 2) * 3',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.add,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.multiply,
- ],
- ints: [
- 1,
- 2,
- 3
- ]);
- }
-
- test_constExpr_prefix_complement() {
- UnlinkedVariable variable = serializeVariableText('const v = ~2;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '~2', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.complement
- ], ints: [
- 2
- ]);
- }
-
- test_constExpr_prefix_negate() {
- UnlinkedVariable variable = serializeVariableText('const v = -(2);');
- assertUnlinkedConst(variable.initializer.bodyExpr, '-(2)', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.negate
- ], ints: [
- 2
- ]);
- }
-
- test_constExpr_prefix_not() {
- UnlinkedVariable variable = serializeVariableText('const v = !true;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '!true',
- operators: [UnlinkedExprOperation.pushTrue, UnlinkedExprOperation.not]);
- }
-
- test_constExpr_pushDouble() {
- UnlinkedVariable variable = serializeVariableText('const v = 123.4567;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '123.4567',
- operators: [UnlinkedExprOperation.pushDouble], doubles: [123.4567]);
- }
-
- test_constExpr_pushFalse() {
- UnlinkedVariable variable = serializeVariableText('const v = false;');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'false',
- operators: [UnlinkedExprOperation.pushFalse]);
- }
-
- test_constExpr_pushInt() {
- UnlinkedVariable variable = serializeVariableText('const v = 1;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '1',
- operators: [UnlinkedExprOperation.pushInt], ints: [1]);
- }
-
- test_constExpr_pushInt_max() {
- UnlinkedVariable variable = serializeVariableText('const v = 0xFFFFFFFF;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '0xFFFFFFFF',
- operators: [
- UnlinkedExprOperation.pushInt,
- ],
- ints: [
- 0xFFFFFFFF
- ]);
- }
-
- test_constExpr_pushInt_negative() {
- UnlinkedVariable variable = serializeVariableText('const v = -5;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '-5', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.negate
- ], ints: [
- 5
- ]);
- }
-
- test_constExpr_pushLongInt_maxNegative() {
- UnlinkedVariable variable =
- serializeVariableText('const v = 0xFFFFFFFFFFFFFFFF;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '0xFFFFFFFFFFFFFFFF',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.negate
- ],
- ints: [
- 1
- ]);
- }
-
- test_constExpr_pushLongInt_maxPositive() {
- UnlinkedVariable variable =
- serializeVariableText('const v = 0x7FFFFFFFFFFFFFFF;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '0x7FFFFFFFFFFFFFFF',
- operators: [UnlinkedExprOperation.pushLongInt],
- ints: [2, 0x7FFFFFFF, 0xFFFFFFFF]);
- }
-
- test_constExpr_pushLongInt_min2() {
- UnlinkedVariable variable = serializeVariableText('const v = 0x100000000;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '0x100000000',
- operators: [
- UnlinkedExprOperation.pushLongInt
- ],
- ints: [
- 2,
- 1,
- 0,
- ]);
- }
-
- test_constExpr_pushLongInt_tooLong() {
- UnlinkedVariable variable =
- serializeVariableText('const v = 0x10000000000000000;');
- assertUnlinkedConst(variable.initializer.bodyExpr, '0x10000000000000000',
- operators: [UnlinkedExprOperation.pushInt], ints: [0]);
- }
-
- test_constExpr_pushNull() {
- UnlinkedVariable variable = serializeVariableText('const v = null;');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'null',
- operators: [UnlinkedExprOperation.pushNull]);
- }
-
- test_constExpr_pushReference_class() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {}
-const v = C;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) =>
- checkTypeRef(r, null, 'C', expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_pushReference_enum() {
- UnlinkedVariable variable = serializeVariableText('''
-enum C {V1, V2, V3}
-const v = C;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) =>
- checkTypeRef(r, null, 'C', expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_pushReference_enumValue() {
- UnlinkedVariable variable = serializeVariableText('''
-enum C {V1, V2, V3}
-const v = C.V1;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.V1', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'V1',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_pushReference_enumValue_viaImport() {
- addNamedSource('/a.dart', '''
-enum C {V1, V2, V3}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = C.V1;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.V1', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'V1',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart'))
- ])
- ]);
- }
-
- test_constExpr_pushReference_enumValues() {
- UnlinkedVariable variable = serializeVariableText('''
-enum C {V1, V2, V3}
-const v = C.values;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.values', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'values',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_pushReference_enumValues_viaImport() {
- addNamedSource('/a.dart', '''
-enum C {V1, V2, V3}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = C.values;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.values', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'values',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart'))
- ])
- ]);
- }
-
- test_constExpr_pushReference_field() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- static const int F = 1;
-}
-const v = C.F;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.F', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'F',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_pushReference_field_imported() {
- addNamedSource('/a.dart', '''
-class C {
- static const int F = 1;
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = C.F;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.F', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'F',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart'))
- ])
- ]);
- }
-
- test_constExpr_pushReference_field_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-class C {
- static const int F = 1;
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = p.C.F;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'p.C.F', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'F',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart')),
- new _PrefixExpectation(ReferenceKind.prefix, 'p'),
- ])
- ]);
- }
-
- test_constExpr_pushReference_field_simpleIdentifier() {
- UnlinkedVariable variable = serializeClassText('''
-class C {
- static const a = b;
- static const b = null;
-}
-''').fields[0];
- assertUnlinkedConst(variable.initializer.bodyExpr, 'b', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'b',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_pushReference_staticGetter() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- static int get x => null;
-}
-const v = C.x;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.x', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'x',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_pushReference_staticGetter_imported() {
- addNamedSource('/a.dart', '''
-class C {
- static int get x => null;
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = C.x;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.x', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'x',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart'))
- ])
- ]);
- }
-
- test_constExpr_pushReference_staticGetter_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-class C {
- static int get x => null;
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = p.C.x;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'p.C.x', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'x',
- expectedKind: ReferenceKind.propertyAccessor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart')),
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ]);
- }
-
- test_constExpr_pushReference_staticMethod() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- static m() {}
-}
-const v = C.m;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.m', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'm',
- expectedKind: ReferenceKind.method,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_pushReference_staticMethod_imported() {
- addNamedSource('/a.dart', '''
-class C {
- static m() {}
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = C.m;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.m', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'm',
- expectedKind: ReferenceKind.method,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart'))
- ])
- ]);
- }
-
- test_constExpr_pushReference_staticMethod_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-class C {
- static m() {}
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = p.C.m;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'p.C.m', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'm',
- expectedKind: ReferenceKind.method,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart')),
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ]);
- }
-
- test_constExpr_pushReference_staticMethod_simpleIdentifier() {
- UnlinkedVariable variable = serializeClassText('''
-class C {
- static const a = m;
- static m() {}
-}
-''').fields[0];
- assertUnlinkedConst(variable.initializer.bodyExpr, 'm', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'm',
- expectedKind: ReferenceKind.method,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_pushReference_topLevelFunction() {
- UnlinkedVariable variable = serializeVariableText('''
-f() {}
-const v = f;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'f', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'f',
- expectedKind: ReferenceKind.topLevelFunction)
- ]);
- }
-
- test_constExpr_pushReference_topLevelFunction_imported() {
- addNamedSource('/a.dart', '''
-f() {}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = f;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'f', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'f',
- expectedKind: ReferenceKind.topLevelFunction)
- ]);
- }
-
- test_constExpr_pushReference_topLevelFunction_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-f() {}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = p.f;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'p.f', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'f',
- expectedKind: ReferenceKind.topLevelFunction,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ]);
- }
-
- test_constExpr_pushReference_topLevelGetter() {
- UnlinkedVariable variable = serializeVariableText('''
-int get x => null;
-const v = x;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'x', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'x',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_constExpr_pushReference_topLevelGetter_imported() {
- addNamedSource('/a.dart', 'int get x => null;');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = x;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'x', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'x',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_constExpr_pushReference_topLevelGetter_imported_withPrefix() {
- addNamedSource('/a.dart', 'int get x => null;');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = p.x;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'p.x', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'x',
- expectedKind: ReferenceKind.topLevelPropertyAccessor,
- expectedPrefix: 'p')
- ]);
- }
-
- test_constExpr_pushReference_topLevelVariable() {
- UnlinkedVariable variable = serializeVariableText('''
-const int a = 1;
-const v = a;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'a', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_constExpr_pushReference_topLevelVariable_imported() {
- addNamedSource('/a.dart', 'const int a = 1;');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-const v = a;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'a', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_constExpr_pushReference_topLevelVariable_imported_withPrefix() {
- addNamedSource('/a.dart', 'const int a = 1;');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = p.a;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'p.a', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) {
- return checkTypeRef(r, absUri('/a.dart'), 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor,
- expectedPrefix: 'p');
- }
- ]);
- }
-
- test_constExpr_pushReference_typeParameter() {
- String text = '''
-class C<T> {
- static const a = T;
-}
-''';
- UnlinkedVariable variable =
- serializeClassText(text, allowErrors: true).fields[0];
- assertUnlinkedConst(variable.initializer.bodyExpr, 'T', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) {
- return checkParamTypeRef(r, 1);
- }
- ]);
- }
-
- test_constExpr_pushReference_unresolved_prefix0() {
- UnlinkedVariable variable = serializeVariableText('''
-const v = foo;
-''', allowErrors: true);
- assertUnlinkedConst(variable.initializer.bodyExpr, 'foo', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) =>
- checkTypeRef(r, null, 'foo', expectedKind: ReferenceKind.unresolved)
- ]);
- }
-
- test_constExpr_pushReference_unresolved_prefix1() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {}
-const v = C.foo;
-''', allowErrors: true);
- assertUnlinkedConst(variable.initializer.bodyExpr, 'C.foo', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- }
-
- test_constExpr_pushReference_unresolved_prefix2() {
- addNamedSource('/a.dart', '''
-class C {}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-const v = p.C.foo;
-''', allowErrors: true);
- assertUnlinkedConst(variable.initializer.bodyExpr, 'p.C.foo', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart')),
- new _PrefixExpectation(ReferenceKind.prefix, 'p'),
- ])
- ]);
- }
-
- test_constExpr_pushString_adjacent() {
- UnlinkedVariable variable =
- serializeVariableText('const v = "aaa" "b" "ccc";');
- assertUnlinkedConst(variable.initializer.bodyExpr, '"aaa" "b" "ccc"',
- operators: [UnlinkedExprOperation.pushString], strings: ['aaabccc']);
- }
-
- test_constExpr_pushString_adjacent_interpolation() {
- UnlinkedVariable variable =
- serializeVariableText(r'const v = "aaa" "bb ${42} bbb" "cccc";');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, r'"aaa" "bb ${42} bbb" "cccc"',
- operators: [
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.concatenate,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.concatenate,
- ],
- ints: [
- 42,
- 3,
- 3,
- ],
- strings: [
- 'aaa',
- 'bb ',
- ' bbb',
- 'cccc'
- ]);
- }
-
- test_constExpr_pushString_interpolation() {
- UnlinkedVariable variable =
- serializeVariableText(r'const v = "aaa ${42} bbb";');
- assertUnlinkedConst(variable.initializer.bodyExpr, r'"aaa ${42} bbb"',
- operators: [
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.concatenate
- ],
- ints: [
- 42,
- 3
- ],
- strings: [
- 'aaa ',
- ' bbb'
- ]);
- }
-
- test_constExpr_pushString_simple() {
- UnlinkedVariable variable = serializeVariableText('const v = "abc";');
- assertUnlinkedConst(variable.initializer.bodyExpr, '"abc"',
- operators: [UnlinkedExprOperation.pushString], strings: ['abc']);
- }
-
- test_constExpr_pushTrue() {
- UnlinkedVariable variable = serializeVariableText('const v = true;');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'true',
- operators: [UnlinkedExprOperation.pushTrue]);
- }
-
- test_constExpr_set_if() {
- UnlinkedVariable variable =
- serializeVariableText('const v = <int>{if (true) 1};');
- assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{if (true) 1}',
- operators: [
- UnlinkedExprOperation.pushTrue,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.ifElement,
- UnlinkedExprOperation.makeTypedSet
- ],
- ints: [
- 1,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_set_if_else() {
- UnlinkedVariable variable =
- serializeVariableText('const v = <int>{if (true) 1 else 2};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '<int>{if (true) 1 else 2}',
- operators: [
- UnlinkedExprOperation.pushTrue,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.ifElseElement,
- UnlinkedExprOperation.makeTypedSet
- ],
- ints: [
- 1,
- 2,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_set_spread() {
- UnlinkedVariable variable =
- serializeVariableText('const v = <int>{...<int>{}};');
- assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{...<int>{}}',
- operators: [
- UnlinkedExprOperation.makeTypedSet,
- UnlinkedExprOperation.spreadElement,
- UnlinkedExprOperation.makeTypedSet
- ],
- ints: [
- 0,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_set_spread_null_aware() {
- UnlinkedVariable variable =
- serializeVariableText('const v = <int>{...?<int>{}};');
- assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{...?<int>{}}',
- operators: [
- UnlinkedExprOperation.makeTypedSet,
- UnlinkedExprOperation.nullAwareSpreadElement,
- UnlinkedExprOperation.makeTypedSet
- ],
- ints: [
- 0,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_constExpr_type_arg_nullability_suffix_none() {
- featureSet = enableNnbd;
- var variable = serializeVariableText('const v = const <int>[];');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const <int>[]',
- operators: [
- UnlinkedExprOperation.makeTypedList
- ],
- ints: [
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum,
- nullabilitySuffix: EntityRefNullabilitySuffix.none)
- ]);
- }
-
- test_constExpr_type_arg_nullability_suffix_question() {
- featureSet = enableNnbd;
- var variable = serializeVariableText('const v = const <int?>[];');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const <int?>[]',
- operators: [
- UnlinkedExprOperation.makeTypedList
- ],
- ints: [
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum,
- nullabilitySuffix: EntityRefNullabilitySuffix.question)
- ]);
- }
-
- test_constExpr_type_arg_nullability_suffix_star() {
- featureSet = disableNnbd;
- var variable = serializeVariableText('const v = const <int>[];');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const <int>[]',
- operators: [
- UnlinkedExprOperation.makeTypedList
- ],
- ints: [
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum,
- nullabilitySuffix: EntityRefNullabilitySuffix.starOrIrrelevant)
- ]);
- }
-
- test_constExpr_type_nullability_suffix_none() {
- featureSet = enableNnbd;
- var variable = serializeVariableText('const v = int;');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'int', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum,
- nullabilitySuffix: EntityRefNullabilitySuffix.none)
- ]);
- }
-
- test_constExpr_type_nullability_suffix_question() {
- // This is a placeholder for testing that `const v = int?;` is serialized
- // correctly, if we decide that this syntax is allowed.
- // TODO(paulberry): fill out this test if necessary.
- // See https://github.com/dart-lang/language/issues/278
-
- // var variable = serializeVariableText('const v = int?;', nnbd: true);
- // assertUnlinkedConst(variable.initializer.bodyExpr, ...);
- }
-
- test_constExpr_type_nullability_suffix_star() {
- featureSet = disableNnbd;
- var variable = serializeVariableText('const v = int;');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'int', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum,
- nullabilitySuffix: EntityRefNullabilitySuffix.starOrIrrelevant)
- ]);
- }
-
- test_constExpr_type_prefixed_nullability_suffix_none() {
- featureSet = enableNnbd;
- var variable = serializeVariableText('const v = core.int;',
- imports: 'import "dart:core" as core;');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'core.int', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum,
- prefixExpectations: [
- _PrefixExpectation(ReferenceKind.prefix, 'core')
- ],
- nullabilitySuffix: EntityRefNullabilitySuffix.none)
- ]);
- }
-
- test_constExpr_type_prefixed_nullability_suffix_question() {
- // This is a placeholder for testing that `const v = core.int?;` is
- // serialized correctly, if we decide that this syntax is allowed.
- // TODO(paulberry): fill out this test if necessary.
- // See https://github.com/dart-lang/language/issues/278
-
- // var variable = serializeVariableText('const v = core.int?;', imports: 'import "dart:core: as core;', nnbd: true);
- // assertUnlinkedConst(variable.initializer.bodyExpr, ...);
- }
-
- test_constExpr_type_prefixed_nullability_suffix_star() {
- featureSet = disableNnbd;
- var variable = serializeVariableText('const v = core.int;',
- imports: 'import "dart:core" as core;');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'core.int', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum,
- prefixExpectations: [
- _PrefixExpectation(ReferenceKind.prefix, 'core')
- ],
- nullabilitySuffix: EntityRefNullabilitySuffix.starOrIrrelevant)
- ]);
- }
-
- test_constructor() {
- String text = 'class C { C(); }';
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(text).executables);
- expect(executable.kind, UnlinkedExecutableKind.constructor);
- expect(executable.returnType, isNull);
- expect(executable.isAsynchronous, isFalse);
- expect(executable.isExternal, isFalse);
- expect(executable.isGenerator, isFalse);
- expect(executable.nameOffset, text.indexOf('C();'));
- expect(executable.periodOffset, 0);
- expect(executable.nameEnd, 0);
- expect(executable.isRedirectedConstructor, isFalse);
- expect(executable.redirectedConstructor, isNull);
- expect(executable.redirectedConstructorName, isEmpty);
- expect(executable.visibleOffset, 0);
- expect(executable.visibleLength, 0);
- }
-
- test_constructor_anonymous() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C(); }').executables);
- expect(executable.name, isEmpty);
- }
-
- test_constructor_const() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { const C(); }').executables);
- expect(executable.isConst, isTrue);
- expect(executable.isExternal, isFalse);
- }
-
- test_constructor_const_external() {
- UnlinkedExecutable executable = findExecutable('',
- executables:
- serializeClassText('class C { external const C(); }').executables);
- expect(executable.isConst, isTrue);
- expect(executable.isExternal, isTrue);
- }
-
- test_constructor_documented() {
- String text = '''
-class C {
- /**
- * Docs
- */
- C();
-}''';
- UnlinkedExecutable executable = serializeClassText(text).executables[0];
- expect(executable.documentationComment, isNotNull);
- checkDocumentationComment(executable.documentationComment, text);
- }
-
- test_constructor_external() {
- UnlinkedExecutable executable = findExecutable('',
- executables:
- serializeClassText('class C { external C(); }').executables);
- expect(executable.isExternal, isTrue);
- }
-
- test_constructor_factory() {
- UnlinkedExecutable executable = findExecutable('',
- executables:
- serializeClassText('class C { factory C() => null; }').executables);
- expect(executable.isFactory, isTrue);
- }
-
- test_constructor_implicit() {
- // Implicit constructors are not serialized.
- UnlinkedExecutable executable = findExecutable(null,
- executables: serializeClassText('class C { C(); }').executables,
- failIfAbsent: false);
- expect(executable, isNull);
- }
-
- test_constructor_initializers_assertInvocation() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class C {
- const C(int x) : assert(x >= 42);
-}
-''').executables);
- expect(executable.constantInitializers, hasLength(1));
- UnlinkedConstructorInitializer initializer =
- executable.constantInitializers[0];
- expect(
- initializer.kind, UnlinkedConstructorInitializerKind.assertInvocation);
- expect(initializer.name, '');
- expect(initializer.expression, isNull);
- expect(initializer.arguments, hasLength(1));
- assertUnlinkedConst(initializer.arguments[0], 'x >= 42', operators: [
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.greaterEqual
- ], ints: [
- 42
- ], strings: [
- 'x'
- ]);
- }
-
- test_constructor_initializers_assertInvocation_message() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class C {
- const C(int x) : assert(x >= 42, 'foo');
-}
-''').executables);
- expect(executable.constantInitializers, hasLength(1));
- UnlinkedConstructorInitializer initializer =
- executable.constantInitializers[0];
- expect(
- initializer.kind, UnlinkedConstructorInitializerKind.assertInvocation);
- expect(initializer.name, '');
- expect(initializer.expression, isNull);
- expect(initializer.arguments, hasLength(2));
- assertUnlinkedConst(initializer.arguments[0], 'x >= 42', operators: [
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.greaterEqual
- ], ints: [
- 42
- ], strings: [
- 'x',
- ]);
- assertUnlinkedConst(initializer.arguments[1], "'foo'", operators: [
- UnlinkedExprOperation.pushString,
- ], strings: [
- 'foo'
- ]);
- }
-
- test_constructor_initializers_field() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class C {
- final x;
- const C() : x = 42;
-}
-''').executables);
- expect(executable.constantInitializers, hasLength(1));
- UnlinkedConstructorInitializer initializer =
- executable.constantInitializers[0];
- expect(initializer.kind, UnlinkedConstructorInitializerKind.field);
- expect(initializer.name, 'x');
- assertUnlinkedConst(initializer.expression, '42',
- operators: [UnlinkedExprOperation.pushInt], ints: [42]);
- expect(initializer.arguments, isEmpty);
- }
-
- test_constructor_initializers_field_withParameter() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class C {
- final x;
- const C(int p) : x = p;
-}
-''').executables);
- expect(executable.constantInitializers, hasLength(1));
- UnlinkedConstructorInitializer initializer =
- executable.constantInitializers[0];
- expect(initializer.kind, UnlinkedConstructorInitializerKind.field);
- expect(initializer.name, 'x');
- assertUnlinkedConst(initializer.expression, 'p',
- operators: [UnlinkedExprOperation.pushParameter], strings: ['p']);
- expect(initializer.arguments, isEmpty);
- }
-
- test_constructor_initializers_notConst() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class C {
- final x;
- C() : x = 42;
-}
-''').executables);
- expect(executable.constantInitializers, isEmpty);
- }
-
- test_constructor_initializers_superInvocation_named() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class A {
- const A.aaa(int p);
-}
-class C extends A {
- const C() : super.aaa(42);
-}
-''').executables);
- expect(executable.constantInitializers, hasLength(1));
- UnlinkedConstructorInitializer initializer =
- executable.constantInitializers[0];
- expect(
- initializer.kind, UnlinkedConstructorInitializerKind.superInvocation);
- expect(initializer.name, 'aaa');
- expect(initializer.expression, isNull);
- expect(initializer.arguments, hasLength(1));
- assertUnlinkedConst(initializer.arguments[0], '42',
- operators: [UnlinkedExprOperation.pushInt], ints: [42]);
- }
-
- test_constructor_initializers_superInvocation_namedExpression() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class A {
- const A(a, {int b, int c});
-}
-class C extends A {
- const C() : super(1, b: 2, c: 3);
-}
-''').executables);
- expect(executable.constantInitializers, hasLength(1));
- UnlinkedConstructorInitializer initializer =
- executable.constantInitializers[0];
- expect(
- initializer.kind, UnlinkedConstructorInitializerKind.superInvocation);
- expect(initializer.name, '');
- expect(initializer.expression, isNull);
- expect(initializer.arguments, hasLength(3));
- assertUnlinkedConst(initializer.arguments[0], '1',
- operators: [UnlinkedExprOperation.pushInt], ints: [1]);
- assertUnlinkedConst(initializer.arguments[1], '2',
- operators: [UnlinkedExprOperation.pushInt], ints: [2]);
- assertUnlinkedConst(initializer.arguments[2], '3',
- operators: [UnlinkedExprOperation.pushInt], ints: [3]);
- expect(initializer.argumentNames, ['b', 'c']);
- }
-
- test_constructor_initializers_superInvocation_unnamed() {
- UnlinkedExecutable executable =
- findExecutable('ccc', executables: serializeClassText(r'''
-class A {
- const A(int p);
-}
-class C extends A {
- const C.ccc() : super(42);
-}
-''').executables);
- expect(executable.constantInitializers, hasLength(1));
- UnlinkedConstructorInitializer initializer =
- executable.constantInitializers[0];
- expect(
- initializer.kind, UnlinkedConstructorInitializerKind.superInvocation);
- expect(initializer.name, '');
- expect(initializer.expression, isNull);
- expect(initializer.arguments, hasLength(1));
- assertUnlinkedConst(initializer.arguments[0], '42',
- operators: [UnlinkedExprOperation.pushInt], ints: [42]);
- }
-
- test_constructor_initializers_thisInvocation_named() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class C {
- const C() : this.named(1, 'bbb');
- const C.named(int a, String b);
-}
-''').executables);
- expect(executable.constantInitializers, hasLength(1));
- UnlinkedConstructorInitializer initializer =
- executable.constantInitializers[0];
- expect(initializer.kind, UnlinkedConstructorInitializerKind.thisInvocation);
- expect(initializer.name, 'named');
- expect(initializer.expression, isNull);
- expect(initializer.arguments, hasLength(2));
- assertUnlinkedConst(initializer.arguments[0], '1',
- operators: [UnlinkedExprOperation.pushInt], ints: [1]);
- assertUnlinkedConst(initializer.arguments[1], "'bbb'",
- operators: [UnlinkedExprOperation.pushString], strings: ['bbb']);
- }
-
- test_constructor_initializers_thisInvocation_namedExpression() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class C {
- const C() : this.named(1, b: 2, c: 3);
- const C.named(a, {int b, int c});
-}
-''').executables);
- expect(executable.constantInitializers, hasLength(1));
- UnlinkedConstructorInitializer initializer =
- executable.constantInitializers[0];
- expect(initializer.kind, UnlinkedConstructorInitializerKind.thisInvocation);
- expect(initializer.name, 'named');
- expect(initializer.expression, isNull);
- expect(initializer.arguments, hasLength(3));
- assertUnlinkedConst(initializer.arguments[0], '1',
- operators: [UnlinkedExprOperation.pushInt], ints: [1]);
- assertUnlinkedConst(initializer.arguments[1], '2',
- operators: [UnlinkedExprOperation.pushInt], ints: [2]);
- assertUnlinkedConst(initializer.arguments[2], '3',
- operators: [UnlinkedExprOperation.pushInt], ints: [3]);
- expect(initializer.argumentNames, ['b', 'c']);
- }
-
- test_constructor_initializers_thisInvocation_unnamed() {
- UnlinkedExecutable executable =
- findExecutable('named', executables: serializeClassText(r'''
-class C {
- const C.named() : this(1, 'bbb');
- const C(int a, String b);
-}
-''').executables);
- expect(executable.constantInitializers, hasLength(1));
- UnlinkedConstructorInitializer initializer =
- executable.constantInitializers[0];
- expect(initializer.kind, UnlinkedConstructorInitializerKind.thisInvocation);
- expect(initializer.name, '');
- expect(initializer.expression, isNull);
- expect(initializer.arguments, hasLength(2));
- assertUnlinkedConst(initializer.arguments[0], '1',
- operators: [UnlinkedExprOperation.pushInt], ints: [1]);
- assertUnlinkedConst(initializer.arguments[1], "'bbb'",
- operators: [UnlinkedExprOperation.pushString], strings: ['bbb']);
- }
-
- test_constructor_initializing_formal() {
- UnlinkedExecutable executable = findExecutable('',
- executables:
- serializeClassText('class C { C(this.x); final x; }').executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.isInitializingFormal, isTrue);
- }
-
- test_constructor_initializing_formal_explicit_type() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C(int this.x); final x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- checkTypeRef(parameter.type, 'dart:core', 'int');
- }
-
- test_constructor_initializing_formal_function_typed() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C(this.x()); final x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.isFunctionTyped, isTrue);
- }
-
- test_constructor_initializing_formal_function_typed_explicit_return_type() {
- UnlinkedExecutable executable = findExecutable('',
- executables:
- serializeClassText('class C { C(int this.x()); Function x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- checkTypeRef(parameter.type, 'dart:core', 'int');
- }
-
- test_constructor_initializing_formal_function_typed_implicit_return_type() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C(this.x()); Function x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.isFunctionTyped, isTrue);
- expect(parameter.type, isNull);
- }
-
- test_constructor_initializing_formal_function_typed_no_parameters() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C(this.x()); final x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.parameters, isEmpty);
- }
-
- test_constructor_initializing_formal_function_typed_parameter() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C(this.x(a)); final x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.parameters, hasLength(1));
- }
-
- test_constructor_initializing_formal_function_typed_parameter_order() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C(this.x(a, b)); final x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.parameters, hasLength(2));
- expect(parameter.parameters[0].name, 'a');
- expect(parameter.parameters[1].name, 'b');
- }
-
- test_constructor_initializing_formal_function_typed_withDefault() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class C {
- C([this.x() = foo]);
- final x;
-}
-int foo() => 0;
-''').executables);
- UnlinkedParam param = executable.parameters[0];
- expect(param.isFunctionTyped, isTrue);
- expect(param.kind, UnlinkedParamKind.optionalPositional);
- expect(param.defaultValueCode, 'foo');
- assertUnlinkedConst(param.initializer.bodyExpr, 'foo', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.topLevelFunction)
- ]);
- }
-
- test_constructor_initializing_formal_implicit_type() {
- // Note: the implicit type of an initializing formal is the type of the
- // field.
- UnlinkedExecutable executable = findExecutable('',
- executables:
- serializeClassText('class C { C(this.x); int x; }').executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.type, isNull);
- }
-
- test_constructor_initializing_formal_name() {
- UnlinkedExecutable executable = findExecutable('',
- executables:
- serializeClassText('class C { C(this.x); final x; }').executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.name, 'x');
- }
-
- test_constructor_initializing_formal_named() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C({this.x}); final x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.kind, UnlinkedParamKind.optionalNamed);
- expect(parameter.initializer, isNull);
- expect(parameter.defaultValueCode, isEmpty);
- }
-
- test_constructor_initializing_formal_named_withDefault() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C({this.x: 42}); final x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.kind, UnlinkedParamKind.optionalNamed);
- expect(parameter.initializer, isNotNull);
- expect(parameter.defaultValueCode, '42');
- _assertCodeRange(parameter.codeRange, 13, 10);
- assertUnlinkedConst(parameter.initializer.bodyExpr, '42',
- operators: [UnlinkedExprOperation.pushInt], ints: [42]);
- }
-
- test_constructor_initializing_formal_non_function_typed() {
- UnlinkedExecutable executable = findExecutable('',
- executables:
- serializeClassText('class C { C(this.x); final x; }').executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.isFunctionTyped, isFalse);
- }
-
- test_constructor_initializing_formal_positional() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C([this.x]); final x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.kind, UnlinkedParamKind.optionalPositional);
- expect(parameter.initializer, isNull);
- expect(parameter.defaultValueCode, isEmpty);
- }
-
- test_constructor_initializing_formal_positional_withDefault() {
- UnlinkedExecutable executable = findExecutable('',
- executables:
- serializeClassText('class C { C([this.x = 42]); final x; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.kind, UnlinkedParamKind.optionalPositional);
- expect(parameter.initializer, isNotNull);
- expect(parameter.defaultValueCode, '42');
- _assertCodeRange(parameter.codeRange, 13, 11);
- assertUnlinkedConst(parameter.initializer.bodyExpr, '42',
- operators: [UnlinkedExprOperation.pushInt], ints: [42]);
- }
-
- test_constructor_initializing_formal_required() {
- UnlinkedExecutable executable = findExecutable('',
- executables:
- serializeClassText('class C { C(this.x); final x; }').executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.kind, UnlinkedParamKind.requiredPositional);
- }
-
- test_constructor_initializing_formal_typedef() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText(
- 'typedef F<T>(T x); class C<X> { C(this.f); F<X> f; }')
- .executables);
- UnlinkedParam parameter = executable.parameters[0];
- expect(parameter.isFunctionTyped, isFalse);
- expect(parameter.parameters, isEmpty);
- }
-
- test_constructor_initializing_formal_withDefault() {
- UnlinkedExecutable executable =
- findExecutable('', executables: serializeClassText(r'''
-class C {
- C([this.x = 42]);
- final int x;
-}''').executables);
- UnlinkedParam param = executable.parameters[0];
- expect(param.kind, UnlinkedParamKind.optionalPositional);
- expect(param.defaultValueCode, '42');
- assertUnlinkedConst(param.initializer.bodyExpr, '42',
- operators: [UnlinkedExprOperation.pushInt], ints: [42]);
- }
-
- test_constructor_named() {
- String text = 'class C { C.foo(); }';
- UnlinkedExecutable executable = findExecutable('foo',
- executables: serializeClassText(text).executables);
- expect(executable.name, 'foo');
- expect(executable.nameOffset, text.indexOf('foo'));
- expect(executable.periodOffset, text.indexOf('.foo'));
- expect(executable.nameEnd, text.indexOf('()'));
- _assertCodeRange(executable.codeRange, 10, 8);
- }
-
- test_constructor_non_const() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C(); }').executables);
- expect(executable.isConst, isFalse);
- }
-
- test_constructor_non_factory() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C(); }').executables);
- expect(executable.isFactory, isFalse);
- }
-
- test_constructor_param_inferred_type_explicit() {
- UnlinkedExecutable ctor =
- serializeClassText('class C { C(int v); }').executables[0];
- expect(ctor.kind, UnlinkedExecutableKind.constructor);
- expect(ctor.parameters[0].inferredTypeSlot, 0);
- }
-
- test_constructor_param_inferred_type_implicit() {
- UnlinkedExecutable ctor =
- serializeClassText('class C { C(v); }').executables[0];
- expect(ctor.kind, UnlinkedExecutableKind.constructor);
- expect(ctor.parameters[0].inferredTypeSlot, 0);
- }
-
- test_constructor_redirected_factory_named() {
- String text = '''
-class C {
- factory C() = D.named;
- C._();
-}
-class D extends C {
- D.named() : super._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'D')
- ]);
- }
-
- test_constructor_redirected_factory_named_generic() {
- String text = '''
-class C<T, U> {
- factory C() = D<U, T>.named;
- C._();
-}
-class D<T, U> extends C<U, T> {
- D.named() : super._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
- numTypeParameters: 2)
- ],
- numTypeArguments: 2);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
- }
-
- test_constructor_redirected_factory_named_imported() {
- addNamedSource('/foo.dart', '''
-import 'test.dart';
-class D extends C {
- D.named() : super._();
-}
-''');
- String text = '''
-import 'foo.dart';
-class C {
- factory C() = D.named;
- C._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.classOrEnum,
- 'D',
- absoluteUri: absUri('/foo.dart'),
- )
- ]);
- }
-
- test_constructor_redirected_factory_named_imported_generic() {
- addNamedSource('/foo.dart', '''
-import 'test.dart';
-class D<T, U> extends C<U, T> {
- D.named() : super._();
-}
-''');
- String text = '''
-import 'foo.dart';
-class C<T, U> {
- factory C() = D<U, T>.named;
- C._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.classOrEnum,
- 'D',
- numTypeParameters: 2,
- absoluteUri: absUri('/foo.dart'),
- )
- ],
- numTypeArguments: 2);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
- }
-
- test_constructor_redirected_factory_named_prefixed() {
- addNamedSource('/foo.dart', '''
-import 'test.dart';
-class D extends C {
- D.named() : super._();
-}
-''');
- String text = '''
-import 'foo.dart' as foo;
-class C {
- factory C() = foo.D.named;
- C._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.classOrEnum,
- 'D',
- absoluteUri: absUri('/foo.dart'),
- ),
- new _PrefixExpectation(ReferenceKind.prefix, 'foo')
- ]);
- }
-
- test_constructor_redirected_factory_named_prefixed_generic() {
- addNamedSource('/foo.dart', '''
-import 'test.dart';
-class D<T, U> extends C<U, T> {
- D.named() : super._();
-}
-''');
- String text = '''
-import 'foo.dart' as foo;
-class C<T, U> {
- factory C() = foo.D<U, T>.named;
- C._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.classOrEnum,
- 'D',
- numTypeParameters: 2,
- absoluteUri: absUri('/foo.dart'),
- ),
- new _PrefixExpectation(ReferenceKind.prefix, 'foo')
- ],
- numTypeArguments: 2);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
- }
-
- test_constructor_redirected_factory_unnamed() {
- String text = '''
-class C {
- factory C() = D;
- C._();
-}
-class D extends C {
- D() : super._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, null, 'D');
- }
-
- test_constructor_redirected_factory_unnamed_generic() {
- String text = '''
-class C<T, U> {
- factory C() = D<U, T>;
- C._();
-}
-class D<T, U> extends C<U, T> {
- D() : super._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, null, 'D',
- numTypeParameters: 2, numTypeArguments: 2);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
- }
-
- test_constructor_redirected_factory_unnamed_imported() {
- addNamedSource('/foo.dart', '''
-import 'test.dart';
-class D extends C {
- D() : super._();
-}
-''');
- String text = '''
-import 'foo.dart';
-class C {
- factory C() = D;
- C._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, absUri('/foo.dart'), 'D');
- }
-
- test_constructor_redirected_factory_unnamed_imported_generic() {
- addNamedSource('/foo.dart', '''
-import 'test.dart';
-class D<T, U> extends C<U, T> {
- D() : super._();
-}
-''');
- String text = '''
-import 'foo.dart';
-class C<T, U> {
- factory C() = D<U, T>;
- C._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, absUri('/foo.dart'), 'D',
- numTypeParameters: 2, numTypeArguments: 2);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
- }
-
- test_constructor_redirected_factory_unnamed_prefixed() {
- addNamedSource('/foo.dart', '''
-import 'test.dart';
-class D extends C {
- D() : super._();
-}
-''');
- String text = '''
-import 'foo.dart' as foo;
-class C {
- factory C() = foo.D;
- C._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, absUri('/foo.dart'), 'D',
- expectedPrefix: 'foo');
- }
-
- test_constructor_redirected_factory_unnamed_prefixed_generic() {
- addNamedSource('/foo.dart', '''
-import 'test.dart';
-class D<T, U> extends C<U, T> {
- D() : super._();
-}
-''');
- String text = '''
-import 'foo.dart' as foo;
-class C<T, U> {
- factory C() = foo.D<U, T>;
- C._();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isTrue);
- expect(executable.redirectedConstructorName, isEmpty);
- checkTypeRef(executable.redirectedConstructor, absUri('/foo.dart'), 'D',
- numTypeParameters: 2, expectedPrefix: 'foo', numTypeArguments: 2);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
- checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
- }
-
- test_constructor_redirected_thisInvocation_named() {
- String text = '''
-class C {
- C() : this.named();
- C.named();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isFalse);
- expect(executable.redirectedConstructorName, 'named');
- expect(executable.redirectedConstructor, isNull);
- }
-
- test_constructor_redirected_thisInvocation_unnamed() {
- String text = '''
-class C {
- C.named() : this();
- C();
-}
-''';
- UnlinkedExecutable executable =
- serializeClassText(text, className: 'C').executables[0];
- expect(executable.isRedirectedConstructor, isTrue);
- expect(executable.isFactory, isFalse);
- expect(executable.redirectedConstructorName, isEmpty);
- expect(executable.redirectedConstructor, isNull);
- }
-
- test_constructor_return_type() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C { C(); }').executables);
- expect(executable.returnType, isNull);
- }
-
- test_constructor_return_type_parameterized() {
- UnlinkedExecutable executable = findExecutable('',
- executables: serializeClassText('class C<T, U> { C(); }').executables);
- expect(executable.returnType, isNull);
- }
-
- test_constructor_withCycles_const() {
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = const D();
-}
-class D {
- final x;
- const D() : x = const C();
-}
-class E {
- final x;
- const E() : x = null;
-}
-''');
- checkConstCycle('C');
- checkConstCycle('D');
- checkConstCycle('E', hasCycle: false);
- }
-
- test_constructor_withCycles_nonConst() {
- serializeLibraryText('''
-class C {
- final x;
- C() : x = new D();
-}
-class D {
- final x;
- D() : x = new C();
-}
-''');
- expect(findClass('C').executables[0].constCycleSlot, 0);
- expect(findClass('D').executables[0].constCycleSlot, 0);
- }
-
- test_constructorCycle_redirectToImplicitConstructor() {
- serializeLibraryText('''
-class C {
- const factory C() = D;
-}
-class D extends C {}
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_redirectToNonConstConstructor() {
- // It's not valid Dart but we need to make sure it doesn't crash
- // summary generation.
- serializeLibraryText('''
-class C {
- const factory C() = D;
-}
-class D extends C {
- D();
-}
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_redirectToSymbolConstructor() {
- // The symbol constructor has some special case behaviors in analyzer.
- // Make sure those special case behaviors don't cause problems.
- serializeLibraryText('''
-class C {
- const factory C(String name) = Symbol;
-}
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToClass() {
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = C;
-}
-''');
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToEnum() {
- serializeLibraryText('''
-enum E { v }
-class C {
- final x;
- const C() : x = E;
-}
-''');
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToEnumValue() {
- serializeLibraryText('''
-enum E { v }
-class C {
- final x;
- const C() : x = E.v;
-}
-''');
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToEnumValues() {
- serializeLibraryText('''
-enum E { v }
-class C {
- final x;
- const C() : x = E.values;
-}
-''');
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToGenericParameter() {
- // It's not valid Dart but we need to make sure it doesn't crash
- // summary generation.
- serializeLibraryText('''
-class C<T> {
- final x;
- const C() : x = T;
-}
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToGenericParameter_asSupertype() {
- // It's not valid Dart but we need to make sure it doesn't crash
- // summary generation.
- serializeLibraryText('''
-class C<T> extends T {
- const C();
-}
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToStaticMethod_inOtherClass() {
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = D.f;
-}
-class D {
- static void f() {}
-}
-''');
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToStaticMethod_inSameClass() {
- serializeLibraryText('''
-class C {
- final x;
- static void f() {}
- const C() : x = f;
-}
-''');
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToTopLevelFunction() {
- serializeLibraryText('''
-void f() {}
-class C {
- final x;
- const C() : x = f;
-}
-''');
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToTypedef() {
- serializeLibraryText('''
-typedef F();
-class C {
- final x;
- const C() : x = F;
-}
-''');
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToUndefinedName() {
- // It's not valid Dart but we need to make sure it doesn't crash
- // summary generation.
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = foo;
-}
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToUndefinedName_viaPrefix() {
- // It's not valid Dart but we need to make sure it doesn't crash
- // summary generation.
- addNamedSource('/a.dart', '');
- serializeLibraryText('''
-import 'a.dart' as a;
-class C {
- final x;
- const C() : x = a.foo;
-}
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_referenceToUndefinedName_viaPrefix_nonExistentFile() {
- // It's not valid Dart but we need to make sure it doesn't crash
- // summary generation.
- allowMissingFiles = true;
- serializeLibraryText('''
-import 'a.dart' as a;
-class C {
- final x;
- const C() : x = a.foo;
-}
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_trivial() {
- serializeLibraryText('''
-class C {
- const C() : this();
-}
-''', allowErrors: true);
- checkConstCycle('C');
- }
-
- test_constructorCycle_viaFactoryRedirect() {
- serializeLibraryText('''
-class C {
- const C();
- const factory C.named() = D;
-}
-class D extends C {
- final x;
- const D() : x = y;
-}
-const y = const C.named();
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- checkConstCycle('C', name: 'named');
- checkConstCycle('D');
- }
-
- test_constructorCycle_viaFinalField() {
- serializeLibraryText('''
-class C {
- final x = const C();
- const C();
-}
-''', allowErrors: true);
- checkConstCycle('C');
- }
-
- test_constructorCycle_viaLength() {
- // It's not valid Dart but we need to make sure it doesn't crash
- // summary generation.
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = y.length;
-}
-const y = const C();
-''', allowErrors: true);
- checkConstCycle('C');
- }
-
- test_constructorCycle_viaNamedConstructor() {
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = const D.named();
-}
-class D {
- final x;
- const D.named() : x = const C();
-}
-''');
- checkConstCycle('C');
- checkConstCycle('D', name: 'named');
- }
-
- test_constructorCycle_viaOrdinaryRedirect() {
- serializeLibraryText('''
-class C {
- final x;
- const C() : this.named();
- const C.named() : x = const C();
-}
-''');
- checkConstCycle('C');
- checkConstCycle('C', name: 'named');
- }
-
- test_constructorCycle_viaOrdinaryRedirect_suppressSupertype() {
- // Since C redirects to C.named, it doesn't implicitly refer to B's unnamed
- // constructor. Therefore there is no cycle.
- serializeLibraryText('''
-class B {
- final x;
- const B() : x = const C();
- const B.named() : x = null;
-}
-class C extends B {
- const C() : this.named();
- const C.named() : super.named();
-}
-''');
- checkConstCycle('B', hasCycle: false);
- checkConstCycle('B', name: 'named', hasCycle: false);
- checkConstCycle('C', hasCycle: false);
- checkConstCycle('C', name: 'named', hasCycle: false);
- }
-
- test_constructorCycle_viaRedirectArgument() {
- serializeLibraryText('''
-class C {
- final x;
- const C() : this.named(y);
- const C.named(this.x);
-}
-const y = const C();
-''', allowErrors: true);
- checkConstCycle('C');
- checkConstCycle('C', name: 'named', hasCycle: false);
- }
-
- test_constructorCycle_viaStaticField_inOtherClass() {
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = D.y;
-}
-class D {
- static const y = const C();
-}
-''', allowErrors: true);
- checkConstCycle('C');
- }
-
- test_constructorCycle_viaStaticField_inSameClass() {
- serializeLibraryText('''
-class C {
- final x;
- static const y = const C();
- const C() : x = y;
-}
-''', allowErrors: true);
- checkConstCycle('C');
- }
-
- test_constructorCycle_viaSuperArgument() {
- serializeLibraryText('''
-class B {
- final x;
- const B(this.x);
-}
-class C extends B {
- const C() : super(y);
-}
-const y = const C();
-''', allowErrors: true);
- checkConstCycle('B', hasCycle: false);
- checkConstCycle('C');
- }
-
- test_constructorCycle_viaSupertype() {
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = const D();
-}
-class D extends C {
- const D();
-}
-''');
- checkConstCycle('C');
- checkConstCycle('D');
- }
-
- test_constructorCycle_viaSupertype_Enum() {
- // It's not valid Dart but we need to make sure it doesn't crash
- // summary generation.
- serializeLibraryText('''
-enum E { v }
-class C extends E {
- const C();
-}
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- }
-
- test_constructorCycle_viaSupertype_explicit() {
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = const D();
- const C.named() : x = const D.named();
-}
-class D extends C {
- const D() : super();
- const D.named() : super.named();
-}
-''');
- checkConstCycle('C');
- checkConstCycle('C', name: 'named');
- checkConstCycle('D');
- checkConstCycle('D', name: 'named');
- }
-
- test_constructorCycle_viaSupertype_explicit_undefined() {
- // It's not valid Dart but we need to make sure it doesn't crash
- // summary generation.
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = const D();
-}
-class D extends C {
- const D() : super.named();
-}
-''', allowErrors: true);
- checkConstCycle('C', hasCycle: false);
- checkConstCycle('D', hasCycle: false);
- }
-
- test_constructorCycle_viaSupertype_withDefaultTypeArgument() {
- serializeLibraryText('''
-class C<T> {
- final x;
- const C() : x = const D();
-}
-class D extends C {
- const D();
-}
-''');
- checkConstCycle('C');
- checkConstCycle('D');
- }
-
- test_constructorCycle_viaSupertype_withTypeArgument() {
- serializeLibraryText('''
-class C<T> {
- final x;
- const C() : x = const D();
-}
-class D extends C<int> {
- const D();
-}
-''');
- checkConstCycle('C');
- checkConstCycle('D');
- }
-
- test_constructorCycle_viaTopLevelVariable() {
- serializeLibraryText('''
-class C {
- final x;
- const C() : x = y;
-}
-const y = const C();
-''', allowErrors: true);
- checkConstCycle('C');
- }
-
- test_constructorCycle_viaTopLevelVariable_imported() {
- addNamedSource('/a.dart', '''
-import 'test.dart';
-const y = const C();
- ''');
- serializeLibraryText('''
-import 'a.dart';
-class C {
- final x;
- const C() : x = y;
-}
-''', allowErrors: true);
- checkConstCycle('C');
- }
-
- test_constructorCycle_viaTopLevelVariable_importedViaPrefix() {
- addNamedSource('/a.dart', '''
-import 'test.dart';
-const y = const C();
- ''');
- serializeLibraryText('''
-import 'a.dart' as a;
-class C {
- final x;
- const C() : x = a.y;
-}
-''', allowErrors: true);
- checkConstCycle('C');
- }
-
- test_dependencies_export_to_export_unused() {
- addNamedSource('/a.dart', 'export "b.dart";');
- addNamedSource('/b.dart', '');
- serializeLibraryText('export "a.dart";');
- // The main test library depends on b.dart, even though it doesn't
- // re-export any names defined in b.dart, because a change to b.dart might
- // cause it to start exporting a name that the main test library *does*
- // use.
- checkHasDependency(absUri('/b.dart'));
- }
-
- test_dependencies_export_unused() {
- addNamedSource('/a.dart', '');
- serializeLibraryText('export "a.dart";');
- // The main test library depends on a.dart, even though it doesn't
- // re-export any names defined in a.dart, because a change to a.dart might
- // cause it to start exporting a name that the main test library *will*
- // re-export.
- checkHasDependency(absUri('/a.dart'));
- }
-
- test_dependencies_import_to_export() {
- addNamedSource('/a.dart', 'library a; export "b.dart"; class A {}');
- addNamedSource('/b.dart', 'library b;');
- serializeLibraryText('import "a.dart"; A a;');
- checkHasDependency(absUri('/a.dart'));
- // The main test library depends on b.dart, because names defined in
- // b.dart are exported by a.dart.
- checkHasDependency(absUri('/b.dart'));
- }
-
- test_dependencies_import_to_export_in_subdirs_absolute_export() {
- addNamedSource('/a/a.dart',
- 'library a; export "${absUri('/a/b/b.dart')}"; class A {}');
- addNamedSource('/a/b/b.dart', 'library b;');
- serializeLibraryText('import "a/a.dart"; A a;');
- checkHasDependency(absUri('/a/a.dart'));
- // The main test library depends on b.dart, because names defined in
- // b.dart are exported by a.dart.
- checkHasDependency(absUri('/a/b/b.dart'));
- }
-
- test_dependencies_import_to_export_in_subdirs_absolute_import() {
- addNamedSource('/a/a.dart', 'library a; export "b/b.dart"; class A {}');
- addNamedSource('/a/b/b.dart', 'library b;');
- serializeLibraryText('import "${absUri('/a/a.dart')}"; A a;');
- checkHasDependency(absUri('/a/a.dart'));
- // The main test library depends on b.dart, because names defined in
- // b.dart are exported by a.dart.
- checkHasDependency(absUri('/a/b/b.dart'));
- }
-
- test_dependencies_import_to_export_in_subdirs_relative() {
- addNamedSource('/a/a.dart', 'library a; export "b/b.dart"; class A {}');
- addNamedSource('/a/b/b.dart', 'library b;');
- serializeLibraryText('import "a/a.dart"; A a;');
- checkHasDependency(absUri('/a/a.dart'));
- // The main test library depends on b.dart, because names defined in
- // b.dart are exported by a.dart.
- checkHasDependency(absUri('/a/b/b.dart'));
- }
-
- test_dependencies_import_to_export_loop() {
- addNamedSource('/a.dart', 'library a; export "b.dart"; class A {}');
- addNamedSource('/b.dart', 'library b; export "a.dart";');
- serializeLibraryText('import "a.dart"; A a;');
- checkHasDependency(absUri('/a.dart'));
- // Serialization should have been able to walk the transitive export
- // dependencies to b.dart without going into an infinite loop.
- checkHasDependency(absUri('/b.dart'));
- }
-
- test_dependencies_import_to_export_transitive_closure() {
- addNamedSource('/a.dart', 'library a; export "b.dart"; class A {}');
- addNamedSource('/b.dart', 'library b; export "c.dart";');
- addNamedSource('/c.dart', 'library c;');
- serializeLibraryText('import "a.dart"; A a;');
- checkHasDependency(absUri('/a.dart'));
- // The main test library depends on c.dart, because names defined in
- // c.dart are exported by b.dart and then re-exported by a.dart.
- checkHasDependency(absUri('/c.dart'));
- }
-
- test_dependencies_import_to_export_unused() {
- addNamedSource('/a.dart', 'export "b.dart";');
- addNamedSource('/b.dart', '');
- serializeLibraryText('import "a.dart";', allowErrors: true);
- // The main test library depends on b.dart, even though it doesn't use any
- // names defined in b.dart, because a change to b.dart might cause it to
- // start exporting a name that the main test library *does* use.
- checkHasDependency(absUri('/b.dart'));
- }
-
- test_dependencies_import_transitive_closure() {
- addNamedSource(
- '/a.dart', 'library a; import "b.dart"; class A extends B {}');
- addNamedSource('/b.dart', 'library b; class B {}');
- serializeLibraryText('import "a.dart"; A a;');
- checkHasDependency(absUri('/a.dart'));
- // The main test library doesn't depend on b.dart, because no change to
- // b.dart can possibly affect the serialized element model for it.
- checkLacksDependency(absUri('/b.dart'));
- }
-
- test_dependencies_import_unused() {
- addNamedSource('/a.dart', '');
- serializeLibraryText('import "a.dart";', allowErrors: true);
- // The main test library depends on a.dart, even though it doesn't use any
- // names defined in a.dart, because a change to a.dart might cause it to
- // start exporting a name that the main test library *does* use.
- checkHasDependency(absUri('/a.dart'));
- }
-
- test_dependencies_parts() {
- addNamedSource(
- '/a.dart', 'library a; part "b.dart"; part "c.dart"; class A {}');
- addNamedSource('/b.dart', 'part of a;');
- addNamedSource('/c.dart', 'part of a;');
- serializeLibraryText('import "a.dart"; A a;');
- int dep = checkHasDependency(absUri('/a.dart'));
- checkDependencyParts(
- linked.dependencies[dep], [absUri('/b.dart'), absUri('/c.dart')]);
- }
-
- test_dependencies_parts_relative_to_importing_library() {
- addNamedSource('/a/b.dart', 'export "c/d.dart";');
- addNamedSource('/a/c/d.dart',
- 'library d; part "e/f.dart"; part "g/h.dart"; class D {}');
- addNamedSource('/a/c/e/f.dart', 'part of d;');
- addNamedSource('/a/c/g/h.dart', 'part of d;');
- serializeLibraryText('import "a/b.dart"; D d;');
- int dep = checkHasDependency(absUri('/a/c/d.dart'));
- checkDependencyParts(linked.dependencies[dep],
- [absUri('/a/c/e/f.dart'), absUri('/a/c/g/h.dart')]);
- }
-
- test_elements_in_part() {
- addNamedSource('/part1.dart', '''
-part of my.lib;
-
-class C {}
-enum E { v }
-var v;
-f() {}
-typedef F();
-''');
- serializeLibraryText('library my.lib; part "part1.dart";');
- UnlinkedUnit unit = unlinkedUnits[1];
- expect(findClass('C', unit: unit), isNotNull);
- expect(findEnum('E', unit: unit), isNotNull);
- expect(findVariable('v', variables: unit.variables), isNotNull);
- expect(findExecutable('f', executables: unit.executables), isNotNull);
- expect(findTypedef('F', unit: unit), isNotNull);
- }
-
- test_enum() {
- String text = 'enum E { v1 }';
- UnlinkedEnum e = serializeEnumText(text);
- expect(e.name, 'E');
- expect(e.nameOffset, text.indexOf('E'));
- expect(e.values, hasLength(1));
- expect(e.values[0].name, 'v1');
- expect(e.values[0].nameOffset, text.indexOf('v1'));
- _assertCodeRange(e.codeRange, 0, 13);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].kind,
- ReferenceKind.classOrEnum);
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'E');
- expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
- expect(unlinkedUnits[0].publicNamespace.names[0].members, hasLength(2));
- expect(unlinkedUnits[0].publicNamespace.names[0].members[0].kind,
- ReferenceKind.propertyAccessor);
- expect(unlinkedUnits[0].publicNamespace.names[0].members[0].name, 'values');
- expect(
- unlinkedUnits[0].publicNamespace.names[0].members[0].numTypeParameters,
- 0);
- expect(unlinkedUnits[0].publicNamespace.names[0].members[1].kind,
- ReferenceKind.propertyAccessor);
- expect(unlinkedUnits[0].publicNamespace.names[0].members[1].name, 'v1');
- expect(
- unlinkedUnits[0].publicNamespace.names[0].members[1].numTypeParameters,
- 0);
- }
-
- test_enum_documented() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-enum E { v }''';
- UnlinkedEnum enm = serializeEnumText(text);
- expect(enm.documentationComment, isNotNull);
- checkDocumentationComment(enm.documentationComment, text);
- }
-
- test_enum_order() {
- UnlinkedEnum e = serializeEnumText('enum E { v1, v2 }');
- expect(e.values, hasLength(2));
- expect(e.values[0].name, 'v1');
- expect(e.values[1].name, 'v2');
- }
-
- test_enum_private() {
- serializeEnumText('enum _E { v1 }', '_E');
- expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
- }
-
- test_enum_value_documented() {
- String text = '''
-enum E {
- /**
- * Docs
- */
- v
-}''';
- UnlinkedEnumValue value = serializeEnumText(text).values[0];
- expect(value.documentationComment, isNotNull);
- checkDocumentationComment(value.documentationComment, text);
- }
-
- test_enum_value_private() {
- serializeEnumText('enum E { _v }', 'E');
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].members, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].members[0].name, 'values');
- }
-
- test_executable_abstract() {
- UnlinkedExecutable executable =
- serializeClassText('abstract class C { f(); }').executables[0];
- expect(executable.isAbstract, isTrue);
- }
-
- test_executable_concrete() {
- UnlinkedExecutable executable =
- serializeClassText('abstract class C { f() {} }').executables[0];
- expect(executable.isAbstract, isFalse);
- }
-
- test_executable_function() {
- String text = ' f() {}';
- UnlinkedExecutable executable = serializeExecutableText(text);
- expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
- expect(executable.returnType, isNull);
- expect(executable.isAsynchronous, isFalse);
- expect(executable.isExternal, isFalse);
- expect(executable.isGenerator, isFalse);
- expect(executable.nameOffset, text.indexOf('f'));
- expect(executable.visibleOffset, 0);
- expect(executable.visibleLength, 0);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].kind,
- ReferenceKind.topLevelFunction);
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f');
- expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
- }
-
- test_executable_function_async() {
- UnlinkedExecutable executable = serializeExecutableText(r'''
-import 'dart:async';
-Future f() async {}
-''');
- expect(executable.isAsynchronous, isTrue);
- expect(executable.isGenerator, isFalse);
- }
-
- test_executable_function_asyncStar() {
- UnlinkedExecutable executable = serializeExecutableText(r'''
-import 'dart:async';
-Stream f() async* {}
-''');
- expect(executable.isAsynchronous, isTrue);
- expect(executable.isGenerator, isTrue);
- }
-
- test_executable_function_explicit_return() {
- UnlinkedExecutable executable =
- serializeExecutableText('dynamic f() => null;');
- checkDynamicTypeRef(executable.returnType);
- }
-
- test_executable_function_external() {
- UnlinkedExecutable executable = serializeExecutableText('external f();');
- expect(executable.isExternal, isTrue);
- }
-
- test_executable_function_private() {
- serializeExecutableText('_f() {}', executableName: '_f');
- expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
- }
-
- test_executable_getter() {
- String text = 'int get f => 1;';
- UnlinkedExecutable executable = serializeExecutableText(text);
- expect(executable.kind, UnlinkedExecutableKind.getter);
- expect(executable.returnType, isNotNull);
- expect(executable.isAsynchronous, isFalse);
- expect(executable.isExternal, isFalse);
- expect(executable.isGenerator, isFalse);
- expect(executable.nameOffset, text.indexOf('f'));
- expect(findVariable('f'), isNull);
- expect(findExecutable('f='), isNull);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].kind,
- ReferenceKind.topLevelPropertyAccessor);
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f');
- }
-
- test_executable_getter_external() {
- UnlinkedExecutable executable =
- serializeExecutableText('external int get f;');
- expect(executable.isExternal, isTrue);
- }
-
- test_executable_getter_private() {
- serializeExecutableText('int get _f => 1;', executableName: '_f');
- expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
- }
-
- test_executable_getter_type() {
- UnlinkedExecutable executable = serializeExecutableText('int get f => 1;');
- checkTypeRef(executable.returnType, 'dart:core', 'int');
- expect(executable.parameters, isEmpty);
- }
-
- test_executable_getter_type_implicit() {
- UnlinkedExecutable executable = serializeExecutableText('get f => 1;');
- expect(executable.returnType, isNull);
- expect(executable.parameters, isEmpty);
- }
-
- test_executable_localFunctions() {
- String code = r'''
-f() {
- f1() {}
- {
- f2() {}
- }
-}
-''';
- UnlinkedExecutable executable = serializeExecutableText(code);
- List<UnlinkedExecutable> functions = executable.localFunctions;
- expect(functions, isEmpty);
- }
-
- test_executable_member_function() {
- UnlinkedExecutable executable = findExecutable('f',
- executables: serializeClassText('class C { f() {} }').executables);
- expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
- expect(executable.returnType, isNull);
- expect(executable.isAsynchronous, isFalse);
- expect(executable.isExternal, isFalse);
- expect(executable.isGenerator, isFalse);
- expect(executable.visibleOffset, 0);
- expect(executable.visibleLength, 0);
- _assertCodeRange(executable.codeRange, 10, 6);
- }
-
- test_executable_member_function_async() {
- UnlinkedExecutable executable =
- findExecutable('f', executables: serializeClassText(r'''
-import 'dart:async';
-class C {
- Future f() async {}
-}
-''').executables);
- expect(executable.isAsynchronous, isTrue);
- expect(executable.isGenerator, isFalse);
- }
-
- test_executable_member_function_asyncStar() {
- UnlinkedExecutable executable =
- findExecutable('f', executables: serializeClassText(r'''
-import 'dart:async';
-class C {
- Stream f() async* {}
-}
-''').executables);
- expect(executable.isAsynchronous, isTrue);
- expect(executable.isGenerator, isTrue);
- }
-
- test_executable_member_function_explicit_return() {
- UnlinkedExecutable executable = findExecutable('f',
- executables:
- serializeClassText('class C { dynamic f() => null; }').executables);
- expect(executable.returnType, isNotNull);
- }
-
- test_executable_member_function_external() {
- UnlinkedExecutable executable = findExecutable('f',
- executables:
- serializeClassText('class C { external f(); }').executables);
- expect(executable.isExternal, isTrue);
- }
-
- test_executable_member_getter() {
- UnlinkedClass cls = serializeClassText('class C { int get f => 1; }');
- UnlinkedExecutable executable =
- findExecutable('f', executables: cls.executables, failIfAbsent: true);
- expect(executable.kind, UnlinkedExecutableKind.getter);
- expect(executable.returnType, isNotNull);
- expect(executable.isAsynchronous, isFalse);
- expect(executable.isExternal, isFalse);
- expect(executable.isGenerator, isFalse);
- expect(executable.isStatic, isFalse);
- _assertCodeRange(executable.codeRange, 10, 15);
- expect(findVariable('f', variables: cls.fields), isNull);
- expect(findExecutable('f=', executables: cls.executables), isNull);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
- expect(unlinkedUnits[0].publicNamespace.names[0].members, isEmpty);
- }
-
- test_executable_member_getter_external() {
- UnlinkedClass cls = serializeClassText('class C { external int get f; }');
- UnlinkedExecutable executable =
- findExecutable('f', executables: cls.executables, failIfAbsent: true);
- expect(executable.isExternal, isTrue);
- }
-
- test_executable_member_getter_static() {
- UnlinkedClass cls =
- serializeClassText('class C { static int get f => 1; }');
- UnlinkedExecutable executable =
- findExecutable('f', executables: cls.executables, failIfAbsent: true);
- expect(executable.isStatic, isTrue);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
- expect(unlinkedUnits[0].publicNamespace.names[0].members, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].members[0].name, 'f');
- expect(unlinkedUnits[0].publicNamespace.names[0].members[0].kind,
- ReferenceKind.propertyAccessor);
- expect(
- unlinkedUnits[0].publicNamespace.names[0].members[0].numTypeParameters,
- 0);
- expect(
- unlinkedUnits[0].publicNamespace.names[0].members[0].members, isEmpty);
- }
-
- test_executable_member_setter() {
- UnlinkedClass cls = serializeClassText('class C { void set f(value) {} }');
- UnlinkedExecutable executable =
- findExecutable('f=', executables: cls.executables, failIfAbsent: true);
- expect(executable.kind, UnlinkedExecutableKind.setter);
- expect(executable.returnType, isNotNull);
- expect(executable.isAsynchronous, isFalse);
- expect(executable.isExternal, isFalse);
- expect(executable.isGenerator, isFalse);
- _assertCodeRange(executable.codeRange, 10, 20);
- expect(findVariable('f', variables: cls.fields), isNull);
- expect(findExecutable('f', executables: cls.executables), isNull);
- }
-
- test_executable_member_setter_external() {
- UnlinkedClass cls =
- serializeClassText('class C { external void set f(value); }');
- UnlinkedExecutable executable =
- findExecutable('f=', executables: cls.executables, failIfAbsent: true);
- expect(executable.isExternal, isTrue);
- }
-
- test_executable_member_setter_implicit_return() {
- UnlinkedClass cls = serializeClassText('class C { set f(value) {} }');
- UnlinkedExecutable executable =
- findExecutable('f=', executables: cls.executables, failIfAbsent: true);
- expect(executable.returnType, isNull);
- }
-
- test_executable_name() {
- UnlinkedExecutable executable = serializeExecutableText('f() {}');
- expect(executable.name, 'f');
- }
-
- test_executable_no_flags() {
- UnlinkedExecutable executable = serializeExecutableText('f() {}');
- expect(executable.isAbstract, isFalse);
- expect(executable.isConst, isFalse);
- expect(executable.isFactory, isFalse);
- expect(executable.isStatic, isFalse);
- }
-
- test_executable_non_static() {
- UnlinkedExecutable executable =
- serializeClassText('class C { f() {} }').executables[0];
- expect(executable.isStatic, isFalse);
- }
-
- test_executable_non_static_top_level() {
- // Top level executables are considered non-static.
- UnlinkedExecutable executable = serializeExecutableText('f() {}');
- expect(executable.isStatic, isFalse);
- }
-
- test_executable_operator() {
- UnlinkedExecutable executable =
- serializeClassText('class C { C operator+(C c) => null; }')
- .executables[0];
- expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
- expect(executable.name, '+');
- expect(executable.returnType, isNotNull);
- expect(executable.isAbstract, false);
- expect(executable.isAsynchronous, isFalse);
- expect(executable.isConst, false);
- expect(executable.isFactory, false);
- expect(executable.isGenerator, isFalse);
- expect(executable.isStatic, false);
- expect(executable.parameters, hasLength(1));
- checkTypeRef(executable.returnType, null, 'C');
- expect(executable.typeParameters, isEmpty);
- expect(executable.isExternal, false);
- }
-
- test_executable_operator_abstract() {
- UnlinkedExecutable executable =
- serializeClassText('class C { C operator+(C c); }', allowErrors: true)
- .executables[0];
- expect(executable.isAbstract, true);
- expect(executable.isAsynchronous, isFalse);
- expect(executable.isExternal, false);
- expect(executable.isGenerator, isFalse);
- }
-
- test_executable_operator_equal() {
- UnlinkedExecutable executable = serializeClassText(
- 'class C { bool operator==(Object other) => false; }')
- .executables[0];
- expect(executable.name, '==');
- }
-
- test_executable_operator_external() {
- UnlinkedExecutable executable =
- serializeClassText('class C { external C operator+(C c); }')
- .executables[0];
- expect(executable.isAbstract, false);
- expect(executable.isAsynchronous, isFalse);
- expect(executable.isExternal, true);
- expect(executable.isGenerator, isFalse);
- }
-
- test_executable_operator_greater_equal() {
- UnlinkedExecutable executable =
- serializeClassText('class C { bool operator>=(C other) => false; }')
- .executables[0];
- expect(executable.name, '>=');
- }
-
- test_executable_operator_index() {
- UnlinkedExecutable executable =
- serializeClassText('class C { bool operator[](int i) => null; }')
- .executables[0];
- expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
- expect(executable.name, '[]');
- expect(executable.returnType, isNotNull);
- expect(executable.isAbstract, false);
- expect(executable.isConst, false);
- expect(executable.isFactory, false);
- expect(executable.isStatic, false);
- expect(executable.parameters, hasLength(1));
- checkTypeRef(executable.returnType, 'dart:core', 'bool');
- expect(executable.typeParameters, isEmpty);
- }
-
- test_executable_operator_index_set() {
- UnlinkedExecutable executable = serializeClassText(
- 'class C { void operator[]=(int i, bool v) => null; }')
- .executables[0];
- expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
- expect(executable.name, '[]=');
- expect(executable.returnType, isNotNull);
- expect(executable.isAbstract, false);
- expect(executable.isConst, false);
- expect(executable.isFactory, false);
- expect(executable.isStatic, false);
- expect(executable.parameters, hasLength(2));
- checkVoidTypeRef(executable.returnType);
- expect(executable.typeParameters, isEmpty);
- }
-
- test_executable_operator_less_equal() {
- UnlinkedExecutable executable =
- serializeClassText('class C { bool operator<=(C other) => false; }')
- .executables[0];
- expect(executable.name, '<=');
- }
-
- test_executable_param_codeRange() {
- UnlinkedExecutable executable = serializeExecutableText('f(int x) {}');
- UnlinkedParam parameter = executable.parameters[0];
- _assertCodeRange(parameter.codeRange, 2, 5);
- }
-
- test_executable_param_function_typed() {
- UnlinkedExecutable executable = serializeExecutableText('f(g()) {}');
- expect(executable.parameters[0].isFunctionTyped, isTrue);
- expect(executable.parameters[0].type, isNull);
- }
-
- test_executable_param_function_typed_explicit_return_type() {
- UnlinkedExecutable executable =
- serializeExecutableText('f(dynamic g()) {}');
- expect(executable.parameters[0].type, isNotNull);
- }
-
- test_executable_param_function_typed_param() {
- UnlinkedExecutable executable = serializeExecutableText('f(g(x)) {}');
- expect(executable.parameters[0].parameters, hasLength(1));
- }
-
- test_executable_param_function_typed_param_none() {
- UnlinkedExecutable executable = serializeExecutableText('f(g()) {}');
- expect(executable.parameters[0].parameters, isEmpty);
- }
-
- test_executable_param_function_typed_param_order() {
- UnlinkedExecutable executable = serializeExecutableText('f(g(x, y)) {}');
- expect(executable.parameters[0].parameters, hasLength(2));
- expect(executable.parameters[0].parameters[0].name, 'x');
- expect(executable.parameters[0].parameters[1].name, 'y');
- }
-
- test_executable_param_function_typed_return_type() {
- UnlinkedExecutable executable = serializeExecutableText('f(int g()) {}');
- checkTypeRef(executable.parameters[0].type, 'dart:core', 'int');
- }
-
- test_executable_param_function_typed_return_type_implicit() {
- UnlinkedExecutable executable = serializeExecutableText('f(g()) {}');
- expect(executable.parameters[0].isFunctionTyped, isTrue);
- expect(executable.parameters[0].type, isNull);
- }
-
- test_executable_param_function_typed_return_type_void() {
- UnlinkedExecutable executable = serializeExecutableText('f(void g()) {}');
- checkVoidTypeRef(executable.parameters[0].type);
- }
-
- test_executable_param_function_typed_withDefault() {
- UnlinkedExecutable executable = serializeExecutableText(r'''
-f([int p(int a2, String b2) = foo]) {}
-int foo(int a, String b) => 0;
-''');
- UnlinkedParam param = executable.parameters[0];
- expect(param.kind, UnlinkedParamKind.optionalPositional);
- expect(param.initializer, isNotNull);
- expect(param.defaultValueCode, 'foo');
- assertUnlinkedConst(param.initializer.bodyExpr, 'foo', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.topLevelFunction)
- ]);
- }
-
- test_executable_param_isFinal() {
- String text = 'f(x, final y) {}';
- UnlinkedExecutable executable = serializeExecutableText(text);
- expect(executable.parameters, hasLength(2));
- expect(executable.parameters[0].name, 'x');
- expect(executable.parameters[0].isFinal, isFalse);
- expect(executable.parameters[1].name, 'y');
- expect(executable.parameters[1].isFinal, isTrue);
- }
-
- test_executable_param_kind_named() {
- UnlinkedExecutable executable = serializeExecutableText('f({x}) {}');
- UnlinkedParam param = executable.parameters[0];
- expect(param.kind, UnlinkedParamKind.optionalNamed);
- expect(param.initializer, isNull);
- expect(param.defaultValueCode, isEmpty);
- }
-
- test_executable_param_kind_named_withDefault() {
- UnlinkedExecutable executable = serializeExecutableText('f({x: 42}) {}');
- UnlinkedParam param = executable.parameters[0];
- expect(param.kind, UnlinkedParamKind.optionalNamed);
- expect(param.initializer, isNotNull);
- expect(param.defaultValueCode, '42');
- _assertCodeRange(param.codeRange, 3, 5);
- assertUnlinkedConst(param.initializer.bodyExpr, '42',
- operators: [UnlinkedExprOperation.pushInt], ints: [42]);
- }
-
- test_executable_param_kind_positional() {
- UnlinkedExecutable executable = serializeExecutableText('f([x]) {}');
- UnlinkedParam param = executable.parameters[0];
- expect(param.kind, UnlinkedParamKind.optionalPositional);
- expect(param.initializer, isNull);
- expect(param.defaultValueCode, isEmpty);
- }
-
- test_executable_param_kind_positional_withDefault() {
- UnlinkedExecutable executable = serializeExecutableText('f([x = 42]) {}');
- UnlinkedParam param = executable.parameters[0];
- expect(param.kind, UnlinkedParamKind.optionalPositional);
- expect(param.initializer, isNotNull);
- expect(param.defaultValueCode, '42');
- _assertCodeRange(param.codeRange, 3, 6);
- assertUnlinkedConst(param.initializer.bodyExpr, '42',
- operators: [UnlinkedExprOperation.pushInt], ints: [42]);
- }
-
- test_executable_param_kind_required() {
- UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
- UnlinkedParam param = executable.parameters[0];
- expect(param.kind, UnlinkedParamKind.requiredPositional);
- expect(param.initializer, isNull);
- expect(param.defaultValueCode, isEmpty);
- }
-
- test_executable_param_name() {
- String text = 'f(x) {}';
- UnlinkedExecutable executable = serializeExecutableText(text);
- expect(executable.parameters, hasLength(1));
- expect(executable.parameters[0].name, 'x');
- expect(executable.parameters[0].nameOffset, text.indexOf('x'));
- }
-
- test_executable_param_no_flags() {
- UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
- expect(executable.parameters[0].isFunctionTyped, isFalse);
- expect(executable.parameters[0].isInitializingFormal, isFalse);
- }
-
- test_executable_param_non_function_typed() {
- UnlinkedExecutable executable = serializeExecutableText('f(g) {}');
- expect(executable.parameters[0].isFunctionTyped, isFalse);
- }
-
- test_executable_param_none() {
- UnlinkedExecutable executable = serializeExecutableText('f() {}');
- expect(executable.parameters, isEmpty);
- }
-
- test_executable_param_of_constructor_no_covariance() {
- UnlinkedExecutable executable =
- serializeClassText('class C { C(x); }').executables[0];
- expect(executable.parameters[0].inheritsCovariantSlot, 0);
- }
-
- test_executable_param_of_method_covariance() {
- UnlinkedExecutable executable =
- serializeClassText('class C { m(x) {} }').executables[0];
- expect(executable.parameters[0].inheritsCovariantSlot, isNot(0));
- }
-
- test_executable_param_of_param_no_covariance() {
- UnlinkedExecutable executable =
- serializeClassText('class C { m(f(x)) {} }').executables[0];
- expect(executable.parameters[0].parameters[0].inheritsCovariantSlot, 0);
- }
-
- test_executable_param_of_setter_covariance() {
- UnlinkedExecutable executable =
- serializeClassText('class C { void set s(x) {} }').executables[0];
- expect(executable.parameters[0].inheritsCovariantSlot, isNot(0));
- }
-
- test_executable_param_of_static_method_no_covariance() {
- UnlinkedExecutable executable =
- serializeClassText('class C { static m(x) {} }').executables[0];
- expect(executable.parameters[0].inheritsCovariantSlot, 0);
- }
-
- test_executable_param_of_top_level_function_no_covariance() {
- UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
- expect(executable.parameters[0].inheritsCovariantSlot, 0);
- }
-
- test_executable_param_order() {
- UnlinkedExecutable executable = serializeExecutableText('f(x, y) {}');
- expect(executable.parameters, hasLength(2));
- expect(executable.parameters[0].name, 'x');
- expect(executable.parameters[1].name, 'y');
- }
-
- test_executable_param_type_explicit() {
- UnlinkedExecutable executable = serializeExecutableText('f(dynamic x) {}');
- checkDynamicTypeRef(executable.parameters[0].type);
- }
-
- test_executable_param_type_implicit() {
- UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
- expect(executable.parameters[0].type, isNull);
- }
-
- test_executable_param_type_typedef() {
- UnlinkedExecutable executable = serializeExecutableText(r'''
-typedef MyFunction(int p);
-f(MyFunction myFunction) {}
-''');
- expect(executable.parameters[0].isFunctionTyped, isFalse);
- checkTypeRef(executable.parameters[0].type, null, 'MyFunction',
- expectedKind: ReferenceKind.typedef);
- }
-
- test_executable_return_type() {
- UnlinkedExecutable executable = serializeExecutableText('int f() => 1;');
- checkTypeRef(executable.returnType, 'dart:core', 'int');
- }
-
- test_executable_return_type_implicit() {
- UnlinkedExecutable executable = serializeExecutableText('f() {}');
- expect(executable.returnType, isNull);
- }
-
- test_executable_return_type_void() {
- UnlinkedExecutable executable = serializeExecutableText('void f() {}');
- checkVoidTypeRef(executable.returnType);
- }
-
- test_executable_setter() {
- String text = 'void set f(value) {}';
- UnlinkedExecutable executable =
- serializeExecutableText(text, executableName: 'f=');
- expect(executable.kind, UnlinkedExecutableKind.setter);
- expect(executable.returnType, isNotNull);
- expect(executable.isAsynchronous, isFalse);
- expect(executable.isExternal, isFalse);
- expect(executable.isGenerator, isFalse);
- expect(executable.nameOffset, text.indexOf('f'));
- expect(findVariable('f'), isNull);
- expect(findExecutable('f'), isNull);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].kind,
- ReferenceKind.topLevelPropertyAccessor);
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f=');
- }
-
- test_executable_setter_external() {
- UnlinkedExecutable executable = serializeExecutableText(
- 'external void set f(value);',
- executableName: 'f=');
- expect(executable.isExternal, isTrue);
- }
-
- test_executable_setter_implicit_return() {
- UnlinkedExecutable executable =
- serializeExecutableText('set f(value) {}', executableName: 'f=');
- expect(executable.returnType, isNull);
- }
-
- test_executable_setter_private() {
- serializeExecutableText('void set _f(value) {}', executableName: '_f=');
- expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
- }
-
- test_executable_setter_type() {
- UnlinkedExecutable executable = serializeExecutableText(
- 'void set f(int value) {}',
- executableName: 'f=');
- checkVoidTypeRef(executable.returnType);
- expect(executable.parameters, hasLength(1));
- expect(executable.parameters[0].name, 'value');
- checkTypeRef(executable.parameters[0].type, 'dart:core', 'int');
- }
-
- test_executable_static() {
- UnlinkedExecutable executable =
- serializeClassText('class C { static f() {} }').executables[0];
- expect(executable.isStatic, isTrue);
- }
-
- test_executable_type_param_f_bound_function() {
- UnlinkedExecutable ex =
- serializeExecutableText('void f<T, U extends List<T>>() {}');
- EntityRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
- checkParamTypeRef(typeArgument, 2);
- }
-
- test_executable_type_param_f_bound_method() {
- UnlinkedExecutable ex =
- serializeMethodText('void f<T, U extends List<T>>() {}');
- EntityRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
- checkParamTypeRef(typeArgument, 2);
- }
-
- test_executable_type_param_f_bound_self_ref_function() {
- UnlinkedExecutable ex =
- serializeExecutableText('void f<T, U extends List<U>>() {}');
- EntityRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
- checkParamTypeRef(typeArgument, 1);
- }
-
- test_executable_type_param_f_bound_self_ref_method() {
- UnlinkedExecutable ex =
- serializeMethodText('void f<T, U extends List<U>>() {}');
- EntityRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
- checkParamTypeRef(typeArgument, 1);
- }
-
- test_executable_type_param_in_parameter_function() {
- UnlinkedExecutable ex = serializeExecutableText('void f<T>(T t) {}');
- checkParamTypeRef(ex.parameters[0].type, 1);
- expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
- }
-
- test_executable_type_param_in_parameter_method() {
- UnlinkedExecutable ex = serializeMethodText('void f<T>(T t) {}');
- checkParamTypeRef(ex.parameters[0].type, 1);
- }
-
- test_executable_type_param_in_return_type_function() {
- UnlinkedExecutable ex = serializeExecutableText('T f<T>() => null;');
- checkParamTypeRef(ex.returnType, 1);
- }
-
- test_executable_type_param_in_return_type_method() {
- UnlinkedExecutable ex = serializeMethodText('T f<T>() => null;');
- checkParamTypeRef(ex.returnType, 1);
- }
-
- test_export_class() {
- addNamedSource('/a.dart', 'class C {}');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'C',
- ReferenceKind.classOrEnum);
- }
-
- test_export_class_alias() {
- addNamedSource(
- '/a.dart', 'class C extends _D with _E {} class _D {} class _E {}');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'C',
- ReferenceKind.classOrEnum);
- }
-
- test_export_configurations() {
- addNamedSource('/foo.dart', 'class A {}');
- addNamedSource('/foo_io.dart', 'class A {}');
- addNamedSource('/foo_html.dart', 'class A {}');
- String libraryText = r'''
-export 'foo.dart'
- if (dart.library.io) 'foo_io.dart'
- if (dart.flavor == 'html') 'foo_html.dart';
-
-class B extends A {}
-''';
- serializeLibraryText(libraryText);
- UnlinkedExportPublic exp = unlinkedUnits[0].publicNamespace.exports[0];
- expect(exp.configurations, hasLength(2));
- {
- UnlinkedConfiguration configuration = exp.configurations[0];
- expect(configuration.name, 'dart.library.io');
- expect(configuration.value, 'true');
- expect(configuration.uri, 'foo_io.dart');
- }
- {
- UnlinkedConfiguration configuration = exp.configurations[1];
- expect(configuration.name, 'dart.flavor');
- expect(configuration.value, 'html');
- expect(configuration.uri, 'foo_html.dart');
- }
- }
-
- test_export_dependency() {
- serializeLibraryText('export "dart:async";');
- expect(unlinkedUnits[0].exports, hasLength(1));
- checkDependency(linked.exportDependencies[0], 'dart:async');
- }
-
- test_export_enum() {
- addNamedSource('/a.dart', 'enum E { v }');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'E',
- ReferenceKind.classOrEnum);
- }
-
- test_export_from_part() {
- addNamedSource('/a.dart', 'library foo; part "b.dart";');
- addNamedSource('/b.dart', 'part of foo; f() {}');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'f',
- ReferenceKind.topLevelFunction,
- expectedTargetUnit: 1);
- }
-
- test_export_function() {
- addNamedSource('/a.dart', 'f() {}');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'f',
- ReferenceKind.topLevelFunction);
- }
-
- test_export_getter() {
- addNamedSource('/a.dart', 'get f => null');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'f',
- ReferenceKind.topLevelPropertyAccessor);
- }
-
- test_export_hide() {
- addNamedSource('/a.dart', 'f() {} g() {}');
- serializeLibraryText('export "a.dart" hide g;');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'f',
- ReferenceKind.topLevelFunction);
- }
-
- test_export_hide_order() {
- serializeLibraryText('export "dart:async" hide Future, Stream;');
- expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
- expect(
- unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows,
- isEmpty);
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides,
- hasLength(2));
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[0],
- 'Future');
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[1],
- 'Stream');
- expect(
- unlinkedUnits[0].publicNamespace.exports[0].combinators[0].offset, 0);
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].end, 0);
- expect(linked.exportNames, isNotEmpty);
- }
-
- test_export_missing() {
- // Unresolved exports are included since this is necessary for proper
- // dependency tracking.
- allowMissingFiles = true;
- serializeLibraryText('export "foo.dart";', allowErrors: true);
- expect(unlinkedUnits[0].imports, hasLength(1));
- checkDependency(linked.exportDependencies[0], absUri('/foo.dart'));
- }
-
- test_export_names_excludes_names_from_library() {
- addNamedSource('/a.dart', 'part of my.lib; int y; int _y;');
- serializeLibraryText('library my.lib; part "a.dart"; int x; int _x;');
- expect(linked.exportNames, isEmpty);
- }
-
- test_export_no_combinators() {
- serializeLibraryText('export "dart:async";');
- expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators, isEmpty);
- }
-
- test_export_not_shadowed_by_prefix() {
- addNamedSource('/a.dart', 'f() {}');
- serializeLibraryText('export "a.dart"; import "dart:core" as f; f.int _x;');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'f',
- ReferenceKind.topLevelFunction);
- }
-
- test_export_offset() {
- String libraryText = ' export "dart:async";';
- serializeLibraryText(libraryText);
- expect(unlinkedUnits[0].exports[0].uriOffset,
- libraryText.indexOf('"dart:async"'));
- expect(unlinkedUnits[0].exports[0].uriEnd, libraryText.indexOf(';'));
- expect(unlinkedUnits[0].exports[0].offset, libraryText.indexOf('export'));
- }
-
- test_export_private() {
- // Private names should not be exported.
- addNamedSource('/a.dart', '_f() {}');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, isEmpty);
- }
-
- test_export_setter() {
- addNamedSource('/a.dart', 'void set f(value) {}');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'f=',
- ReferenceKind.topLevelPropertyAccessor);
- }
-
- test_export_shadowed() {
- // f() is not shown in exportNames because it is already defined at top
- // level in the library.
- addNamedSource('/a.dart', 'f() {}');
- serializeLibraryText('export "a.dart"; f() {}');
- expect(linked.exportNames, isEmpty);
- }
-
- test_export_shadowed_variable() {
- // Neither `v` nor `v=` is shown in exportNames because both are defined at
- // top level in the library by the declaration `var v;`.
- addNamedSource('/a.dart', 'var v;');
- serializeLibraryText('export "a.dart"; var v;');
- expect(linked.exportNames, isEmpty);
- }
-
- test_export_shadowed_variable_const() {
- // `v=` is shown in exportNames because the top level declaration
- // `const v = 0;` only shadows `v`, not `v=`.
- addNamedSource('/a.dart', 'var v;');
- serializeLibraryText('export "a.dart"; const v = 0;');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'v=',
- ReferenceKind.topLevelPropertyAccessor);
- }
-
- test_export_shadowed_variable_final() {
- // `v=` is shown in exportNames because the top level declaration
- // `final v = 0;` only shadows `v`, not `v=`.
- addNamedSource('/a.dart', 'var v;');
- serializeLibraryText('export "a.dart"; final v = 0;');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'v=',
- ReferenceKind.topLevelPropertyAccessor);
- }
-
- test_export_show() {
- addNamedSource('/a.dart', 'f() {} g() {}');
- serializeLibraryText('export "a.dart" show f;');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'f',
- ReferenceKind.topLevelFunction);
- }
-
- test_export_show_order() {
- String libraryText = 'export "dart:async" show Future, Stream;';
- serializeLibraryText(libraryText);
- expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
- expect(
- unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows,
- hasLength(2));
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides,
- isEmpty);
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[0],
- 'Future');
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[1],
- 'Stream');
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].offset,
- libraryText.indexOf('show'));
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].end,
- libraryText.indexOf(';'));
- }
-
- test_export_typedef() {
- addNamedSource('/a.dart', 'typedef F();');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, hasLength(1));
- checkExportName(
- linked.exportNames[0], absUri('/a.dart'), 'F', ReferenceKind.typedef);
- }
-
- test_export_typedef_genericFunction() {
- addNamedSource('/a.dart', 'typedef F<S> = S Function<T>(T x);');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, hasLength(1));
- checkExportName(linked.exportNames[0], absUri('/a.dart'), 'F',
- ReferenceKind.genericFunctionTypedef);
- }
-
- test_export_uri() {
- addNamedSource('/a.dart', 'library my.lib;');
- String uriString = '"a.dart"';
- String libraryText = 'export $uriString;';
- serializeLibraryText(libraryText);
- var unlinkedExports = unlinkedUnits[0].publicNamespace.exports;
- expect(unlinkedExports, hasLength(1));
- expect(unlinkedExports[0].uri, 'a.dart');
- expect(unlinkedExports[0].configurations, isEmpty);
- }
-
- test_export_uri_invalid() {
- String uriString = ':[invalid uri]';
- String libraryText = 'export "$uriString";';
- serializeLibraryText(libraryText);
- expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.exports[0].uri, uriString);
- }
-
- test_export_uri_nullStringValue() {
- String libraryText = r'''
-export "${'a'}.dart";
-''';
- serializeLibraryText(libraryText);
- var unlinkedExports = unlinkedUnits[0].publicNamespace.exports;
- expect(unlinkedExports, hasLength(1));
- expect(unlinkedExports[0].uri, '');
- expect(unlinkedExports[0].configurations, isEmpty);
- }
-
- test_export_variable() {
- addNamedSource('/a.dart', 'var v;');
- serializeLibraryText('export "a.dart";');
- expect(linked.exportNames, hasLength(2));
- LinkedExportName getter =
- linked.exportNames.firstWhere((e) => e.name == 'v');
- expect(getter, isNotNull);
- checkExportName(
- getter, absUri('/a.dart'), 'v', ReferenceKind.topLevelPropertyAccessor);
- LinkedExportName setter =
- linked.exportNames.firstWhere((e) => e.name == 'v=');
- expect(setter, isNotNull);
- checkExportName(setter, absUri('/a.dart'), 'v=',
- ReferenceKind.topLevelPropertyAccessor);
- }
-
- test_expr_assignOperator_assign() {
- _assertAssignmentOperator(
- '(a = 1 + 2) + 3', UnlinkedExprAssignOperator.assign);
- }
-
- test_expr_assignOperator_bitAnd() {
- _assertAssignmentOperator(
- '(a &= 1 + 2) + 3', UnlinkedExprAssignOperator.bitAnd);
- }
-
- test_expr_assignOperator_bitOr() {
- _assertAssignmentOperator(
- '(a |= 1 + 2) + 3', UnlinkedExprAssignOperator.bitOr);
- }
-
- test_expr_assignOperator_bitXor() {
- _assertAssignmentOperator(
- '(a ^= 1 + 2) + 3', UnlinkedExprAssignOperator.bitXor);
- }
-
- test_expr_assignOperator_divide() {
- _assertAssignmentOperator(
- '(a /= 1 + 2) + 3', UnlinkedExprAssignOperator.divide);
- }
-
- test_expr_assignOperator_floorDivide() {
- _assertAssignmentOperator(
- '(a ~/= 1 + 2) + 3', UnlinkedExprAssignOperator.floorDivide);
- }
-
- test_expr_assignOperator_ifNull() {
- _assertAssignmentOperator(
- '(a ??= 1 + 2) + 3', UnlinkedExprAssignOperator.ifNull);
- }
-
- test_expr_assignOperator_minus() {
- _assertAssignmentOperator(
- '(a -= 1 + 2) + 3', UnlinkedExprAssignOperator.minus);
- }
-
- test_expr_assignOperator_modulo() {
- _assertAssignmentOperator(
- '(a %= 1 + 2) + 3', UnlinkedExprAssignOperator.modulo);
- }
-
- test_expr_assignOperator_multiply() {
- _assertAssignmentOperator(
- '(a *= 1 + 2) + 3', UnlinkedExprAssignOperator.multiply);
- }
-
- test_expr_assignOperator_plus() {
- _assertAssignmentOperator(
- '(a += 1 + 2) + 3', UnlinkedExprAssignOperator.plus);
- }
-
- test_expr_assignOperator_shiftLeft() {
- _assertAssignmentOperator(
- '(a <<= 1 + 2) + 3', UnlinkedExprAssignOperator.shiftLeft);
- }
-
- test_expr_assignOperator_shiftRight() {
- _assertAssignmentOperator(
- '(a >>= 1 + 2) + 3', UnlinkedExprAssignOperator.shiftRight);
- }
-
- test_expr_assignToIndex_ofFieldSequence() {
- UnlinkedVariable variable = serializeVariableText('''
-class A {
- B b;
-}
-class B {
- C c;
-}
-class C {
- List<int> f = <int>[0, 1, 2];
-}
-A a = new A();
-final v = (a.b.c.f[1] = 5);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '(a.b.c.f[1] = 5)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToIndex,
- ],
- assignmentOperators: [(UnlinkedExprAssignOperator.assign)],
- ints: [5, 1],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'f',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.unresolved, 'c'),
- new _PrefixExpectation(ReferenceKind.unresolved, 'b'),
- new _PrefixExpectation(
- ReferenceKind.topLevelPropertyAccessor, 'a')
- ])
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_assignToIndex_ofIndexExpression() {
- UnlinkedVariable variable = serializeVariableText('''
-class A {
- List<B> b;
-}
-class B {
- List<C> c;
-}
-class C {
- List<int> f = <int>[0, 1, 2];
-}
-A a = new A();
-final v = (a.b[1].c[2].f[3] = 5);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '(a.b[1].c[2].f[3] = 5)',
- isValidConst: false,
- operators: [
- // 5
- UnlinkedExprOperation.pushInt,
- // a.b[1]
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.extractIndex,
- // c[2]
- UnlinkedExprOperation.extractProperty,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.extractIndex,
- // f[3] = 5
- UnlinkedExprOperation.extractProperty,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToIndex,
- ],
- assignmentOperators: [(UnlinkedExprAssignOperator.assign)],
- ints: [
- 5,
- 1,
- 2,
- 3,
- ],
- strings: ['c', 'f'],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'b',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.topLevelPropertyAccessor, 'a')
- ])
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_assignToIndex_ofTopLevelVariable() {
- UnlinkedVariable variable = serializeVariableText('''
-List<int> a = <int>[0, 1, 2];
-final v = (a[1] = 5);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '(a[1] = 5)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToIndex,
- ],
- assignmentOperators: [(UnlinkedExprAssignOperator.assign)],
- ints: [
- 5,
- 1,
- ],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_assignToProperty_ofInstanceCreation() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- int f;
-}
-final v = (new C().f = 5);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '(new C().f = 5)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.invokeConstructor,
- UnlinkedExprOperation.assignToProperty,
- ],
- assignmentOperators: [(UnlinkedExprAssignOperator.assign)],
- ints: [
- 5,
- 0,
- 0,
- ],
- strings: ['f'],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'C',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_assignToRef_classStaticField() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- static int f;
-}
-final v = (C.f = 1);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '(C.f = 1)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- ],
- assignmentOperators: [(UnlinkedExprAssignOperator.assign)],
- ints: [
- 1,
- ],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'f',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_assignToRef_fieldSequence() {
- UnlinkedVariable variable = serializeVariableText('''
-class A {
- B b;
-}
-class B {
- C c;
-}
-class C {
- int f;
-}
-A a = new A();
-final v = (a.b.c.f = 1);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '(a.b.c.f = 1)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- ],
- assignmentOperators: [(UnlinkedExprAssignOperator.assign)],
- ints: [
- 1,
- ],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'f',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.unresolved, 'c'),
- new _PrefixExpectation(ReferenceKind.unresolved, 'b'),
- new _PrefixExpectation(
- ReferenceKind.topLevelPropertyAccessor, 'a')
- ])
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_assignToRef_postfixDecrement() {
- _assertRefPrefixPostfixIncrementDecrement(
- 'a-- + 2', UnlinkedExprAssignOperator.postfixDecrement);
- }
-
- test_expr_assignToRef_postfixIncrement() {
- _assertRefPrefixPostfixIncrementDecrement(
- 'a++ + 2', UnlinkedExprAssignOperator.postfixIncrement);
- }
-
- test_expr_assignToRef_prefixDecrement() {
- _assertRefPrefixPostfixIncrementDecrement(
- '--a + 2', UnlinkedExprAssignOperator.prefixDecrement);
- }
-
- test_expr_assignToRef_prefixIncrement() {
- _assertRefPrefixPostfixIncrementDecrement(
- '++a + 2', UnlinkedExprAssignOperator.prefixIncrement);
- }
-
- test_expr_assignToRef_topLevelVariable() {
- UnlinkedVariable variable = serializeVariableText('''
-int a = 0;
-final v = (a = 1);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '(a = 1)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- ],
- assignmentOperators: [(UnlinkedExprAssignOperator.assign)],
- ints: [
- 1,
- ],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_assignToRef_topLevelVariable_imported() {
- addNamedSource('/a.dart', '''
-int a = 0;
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart';
-final v = (a = 1);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '(a = 1)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- ],
- assignmentOperators: [(UnlinkedExprAssignOperator.assign)],
- ints: [
- 1,
- ],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_assignToRef_topLevelVariable_imported_withPrefix() {
- addNamedSource('/a.dart', '''
-int a = 0;
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-final v = (p.a = 1);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '(p.a = 1)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- ],
- assignmentOperators: [(UnlinkedExprAssignOperator.assign)],
- ints: [
- 1,
- ],
- strings: [],
- referenceValidators: [
- (EntityRef r) {
- return checkTypeRef(r, absUri('/a.dart'), 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor,
- expectedPrefix: 'p');
- }
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_cascadeSection_assignToIndex() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- List<int> items;
-}
-final C c = new C();
-final v = c.items..[1] = 2;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'c.items..[1] = 2',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushReference,
- ],
- assignmentOperators: [],
- ints: [],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'items',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.topLevelPropertyAccessor, 'c'),
- ])
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_cascadeSection_assignToProperty() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- int f1 = 0;
- int f2 = 0;
-}
-final v = new C()..f1 = 1..f2 += 2;
-''');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'new C()..f1 = 1..f2 += 2',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- assignmentOperators: [],
- ints: [0, 0],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'C',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_cascadeSection_embedded() {
- UnlinkedVariable variable = serializeVariableText('''
-class A {
- int fa1;
- B b;
- int fa2;
-}
-class B {
- int fb;
-}
-final v = new A()
- ..fa1 = 1
- ..b = (new B()..fb = 2)
- ..fa2 = 3;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- 'new A()..fa1 = 1..b = (new B()..fb = 2)..fa2 = 3',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- ],
- assignmentOperators: [],
- ints: [
- 0,
- 0,
- ],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'A',
- expectedKind: ReferenceKind.classOrEnum),
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_cascadeSection_invokeMethod() {
- UnlinkedVariable variable = serializeVariableText('''
-class A {
- int m(int _) => 0;
-}
-final A a = new A();
-final v = a..m(5).abs()..m(6);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'a..m(5).abs()..m(6)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushReference,
- ],
- ints: [],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_extractIndex_ofClassField() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- List<int> get items => null;
-}
-final v = new C().items[5];
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'new C().items[5]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- UnlinkedExprOperation.extractProperty,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.extractIndex,
- ],
- ints: [0, 0, 5],
- strings: ['items'],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'C',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_extractProperty_ofInvokeConstructor() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- int f = 0;
-}
-final v = new C().f;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'new C().f',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- UnlinkedExprOperation.extractProperty,
- ],
- ints: [0, 0],
- strings: ['f'],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'C',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_functionExpression_asArgument() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = foo(5, () => 42);
-foo(a, b) {}
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'foo(5, () => 42)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushLocalFunctionReference,
- UnlinkedExprOperation.invokeMethodRef
- ],
- ints: [5, 0, 0, 0, 2, 0],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.topLevelFunction)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_functionExpression_asArgument_multiple() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = foo(5, () => 42, () => 43);
-foo(a, b, c) {}
-''');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'foo(5, () => 42, () => 43)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushLocalFunctionReference,
- UnlinkedExprOperation.pushLocalFunctionReference,
- UnlinkedExprOperation.invokeMethodRef
- ],
- ints: [5, 0, 0, 0, 1, 0, 3, 0],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'foo',
- expectedKind: ReferenceKind.topLevelFunction)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_functionExpression_withBlockBody() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = () { return 42; };
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '() { return 42; }',
- isValidConst: false,
- operators: [UnlinkedExprOperation.pushLocalFunctionReference],
- ints: [0, 0],
- forTypeInferenceOnly: true);
- }
-
- test_expr_functionExpression_withExpressionBody() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = () => 42;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '() => 42',
- isValidConst: false,
- operators: [UnlinkedExprOperation.pushLocalFunctionReference],
- ints: [0, 0],
- forTypeInferenceOnly: true);
- }
-
- test_expr_functionExpressionInvocation_withBlockBody() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = ((a, b) {return 42;})(1, 2);
-''');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '((a, b) {return 42;})(1, 2)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushLocalFunctionReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.invokeMethod
- ],
- ints: [0, 0, 1, 2, 0, 2, 0],
- strings: ['call'],
- forTypeInferenceOnly: true);
- }
-
- test_expr_functionExpressionInvocation_withExpressionBody() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = ((a, b) => 42)(1, 2);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '((a, b) => 42)(1, 2)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushLocalFunctionReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.invokeMethod
- ],
- ints: [0, 0, 1, 2, 0, 2, 0],
- strings: ['call'],
- forTypeInferenceOnly: true);
- }
-
- test_expr_inClosure() {
- UnlinkedVariable variable = serializeVariableText('var v = () => 1;');
- assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr, '1',
- operators: [UnlinkedExprOperation.pushInt],
- ints: [1],
- forTypeInferenceOnly: true);
- }
-
- test_expr_inClosure_noTypeInferenceNeeded() {
- // We don't serialize closure body expressions for closures that don't need
- // to participate in type inference.
- UnlinkedVariable variable = serializeVariableText('Object v = () => 1;');
- expect(variable.initializer.localFunctions[0].bodyExpr, isNull);
- }
-
- test_expr_inClosure_refersToOuterParam() {
- UnlinkedVariable variable =
- serializeVariableText('var v = (x) => (y) => x;');
- assertUnlinkedConst(
- variable.initializer.localFunctions[0].localFunctions[0].bodyExpr, 'x',
- operators: [UnlinkedExprOperation.pushParameter],
- strings: ['x'],
- forTypeInferenceOnly: true);
- }
-
- test_expr_inClosure_refersToParam() {
- UnlinkedVariable variable = serializeVariableText('var v = (x) => x;');
- assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr, 'x',
- operators: [UnlinkedExprOperation.pushParameter],
- strings: ['x'],
- forTypeInferenceOnly: true);
- }
-
- test_expr_inClosure_refersToParam_methodCall() {
- UnlinkedVariable variable = serializeVariableText('var v = (x) => x.f();');
- assertUnlinkedConst(
- variable.initializer.localFunctions[0].bodyExpr, 'x.f()',
- operators: [
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.invokeMethod
- ],
- strings: ['x', 'f'],
- ints: [0, 0, 0],
- forTypeInferenceOnly: true);
- }
-
- test_expr_inClosure_refersToParam_methodCall_prefixed() {
- UnlinkedVariable variable =
- serializeVariableText('var v = (x) => x.y.f();');
- assertUnlinkedConst(
- variable.initializer.localFunctions[0].bodyExpr, 'x.y.f()',
- operators: [
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.extractProperty,
- UnlinkedExprOperation.invokeMethod
- ],
- strings: ['x', 'y', 'f'],
- ints: [0, 0, 0],
- forTypeInferenceOnly: true);
- }
-
- test_expr_inClosure_refersToParam_outOfScope() {
- UnlinkedVariable variable =
- serializeVariableText('var x; var v = (b) => (b ? (x) => x : x);');
- assertUnlinkedConst(
- variable.initializer.localFunctions[0].bodyExpr, '(b ? (x) => x : x)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.pushLocalFunctionReference,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.conditional,
- ],
- strings: ['b'],
- ints: [0, 0],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'x',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_inClosure_refersToParam_prefixedIdentifier() {
- UnlinkedVariable variable = serializeVariableText('var v = (x) => x.y;');
- assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr, 'x.y',
- operators: [
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.extractProperty
- ],
- strings: ['x', 'y'],
- forTypeInferenceOnly: true);
- }
-
- test_expr_inClosure_refersToParam_prefixedIdentifier_assign() {
- UnlinkedVariable variable =
- serializeVariableText('var v = (x) => x.y = null;');
- assertUnlinkedConst(
- variable.initializer.localFunctions[0].bodyExpr, 'x.y = null',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushNull,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.assignToProperty
- ],
- strings: ['x', 'y'],
- assignmentOperators: [UnlinkedExprAssignOperator.assign],
- forTypeInferenceOnly: true);
- }
-
- test_expr_inClosure_refersToParam_prefixedPrefixedIdentifier() {
- UnlinkedVariable variable = serializeVariableText('var v = (x) => x.y.z;');
- assertUnlinkedConst(
- variable.initializer.localFunctions[0].bodyExpr, 'x.y.z',
- operators: [
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.extractProperty,
- UnlinkedExprOperation.extractProperty
- ],
- strings: ['x', 'y', 'z'],
- forTypeInferenceOnly: true);
- }
-
- test_expr_inClosure_refersToParam_prefixedPrefixedIdentifier_assign() {
- UnlinkedVariable variable =
- serializeVariableText('var v = (x) => x.y.z = null;');
- assertUnlinkedConst(
- variable.initializer.localFunctions[0].bodyExpr, 'x.y.z = null',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushNull,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.extractProperty,
- UnlinkedExprOperation.assignToProperty
- ],
- strings: ['x', 'y', 'z'],
- assignmentOperators: [UnlinkedExprAssignOperator.assign],
- forTypeInferenceOnly: true);
- }
-
- test_expr_invalid_typeParameter_asPrefix() {
- var variable = serializeClassText('''
-class C<T> {
- final f = T.k;
-}
-''').fields[0];
- if (containsNonConstExprs) {
- assertUnlinkedConst(variable.initializer.bodyExpr, 'T.k',
- isValidConst: false, operators: []);
- } else {
- expect(variable.initializer.bodyExpr, isNull);
- }
- }
-
- test_expr_invokeMethod_instance() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- int m(a, {b, c}) => 42;
-}
-final v = new C().m(1, b: 2, c: 3);
-''');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'new C().m(1, b: 2, c: 3)',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.invokeMethod,
- ],
- ints: [0, 0, 1, 2, 3, 2, 1, 0],
- strings: ['b', 'c', 'm'],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'C',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_invokeMethod_withTypeParameters() {
- UnlinkedVariable variable = serializeVariableText('''
-class C {
- f<T, U>() => null;
-}
-final v = new C().f<int, String>();
-''');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, 'new C().f<int, String>()',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.invokeConstructor,
- UnlinkedExprOperation.invokeMethod
- ],
- ints: [0, 0, 0, 0, 2],
- strings: ['f'],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'C'),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int'),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'String')
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_invokeMethodRef_instance() {
- UnlinkedVariable variable = serializeVariableText('''
-class A {
- B b;
-}
-class B {
- C c;
-}
-class C {
- int m(int a, int b) => a + b;
-}
-A a = new A();
-final v = a.b.c.m(10, 20);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'a.b.c.m(10, 20)',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.invokeMethodRef,
- ],
- ints: [10, 20, 0, 2, 0],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'm',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.unresolved, 'c'),
- new _PrefixExpectation(ReferenceKind.unresolved, 'b'),
- new _PrefixExpectation(
- ReferenceKind.topLevelPropertyAccessor, 'a')
- ])
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_invokeMethodRef_static_importedWithPrefix() {
- addNamedSource('/a.dart', '''
-class C {
- static int m() => 42;
-}
-''');
- UnlinkedVariable variable = serializeVariableText('''
-import 'a.dart' as p;
-final v = p.C.m();
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'p.C.m()',
- operators: [
- UnlinkedExprOperation.invokeMethodRef,
- ],
- ints: [0, 0, 0],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'm',
- expectedKind: ReferenceKind.method,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart')),
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_invokeMethodRef_with_reference_arg() {
- UnlinkedVariable variable = serializeVariableText('''
-f(x) => null;
-final u = null;
-final v = f(u);
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'f(u)',
- operators: [
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.invokeMethodRef
- ],
- ints: [0, 1, 0],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'u',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'f',
- expectedKind: ReferenceKind.topLevelFunction)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_invokeMethodRef_withTypeParameters() {
- UnlinkedVariable variable = serializeVariableText('''
-f<T, U>() => null;
-final v = f<int, String>();
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'f<int, String>()',
- operators: [UnlinkedExprOperation.invokeMethodRef],
- ints: [0, 0, 2],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'f',
- expectedKind: ReferenceKind.topLevelFunction,
- numTypeParameters: 2),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int'),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'String')
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_list_for() {
- UnlinkedVariable variable =
- serializeVariableText('int i; var v = [for (i = 0; i < 10; i++) i];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '[for (i = 0; i < 10; i++) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.assign,
- UnlinkedExprAssignOperator.postfixIncrement
- ],
- ints: [
- 0,
- 10,
- 1,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_expr_list_for_each_with_declaration_typed() {
- UnlinkedVariable variable =
- serializeVariableText('var v = [for (int i in []) i];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '[for (int i in []) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.makeUntypedList,
- UnlinkedExprOperation.forEachPartsWithTypedDeclaration,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- ints: [
- 0,
- 1
- ],
- strings: [
- 'i',
- 'i'
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int')
- ]);
- }
-
- test_expr_list_for_each_with_declaration_untyped() {
- UnlinkedVariable variable =
- serializeVariableText('var v = [for (var i in []) i];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '[for (var i in []) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.makeUntypedList,
- UnlinkedExprOperation.forEachPartsWithUntypedDeclaration,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- ints: [
- 0,
- 1
- ],
- strings: [
- 'i',
- 'i'
- ]);
- }
-
- test_expr_list_for_each_with_identifier() {
- UnlinkedVariable variable =
- serializeVariableText('int i; var v = [for (i in []) i];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '[for (i in []) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.makeUntypedList,
- UnlinkedExprOperation.forEachPartsWithIdentifier,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- ints: [
- 0,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_expr_list_for_each_with_identifier_await() {
- UnlinkedVariable variable =
- serializeVariableText('int i; var v = [await for (i in []) i];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '[await for (i in []) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.makeUntypedList,
- UnlinkedExprOperation.forEachPartsWithIdentifier,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.forElementWithAwait,
- UnlinkedExprOperation.makeUntypedList
- ],
- ints: [
- 0,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_expr_list_for_empty_condition() {
- UnlinkedVariable variable =
- serializeVariableText('int i; var v = [for (i = 0;; i++) i];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '[for (i = 0;; i++) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.pushEmptyExpression,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.assign,
- UnlinkedExprAssignOperator.postfixIncrement
- ],
- ints: [
- 0,
- 1,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_expr_list_for_empty_initializer() {
- UnlinkedVariable variable =
- serializeVariableText('int i; var v = [for (; i < 10; i++) i];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '[for (; i < 10; i++) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushEmptyExpression,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.postfixIncrement
- ],
- ints: [
- 10,
- 1,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_expr_list_for_two_updaters() {
- UnlinkedVariable variable = serializeVariableText(
- 'int i; int j; var v = [for (i = 0; i < 10; i++, j++) i];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '[for (i = 0; i < 10; i++, j++) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.assign,
- UnlinkedExprAssignOperator.postfixIncrement,
- UnlinkedExprAssignOperator.postfixIncrement
- ],
- ints: [
- 0,
- 10,
- 2,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'j',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_expr_list_for_with_one_declaration_typed() {
- UnlinkedVariable variable =
- serializeVariableText('var v = [for (int i = 0; i < 10; i++) i];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '[for (int i = 0; i < 10; i++) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.variableDeclarationStart,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.variableDeclaration,
- UnlinkedExprOperation.forInitializerDeclarationsTyped,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less,
- UnlinkedExprOperation.assignToParameter,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.postfixIncrement
- ],
- ints: [
- 0,
- 0,
- 1,
- 10,
- 1,
- 1
- ],
- strings: [
- 'i',
- 'i',
- 'i',
- 'i'
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int')
- ]);
- }
-
- test_expr_list_for_with_one_declaration_untyped() {
- UnlinkedVariable variable =
- serializeVariableText('var v = [for (var i = 0; i < 10; i++) i];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '[for (var i = 0; i < 10; i++) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.variableDeclarationStart,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.variableDeclaration,
- UnlinkedExprOperation.forInitializerDeclarationsUntyped,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less,
- UnlinkedExprOperation.assignToParameter,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.postfixIncrement
- ],
- ints: [
- 0,
- 0,
- 1,
- 10,
- 1,
- 1
- ],
- strings: [
- 'i',
- 'i',
- 'i',
- 'i'
- ]);
- }
-
- test_expr_list_for_with_two_declarations_untyped() {
- UnlinkedVariable variable = serializeVariableText(
- 'var v = [for (var i = 0, j = 0; i < 10; i++) i];');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- '[for (var i = 0, j = 0; i < 10; i++) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.variableDeclarationStart,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.variableDeclaration,
- UnlinkedExprOperation.variableDeclarationStart,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.variableDeclaration,
- UnlinkedExprOperation.forInitializerDeclarationsUntyped,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less,
- UnlinkedExprOperation.assignToParameter,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.postfixIncrement
- ],
- ints: [
- 0,
- 0,
- 0,
- 0,
- 2,
- 10,
- 1,
- 1
- ],
- strings: [
- 'i',
- 'j',
- 'i',
- 'i',
- 'i'
- ]);
- }
-
- test_expr_list_for_with_uninitialized_declaration_untyped() {
- UnlinkedVariable variable =
- serializeVariableText('var v = [for (var i; i < 10; i++) i];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '[for (var i; i < 10; i++) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.variableDeclarationStart,
- UnlinkedExprOperation.pushEmptyExpression,
- UnlinkedExprOperation.variableDeclaration,
- UnlinkedExprOperation.forInitializerDeclarationsUntyped,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less,
- UnlinkedExprOperation.assignToParameter,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushParameter,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.postfixIncrement
- ],
- ints: [
- 0,
- 1,
- 10,
- 1,
- 1
- ],
- strings: [
- 'i',
- 'i',
- 'i',
- 'i'
- ]);
- }
-
- test_expr_list_for_zero_updaters() {
- UnlinkedVariable variable =
- serializeVariableText('int i; var v = [for (i = 0; i < 10;) i];');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '[for (i = 0; i < 10;) i]',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedList
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.assign
- ],
- ints: [
- 0,
- 10,
- 0,
- 1
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_expr_makeTypedList() {
- UnlinkedVariable variable =
- serializeVariableText('var v = <int>[11, 22, 33];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '<int>[11, 22, 33]',
- operators: [UnlinkedExprOperation.makeTypedList],
- ints: [0],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_makeTypedMap() {
- UnlinkedVariable variable = serializeVariableText(
- 'var v = <int, String>{11: "aaa", 22: "bbb", 33: "ccc"};');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- '<int, String>{11: "aaa", 22: "bbb", 33: "ccc"}',
- operators: [UnlinkedExprOperation.makeTypedMap2],
- ints: [0],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'String',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_makeTypedSet() {
- UnlinkedVariable variable =
- serializeVariableText('var v = <int>{11, 22, 33};');
- assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{11, 22, 33}',
- operators: [UnlinkedExprOperation.makeTypedSet],
- ints: [0],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_makeUntypedList() {
- UnlinkedVariable variable = serializeVariableText('var v = [11, 22, 33];');
- assertUnlinkedConst(variable.initializer.bodyExpr, '[11, 22, 33]',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeUntypedList
- ],
- ints: [11, 22, 33, 3],
- forTypeInferenceOnly: true);
- }
-
- test_expr_makeUntypedMap() {
- UnlinkedVariable variable =
- serializeVariableText('var v = {11: "aaa", 22: "bbb", 33: "ccc"};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '{11: "aaa", 22: "bbb", 33: "ccc"}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushString,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.makeUntypedSetOrMap
- ],
- ints: [11, 22, 33, 3],
- strings: ['aaa', 'bbb', 'ccc'],
- forTypeInferenceOnly: true);
- }
-
- test_expr_makeUntypedSet() {
- UnlinkedVariable variable = serializeVariableText('var v = {11, 22, 33};');
- assertUnlinkedConst(variable.initializer.bodyExpr, '{11, 22, 33}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeUntypedSetOrMap
- ],
- ints: [11, 22, 33, 3],
- forTypeInferenceOnly: true);
- }
-
- test_expr_map_for() {
- UnlinkedVariable variable = serializeVariableText(
- 'int i; var v = {1: 2, for (i = 0; i < 10; i++) i: i};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '{1: 2, for (i = 0; i < 10; i++) i: i}',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.makeMapLiteralEntry,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedSetOrMap
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.assign,
- UnlinkedExprAssignOperator.postfixIncrement
- ],
- ints: [
- 1,
- 2,
- 0,
- 10,
- 1,
- 2
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_expr_set_for() {
- UnlinkedVariable variable = serializeVariableText(
- 'int i; var v = {1, for (i = 0; i < 10; i++) i};');
- assertUnlinkedConst(
- variable.initializer.bodyExpr, '{1, for (i = 0; i < 10; i++) i}',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.less,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.forParts,
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.forElement,
- UnlinkedExprOperation.makeUntypedSetOrMap
- ],
- assignmentOperators: [
- UnlinkedExprAssignOperator.assign,
- UnlinkedExprAssignOperator.postfixIncrement
- ],
- ints: [
- 1,
- 0,
- 10,
- 1,
- 2
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'i',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_expr_super() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = super;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'super',
- operators: [
- UnlinkedExprOperation.pushSuper,
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_this() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = this;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'this',
- operators: [
- UnlinkedExprOperation.pushThis,
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_throwException() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = throw 1 + 2;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, 'throw 1 + 2',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.add,
- UnlinkedExprOperation.throwException,
- ],
- ints: [1, 2],
- forTypeInferenceOnly: true);
- }
-
- test_expr_typeCast() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = 42 as num;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '42 as num',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.typeCast,
- ],
- ints: [42],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'num',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_expr_typeCheck() {
- UnlinkedVariable variable = serializeVariableText('''
-final v = 42 is num;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, '42 is num',
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.typeCheck,
- ],
- ints: [42],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'num',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- forTypeInferenceOnly: true);
- }
-
- test_field() {
- UnlinkedClass cls = serializeClassText('class C { int i; }');
- UnlinkedVariable variable = findVariable('i', variables: cls.fields);
- expect(variable, isNotNull);
- expect(variable.isConst, isFalse);
- expect(variable.isLate, isFalse);
- expect(variable.isStatic, isFalse);
- expect(variable.isFinal, isFalse);
- expect(variable.initializer, isNull);
- expect(variable.inheritsCovariantSlot, isNot(0));
- expect(findExecutable('i', executables: cls.executables), isNull);
- expect(findExecutable('i=', executables: cls.executables), isNull);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
- expect(unlinkedUnits[0].publicNamespace.names[0].members, isEmpty);
- }
-
- test_field_const() {
- UnlinkedVariable variable =
- serializeClassText('class C { static const int i = 0; }').fields[0];
- expect(variable.isConst, isTrue);
- expect(variable.inheritsCovariantSlot, 0);
- assertUnlinkedConst(variable.initializer.bodyExpr, '0',
- operators: [UnlinkedExprOperation.pushInt], ints: [0]);
- }
-
- test_field_documented() {
- String text = '''
-class C {
- /**
- * Docs
- */
- var v;
-}''';
- UnlinkedVariable variable = serializeClassText(text).fields[0];
- expect(variable.documentationComment, isNotNull);
- checkDocumentationComment(variable.documentationComment, text);
- }
-
- test_field_final_notConstExpr() {
- UnlinkedVariable variable = serializeClassText(r'''
-class C {
- final f = 1 + m();
- static int m() => 42;
-}''').fields[0];
- expect(variable.isFinal, isTrue);
- if (containsNonConstExprs) {
- assertUnlinkedConst(variable.initializer.bodyExpr, '1 + m()', operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.invokeMethodRef,
- UnlinkedExprOperation.add,
- ], ints: [
- 1,
- 0,
- 0,
- 0
- ], strings: [], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'm',
- expectedKind: ReferenceKind.method,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
- } else {
- expect(variable.initializer.bodyExpr, isNull);
- }
- }
-
- test_field_final_typeParameter() {
- UnlinkedVariable variable = serializeClassText(r'''
-class C<T> {
- final f = <T>[];
-}''').fields[0];
- expect(variable.isFinal, isTrue);
- if (containsNonConstExprs) {
- assertUnlinkedConst(variable.initializer.bodyExpr, '<T>[]',
- operators: [UnlinkedExprOperation.makeTypedList],
- ints: [0],
- referenceValidators: [(EntityRef r) => checkParamTypeRef(r, 1)]);
- } else {
- expect(variable.initializer.bodyExpr, isNull);
- }
- }
-
- test_field_formal_param_inferred_type_explicit() {
- UnlinkedClass cls = serializeClassText(
- 'class C extends D { var v; C(int this.v); }'
- ' abstract class D { num get v; }',
- className: 'C');
- checkInferredTypeSlot(cls.fields[0].inferredTypeSlot, 'dart:core', 'num');
- expect(cls.executables[0].kind, UnlinkedExecutableKind.constructor);
- expect(cls.executables[0].parameters[0].inferredTypeSlot, 0);
- }
-
- test_field_formal_param_inferred_type_implicit() {
- // Both the field `v` and the constructor argument `this.v` will have their
- // type inferred by strong mode. But only the field should have its
- // inferred type stored in the summary, since the standard rules for field
- // formal parameters will take care of the rest (they implicitly inherit
- // the type of the associated field).
- UnlinkedClass cls = serializeClassText(
- 'class C extends D { var v; C(this.v); }'
- ' abstract class D { int get v; }',
- className: 'C');
- checkInferredTypeSlot(cls.fields[0].inferredTypeSlot, 'dart:core', 'int');
- expect(cls.executables[0].kind, UnlinkedExecutableKind.constructor);
- expect(cls.executables[0].parameters[0].inferredTypeSlot, 0);
- }
-
- test_field_inferred_type_nonstatic_explicit_initialized() {
- UnlinkedVariable v = serializeClassText('class C { num v = 0; }').fields[0];
- expect(v.inferredTypeSlot, 0);
- }
-
- test_field_inferred_type_nonstatic_explicit_uninitialized() {
- UnlinkedVariable v = serializeClassText(
- 'class C extends D { num v; } abstract class D { int get v; }',
- className: 'C',
- allowErrors: true)
- .fields[0];
- expect(v.inferredTypeSlot, 0);
- }
-
- test_field_inferred_type_nonstatic_implicit_initialized() {
- UnlinkedVariable v = serializeClassText('class C { var v = 0; }').fields[0];
- checkInferredTypeSlot(v.inferredTypeSlot, 'dart:core', 'int');
- }
-
- test_field_inferred_type_nonstatic_implicit_uninitialized() {
- UnlinkedVariable v = serializeClassText(
- 'class C extends D { var v; } abstract class D { int get v; }',
- className: 'C')
- .fields[0];
- checkInferredTypeSlot(v.inferredTypeSlot, 'dart:core', 'int');
- }
-
- test_field_inferred_type_static_explicit_initialized() {
- UnlinkedVariable v =
- serializeClassText('class C { static int v = 0; }').fields[0];
- expect(v.inferredTypeSlot, 0);
- }
-
- test_field_inferred_type_static_implicit_initialized() {
- UnlinkedVariable v =
- serializeClassText('class C { static var v = 0; }').fields[0];
- checkInferredTypeSlot(v.inferredTypeSlot, 'dart:core', 'int');
- }
-
- test_field_inferred_type_static_implicit_uninitialized() {
- UnlinkedVariable v =
- serializeClassText('class C { static var v; }').fields[0];
- expect(v.inferredTypeSlot, 0);
- }
-
- test_field_initializer_constConstructor_typed() {
- UnlinkedVariable variable = serializeClassText('''
-class C {
- int x = 0;
- const C();
-}
-''').fields[0];
- expect(variable.initializer.bodyExpr, isNull);
- expect(variable.inheritsCovariantSlot, isNot(0));
- }
-
- test_field_initializer_final_constConstructor_typed() {
- UnlinkedVariable variable = serializeClassText('''
-class C {
- final int x = 0;
- const C();
-}
-''').fields[0];
- expect(variable.initializer.bodyExpr, isNotNull);
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_initializer_final_constConstructor_untyped() {
- UnlinkedVariable variable = serializeClassText('''
-class C {
- final x = 0;
- const C();
-}
-''').fields[0];
- expect(variable.initializer.bodyExpr, isNotNull);
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_initializer_final_typed() {
- UnlinkedVariable variable =
- serializeClassText('class C { final int x = 0; }').fields[0];
- expect(variable.initializer.bodyExpr, isNull);
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_initializer_final_untyped() {
- UnlinkedVariable variable =
- serializeClassText('class C { final x = 0; }').fields[0];
- if (containsNonConstExprs) {
- expect(variable.initializer.bodyExpr, isNotNull);
- } else {
- expect(variable.initializer.bodyExpr, isNull);
- }
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_initializer_static_constConstructor_typed() {
- UnlinkedVariable variable = serializeClassText('''
-class C {
- static int x = 0;
- const C();
-}
-''').fields[0];
- expect(variable.initializer.bodyExpr, isNull);
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_initializer_static_constConstructor_untyped() {
- UnlinkedVariable variable = serializeClassText('''
-class C {
- static var x = 0;
- const C();
-}
-''').fields[0];
- if (containsNonConstExprs) {
- expect(variable.initializer.bodyExpr, isNotNull);
- } else {
- expect(variable.initializer.bodyExpr, isNull);
- }
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_initializer_static_final_constConstructor_typed() {
- UnlinkedVariable variable = serializeClassText('''
-class C {
- static final int x = 0;
- const C();
-}
-''').fields[0];
- expect(variable.initializer.bodyExpr, isNull);
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_initializer_static_final_constConstructor_untyped() {
- UnlinkedVariable variable = serializeClassText('''
-class C {
- static final x = 0;
- const C();
-}
-''').fields[0];
- if (containsNonConstExprs) {
- expect(variable.initializer.bodyExpr, isNotNull);
- } else {
- expect(variable.initializer.bodyExpr, isNull);
- }
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_initializer_typed() {
- UnlinkedVariable variable =
- serializeClassText('class C { int x = 0; }').fields[0];
- expect(variable.initializer.bodyExpr, isNull);
- expect(variable.inheritsCovariantSlot, isNot(0));
- }
-
- test_field_initializer_untyped() {
- UnlinkedVariable variable =
- serializeClassText('class C { var x = 0; }').fields[0];
- if (containsNonConstExprs) {
- expect(variable.initializer.bodyExpr, isNotNull);
- } else {
- expect(variable.initializer.bodyExpr, isNull);
- }
- expect(variable.inheritsCovariantSlot, isNot(0));
- }
-
- test_field_late() {
- featureSet = enableNnbd;
- UnlinkedClass cls = serializeClassText('class C { late int i; }');
- UnlinkedVariable variable = findVariable('i', variables: cls.fields);
- expect(variable, isNotNull);
- expect(variable.isConst, isFalse);
- expect(variable.isLate, isTrue);
- expect(variable.isStatic, isFalse);
- expect(variable.isFinal, isFalse);
- expect(variable.initializer, isNull);
- expect(variable.inheritsCovariantSlot, isNot(0));
- expect(findExecutable('i', executables: cls.executables), isNull);
- expect(findExecutable('i=', executables: cls.executables), isNull);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
- expect(unlinkedUnits[0].publicNamespace.names[0].members, isEmpty);
- }
-
- test_field_static() {
- UnlinkedVariable variable =
- serializeClassText('class C { static int i; }').fields[0];
- expect(variable.isLate, isFalse);
- expect(variable.isStatic, isTrue);
- expect(variable.initializer, isNull);
- expect(variable.inheritsCovariantSlot, 0);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
- expect(unlinkedUnits[0].publicNamespace.names[0].members, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].members[0].name, 'i');
- expect(unlinkedUnits[0].publicNamespace.names[0].members[0].kind,
- ReferenceKind.propertyAccessor);
- expect(
- unlinkedUnits[0].publicNamespace.names[0].members[0].numTypeParameters,
- 0);
- expect(
- unlinkedUnits[0].publicNamespace.names[0].members[0].members, isEmpty);
- }
-
- test_field_static_final() {
- UnlinkedVariable variable =
- serializeClassText('class C { static final int i = 0; }').fields[0];
- expect(variable.isLate, isFalse);
- expect(variable.isStatic, isTrue);
- expect(variable.isFinal, isTrue);
- expect(variable.initializer.bodyExpr, isNull);
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_static_final_late() {
- featureSet = enableNnbd;
- UnlinkedVariable variable =
- serializeClassText('class C { static late final int i = 0; }')
- .fields[0];
- expect(variable.isLate, isTrue);
- expect(variable.isStatic, isTrue);
- expect(variable.isFinal, isTrue);
- expect(variable.initializer.bodyExpr, isNull);
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_static_final_untyped() {
- UnlinkedVariable variable =
- serializeClassText('class C { static final x = 0; }').fields[0];
- if (containsNonConstExprs) {
- expect(variable.initializer.bodyExpr, isNotNull);
- } else {
- expect(variable.initializer.bodyExpr, isNull);
- }
- expect(variable.inheritsCovariantSlot, 0);
- }
-
- test_field_static_late() {
- featureSet = enableNnbd;
- UnlinkedVariable variable =
- serializeClassText('class C { static late int i; }').fields[0];
- expect(variable.isLate, isTrue);
- expect(variable.isStatic, isTrue);
- expect(variable.initializer, isNull);
- expect(variable.inheritsCovariantSlot, 0);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
- expect(unlinkedUnits[0].publicNamespace.names[0].members, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.names[0].members[0].name, 'i');
- expect(unlinkedUnits[0].publicNamespace.names[0].members[0].kind,
- ReferenceKind.propertyAccessor);
- expect(
- unlinkedUnits[0].publicNamespace.names[0].members[0].numTypeParameters,
- 0);
- expect(
- unlinkedUnits[0].publicNamespace.names[0].members[0].members, isEmpty);
- }
-
- test_fully_linked_references_follow_other_references() {
- if (skipFullyLinkedData) {
- return;
- }
- serializeLibraryText('final x = 0; String y;');
- checkLinkedTypeSlot(
- unlinkedUnits[0].variables[0].inferredTypeSlot, 'dart:core', 'int');
- checkTypeRef(unlinkedUnits[0].variables[1].type, 'dart:core', 'String');
- // Even though the definition of y follows the definition of x, the linked
- // type reference for x should use a higher numbered reference than the
- // unlinked type reference for y.
- EntityRef propagatedType =
- getTypeRefForSlot(unlinkedUnits[0].variables[0].inferredTypeSlot);
- expect(unlinkedUnits[0].variables[1].type.reference,
- lessThan(propagatedType.reference));
- }
-
- test_function_documented() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-f() {}''';
- UnlinkedExecutable executable = serializeExecutableText(text);
- expect(executable.documentationComment, isNotNull);
- checkDocumentationComment(executable.documentationComment, text);
- }
-
- test_function_inferred_type_implicit_param() {
- UnlinkedExecutable f = serializeExecutableText('void f(value) {}');
- expect(f.parameters[0].inferredTypeSlot, 0);
- }
-
- test_function_inferred_type_implicit_return() {
- UnlinkedExecutable f = serializeExecutableText('f() => null;');
- expect(f.inferredReturnTypeSlot, 0);
- }
-
- test_function_type_nullability_suffix_none() {
- featureSet = enableNnbd;
- EntityRef typeRef = serializeTypeText('void Function()');
- expect(typeRef.entityKind, EntityRefKind.genericFunctionType);
- expect(typeRef.nullabilitySuffix, EntityRefNullabilitySuffix.none);
- }
-
- test_function_type_nullability_suffix_question() {
- featureSet = enableNnbd;
- EntityRef typeRef = serializeTypeText('void Function()?');
- expect(typeRef.entityKind, EntityRefKind.genericFunctionType);
- expect(typeRef.nullabilitySuffix, EntityRefNullabilitySuffix.question);
- }
-
- test_function_type_nullability_suffix_star() {
- featureSet = disableNnbd;
- EntityRef typeRef = serializeTypeText('void Function()');
- expect(typeRef.entityKind, EntityRefKind.genericFunctionType);
- expect(
- typeRef.nullabilitySuffix, EntityRefNullabilitySuffix.starOrIrrelevant);
- }
-
- test_generic_method_in_generic_class() {
- UnlinkedClass cls = serializeClassText(
- 'class C<T, U> { void m<V, W>(T t, U u, V v, W w) {} }');
- List<UnlinkedParam> params = cls.executables[0].parameters;
- checkParamTypeRef(params[0].type, 4);
- checkParamTypeRef(params[1].type, 3);
- checkParamTypeRef(params[2].type, 2);
- checkParamTypeRef(params[3].type, 1);
- }
-
- test_getter_documented() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-get f => null;''';
- UnlinkedExecutable executable = serializeExecutableText(text);
- expect(executable.documentationComment, isNotNull);
- checkDocumentationComment(executable.documentationComment, text);
- }
-
- test_getter_inferred_type_nonstatic_explicit_return() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { num get f => null; }'
- ' abstract class D { int get f; }',
- className: 'C',
- allowErrors: true)
- .executables[0];
- expect(f.inferredReturnTypeSlot, 0);
- }
-
- test_getter_inferred_type_nonstatic_implicit_return() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { get f => null; } abstract class D { int get f; }',
- className: 'C')
- .executables[0];
- checkInferredTypeSlot(f.inferredReturnTypeSlot, 'dart:core', 'int');
- }
-
- test_getter_inferred_type_static_implicit_return() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { static get f => null; }'
- ' class D { static int get f => null; }',
- className: 'C')
- .executables[0];
- expect(f.inferredReturnTypeSlot, 0);
- }
-
- test_implicit_dependencies_follow_other_dependencies() {
- if (skipFullyLinkedData) {
- return;
- }
- addNamedSource('/a.dart', 'import "b.dart"; class C {} D f() => null;');
- addNamedSource('/b.dart', 'class D {}');
- serializeLibraryText('import "a.dart"; final x = f(); C y;');
- // The dependency on b.dart is implicit, so it should be placed at the end
- // of the dependency list, after a.dart, even though the code that refers
- // to b.dart comes before the code that refers to a.dart.
- int aDep = checkHasDependency(absUri('/a.dart'), fullyLinked: false);
- int bDep = checkHasDependency(absUri('/b.dart'), fullyLinked: true);
- expect(aDep, lessThan(bDep));
- }
-
- test_import_configurations() {
- addNamedSource('/foo.dart', 'bar() {}');
- addNamedSource('/foo_io.dart', 'bar() {}');
- addNamedSource('/foo_html.dart', 'bar() {}');
- String libraryText = r'''
-import 'foo.dart'
- if (dart.library.io) 'foo_io.dart'
- if (dart.flavor == 'html') 'foo_html.dart';
-''';
- serializeLibraryText(libraryText);
- UnlinkedImport imp = unlinkedUnits[0].imports[0];
- expect(imp.configurations, hasLength(2));
- {
- UnlinkedConfiguration configuration = imp.configurations[0];
- expect(configuration.name, 'dart.library.io');
- expect(configuration.value, 'true');
- expect(configuration.uri, 'foo_io.dart');
- }
- {
- UnlinkedConfiguration configuration = imp.configurations[1];
- expect(configuration.name, 'dart.flavor');
- expect(configuration.value, 'html');
- expect(configuration.uri, 'foo_html.dart');
- }
- }
-
- test_import_deferred() {
- serializeLibraryText(
- 'import "dart:async" deferred as a; main() { print(a.Future); }');
- expect(unlinkedUnits[0].imports[0].isDeferred, isTrue);
- }
-
- test_import_dependency() {
- serializeLibraryText('import "dart:async"; Future x;');
- // Second import is the implicit import of dart:core
- expect(unlinkedUnits[0].imports, hasLength(2));
- checkDependency(linked.importDependencies[0], 'dart:async');
- }
-
- test_import_explicit() {
- serializeLibraryText('import "dart:core"; int i;');
- expect(unlinkedUnits[0].imports, hasLength(1));
- expect(unlinkedUnits[0].imports[0].isImplicit, isFalse);
- }
-
- test_import_hide_order() {
- serializeLibraryText(
- 'import "dart:async" hide Future, Stream; Completer c;');
- // Second import is the implicit import of dart:core
- expect(unlinkedUnits[0].imports, hasLength(2));
- expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
- expect(unlinkedUnits[0].imports[0].combinators[0].shows, isEmpty);
- expect(unlinkedUnits[0].imports[0].combinators[0].hides, hasLength(2));
- expect(unlinkedUnits[0].imports[0].combinators[0].hides[0], 'Future');
- expect(unlinkedUnits[0].imports[0].combinators[0].hides[1], 'Stream');
- expect(unlinkedUnits[0].imports[0].combinators[0].offset, 0);
- expect(unlinkedUnits[0].imports[0].combinators[0].end, 0);
- }
-
- test_import_implicit() {
- // The implicit import of dart:core is represented in the model.
- serializeLibraryText('');
- expect(unlinkedUnits[0].imports, hasLength(1));
- checkDependency(linked.importDependencies[0], 'dart:core');
- expect(unlinkedUnits[0].imports[0].uri, isEmpty);
- expect(unlinkedUnits[0].imports[0].uriOffset, 0);
- expect(unlinkedUnits[0].imports[0].uriEnd, 0);
- expect(unlinkedUnits[0].imports[0].prefixReference, 0);
- expect(unlinkedUnits[0].imports[0].combinators, isEmpty);
- expect(unlinkedUnits[0].imports[0].isImplicit, isTrue);
- }
-
- test_import_missing() {
- // Unresolved imports are included since this is necessary for proper
- // dependency tracking.
- allowMissingFiles = true;
- serializeLibraryText('import "foo.dart";', allowErrors: true);
- // Second import is the implicit import of dart:core
- expect(unlinkedUnits[0].imports, hasLength(2));
- checkDependency(linked.importDependencies[0], absUri('/foo.dart'));
- }
-
- test_import_no_combinators() {
- serializeLibraryText('import "dart:async"; Future x;');
- // Second import is the implicit import of dart:core
- expect(unlinkedUnits[0].imports, hasLength(2));
- expect(unlinkedUnits[0].imports[0].combinators, isEmpty);
- }
-
- test_import_no_flags() {
- serializeLibraryText('import "dart:async"; Future x;');
- expect(unlinkedUnits[0].imports[0].isImplicit, isFalse);
- expect(unlinkedUnits[0].imports[0].isDeferred, isFalse);
- }
-
- test_import_non_deferred() {
- serializeLibraryText(
- 'import "dart:async" as a; main() { print(a.Future); }');
- expect(unlinkedUnits[0].imports[0].isDeferred, isFalse);
- }
-
- test_import_of_file_with_missing_part() {
- // Other references in foo.dart should be resolved even though foo.dart's
- // part declaration for bar.dart refers to a non-existent file.
- allowMissingFiles = true;
- addNamedSource('/foo.dart', 'part "bar.dart"; class C {}');
- serializeLibraryText('import "foo.dart"; C x;');
- checkTypeRef(findVariable('x').type, absUri('/foo.dart'), 'C');
- }
-
- test_import_of_missing_export() {
- // Other references in foo.dart should be resolved even though foo.dart's
- // re-export of bar.dart refers to a non-existent file.
- allowMissingFiles = true;
- addNamedSource('/foo.dart', 'export "bar.dart"; class C {}');
- serializeLibraryText('import "foo.dart"; C x;');
- checkTypeRef(findVariable('x').type, absUri('/foo.dart'), 'C');
- }
-
- test_import_offset() {
- String libraryText = ' import "dart:async"; Future x;';
- serializeLibraryText(libraryText);
- expect(unlinkedUnits[0].imports[0].offset, libraryText.indexOf('import'));
- expect(unlinkedUnits[0].imports[0].uriOffset,
- libraryText.indexOf('"dart:async"'));
- expect(unlinkedUnits[0].imports[0].uriEnd, libraryText.indexOf('; Future'));
- }
-
- test_import_prefix_name() {
- String libraryText = 'import "dart:async" as a; a.Future x;';
- serializeLibraryText(libraryText);
- // Second import is the implicit import of dart:core
- expect(unlinkedUnits[0].imports, hasLength(2));
- checkPrefix(unlinkedUnits[0].imports[0].prefixReference, 'a');
- expect(unlinkedUnits[0].imports[0].prefixOffset, libraryText.indexOf('a;'));
- }
-
- test_import_prefix_none() {
- serializeLibraryText('import "dart:async"; Future x;');
- // Second import is the implicit import of dart:core
- expect(unlinkedUnits[0].imports, hasLength(2));
- expect(unlinkedUnits[0].imports[0].prefixReference, 0);
- }
-
- test_import_prefix_not_in_public_namespace() {
- serializeLibraryText('import "dart:async" as a; a.Future v;');
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'v');
- expect(unlinkedUnits[0].publicNamespace.names[1].name, 'v=');
- }
-
- test_import_prefix_reference() {
- UnlinkedVariable variable =
- serializeVariableText('import "dart:async" as a; a.Future v;');
- checkTypeRef(variable.type, 'dart:async', 'Future',
- expectedPrefix: 'a', numTypeParameters: 1);
- }
-
- test_import_prefixes_take_precedence_over_imported_names() {
- addNamedSource('/a.dart', 'class b {} class A');
- addNamedSource('/b.dart', 'class Cls {}');
- addNamedSource('/c.dart', 'class Cls {}');
- addNamedSource('/d.dart', 'class c {} class D');
- serializeLibraryText('''
-import 'a.dart';
-import 'b.dart' as b;
-import 'c.dart' as c;
-import 'd.dart';
-A aCls;
-b.Cls bCls;
-c.Cls cCls;
-D dCls;
-''');
- checkTypeRef(findVariable('aCls').type, absUri('/a.dart'), 'A');
- checkTypeRef(findVariable('bCls').type, absUri('/b.dart'), 'Cls',
- expectedPrefix: 'b');
- checkTypeRef(findVariable('cCls').type, absUri('/c.dart'), 'Cls',
- expectedPrefix: 'c');
- checkTypeRef(findVariable('dCls').type, absUri('/d.dart'), 'D');
- }
-
- test_import_reference() {
- UnlinkedVariable variable =
- serializeVariableText('import "dart:async"; Future v;');
- checkTypeRef(variable.type, 'dart:async', 'Future', numTypeParameters: 1);
- }
-
- test_import_reference_merged_no_prefix() {
- serializeLibraryText('''
-import "dart:async" show Future;
-import "dart:async" show Stream;
-
-Future f;
-Stream s;
-''');
- {
- EntityRef typeRef = findVariable('f').type;
- checkTypeRef(typeRef, 'dart:async', 'Future', numTypeParameters: 1);
- }
- {
- EntityRef typeRef = findVariable('s').type;
- checkTypeRef(typeRef, 'dart:async', 'Stream',
- expectedTargetUnit: 1, numTypeParameters: 1);
- }
- }
-
- test_import_reference_merged_prefixed() {
- serializeLibraryText('''
-import "dart:async" as a show Future;
-import "dart:async" as a show Stream;
-
-a.Future f;
-a.Stream s;
-''');
- {
- EntityRef typeRef = findVariable('f').type;
- checkTypeRef(typeRef, 'dart:async', 'Future',
- expectedPrefix: 'a', numTypeParameters: 1);
- }
- {
- EntityRef typeRef = findVariable('s').type;
- checkTypeRef(typeRef, 'dart:async', 'Stream',
- expectedTargetUnit: 1, expectedPrefix: 'a', numTypeParameters: 1);
- }
- }
-
- test_import_reference_merged_prefixed_separate_libraries() {
- addNamedSource('/a.dart', 'class A {}');
- addNamedSource('/b.dart', 'class B {}');
- serializeLibraryText('''
-import 'a.dart' as p;
-import 'b.dart' as p;
-
-p.A a;
-p.B b;
-''');
- checkTypeRef(findVariable('a').type, absUri('/a.dart'), 'A',
- expectedPrefix: 'p');
- checkTypeRef(findVariable('b').type, absUri('/b.dart'), 'B',
- expectedPrefix: 'p');
- }
-
- test_import_self() {
- serializeLibraryText('''
-import 'test.dart' as p;
-class C {}
-class D extends p.C {} // Prevent "unused import" warning
-''');
- expect(unlinkedUnits[0].imports[0].uri, 'test.dart');
- checkDependency(linked.importDependencies[0], absUri('/test.dart'));
- checkTypeRef(
- unlinkedUnits[0].classes[1].supertype, absUri('/test.dart'), 'C',
- expectedPrefix: 'p');
- }
-
- test_import_show_order() {
- String libraryText =
- 'import "dart:async" show Future, Stream; Future x; Stream y;';
- serializeLibraryText(libraryText);
- // Second import is the implicit import of dart:core
- expect(unlinkedUnits[0].imports, hasLength(2));
- expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
- expect(unlinkedUnits[0].imports[0].combinators[0].shows, hasLength(2));
- expect(unlinkedUnits[0].imports[0].combinators[0].hides, isEmpty);
- expect(unlinkedUnits[0].imports[0].combinators[0].shows[0], 'Future');
- expect(unlinkedUnits[0].imports[0].combinators[0].shows[1], 'Stream');
- expect(unlinkedUnits[0].imports[0].combinators[0].offset,
- libraryText.indexOf('show'));
- expect(unlinkedUnits[0].imports[0].combinators[0].end,
- libraryText.indexOf('; Future'));
- }
-
- test_import_uri() {
- String uriString = '"dart:async"';
- String libraryText = 'import $uriString; Future x;';
- serializeLibraryText(libraryText);
- // Second import is the implicit import of dart:core
- expect(unlinkedUnits[0].imports, hasLength(2));
- expect(unlinkedUnits[0].imports[0].uri, 'dart:async');
- }
-
- test_import_uri_invalid() {
- String uriString = ':[invalid uri]';
- String libraryText = 'import "$uriString";';
- serializeLibraryText(libraryText);
- // Second import is the implicit import of dart:core
- expect(unlinkedUnits[0].imports, hasLength(2));
- expect(unlinkedUnits[0].imports[0].uri, uriString);
- }
-
- test_import_uri_nullStringValue() {
- String libraryText = r'''
-import "${'a'}.dart";
-''';
- serializeLibraryText(libraryText);
- // Second import is the implicit import of dart:core
- expect(unlinkedUnits[0].imports, hasLength(2));
- expect(unlinkedUnits[0].imports[0].uri, '');
- }
-
- test_inferred_function_type_parameter_type_with_unrelated_type_param() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedClass c = serializeClassText('''
-abstract class B<T> {
- void f(void g());
-}
-class C<T> extends B<T> {
- void f(g) {}
-}
-''');
- expect(c.executables, hasLength(1));
- UnlinkedExecutable f = c.executables[0];
- expect(f.parameters, hasLength(1));
- UnlinkedParam g = f.parameters[0];
- expect(g.name, 'g');
- EntityRef typeRef = getTypeRefForSlot(g.inferredTypeSlot);
-
- // The type that is inferred for C.f's parameter g is "() -> void".
- // Therefore it has no type arguments. However, the associated element for
- // that function type is B.f's parameter g, and B has a type parameter, so
- // the inferred type *may* safely record that T as a type parameter, in
- // which case this assertion can be altered accordingly.
- checkTypeRef(typeRef, null, 'f',
- numTypeArguments: 0, entityKind: EntityRefKind.genericFunctionType);
- }
-
- test_inferred_type_keeps_leading_dynamic() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedClass cls =
- serializeClassText('class C { final x = <dynamic, int>{}; }');
- EntityRef type = getTypeRefForSlot(cls.fields[0].inferredTypeSlot);
- // Check that x has inferred type `Map<dynamic, int>`.
- checkLinkedTypeRef(type, 'dart:core', 'Map',
- numTypeParameters: 2, numTypeArguments: 2);
- checkLinkedTypeRef(type.typeArguments[0], null, 'dynamic');
- checkLinkedTypeRef(type.typeArguments[1], 'dart:core', 'int');
- }
-
- test_inferred_type_reference_shared_prefixed() {
- if (skipFullyLinkedData) {
- return;
- }
- // Variable `y` has an inferred type of `p.C`. Verify that the reference
- // used by the explicit type of `x` is re-used for the inferred type.
- addNamedSource('/a.dart', 'class C {}');
- serializeLibraryText('import "a.dart" as p; p.C x; var y = new p.C();');
- EntityRef xType = findVariable('x').type;
- EntityRef yType = getTypeRefForSlot(findVariable('y').inferredTypeSlot);
- expect(yType.reference, xType.reference);
- }
-
- test_inferred_type_refers_to_bound_type_param() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedClass cls = serializeClassText(
- 'class C<T> extends D<int, T> { var v; }'
- ' abstract class D<U, V> { Map<V, U> get v; }',
- className: 'C');
- EntityRef type = getTypeRefForSlot(cls.fields[0].inferredTypeSlot);
- // Check that v has inferred type Map<T, int>.
- checkLinkedTypeRef(type, 'dart:core', 'Map',
- numTypeParameters: 2, numTypeArguments: 2);
- checkParamTypeRef(type.typeArguments[0], 1);
- checkLinkedTypeRef(type.typeArguments[1], 'dart:core', 'int');
- }
-
- test_inferred_type_refers_to_function_typed_param_of_typedef() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedVariable v = serializeVariableText('''
-typedef void F(int g(String s));
-F h() => null;
-var v = h();
-''');
- EntityRef typeRef = getTypeRefForSlot(v.inferredTypeSlot);
- checkLinkedTypeRef(typeRef, null, 'F', expectedKind: ReferenceKind.typedef);
- expect(typeRef.implicitFunctionTypeIndices, isEmpty);
- }
-
- test_inferred_type_refers_to_function_typed_parameter_type_generic_class() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedClass cls = serializeClassText(
- 'class C<T, U> extends D<U, int> { void f(int x, g) {} }'
- ' abstract class D<V, W> { void f(int x, W g(V s)); }',
- className: 'C');
- EntityRef type =
- getTypeRefForSlot(cls.executables[0].parameters[1].inferredTypeSlot);
- // Check that parameter g's inferred type is the type implied by D.f's 1st
- // (zero-based) parameter.
- expect(type.implicitFunctionTypeIndices, isEmpty);
- expect(type.paramReference, 0);
- // Note: this *may* legally have two type arguments (V, W), but for the
- // moment does not in practice, so we assert isEmpty.
- expect(type.typeArguments, isEmpty);
- expect(type.entityKind, EntityRefKind.syntheticFunction);
- expect(type.syntheticParams, hasLength(1));
- checkParamTypeRef(type.syntheticParams[0].type, 1);
- checkLinkedTypeRef(type.syntheticReturnType, 'dart:core', 'int');
- }
-
- test_inferred_type_refers_to_function_typed_parameter_type_other_lib() {
- if (skipFullyLinkedData) {
- return;
- }
- addNamedSource('/a.dart', 'import "b.dart"; abstract class D extends E {}');
- addNamedSource(
- '/b.dart', 'abstract class E { void f(int x, int g(String s)); }');
- UnlinkedClass cls = serializeClassText(
- 'import "a.dart"; class C extends D { void f(int x, g) {} }');
- EntityRef type =
- getTypeRefForSlot(cls.executables[0].parameters[1].inferredTypeSlot);
- expect(type.implicitFunctionTypeIndices, isEmpty);
- expect(type.paramReference, 0);
- // Note: this *may* legally have two type arguments (V, W), but for the
- // moment does not in practice, so we assert isEmpty.
- expect(type.typeArguments, isEmpty);
- expect(type.entityKind, EntityRefKind.syntheticFunction);
- expect(type.syntheticParams, hasLength(1));
- checkLinkedTypeRef(type.syntheticReturnType, 'dart:core', 'int');
- checkLinkedTypeRef(type.syntheticParams[0].type, 'dart:core', 'String');
- }
-
- test_inferred_type_refers_to_method_function_typed_parameter_type() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedClass cls = serializeClassText(
- 'class C extends D { void f(int x, g) {} }'
- ' abstract class D { void f(int x, int g(String s)); }',
- className: 'C');
- EntityRef type =
- getTypeRefForSlot(cls.executables[0].parameters[1].inferredTypeSlot);
-
- expect(type.implicitFunctionTypeIndices, isEmpty);
- expect(type.paramReference, 0);
- // Note: this *may* legally have two type arguments (V, W), but for the
- // moment does not in practice, so we assert isEmpty.
- expect(type.typeArguments, isEmpty);
- expect(type.entityKind, EntityRefKind.syntheticFunction);
- expect(type.syntheticParams, hasLength(1));
- checkLinkedTypeRef(type.syntheticReturnType, 'dart:core', 'int');
- checkLinkedTypeRef(type.syntheticParams[0].type, 'dart:core', 'String');
- }
-
- test_inferred_type_refers_to_nested_function_typed_param() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedVariable v = serializeVariableText('''
-dynamic f(void g(int x, void h())) => null;
-T extract<T>(dynamic f2(void g2(int x2, T h2)) => null;
-var v = extract(f);
-''');
- EntityRef typeRef = getTypeRefForSlot(v.inferredTypeSlot);
- checkLinkedTypeRef(typeRef, null, 'f',
- expectedKind: ReferenceKind.topLevelFunction);
- expect(typeRef.implicitFunctionTypeIndices, [0, 1]);
- }
-
- test_inferred_type_refers_to_nested_function_typed_param_named() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedVariable v = serializeVariableText('''
-dynamic f({void g(int x, void h())}) => null;
-T extract<T>(dynamic f2({void g(int x2, T h2)})) => null;
-var v = extract(f);
-''');
- EntityRef typeRef = getTypeRefForSlot(v.inferredTypeSlot);
- checkLinkedTypeRef(typeRef, null, 'f',
- expectedKind: ReferenceKind.topLevelFunction);
- expect(typeRef.implicitFunctionTypeIndices, [0, 1]);
- }
-
- test_inferred_type_refers_to_setter_function_typed_parameter_type() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedClass cls = serializeClassText(
- 'class C extends D { void set f(g) {} }'
- ' abstract class D { void set f(int g(String s)); }',
- className: 'C');
- EntityRef type =
- getTypeRefForSlot(cls.executables[0].parameters[0].inferredTypeSlot);
- // Check that parameter g's inferred type is the type implied by D.f's 1st
- // (zero-based) parameter.
- expect(type.implicitFunctionTypeIndices, [0]);
- expect(type.paramReference, 0);
- expect(type.typeArguments, isEmpty);
- expect(type.reference,
- greaterThanOrEqualTo(unlinkedUnits[0].references.length));
- LinkedReference linkedReference =
- linked.units[0].references[type.reference];
- expect(linkedReference.dependency, 0);
- expect(linkedReference.kind, ReferenceKind.propertyAccessor);
- expect(linkedReference.name, 'f=');
- expect(linkedReference.numTypeParameters, 0);
- expect(linkedReference.unit, 0);
- expect(linkedReference.containingReference, isNot(0));
- expect(linkedReference.containingReference, lessThan(type.reference));
- checkReferenceIndex(linkedReference.containingReference, null, 'D');
- }
-
- test_inferred_type_skips_trailing_dynamic() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedClass cls =
- serializeClassText('class C { final x = <int, dynamic>{}; }');
- EntityRef type = getTypeRefForSlot(cls.fields[0].inferredTypeSlot);
- // Check that x has inferred type `Map<int, dynamic>`.
- checkLinkedTypeRef(type, 'dart:core', 'Map',
- numTypeParameters: 2, numTypeArguments: 2);
- checkLinkedTypeRef(type.typeArguments[0], 'dart:core', 'int');
- checkLinkedDynamicTypeRef(type.typeArguments[1]);
- }
-
- test_inferred_type_skips_unnecessary_dynamic() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedClass cls = serializeClassText('class C { final x = []; }');
- EntityRef type = getTypeRefForSlot(cls.fields[0].inferredTypeSlot);
- // Check that x has inferred type `List<dynamic>`.
- checkLinkedTypeRef(type, 'dart:core', 'List',
- numTypeParameters: 1, numTypeArguments: 1);
- }
-
- test_inferred_type_undefined() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedVariable v = serializeVariableText('var v = <Undefined>[];');
- var typeRef = getTypeRefForSlot(v.inferredTypeSlot);
- checkLinkedTypeRef(typeRef, 'dart:core', 'List',
- numTypeArguments: 1, numTypeParameters: 1);
- checkLinkedDynamicTypeRef(typeRef.typeArguments[0]);
- }
-
- test_initializer_executable_with_bottom_return_type() {
- // The synthetic executable for `v` has type `() => Bottom`.
- UnlinkedVariable variable = serializeVariableText('int v = null;');
- expect(variable.initializer.returnType, isNull);
- checkInferredTypeSlot(
- variable.initializer.inferredReturnTypeSlot, null, 'Never',
- onlyInStrongMode: false);
- }
-
- test_initializer_executable_with_imported_return_type() {
- addNamedSource('/a.dart', 'class C { D d; } class D {}');
- // The synthetic executable for `v` has type `() => D`; `D` is defined in
- // a library that is imported. Note: `v` is mis-typed as `int` to prevent
- // type propagation, which would complicate the test.
- UnlinkedVariable variable = serializeVariableText(
- 'import "a.dart"; int v = new C().d;',
- allowErrors: true);
- expect(variable.initializer.returnType, isNull);
- checkInferredTypeSlot(
- variable.initializer.inferredReturnTypeSlot, absUri('/a.dart'), 'D',
- onlyInStrongMode: false);
- checkHasDependency(absUri('/a.dart'), fullyLinked: false);
- }
-
- test_initializer_executable_with_return_type_from_closure() {
- if (skipFullyLinkedData) {
- return;
- }
- // The synthetic executable for `v` has type `() => () => int`, where the
- // `() => int` part refers to the closure declared inside the initializer
- // for v. Note: `v` is mis-typed as `int` to prevent type propagation,
- // which would complicate the test.
- UnlinkedVariable variable =
- serializeVariableText('int v = () => 0;', allowErrors: true);
- EntityRef closureType =
- getTypeRefForSlot(variable.initializer.inferredReturnTypeSlot);
- checkLinkedTypeRef(closureType, null, '',
- expectedKind: ReferenceKind.function);
- int initializerIndex =
- definingUnit.references[closureType.reference].containingReference;
- checkReferenceIndex(initializerIndex, null, '',
- expectedKind: ReferenceKind.function);
- int variableIndex =
- definingUnit.references[initializerIndex].containingReference;
- checkReferenceIndex(variableIndex, null, 'v',
- expectedKind: ReferenceKind.topLevelPropertyAccessor);
- expect(definingUnit.references[variableIndex].containingReference, 0);
- }
-
- test_initializer_executable_with_return_type_from_closure_field() {
- if (skipFullyLinkedData) {
- return;
- }
- // The synthetic executable for `v` has type `() => () => int`, where the
- // `() => int` part refers to the closure declared inside the initializer
- // for v. Note: `v` is mis-typed as `int` to prevent type propagation,
- // which would complicate the test.
- UnlinkedClass cls = serializeClassText('''
-class C {
- int v = () => 0;
-}
-''', allowErrors: true);
- UnlinkedVariable variable = cls.fields[0];
- EntityRef closureType =
- getTypeRefForSlot(variable.initializer.inferredReturnTypeSlot);
- checkLinkedTypeRef(closureType, null, '',
- expectedKind: ReferenceKind.function);
- int initializerIndex =
- definingUnit.references[closureType.reference].containingReference;
- checkReferenceIndex(initializerIndex, null, '',
- expectedKind: ReferenceKind.function);
- int variableIndex =
- definingUnit.references[initializerIndex].containingReference;
- checkReferenceIndex(variableIndex, null, 'v',
- expectedKind: ReferenceKind.propertyAccessor);
- int classIndex = definingUnit.references[variableIndex].containingReference;
- checkReferenceIndex(classIndex, null, 'C');
- expect(definingUnit.references[classIndex].containingReference, 0);
- }
-
- test_initializer_executable_with_unimported_return_type() {
- addNamedSource('/a.dart', 'import "b.dart"; class C { D d; }');
- addNamedSource('/b.dart', 'class D {}');
- // The synthetic executable for `v` has type `() => D`; `D` is defined in
- // a library that is not imported. Note: `v` is mis-typed as `int` to
- // prevent type propagation, which would complicate the test.
- UnlinkedVariable variable = serializeVariableText(
- 'import "a.dart"; int v = new C().d;',
- allowErrors: true);
- expect(variable.initializer.returnType, isNull);
- checkInferredTypeSlot(
- variable.initializer.inferredReturnTypeSlot, absUri('/b.dart'), 'D',
- onlyInStrongMode: false);
- if (!skipFullyLinkedData) {
- checkHasDependency('b.dart', fullyLinked: true);
- }
- }
-
- test_library_documented() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-library foo;''';
- serializeLibraryText(text);
- expect(unlinkedUnits[0].libraryDocumentationComment, isNotNull);
- checkDocumentationComment(
- unlinkedUnits[0].libraryDocumentationComment, text);
- }
-
- test_library_name_with_spaces() {
- String text = 'library foo . bar ;';
- serializeLibraryText(text);
- expect(unlinkedUnits[0].libraryName, 'foo.bar');
- expect(unlinkedUnits[0].libraryNameOffset, text.indexOf('foo . bar'));
- expect(unlinkedUnits[0].libraryNameLength, 'foo . bar'.length);
- }
-
- test_library_named() {
- String text = 'library foo.bar;';
- serializeLibraryText(text);
- expect(unlinkedUnits[0].libraryName, 'foo.bar');
- expect(unlinkedUnits[0].libraryNameOffset, text.indexOf('foo.bar'));
- expect(unlinkedUnits[0].libraryNameLength, 'foo.bar'.length);
- }
-
- test_library_unnamed() {
- serializeLibraryText('');
- expect(unlinkedUnits[0].libraryName, isEmpty);
- expect(unlinkedUnits[0].libraryNameOffset, 0);
- expect(unlinkedUnits[0].libraryNameLength, 0);
- }
-
- test_library_with_missing_part() {
- // References to other parts should still be resolved.
- allowMissingFiles = true;
- addNamedSource('/bar.dart', 'part of my.lib; class C {}');
- serializeLibraryText(
- 'library my.lib; part "foo.dart"; part "bar.dart"; C c;',
- allowErrors: true);
- checkTypeRef(findVariable('c').type, null, 'C', expectedTargetUnit: 2);
- }
-
- test_lineStarts() {
- String text = '''
-int foo;
-class Test {}
-
-int bar;'''
- .replaceAll('\r\n', '\n');
- serializeLibraryText(text);
- expect(unlinkedUnits[0].lineStarts, [0, 9, 23, 24]);
- }
-
- test_linked_reference_reuse() {
- if (skipFullyLinkedData) {
- return;
- }
- // When the reference for a linked type is the same as an explicitly
- // referenced type, the explicit reference should be re-used.
- addNamedSource('/a.dart', 'class C {}');
- addNamedSource('/b.dart', 'import "a.dart"; C f() => null;');
- serializeLibraryText(
- 'import "a.dart"; import "b.dart"; C c1; final c2 = f();');
- int explicitReference = findVariable('c1').type.reference;
- expect(getTypeRefForSlot(findVariable('c2').inferredTypeSlot).reference,
- explicitReference);
- }
-
- test_linked_type_dependency_reuse() {
- if (skipFullyLinkedData) {
- return;
- }
- // When the dependency for a linked type is the same as an explicit
- // dependency, the explicit dependency should be re-used.
- addNamedSource('/a.dart', 'class C {} class D {}');
- addNamedSource('/b.dart', 'import "a.dart"; D f() => null;');
- serializeLibraryText(
- 'import "a.dart"; import "b.dart"; C c; final d = f();');
- int cReference = findVariable('c').type.reference;
- int explicitDependency = linked.units[0].references[cReference].dependency;
- int dReference =
- getTypeRefForSlot(findVariable('d').inferredTypeSlot).reference;
- expect(
- linked.units[0].references[dReference].dependency, explicitDependency);
- }
-
- test_local_names_take_precedence_over_imported_names() {
- addNamedSource('/a.dart', 'class C {} class D {}');
- serializeLibraryText('''
-import 'a.dart';
-class C {}
-C c;
-D d;''');
- checkTypeRef(findVariable('c').type, null, 'C');
- checkTypeRef(findVariable('d').type, absUri('/a.dart'), 'D');
- }
-
- test_localNameShadowsImportPrefix() {
- serializeLibraryText('import "dart:async" as a; class a {}; a x;');
- checkTypeRef(findVariable('x').type, null, 'a');
- }
-
- test_metadata_classDeclaration() {
- checkAnnotationA(
- serializeClassText('const a = null; @a class C {}').annotations);
- }
-
- test_metadata_classTypeAlias() {
- checkAnnotationA(serializeClassText(
- 'const a = null; @a class C = D with E; class D {} class E {}',
- className: 'C')
- .annotations);
- }
-
- test_metadata_constructor_call_named() {
- UnlinkedClass cls = serializeClassText(
- 'class A { const A.named(); } @A.named() class C {}');
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'A.named()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'A')
- ])
- ]);
- }
-
- test_metadata_constructor_call_named_prefixed() {
- addNamedSource('/foo.dart', 'class A { const A.named(); }');
- UnlinkedClass cls = serializeClassText(
- 'import "foo.dart" as foo; @foo.A.named() class C {}');
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'foo.A.named()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.constructor,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.classOrEnum,
- 'A',
- absoluteUri: absUri('/foo.dart'),
- ),
- new _PrefixExpectation(ReferenceKind.prefix, 'foo')
- ])
- ]);
- }
-
- test_metadata_constructor_call_named_prefixed_unresolved_class() {
- addNamedSource('/foo.dart', '');
- UnlinkedClass cls = serializeClassText(
- 'import "foo.dart" as foo; @foo.A.named() class C {}',
- allowErrors: true);
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'foo.A.named()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.unresolved, 'A'),
- new _PrefixExpectation(ReferenceKind.prefix, 'foo')
- ])
- ]);
- }
-
- test_metadata_constructor_call_named_prefixed_unresolved_constructor() {
- addNamedSource('/foo.dart', 'class A {}');
- UnlinkedClass cls = serializeClassText(
- 'import "foo.dart" as foo; @foo.A.named() class C {}',
- allowErrors: true);
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'foo.A.named()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(
- ReferenceKind.classOrEnum,
- 'A',
- absoluteUri: absUri('/foo.dart'),
- ),
- new _PrefixExpectation(ReferenceKind.prefix, 'foo')
- ])
- ]);
- }
-
- test_metadata_constructor_call_named_unresolved_class() {
- UnlinkedClass cls =
- serializeClassText('@A.named() class C {}', allowErrors: true);
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'A.named()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.unresolved, 'A')
- ])
- ]);
- }
-
- test_metadata_constructor_call_named_unresolved_constructor() {
- UnlinkedClass cls = serializeClassText('class A {} @A.named() class C {}',
- allowErrors: true);
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'A.named()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'named',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'A')
- ])
- ]);
- }
-
- test_metadata_constructor_call_unnamed() {
- UnlinkedClass cls =
- serializeClassText('class A { const A(); } @A() class C {}');
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'A()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) =>
- checkTypeRef(r, null, 'A', expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_metadata_constructor_call_unnamed_prefixed() {
- addNamedSource('/foo.dart', 'class A { const A(); }');
- UnlinkedClass cls =
- serializeClassText('import "foo.dart" as foo; @foo.A() class C {}');
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'foo.A()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, absUri('/foo.dart'), 'A',
- expectedKind: ReferenceKind.classOrEnum, expectedPrefix: 'foo')
- ]);
- }
-
- test_metadata_constructor_call_unnamed_prefixed_unresolved() {
- addNamedSource('/foo.dart', '');
- UnlinkedClass cls = serializeClassText(
- 'import "foo.dart" as foo; @foo.A() class C {}',
- allowErrors: true);
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'foo.A()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'A',
- expectedKind: ReferenceKind.unresolved, expectedPrefix: 'foo')
- ]);
- }
-
- test_metadata_constructor_call_unnamed_unresolved() {
- UnlinkedClass cls =
- serializeClassText('@A() class C {}', allowErrors: true);
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'A()', operators: [
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 0
- ], referenceValidators: [
- (EntityRef r) =>
- checkTypeRef(r, null, 'A', expectedKind: ReferenceKind.unresolved)
- ]);
- }
-
- test_metadata_constructor_call_with_args() {
- UnlinkedClass cls =
- serializeClassText('class A { const A(x); } @A(null) class C {}');
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'A(null)', operators: [
- UnlinkedExprOperation.pushNull,
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 1
- ], referenceValidators: [
- (EntityRef r) =>
- checkTypeRef(r, null, 'A', expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_metadata_constructorDeclaration_named() {
- checkAnnotationA(
- serializeClassText('const a = null; class C { @a C.named(); }')
- .executables[0]
- .annotations);
- }
-
- test_metadata_constructorDeclaration_unnamed() {
- checkAnnotationA(serializeClassText('const a = null; class C { @a C(); }')
- .executables[0]
- .annotations);
- }
-
- test_metadata_enumConstantDeclaration() {
- checkAnnotationA(serializeEnumText('const a = null; enum E { @a v }')
- .values[0]
- .annotations);
- }
-
- test_metadata_enumDeclaration() {
- checkAnnotationA(
- serializeEnumText('const a = null; @a enum E { v }').annotations);
- }
-
- test_metadata_exportDirective() {
- addNamedSource('/foo.dart', '');
- serializeLibraryText('@a export "foo.dart"; const a = null;');
- checkAnnotationA(unlinkedUnits[0].exports[0].annotations);
- }
-
- test_metadata_fieldDeclaration() {
- checkAnnotationA(serializeClassText('const a = null; class C { @a int x; }')
- .fields[0]
- .annotations);
- }
-
- test_metadata_fieldFormalParameter() {
- checkAnnotationA(
- serializeClassText('const a = null; class C { var x; C(@a this.x); }')
- .executables[0]
- .parameters[0]
- .annotations);
- }
-
- test_metadata_fieldFormalParameter_withDefault() {
- checkAnnotationA(serializeClassText(
- 'const a = null; class C { var x; C([@a this.x = null]); }')
- .executables[0]
- .parameters[0]
- .annotations);
- }
-
- test_metadata_functionDeclaration_function() {
- checkAnnotationA(
- serializeExecutableText('const a = null; @a f() {}').annotations);
- }
-
- test_metadata_functionDeclaration_getter() {
- checkAnnotationA(
- serializeExecutableText('const a = null; @a get f => null;')
- .annotations);
- }
-
- test_metadata_functionDeclaration_setter() {
- checkAnnotationA(serializeExecutableText(
- 'const a = null; @a set f(value) {}',
- executableName: 'f=')
- .annotations);
- }
-
- test_metadata_functionTypeAlias() {
- checkAnnotationA(
- serializeTypedefText('const a = null; @a typedef F();').annotations);
- }
-
- test_metadata_functionTypedFormalParameter() {
- checkAnnotationA(serializeExecutableText('const a = null; f(@a g()) {}')
- .parameters[0]
- .annotations);
- }
-
- test_metadata_functionTypedFormalParameter_withDefault() {
- checkAnnotationA(
- serializeExecutableText('const a = null; f([@a g() = null]) {}')
- .parameters[0]
- .annotations);
- }
-
- test_metadata_importDirective() {
- addNamedSource('/foo.dart', 'const b = null;');
- serializeLibraryText('@a import "foo.dart"; const a = b;');
- checkAnnotationA(unlinkedUnits[0].imports[0].annotations);
- }
-
- test_metadata_invalid_assignable() {
- // Verify that the following does not cause an exception to be thrown.
- serializeLibraryText('@a(-b=""c');
- expect(unlinkedUnits, hasLength(1));
- List<UnlinkedVariable> variables = unlinkedUnits[0].variables;
- if (Parser.useFasta) {
- // Fasta recovers by appending `)` after `c`
- expect(variables, isEmpty);
- } else {
- expect(variables, hasLength(1));
- List<UnlinkedExpr> annotations = variables[0].annotations;
- expect(annotations, hasLength(1));
- expect(annotations[0].isValidConst, isFalse);
- }
- }
-
- test_metadata_invalid_instanceCreation_argument_super() {
- List<UnlinkedExpr> annotations = serializeClassText('''
-class A {
- const A(_);
-}
-
-@A(super)
-class C {}
-''').annotations;
- expect(annotations, hasLength(1));
- assertUnlinkedConst(annotations[0], 'A(super)', operators: [
- UnlinkedExprOperation.pushSuper,
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 1
- ], referenceValidators: [
- (EntityRef r) =>
- checkTypeRef(r, null, 'A', expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_metadata_invalid_instanceCreation_argument_this() {
- List<UnlinkedExpr> annotations = serializeClassText('''
-class A {
- const A(_);
-}
-
-@A(this)
-class C {}
-''').annotations;
- expect(annotations, hasLength(1));
- assertUnlinkedConst(annotations[0], 'A(this)', operators: [
- UnlinkedExprOperation.pushThis,
- UnlinkedExprOperation.invokeConstructor,
- ], ints: [
- 0,
- 1
- ], referenceValidators: [
- (EntityRef r) =>
- checkTypeRef(r, null, 'A', expectedKind: ReferenceKind.classOrEnum)
- ]);
- }
-
- test_metadata_libraryDirective() {
- serializeLibraryText('@a library L; const a = null;');
- checkAnnotationA(unlinkedUnits[0].libraryAnnotations);
- }
-
- test_metadata_methodDeclaration_getter() {
- checkAnnotationA(
- serializeClassText('const a = null; class C { @a get m => null; }')
- .executables[0]
- .annotations);
- }
-
- test_metadata_methodDeclaration_method() {
- checkAnnotationA(serializeClassText('const a = null; class C { @a m() {} }')
- .executables[0]
- .annotations);
- }
-
- test_metadata_methodDeclaration_setter() {
- checkAnnotationA(
- serializeClassText('const a = null; class C { @a set m(value) {} }')
- .executables[0]
- .annotations);
- }
-
- test_metadata_mixinDeclaration() {
- checkAnnotationA(
- serializeMixinText('const a = null; @a mixin M {}').annotations);
- }
-
- test_metadata_multiple_annotations() {
- UnlinkedClass cls =
- serializeClassText('const a = null, b = null; @a @b class C {}');
- List<UnlinkedExpr> annotations = cls.annotations;
- expect(annotations, hasLength(2));
- assertUnlinkedConst(annotations[0], 'a', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- assertUnlinkedConst(annotations[1], 'b', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'b',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ]);
- }
-
- test_metadata_partDirective() {
- addNamedSource('/foo.dart', 'part of L;');
- serializeLibraryText('library L; @a part "foo.dart"; const a = null;');
- checkAnnotationA(unlinkedUnits[0].parts[0].annotations);
- }
-
- test_metadata_prefixed_variable() {
- addNamedSource('/a.dart', 'const b = null;');
- UnlinkedClass cls =
- serializeClassText('import "a.dart" as a; @a.b class C {}');
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'a.b', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'b',
- expectedKind: ReferenceKind.topLevelPropertyAccessor,
- expectedPrefix: 'a')
- ]);
- }
-
- test_metadata_prefixed_variable_unresolved() {
- addNamedSource('/a.dart', '');
- UnlinkedClass cls = serializeClassText(
- 'import "a.dart" as a; @a.b class C {}',
- allowErrors: true);
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'a.b', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'b',
- expectedKind: ReferenceKind.unresolved, expectedPrefix: 'a')
- ]);
- }
-
- test_metadata_simpleFormalParameter() {
- checkAnnotationA(serializeExecutableText('const a = null; f(@a x) {}')
- .parameters[0]
- .annotations);
- }
-
- test_metadata_simpleFormalParameter_withDefault() {
- checkAnnotationA(
- serializeExecutableText('const a = null; f([@a x = null]) {}')
- .parameters[0]
- .annotations);
- }
-
- test_metadata_topLevelVariableDeclaration() {
- checkAnnotationA(
- serializeVariableText('const a = null; @a int v;').annotations);
- }
-
- test_metadata_typeParameter_ofClass() {
- checkAnnotationA(serializeClassText('const a = null; class C<@a T> {}')
- .typeParameters[0]
- .annotations);
- }
-
- test_metadata_typeParameter_ofClassTypeAlias() {
- checkAnnotationA(serializeClassText(
- 'const a = null; class C<@a T> = D with E; class D {} class E {}',
- className: 'C')
- .typeParameters[0]
- .annotations);
- }
-
- test_metadata_typeParameter_ofFunction() {
- checkAnnotationA(serializeExecutableText('const a = null; f<@a T>() {}')
- .typeParameters[0]
- .annotations);
- }
-
- test_metadata_typeParameter_ofTypedef() {
- checkAnnotationA(serializeTypedefText('const a = null; typedef F<@a T>();')
- .typeParameters[0]
- .annotations);
- }
-
- test_metadata_variable_unresolved() {
- UnlinkedClass cls = serializeClassText('@a class C {}', allowErrors: true);
- expect(cls.annotations, hasLength(1));
- assertUnlinkedConst(cls.annotations[0], 'a', operators: [
- UnlinkedExprOperation.pushReference
- ], referenceValidators: [
- (EntityRef r) =>
- checkTypeRef(r, null, 'a', expectedKind: ReferenceKind.unresolved)
- ]);
- }
-
- test_method_documented() {
- String text = '''
-class C {
- /**
- * Docs
- */
- f() {}
-}''';
- UnlinkedExecutable executable = serializeClassText(text).executables[0];
- expect(executable.documentationComment, isNotNull);
- checkDocumentationComment(executable.documentationComment, text);
- }
-
- test_method_inferred_type_nonstatic_explicit_param() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { void f(num value) {} }'
- ' abstract class D { void f(int value); }',
- className: 'C')
- .executables[0];
- expect(f.parameters[0].inferredTypeSlot, 0);
- }
-
- test_method_inferred_type_nonstatic_explicit_return() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { num f() => null; } abstract class D { int f(); }',
- className: 'C',
- allowErrors: true)
- .executables[0];
- expect(f.inferredReturnTypeSlot, 0);
- }
-
- test_method_inferred_type_nonstatic_implicit_param() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { void f(value) {} }'
- ' abstract class D { void f(int value); }',
- className: 'C')
- .executables[0];
- checkInferredTypeSlot(f.parameters[0].inferredTypeSlot, 'dart:core', 'int');
- }
-
- test_method_inferred_type_nonstatic_implicit_return() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { f() => null; } abstract class D { int f(); }',
- className: 'C')
- .executables[0];
- checkInferredTypeSlot(f.inferredReturnTypeSlot, 'dart:core', 'int');
- }
-
- test_method_inferred_type_static_implicit_param() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { static void f(value) {} }'
- ' class D { static void f(int value) {} }',
- className: 'C')
- .executables[0];
- expect(f.parameters[0].inferredTypeSlot, 0);
- }
-
- test_method_inferred_type_static_implicit_return() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { static f() => null; }'
- ' class D { static int f() => null; }',
- className: 'C')
- .executables[0];
- expect(f.inferredReturnTypeSlot, 0);
- }
-
- test_mixin() {
- UnlinkedClass mixin = serializeMixinText('mixin M {}');
- expect(mixin.name, 'M');
- expect(mixin.nameOffset, 6);
-
- expect(mixin.executables, isEmpty);
- expect(mixin.interfaces, isEmpty);
- expect(mixin.mixins, isEmpty);
- expect(mixin.superclassConstraints, isEmpty);
- }
-
- test_mixin_codeRange() {
- UnlinkedClass mixin = serializeMixinText(' mixin M {}');
- _assertCodeRange(mixin.codeRange, 1, 10);
- }
-
- test_mixin_documented() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-mixin M {}''';
- UnlinkedClass mixin = serializeMixinText(text);
- expect(mixin.documentationComment, isNotNull);
- checkDocumentationComment(mixin.documentationComment, text);
- }
-
- test_mixin_documented_tripleSlash() {
- String text = '''
-/// aaa
-/// bbbb
-/// cc
-mixin M {}''';
- UnlinkedClass mixin = serializeMixinText(text);
- UnlinkedDocumentationComment comment = mixin.documentationComment;
- expect(comment, isNotNull);
- expect(comment.text, '/// aaa\n/// bbbb\n/// cc');
- }
-
- test_mixin_executables() {
- UnlinkedClass mixin = serializeMixinText(r'''
-mixin M {
- double f;
- int get g => 0;
- set s(int v) {}
- int m(int v) => 0;
-}
-''');
- expect(mixin.fields, hasLength(1));
- expect(mixin.fields[0].name, 'f');
- checkTypeRef(mixin.fields[0].type, 'dart:core', 'double');
-
- expect(mixin.executables, hasLength(3));
-
- expect(mixin.executables[0].name, 'g');
- expect(mixin.executables[0].kind, UnlinkedExecutableKind.getter);
- checkTypeRef(mixin.executables[0].returnType, 'dart:core', 'int');
-
- expect(mixin.executables[1].name, 's=');
- expect(mixin.executables[1].kind, UnlinkedExecutableKind.setter);
-
- expect(mixin.executables[2].name, 'm');
- expect(mixin.executables[2].kind, UnlinkedExecutableKind.functionOrMethod);
- checkTypeRef(mixin.executables[2].returnType, 'dart:core', 'int');
- }
-
- test_mixin_implements() {
- UnlinkedClass mixin = serializeMixinText(r'''
-class A {}
-class B {}
-mixin M implements A, B {}
-''');
- expect(mixin.executables, isEmpty);
- expect(mixin.mixins, isEmpty);
- expect(mixin.superclassConstraints, isEmpty);
-
- expect(mixin.interfaces, hasLength(2));
- checkTypeRef(mixin.interfaces[0], null, 'A');
- checkTypeRef(mixin.interfaces[1], null, 'B');
- }
-
- test_mixin_superclassConstraints() {
- UnlinkedClass mixin = serializeMixinText(r'''
-class A {}
-class B {}
-class C {}
-class D {}
-mixin M on A, B implements C, D {}
-''');
- expect(mixin.executables, isEmpty);
- expect(mixin.mixins, isEmpty);
-
- expect(mixin.superclassConstraints, hasLength(2));
- checkTypeRef(mixin.superclassConstraints[0], null, 'A');
- checkTypeRef(mixin.superclassConstraints[1], null, 'B');
-
- expect(mixin.interfaces, hasLength(2));
- checkTypeRef(mixin.interfaces[0], null, 'C');
- checkTypeRef(mixin.interfaces[1], null, 'D');
- }
-
- test_mixin_superInvokedNames_methodInvocation() {
- UnlinkedClass mixin = serializeMixinText('''
-mixin M {
- void x() {
- super.a();
- super.b().c();
- }
-}
-''');
- expect(mixin.superInvokedNames, unorderedEquals(['a', 'b']));
- }
-
- test_mixin_superInvokedNames_operator_binary() {
- UnlinkedClass mixin = serializeMixinText('''
-mixin M {
- void x() {
- super + 1;
- super - 2;
- }
-}
-''');
- expect(mixin.superInvokedNames, unorderedEquals(['+', '-']));
- }
-
- test_mixin_superInvokedNames_operator_index() {
- UnlinkedClass mixin = serializeMixinText('''
-mixin M {
- void x() {
- super[0];
- }
-}
-''');
- expect(mixin.superInvokedNames, unorderedEquals(['[]']));
- }
-
- test_mixin_superInvokedNames_operator_index_indexEq() {
- UnlinkedClass mixin = serializeMixinText('''
-mixin M {
- void x() {
- super[0] += 1;
- }
-}
-''');
- expect(mixin.superInvokedNames, unorderedEquals(['[]', '[]=']));
- }
-
- test_mixin_superInvokedNames_operator_indexEq() {
- UnlinkedClass mixin = serializeMixinText('''
-mixin M {
- void x() {
- super[0] = 1;
- }
-}
-''');
- expect(mixin.superInvokedNames, unorderedEquals(['[]=']));
- }
-
- test_mixin_superInvokedNames_operator_prefix() {
- UnlinkedClass mixin = serializeMixinText('''
-mixin M {
- void x() {
- ~super;
- -super;
- }
-}
-''');
- expect(mixin.superInvokedNames, unorderedEquals(['~', 'unary-']));
- }
-
- test_mixin_superInvokedNames_propertyAccess_get() {
- UnlinkedClass mixin = serializeMixinText('''
-mixin M {
- void x() {
- super.a;
- super.b.c;
-
- ~super.e;
- -super.d;
- }
-}
-''');
- expect(mixin.superInvokedNames, unorderedEquals(['a', 'b', 'd', 'e']));
- }
-
- test_mixin_superInvokedNames_propertyAccess_get_set() {
- UnlinkedClass mixin = serializeMixinText('''
-mixin M {
- void x() {
- super.a++;
- --super.b;
- super.c += 1;
- }
-}
-''');
- expect(
- mixin.superInvokedNames,
- unorderedEquals(['a', 'b', 'c', 'a=', 'b=', 'c=']),
- );
- }
-
- test_mixin_superInvokedNames_propertyAccess_set() {
- UnlinkedClass mixin = serializeMixinText('''
-mixin M {
- void x() {
- super.a = 1;
- }
-}
-''');
- expect(mixin.superInvokedNames, unorderedEquals(['a=']));
- }
-
- test_mixin_typeParameters() {
- UnlinkedClass mixin = serializeMixinText('mixin M<T extends num, U> {}');
- expect(mixin.typeParameters, hasLength(2));
-
- expect(mixin.typeParameters[0].name, 'T');
- checkTypeRef(mixin.typeParameters[0].bound, 'dart:core', 'num');
-
- expect(mixin.typeParameters[1].name, 'U');
- expect(mixin.typeParameters[1].bound, isNull);
- }
-
- test_nested_generic_functions() {
- UnlinkedExecutable executable = serializeVariableText('''
-var v = (() {
- void f<T, U>() {
- void g<V, W>() {
- void h<X, Y>(T t, U u, V v W w, X x, Y y) {
- }
- }
- }
-});
-''').initializer.localFunctions[0].localFunctions[0];
- expect(executable.typeParameters, hasLength(2));
- expect(executable.localFunctions[0].typeParameters, hasLength(2));
- expect(executable.localFunctions[0].localFunctions[0].typeParameters,
- hasLength(2));
- List<UnlinkedParam> parameters =
- executable.localFunctions[0].localFunctions[0].parameters;
- checkParamTypeRef(findParameter(parameters, 't').type, 6);
- checkParamTypeRef(findParameter(parameters, 'u').type, 5);
- checkParamTypeRef(findParameter(parameters, 'v').type, 4);
- checkParamTypeRef(findParameter(parameters, 'w').type, 3);
- checkParamTypeRef(findParameter(parameters, 'x').type, 2);
- checkParamTypeRef(findParameter(parameters, 'y').type, 1);
- }
-
- test_new_typedef_notSimplyBoundedSlot() {
- var typedef =
- serializeTypedefText('typedef F<T extends F> = void Function();');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- contains(typedef.notSimplyBoundedSlot));
- }
- }
-
- test_new_typedef_notSimplyBoundedSlot_simple_no_bounds() {
- // If no bounds are specified, then the typedef is simply bounded, however
- // it still gets a slot because all typedefs are assigned a slot.
- var typedef = serializeTypedefText('typedef F<T> = void Function();');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- isNot(contains(typedef.notSimplyBoundedSlot)));
- }
- }
-
- test_new_typedef_notSimplyBoundedSlot_simple_non_generic() {
- // If no type parameters are specified, then the typedef is simply bounded,
- // however it still gets a slot because all typedefs are assigned a slot.
- var typedef = serializeTypedefText('typedef F = void Function();');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- isNot(contains(typedef.notSimplyBoundedSlot)));
- }
- }
-
- test_old_typedef_notSimplyBoundedSlot() {
- var typedef = serializeTypedefText('typedef void F<T extends F>();');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- contains(typedef.notSimplyBoundedSlot));
- }
- }
-
- test_old_typedef_notSimplyBoundedSlot_simple_because_non_generic() {
- // If no type parameters are specified, then the typedef is simply bounded,
- // however it still gets a slot because all typedefs are assigned a slot.
- var typedef = serializeTypedefText('typedef void F();');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- isNot(contains(typedef.notSimplyBoundedSlot)));
- }
- }
-
- test_old_typedef_notSimplyBoundedSlot_simple_no_bounds() {
- // If no bounds are specified, then the typedef is simply bounded, however
- // it still gets a slot because all typedefs are assigned a slot.
- var typedef = serializeTypedefText('typedef void F<T>();');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- isNot(contains(typedef.notSimplyBoundedSlot)));
- }
- }
-
- test_parameter_visibleRange_abstractMethod() {
- UnlinkedExecutable m = findExecutable('m',
- executables:
- serializeClassText('abstract class C { m(p); }').executables,
- failIfAbsent: true);
- _assertParameterZeroVisibleRange(m.parameters[0]);
- }
-
- test_parameter_visibleRange_function_blockBody() {
- String text = r'''
-var v = (() {
- f(x) { // 1
- f2(y) { // 2
- } // 3
- } // 4
-});
-''';
- var closure = serializeVariableText(text).initializer.localFunctions[0];
- UnlinkedExecutable f = closure.localFunctions[0];
- UnlinkedExecutable f2 = f.localFunctions[0];
- _assertParameterVisible(text, f.parameters[0], '{ // 1', '} // 4');
- _assertParameterVisible(text, f2.parameters[0], '{ // 2', '} // 3');
- }
-
- test_parameter_visibleRange_function_emptyBody() {
- UnlinkedExecutable f = serializeExecutableText('external f(x);');
- _assertParameterZeroVisibleRange(f.parameters[0]);
- }
-
- test_parameter_visibleRange_function_expressionBody() {
- String text = r'''
-f(x) => 42;
-''';
- UnlinkedExecutable f = serializeExecutableText(text);
- _assertParameterVisible(text, f.parameters[0], '=>', ';');
- }
-
- test_parameter_visibleRange_inFunctionTypedParameter() {
- String text = 'f(g(p)) {}';
- UnlinkedExecutable f = serializeExecutableText(text);
- UnlinkedParam g = f.parameters[0];
- UnlinkedParam p = g.parameters[0];
- expect(g.name, 'g');
- expect(p.name, 'p');
- _assertParameterVisible(text, g, '{', '}');
- _assertParameterZeroVisibleRange(p);
- }
-
- test_parameter_visibleRange_invalid_fieldFormalParameter() {
- UnlinkedExecutable m =
- findExecutable('m', executables: serializeClassText(r'''
-class C {
- int foo;
- void m(this.foo) {}
-}
-''').executables);
- _assertParameterZeroVisibleRange(m.parameters[0]);
- }
-
- test_parameter_visibleRange_typedef() {
- UnlinkedTypedef type = serializeTypedefText('typedef F(x);');
- _assertParameterZeroVisibleRange(type.parameters[0]);
- }
-
- test_part_declaration() {
- addNamedSource('/a.dart', 'part of my.lib;');
- String text = 'library my.lib; part "a.dart"; // <-part';
- serializeLibraryText(text);
- expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.parts[0], 'a.dart');
- expect(unlinkedUnits[0].parts, hasLength(1));
- expect(unlinkedUnits[0].parts[0].uriOffset, text.indexOf('"a.dart"'));
- expect(unlinkedUnits[0].parts[0].uriEnd, text.indexOf('; // <-part'));
- }
-
- test_part_declaration_invalidUri_nullStringValue() {
- addNamedSource('/a.dart', 'part of my.lib;');
- String text = r'''
-library my.lib;
-part "${'a'}.dart"; // <-part
-''';
- serializeLibraryText(text);
- expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.parts[0], '');
- expect(unlinkedUnits[0].parts, hasLength(1));
- expect(unlinkedUnits[0].parts[0].uriOffset, text.indexOf(r'"${'));
- expect(unlinkedUnits[0].parts[0].uriEnd, text.indexOf('; // <-part'));
- }
-
- test_part_isPartOf() {
- addNamedSource('/a.dart', 'part of foo; class C {}');
- serializeLibraryText('library foo; part "a.dart";');
- expect(unlinkedUnits[0].isPartOf, isFalse);
- expect(unlinkedUnits[1].isPartOf, isTrue);
- }
-
- test_part_uri_invalid() {
- String uriString = ':[invalid uri]';
- String libraryText = 'part "$uriString";';
- serializeLibraryText(libraryText);
- expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.parts[0], uriString);
- }
-
- test_parts_defining_compilation_unit() {
- serializeLibraryText('');
- expect(linked.units, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.parts, isEmpty);
- }
-
- test_parts_included() {
- addNamedSource('/part1.dart', 'part of my.lib;');
- String partString = '"part1.dart"';
- String libraryText = 'library my.lib; part $partString;';
- serializeLibraryText(libraryText);
- expect(linked.units, hasLength(2));
- expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.parts[0], 'part1.dart');
- }
-
- test_public_namespace_of_part() {
- addNamedSource('/a.dart', 'part of foo; class C {}');
- serializeLibraryText('library foo; part "a.dart";');
- expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
- expect(unlinkedUnits[1].publicNamespace.names, hasLength(1));
- expect(unlinkedUnits[1].publicNamespace.names[0].name, 'C');
- }
-
- test_reference_zero() {
- // Element zero of the references table should be populated in a standard
- // way.
- serializeLibraryText('');
- UnlinkedReference unlinkedReference0 = unlinkedUnits[0].references[0];
- expect(unlinkedReference0.name, '');
- expect(unlinkedReference0.prefixReference, 0);
- LinkedReference linkedReference0 = linked.units[0].references[0];
- expect(linkedReference0.containingReference, 0);
- expect(linkedReference0.dependency, 0);
- expect(linkedReference0.kind, ReferenceKind.unresolved);
- expect(linkedReference0.name, '');
- expect(linkedReference0.numTypeParameters, 0);
- expect(linkedReference0.unit, 0);
- }
-
- test_setter_documented() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-void set f(value) {}''';
- UnlinkedExecutable executable =
- serializeExecutableText(text, executableName: 'f=');
- expect(executable.documentationComment, isNotNull);
- checkDocumentationComment(executable.documentationComment, text);
- }
-
- test_setter_inferred_type_nonstatic_explicit_param() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { void set f(num value) {} }'
- ' abstract class D { void set f(int value); }',
- className: 'C')
- .executables[0];
- expect(f.parameters[0].inferredTypeSlot, 0);
- }
-
- test_setter_inferred_type_nonstatic_explicit_return() {
- UnlinkedExecutable f =
- serializeClassText('class C { void set f(int value) {} }')
- .executables[0];
- expect(f.inferredReturnTypeSlot, 0);
- }
-
- test_setter_inferred_type_nonstatic_implicit_param() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { void set f(value) {} }'
- ' abstract class D { void set f(int value); }',
- className: 'C')
- .executables[0];
- checkInferredTypeSlot(f.parameters[0].inferredTypeSlot, 'dart:core', 'int');
- }
-
- test_setter_inferred_type_nonstatic_implicit_return() {
- UnlinkedExecutable f =
- serializeClassText('class C { set f(int value) {} }').executables[0];
- checkInferredTypeSlot(f.inferredReturnTypeSlot, null, 'void');
- }
-
- test_setter_inferred_type_static_implicit_param() {
- UnlinkedExecutable f = serializeClassText(
- 'class C extends D { static void set f(value) {} }'
- ' class D { static void set f(int value) {} }',
- className: 'C')
- .executables[0];
- expect(f.parameters[0].inferredTypeSlot, 0);
- }
-
- test_setter_inferred_type_static_implicit_return() {
- UnlinkedExecutable f =
- serializeClassText('class C { static set f(int value) {} }')
- .executables[0];
- expect(f.inferredReturnTypeSlot, 0);
- }
-
- test_setter_inferred_type_top_level_implicit_param() {
- UnlinkedExecutable f =
- serializeExecutableText('void set f(value) {}', executableName: 'f=');
- expect(f.parameters[0].inferredTypeSlot, 0);
- }
-
- test_setter_inferred_type_top_level_implicit_return() {
- UnlinkedExecutable f =
- serializeExecutableText('set f(int value) {}', executableName: 'f=');
- expect(f.inferredReturnTypeSlot, 0);
- }
-
- test_slot_reuse() {
- // Different compilation units have independent notions of slot id, so slot
- // ids should be reused.
- addNamedSource('/a.dart', 'part of foo; final v = 0;');
- serializeLibraryText('library foo; part "a.dart"; final w = 0;');
- expect(unlinkedUnits[1].variables[0].inferredTypeSlot,
- unlinkedUnits[0].variables[0].inferredTypeSlot);
- }
-
- test_syntheticFunctionType_genericClosure() {
- if (skipFullyLinkedData) {
- return;
- }
- // TODO(paulberry): once proper generic method syntax supports generic
- // closures, rewrite the test below without using generic comment syntax,
- // and remove this hack. See dartbug.com/25819
- UnlinkedVariable variable = serializeVariableText('''
-final v = f() ? /*<T>*/(T t) => 0 : /*<T>*/(T t) => 1;
-bool f() => true;
-''');
- EntityRef inferredType = getTypeRefForSlot(variable.inferredTypeSlot);
- checkLinkedTypeRef(inferredType.syntheticReturnType, 'dart:core', 'int');
- expect(inferredType.syntheticParams, hasLength(1));
- checkLinkedTypeRef(inferredType.syntheticParams[0].type, null, 'Never');
- }
-
- test_syntheticFunctionType_inGenericClass() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedVariable variable = serializeClassText('''
-class C<T, U> {
- var v = f() ? (T t, U u) => 0 : (T t, U u) => 1;
-}
-bool f() => false;
-''').fields[0];
- EntityRef inferredType =
- getTypeRefForSlot(variable.initializer.inferredReturnTypeSlot);
- checkLinkedTypeRef(inferredType.syntheticReturnType, 'dart:core', 'int');
- checkParamTypeRef(inferredType.syntheticParams[0].type, 2);
- checkParamTypeRef(inferredType.syntheticParams[1].type, 1);
- }
-
- test_type_arguments_explicit() {
- EntityRef typeRef = serializeTypeText('List<int>');
- checkTypeRef(typeRef, 'dart:core', 'List',
- numTypeParameters: 1, numTypeArguments: 1);
- checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'int');
- }
-
- test_type_arguments_explicit_dynamic() {
- EntityRef typeRef = serializeTypeText('List<dynamic>');
- checkTypeRef(typeRef, 'dart:core', 'List',
- numTypeParameters: 1, numTypeArguments: 1);
- checkDynamicTypeRef(typeRef.typeArguments[0]);
- }
-
- test_type_arguments_explicit_dynamic_dynamic() {
- EntityRef typeRef = serializeTypeText('Map<dynamic, dynamic>');
- checkTypeRef(typeRef, 'dart:core', 'Map',
- numTypeParameters: 2, numTypeArguments: 2);
- checkDynamicTypeRef(typeRef.typeArguments[0]);
- checkDynamicTypeRef(typeRef.typeArguments[1]);
- }
-
- test_type_arguments_explicit_dynamic_int() {
- EntityRef typeRef = serializeTypeText('Map<dynamic, int>');
- checkTypeRef(typeRef, 'dart:core', 'Map',
- numTypeParameters: 2, numTypeArguments: 2);
- checkDynamicTypeRef(typeRef.typeArguments[0]);
- checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'int');
- }
-
- test_type_arguments_explicit_dynamic_typedef() {
- EntityRef typeRef =
- serializeTypeText('F<dynamic>', otherDeclarations: 'typedef T F<T>();');
- checkTypeRef(typeRef, null, 'F',
- expectedKind: ReferenceKind.typedef,
- numTypeParameters: 1,
- numTypeArguments: 1);
- checkDynamicTypeRef(typeRef.typeArguments[0]);
- }
-
- test_type_arguments_explicit_String_dynamic() {
- EntityRef typeRef = serializeTypeText('Map<String, dynamic>');
- checkTypeRef(typeRef, 'dart:core', 'Map',
- numTypeParameters: 2, numTypeArguments: 2);
- checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'String');
- checkDynamicTypeRef(typeRef.typeArguments[1]);
- }
-
- test_type_arguments_explicit_String_int() {
- EntityRef typeRef = serializeTypeText('Map<String, int>');
- checkTypeRef(typeRef, 'dart:core', 'Map',
- numTypeParameters: 2, numTypeArguments: 2);
- checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'String');
- checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'int');
- }
-
- test_type_arguments_explicit_typedef() {
- EntityRef typeRef =
- serializeTypeText('F<int>', otherDeclarations: 'typedef T F<T>();');
- checkTypeRef(typeRef, null, 'F',
- expectedKind: ReferenceKind.typedef,
- numTypeParameters: 1,
- numTypeArguments: 1);
- checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'int');
- }
-
- test_type_arguments_implicit() {
- EntityRef typeRef = serializeTypeText('List');
- checkTypeRef(typeRef, 'dart:core', 'List', numTypeParameters: 1);
- }
-
- test_type_arguments_implicit_typedef() {
- EntityRef typeRef =
- serializeTypeText('F', otherDeclarations: 'typedef T F<T>();');
- checkTypeRef(typeRef, null, 'F',
- expectedKind: ReferenceKind.typedef, numTypeParameters: 1);
- }
-
- test_type_arguments_implicit_typedef_withBound() {
- EntityRef typeRef = serializeTypeText('F',
- otherDeclarations: 'typedef T F<T extends num>();');
- checkTypeRef(typeRef, null, 'F',
- expectedKind: ReferenceKind.typedef, numTypeParameters: 1);
- }
-
- test_type_arguments_order() {
- EntityRef typeRef = serializeTypeText('Map<int, Object>');
- checkTypeRef(typeRef, 'dart:core', 'Map',
- numTypeParameters: 2, numTypeArguments: 2);
- checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'int');
- checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'Object');
- }
-
- test_type_dynamic() {
- checkDynamicTypeRef(serializeTypeText('dynamic'));
- }
-
- test_type_inference_based_on_type_parameter() {
- var class_ = serializeClassText('''
-class C<T> {
- var field = T;
-}
-''');
- var field = class_.fields[0];
- checkLinkedTypeSlot(field.inferredTypeSlot, 'dart:core', 'Type');
- }
-
- test_type_invalid_typeParameter_asPrefix() {
- UnlinkedClass c = serializeClassText('''
-class C<T> {
- m(T.K p) {}
-}
-''');
- UnlinkedExecutable m = c.executables[0];
- expect(m.name, 'm');
- checkTypeRef(m.parameters[0].type, null, 'dynamic');
- }
-
- test_type_nullability_suffix_none() {
- featureSet = enableNnbd;
- EntityRef typeRef = serializeTypeText('int');
- checkTypeRef(typeRef, 'dart:core', 'int',
- nullabilitySuffix: EntityRefNullabilitySuffix.none);
- }
-
- test_type_nullability_suffix_question() {
- featureSet = enableNnbd;
- EntityRef typeRef = serializeTypeText('int?');
- checkTypeRef(typeRef, 'dart:core', 'int',
- nullabilitySuffix: EntityRefNullabilitySuffix.question);
- }
-
- test_type_nullability_suffix_star() {
- featureSet = disableNnbd;
- EntityRef typeRef = serializeTypeText('int');
- checkTypeRef(typeRef, 'dart:core', 'int',
- nullabilitySuffix: EntityRefNullabilitySuffix.starOrIrrelevant);
- }
-
- test_type_param_codeRange() {
- UnlinkedClass cls =
- serializeClassText('class A {} class C<T extends A> {}');
- UnlinkedTypeParam typeParameter = cls.typeParameters[0];
- _assertCodeRange(typeParameter.codeRange, 19, 11);
- }
-
- test_type_param_not_shadowed_by_constructor() {
- UnlinkedClass cls =
- serializeClassText('class C<D> { D x; C.D(); } class D {}');
- checkParamTypeRef(cls.fields[0].type, 1);
- }
-
- test_type_param_not_shadowed_by_field_in_extends() {
- UnlinkedClass cls =
- serializeClassText('class C<T> extends D<T> { T x; } class D<T> {}');
- checkParamTypeRef(cls.supertype.typeArguments[0], 1);
- }
-
- test_type_param_not_shadowed_by_field_in_implements() {
- UnlinkedClass cls =
- serializeClassText('class C<T> implements D<T> { T x; } class D<T> {}');
- checkParamTypeRef(cls.interfaces[0].typeArguments[0], 1);
- }
-
- test_type_param_not_shadowed_by_field_in_with() {
- UnlinkedClass cls = serializeClassText(
- 'class C<T> extends Object with D<T> { T x; } class D<T> {}');
- checkParamTypeRef(cls.mixins[0].typeArguments[0], 1);
- }
-
- test_type_param_not_shadowed_by_method_parameter() {
- UnlinkedClass cls = serializeClassText('class C<T> { f(int T, T x) {} }');
- checkParamTypeRef(cls.executables[0].parameters[1].type, 1);
- }
-
- test_type_param_not_shadowed_by_setter() {
- // The code under test should not produce a compile-time error, but it
- // does.
- bool workAroundBug25525 = true;
- UnlinkedClass cls = serializeClassText(
- 'class C<D> { D x; void set D(value) {} } class D {}',
- allowErrors: workAroundBug25525);
- checkParamTypeRef(cls.fields[0].type, 1);
- }
-
- test_type_param_not_shadowed_by_typedef_parameter() {
- UnlinkedTypedef typedef =
- serializeTypedefText('typedef void F<T>(int T, T x);');
- checkParamTypeRef(typedef.parameters[1].type, 1);
- }
-
- test_type_param_shadowed_by_field() {
- UnlinkedClass cls = serializeClassText(
- 'class C<D> { D x; int D; } class D {}',
- allowErrors: true);
- checkDynamicTypeRef(cls.fields[0].type);
- }
-
- test_type_param_shadowed_by_getter() {
- UnlinkedClass cls = serializeClassText(
- 'class C<D> { D x; int get D => null; } class D {}',
- allowErrors: true);
- checkDynamicTypeRef(cls.fields[0].type);
- }
-
- test_type_param_shadowed_by_method() {
- UnlinkedClass cls = serializeClassText(
- 'class C<D> { D x; void D() {} } class D {}',
- allowErrors: true);
- checkDynamicTypeRef(cls.fields[0].type);
- }
-
- test_type_param_shadowed_by_type_param() {
- UnlinkedClass cls =
- serializeClassText('class C<T> { T f<T>(T x) => null; }');
- checkParamTypeRef(cls.executables[0].returnType, 1);
- checkParamTypeRef(cls.executables[0].parameters[0].type, 1);
- }
-
- test_type_reference_from_part() {
- addNamedSource('/a.dart', 'part of foo; C v;');
- serializeLibraryText('library foo; part "a.dart"; class C {}');
- checkTypeRef(findVariable('v', variables: unlinkedUnits[1].variables).type,
- null, 'C',
- expectedKind: ReferenceKind.classOrEnum,
- linkedSourceUnit: linked.units[1],
- unlinkedSourceUnit: unlinkedUnits[1]);
- }
-
- test_type_reference_from_part_withPrefix() {
- addNamedSource('/a.dart', 'class C {}');
- addNamedSource('/p.dart', 'part of foo; a.C v;');
- serializeLibraryText(
- 'library foo; import "a.dart"; import "a.dart" as a; part "p.dart";',
- allowErrors: true);
- checkTypeRef(findVariable('v', variables: unlinkedUnits[1].variables).type,
- absUri('/a.dart'), 'C',
- expectedPrefix: 'a',
- linkedSourceUnit: linked.units[1],
- unlinkedSourceUnit: unlinkedUnits[1]);
- }
-
- test_type_reference_to_class_argument() {
- UnlinkedClass cls = serializeClassText('class C<T, U> { T t; U u; }');
- {
- EntityRef typeRef =
- findVariable('t', variables: cls.fields, failIfAbsent: true).type;
- checkParamTypeRef(typeRef, 2);
- }
- {
- EntityRef typeRef =
- findVariable('u', variables: cls.fields, failIfAbsent: true).type;
- checkParamTypeRef(typeRef, 1);
- }
- }
-
- test_type_reference_to_import_of_export() {
- addNamedSource('/a.dart', 'library a; export "b.dart";');
- addNamedSource('/b.dart', 'library b; class C {}');
- checkTypeRef(serializeTypeText('C', otherDeclarations: 'import "a.dart";'),
- absUri('/b.dart'), 'C');
- }
-
- test_type_reference_to_import_of_export_via_prefix() {
- addNamedSource('/a.dart', 'library a; export "b.dart";');
- addNamedSource('/b.dart', 'library b; class C {}');
- checkTypeRef(
- serializeTypeText('p.C', otherDeclarations: 'import "a.dart" as p;'),
- absUri('/b.dart'),
- 'C',
- expectedPrefix: 'p');
- }
-
- test_type_reference_to_imported_part() {
- addNamedSource('/a.dart', 'library my.lib; part "b.dart";');
- addNamedSource('/b.dart', 'part of my.lib; class C {}');
- checkTypeRef(
- serializeTypeText('C',
- otherDeclarations: 'library my.lib; import "a.dart";'),
- absUri('/a.dart'),
- 'C',
- expectedTargetUnit: 1);
- }
-
- test_type_reference_to_imported_part_with_prefix() {
- addNamedSource('/a.dart', 'library my.lib; part "b.dart";');
- addNamedSource('/b.dart', 'part of my.lib; class C {}');
- checkTypeRef(
- serializeTypeText('p.C',
- otherDeclarations: 'library my.lib; import "a.dart" as p;'),
- absUri('/a.dart'),
- 'C',
- expectedPrefix: 'p',
- expectedTargetUnit: 1);
- }
-
- test_type_reference_to_internal_class() {
- checkTypeRef(
- serializeTypeText('C', otherDeclarations: 'class C {}'), null, 'C');
- }
-
- test_type_reference_to_internal_class_alias() {
- checkTypeRef(
- serializeTypeText('C',
- otherDeclarations: 'class C = D with E; class D {} class E {}'),
- null,
- 'C');
- }
-
- test_type_reference_to_internal_enum() {
- checkTypeRef(serializeTypeText('E', otherDeclarations: 'enum E { value }'),
- null, 'E');
- }
-
- test_type_reference_to_local_part() {
- addNamedSource('/a.dart', 'part of my.lib; class C {}');
- checkTypeRef(
- serializeTypeText('C',
- otherDeclarations: 'library my.lib; part "a.dart";'),
- null,
- 'C',
- expectedTargetUnit: 1);
- }
-
- test_type_reference_to_nonexistent_file_via_prefix() {
- allowMissingFiles = true;
- EntityRef typeRef = serializeTypeText('p.C',
- otherDeclarations: 'import "foo.dart" as p;', allowErrors: true);
- checkUnresolvedTypeRef(typeRef, 'p', 'C');
- }
-
- test_type_reference_to_part() {
- addNamedSource('/a.dart', 'part of foo; class C { C(); }');
- serializeLibraryText('library foo; part "a.dart"; C c;');
- checkTypeRef(unlinkedUnits[0].variables.single.type, null, 'C',
- expectedKind: ReferenceKind.classOrEnum, expectedTargetUnit: 1);
- }
-
- test_type_reference_to_type_visible_via_multiple_import_prefixes() {
- addNamedSource('/lib1.dart', 'class C');
- addNamedSource('/lib2.dart', 'export "lib1.dart";');
- addNamedSource('/lib3.dart', 'export "lib1.dart";');
- addNamedSource('/lib4.dart', 'export "lib1.dart";');
- serializeLibraryText('''
-import 'lib2.dart';
-import 'lib3.dart' as a;
-import 'lib4.dart' as b;
-C c2;
-a.C c3;
-b.C c4;''');
- // Note: it is important that each reference to class C records the prefix
- // used to find it; otherwise it's possible that relinking might produce an
- // incorrect result after a change to lib2.dart, lib3.dart, or lib4.dart.
- checkTypeRef(findVariable('c2').type, absUri('/lib1.dart'), 'C');
- checkTypeRef(findVariable('c3').type, absUri('/lib1.dart'), 'C',
- expectedPrefix: 'a');
- checkTypeRef(findVariable('c4').type, absUri('/lib1.dart'), 'C',
- expectedPrefix: 'b');
- }
-
- test_type_reference_to_typedef() {
- checkTypeRef(serializeTypeText('F', otherDeclarations: 'typedef void F();'),
- null, 'F',
- expectedKind: ReferenceKind.typedef);
- }
-
- test_type_unit_counts_unreferenced_units() {
- addNamedSource('/a.dart', 'library a; part "b.dart"; part "c.dart";');
- addNamedSource('/b.dart', 'part of a;');
- addNamedSource('/c.dart', 'part of a; class C {}');
- EntityRef typeRef =
- serializeTypeText('C', otherDeclarations: 'import "a.dart";');
- // The referenced unit should be 2, since unit 0 is a.dart and unit 1 is
- // b.dart. a.dart and b.dart are counted even though nothing is imported
- // from them.
- checkTypeRef(typeRef, absUri('/a.dart'), 'C', expectedTargetUnit: 2);
- }
-
- test_type_unresolved() {
- EntityRef typeRef = serializeTypeText('Foo', allowErrors: true);
- checkUnresolvedTypeRef(typeRef, null, 'Foo');
- }
-
- test_typedef_codeRange() {
- UnlinkedTypedef type = serializeTypedefText('typedef F();');
- _assertCodeRange(type.codeRange, 0, 12);
- }
-
- test_typedef_documented() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-typedef F();''';
- UnlinkedTypedef typedef = serializeTypedefText(text);
- expect(typedef.documentationComment, isNotNull);
- checkDocumentationComment(typedef.documentationComment, text);
- }
-
- test_typedef_genericFunction_reference() {
- EntityRef typeRef = serializeTypeText('F',
- otherDeclarations: 'typedef F<S> = S Function<T>(T x);');
- checkTypeRef(typeRef, null, 'F',
- numTypeParameters: 1,
- expectedKind: ReferenceKind.genericFunctionTypedef);
- }
-
- test_typedef_genericFunction_typeNames() {
- UnlinkedTypedef typedef =
- serializeTypedefText('typedef F<S> = S Function(int x, String y);');
- expect(typedef.style, TypedefStyle.genericFunctionType);
- expect(typedef.typeParameters, hasLength(1));
- expect(typedef.typeParameters[0].name, 'S');
- expect(typedef.parameters, isEmpty);
-
- EntityRef genericFunction = typedef.returnType;
- expect(genericFunction.entityKind, EntityRefKind.genericFunctionType);
- expect(genericFunction.typeParameters, isEmpty);
-
- List<UnlinkedParam> functionParameters = genericFunction.syntheticParams;
- expect(functionParameters, hasLength(2));
- expect(functionParameters[0].name, 'x');
- expect(functionParameters[1].name, 'y');
- checkLinkedTypeRef(functionParameters[0].type, 'dart:core', 'int');
- checkLinkedTypeRef(functionParameters[1].type, 'dart:core', 'String');
-
- checkParamTypeRef(genericFunction.syntheticReturnType, 1);
- }
-
- test_typedef_genericFunction_typeParameters() {
- UnlinkedTypedef typedef =
- serializeTypedefText('typedef F<S> = S Function<T1, T2>(T1 x, T2 y);');
- expect(typedef.style, TypedefStyle.genericFunctionType);
- expect(typedef.typeParameters, hasLength(1));
- expect(typedef.typeParameters[0].name, 'S');
- expect(typedef.parameters, isEmpty);
-
- EntityRef genericFunction = typedef.returnType;
- expect(genericFunction.entityKind, EntityRefKind.genericFunctionType);
-
- expect(genericFunction.typeParameters, hasLength(2));
- expect(genericFunction.typeParameters[0].name, 'T1');
- expect(genericFunction.typeParameters[1].name, 'T2');
-
- expect(genericFunction.syntheticParams, hasLength(2));
- expect(genericFunction.syntheticParams[0].name, 'x');
- expect(genericFunction.syntheticParams[1].name, 'y');
- checkParamTypeRef(genericFunction.syntheticParams[0].type, 2);
- checkParamTypeRef(genericFunction.syntheticParams[1].type, 1);
-
- checkParamTypeRef(genericFunction.syntheticReturnType, 3);
- }
-
- test_typedef_name() {
- String text = 'typedef F();';
- UnlinkedTypedef type = serializeTypedefText(text);
- expect(type.name, 'F');
- expect(type.nameOffset, text.indexOf('F'));
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
- expect(
- unlinkedUnits[0].publicNamespace.names[0].kind, ReferenceKind.typedef);
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'F');
- expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
- }
-
- test_typedef_notSimplyBounded_dependency_via_param_type_new_style_name_included() {
- // F is considered "not simply bounded" because it expands to a type that
- // refers to C, which is not simply bounded.
- UnlinkedTypedef typedef = serializeTypedefText(
- 'typedef F = void Function(C c); class C<T extends C<T>> {}');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- contains(typedef.notSimplyBoundedSlot));
- }
- }
-
- test_typedef_notSimplyBounded_dependency_via_param_type_new_style_name_omitted() {
- // F is considered "not simply bounded" because it expands to a type that
- // refers to C, which is not simply bounded.
- UnlinkedTypedef typedef = serializeTypedefText(
- 'typedef F = void Function(C); class C<T extends C<T>> {}');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- contains(typedef.notSimplyBoundedSlot));
- }
- }
-
- test_typedef_notSimplyBounded_dependency_via_param_type_old_style() {
- // F is considered "not simply bounded" because it expands to a type that
- // refers to C, which is not simply bounded.
- UnlinkedTypedef typedef =
- serializeTypedefText('typedef void F(C c); class C<T extends C<T>> {}');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- contains(typedef.notSimplyBoundedSlot));
- }
- }
-
- test_typedef_notSimplyBounded_dependency_via_return_type_new_style() {
- // F is considered "not simply bounded" because it expands to a type that
- // refers to C, which is not simply bounded.
- UnlinkedTypedef typedef = serializeTypedefText(
- 'typedef F = C Function(); class C<T extends C<T>> {}');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- contains(typedef.notSimplyBoundedSlot));
- }
- }
-
- test_typedef_notSimplyBounded_dependency_via_return_type_old_style() {
- // F is considered "not simply bounded" because it expands to a type that
- // refers to C, which is not simply bounded.
- UnlinkedTypedef typedef =
- serializeTypedefText('typedef C F(); class C<T extends C<T>> {}');
- expect(typedef.notSimplyBoundedSlot, isNot(0));
- if (!skipFullyLinkedData) {
- expect(linked.units[0].notSimplyBounded,
- contains(typedef.notSimplyBoundedSlot));
- }
- }
-
- test_typedef_param_none() {
- UnlinkedTypedef type = serializeTypedefText('typedef F();');
- expect(type.parameters, isEmpty);
- }
-
- test_typedef_param_order() {
- UnlinkedTypedef type = serializeTypedefText('typedef F(x, y);');
- expect(type.parameters, hasLength(2));
- expect(type.parameters[0].name, 'x');
- expect(type.parameters[1].name, 'y');
- }
-
- test_typedef_private() {
- serializeTypedefText('typedef _F();', '_F');
- expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
- }
-
- test_typedef_reference_generic() {
- EntityRef typeRef =
- serializeTypeText('F', otherDeclarations: 'typedef void F<A, B>();');
- checkTypeRef(typeRef, null, 'F',
- numTypeParameters: 2, expectedKind: ReferenceKind.typedef);
- }
-
- test_typedef_reference_generic_imported() {
- addNamedSource('/lib.dart', 'typedef void F<A, B>();');
- EntityRef typeRef =
- serializeTypeText('F', otherDeclarations: 'import "lib.dart";');
- checkTypeRef(typeRef, absUri('/lib.dart'), 'F',
- numTypeParameters: 2, expectedKind: ReferenceKind.typedef);
- }
-
- test_typedef_return_type_explicit() {
- UnlinkedTypedef type = serializeTypedefText('typedef int F();');
- checkTypeRef(type.returnType, 'dart:core', 'int');
- }
-
- test_typedef_type_param_in_parameter() {
- UnlinkedTypedef type = serializeTypedefText('typedef F<T>(T t);');
- checkParamTypeRef(type.parameters[0].type, 1);
- expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
- }
-
- test_typedef_type_param_in_return_type() {
- UnlinkedTypedef type = serializeTypedefText('typedef T F<T>();');
- checkParamTypeRef(type.returnType, 1);
- }
-
- test_typedef_type_param_none() {
- UnlinkedTypedef type = serializeTypedefText('typedef F();');
- expect(type.typeParameters, isEmpty);
- }
-
- test_typedef_type_param_order() {
- UnlinkedTypedef type = serializeTypedefText('typedef F<T, U>();');
- expect(type.typeParameters, hasLength(2));
- expect(type.typeParameters[0].name, 'T');
- expect(type.typeParameters[1].name, 'U');
- }
-
- test_unit_codeRange() {
- serializeLibraryText(' int a = 1; ');
- UnlinkedUnit unit = unlinkedUnits[0];
- _assertCodeRange(unit.codeRange, 0, 14);
- }
-
- test_unresolved_export() {
- allowMissingFiles = true;
- serializeLibraryText("export 'foo.dart';", allowErrors: true);
- expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.exports[0].uri, 'foo.dart');
- expect(linked.exportDependencies, hasLength(1));
- checkDependency(linked.exportDependencies[0], absUri('/foo.dart'));
- }
-
- test_unresolved_import() {
- allowMissingFiles = true;
- serializeLibraryText("import 'foo.dart';", allowErrors: true);
- expect(unlinkedUnits[0].imports, hasLength(2));
- expect(unlinkedUnits[0].imports[0].uri, 'foo.dart');
- // Note: imports[1] is the implicit import of dart:core.
- expect(unlinkedUnits[0].imports[1].isImplicit, true);
- expect(linked.importDependencies, hasLength(2));
- checkDependency(linked.importDependencies[0], absUri('/foo.dart'));
- }
-
- test_unresolved_part() {
- allowMissingFiles = true;
- serializeLibraryText("part 'foo.dart';", allowErrors: true);
- expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
- expect(unlinkedUnits[0].publicNamespace.parts[0], 'foo.dart');
- }
-
- test_unresolved_reference_in_multiple_parts() {
- addNamedSource('/a.dart', 'part of foo; int x; Unresolved y;');
- serializeLibraryText('library foo; part "a.dart"; Unresolved z;',
- allowErrors: true);
- // The unresolved types in the defining compilation unit and the part
- // should both work correctly even though they use different reference
- // indices.
- checkUnresolvedTypeRef(
- unlinkedUnits[0].variables[0].type, null, 'Unresolved');
- checkUnresolvedTypeRef(
- unlinkedUnits[1].variables[1].type, null, 'Unresolved',
- linkedSourceUnit: linked.units[1],
- unlinkedSourceUnit: unlinkedUnits[1]);
- }
-
- test_unresolved_reference_shared() {
- // Both `x` and `y` use unresolved identifier `C` as their type. Verify
- // that they both use the same unresolved reference.
- serializeLibraryText('C x; C y;', allowErrors: true);
- EntityRef xType = findVariable('x').type;
- EntityRef yType = findVariable('y').type;
- expect(xType.reference, yType.reference);
- }
-
- test_unused_type_parameter() {
- if (skipFullyLinkedData) {
- return;
- }
- UnlinkedVariable variable = serializeVariableText('''
-class C<T> {
- void f() {}
-}
-C<int> c;
-var v = c.f;
-''');
- EntityRef type =
- getTypeRefForSlot(variable.initializer.inferredReturnTypeSlot);
- expect(type.typeArguments, hasLength(1));
- checkLinkedTypeRef(type.typeArguments[0], 'dart:core', 'int');
- }
-
- test_variable() {
- String text = 'int i;';
- UnlinkedVariable v = serializeVariableText(text, variableName: 'i');
- expect(v.nameOffset, text.indexOf('i;'));
- expect(findExecutable('i'), isNull);
- expect(findExecutable('i='), isNull);
- expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
- expect(unlinkedUnits[0].publicNamespace.names[0].kind,
- ReferenceKind.topLevelPropertyAccessor);
- expect(unlinkedUnits[0].publicNamespace.names[0].name, 'i');
- expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
- expect(unlinkedUnits[0].publicNamespace.names[1].kind,
- ReferenceKind.topLevelPropertyAccessor);
- expect(unlinkedUnits[0].publicNamespace.names[1].name, 'i=');
- expect(unlinkedUnits[0].publicNamespace.names[1].numTypeParameters, 0);
- }
-
- test_variable_codeRange() {
- serializeLibraryText(' int a = 1, b = 22;');
- List<UnlinkedVariable> variables = unlinkedUnits[0].variables;
- _assertCodeRange(variables[0].codeRange, 1, 9);
- _assertCodeRange(variables[1].codeRange, 12, 6);
- }
-
- test_variable_const() {
- UnlinkedVariable variable =
- serializeVariableText('const int i = 0;', variableName: 'i');
- expect(variable.isConst, isTrue);
- }
-
- test_variable_documented() {
- String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-var v;''';
- UnlinkedVariable variable = serializeVariableText(text);
- expect(variable.documentationComment, isNotNull);
- checkDocumentationComment(variable.documentationComment, text);
- }
-
- test_variable_explicit_dynamic() {
- UnlinkedVariable variable = serializeVariableText('dynamic v;');
- checkDynamicTypeRef(variable.type);
- }
-
- test_variable_implicit_dynamic() {
- UnlinkedVariable variable = serializeVariableText('var v;');
- expect(variable.type, isNull);
- }
-
- test_variable_inferred_type_explicit_initialized() {
- UnlinkedVariable v = serializeVariableText('int v = 0;');
- expect(v.inferredTypeSlot, 0);
- }
-
- test_variable_inferred_type_implicit_initialized() {
- UnlinkedVariable v = serializeVariableText('var v = 0;');
- checkInferredTypeSlot(v.inferredTypeSlot, 'dart:core', 'int');
- }
-
- test_variable_inferred_type_implicit_uninitialized() {
- UnlinkedVariable v = serializeVariableText('var v;');
- expect(v.inferredTypeSlot, 0);
- }
-
- test_variable_initializer() {
- UnlinkedVariable variable =
- serializeVariableText('int i = 0;', variableName: 'i');
- expect(variable.initializer.bodyExpr, isNull);
- }
-
- test_variable_initializer_final() {
- UnlinkedVariable variable =
- serializeVariableText('final int i = 0;', variableName: 'i');
- expect(variable.isFinal, isTrue);
- expect(variable.initializer.bodyExpr, isNull);
- }
-
- test_variable_initializer_final_untyped() {
- if (skipFullyLinkedData) return;
- UnlinkedVariable variable = serializeVariableText('final v = 0;');
- var typeRef = getTypeRefForSlot(variable.inferredTypeSlot);
- checkLinkedTypeRef(typeRef, 'dart:core', 'int');
- if (containsNonConstExprs) {
- expect(variable.initializer.bodyExpr, isNotNull);
- } else {
- expect(variable.initializer.bodyExpr, isNull);
- }
- }
-
- test_variable_initializer_literal() {
- UnlinkedVariable variable = serializeVariableText('var v = 42;');
- UnlinkedExecutable initializer = variable.initializer;
- expect(initializer, isNotNull);
- expect(initializer.nameOffset, 8);
- expect(initializer.name, isEmpty);
- expect(initializer.localFunctions, isEmpty);
- }
-
- test_variable_initializer_noInitializer() {
- UnlinkedVariable variable = serializeVariableText('var v;');
- expect(variable.initializer, isNull);
- }
-
- test_variable_initializer_untyped() {
- if (skipFullyLinkedData) return;
- UnlinkedVariable variable = serializeVariableText('var v = 0;');
- var typeRef = getTypeRefForSlot(variable.inferredTypeSlot);
- checkLinkedTypeRef(typeRef, 'dart:core', 'int');
- if (containsNonConstExprs) {
- expect(variable.initializer.bodyExpr, isNotNull);
- } else {
- expect(variable.initializer.bodyExpr, isNull);
- }
- }
-
- test_variable_initializer_withLocals() {
- String text = 'var v = <dynamic, dynamic>{"1": () { f1() {} var v1; }, '
- '"2": () { f2() {} var v2; }};';
- UnlinkedVariable variable = serializeVariableText(text);
- UnlinkedExecutable initializer = variable.initializer;
- expect(initializer, isNotNull);
- expect(initializer.nameOffset, text.indexOf('<dynamic, dynamic>{"1'));
- expect(initializer.name, isEmpty);
- expect(initializer.localFunctions, hasLength(2));
- // closure: () { f1() {} var v1; }
- {
- UnlinkedExecutable closure = initializer.localFunctions[0];
- expect(closure.nameOffset, text.indexOf('() { f1()'));
- expect(closure.name, isEmpty);
- // closure - f1
- expect(closure.localFunctions, hasLength(1));
- expect(closure.localFunctions[0].name, 'f1');
- expect(closure.localFunctions[0].nameOffset, text.indexOf('f1()'));
- }
- // closure: () { f2() {} var v2; }
- {
- UnlinkedExecutable closure = initializer.localFunctions[1];
- expect(closure.nameOffset, text.indexOf('() { f2()'));
- expect(closure.name, isEmpty);
- // closure - f1
- expect(closure.localFunctions, hasLength(1));
- expect(closure.localFunctions[0].name, 'f2');
- expect(closure.localFunctions[0].nameOffset, text.indexOf('f2()'));
- }
- }
-
- test_variable_late() {
- featureSet = enableNnbd;
- UnlinkedVariable variable =
- serializeVariableText('late int i;', variableName: 'i');
- expect(variable.isLate, isTrue);
- expect(variable.isStatic, isFalse);
- expect(variable.isConst, isFalse);
- expect(variable.isFinal, isFalse);
- }
-
- test_variable_name() {
- UnlinkedVariable variable =
- serializeVariableText('int i;', variableName: 'i');
- expect(variable.name, 'i');
- }
-
- test_variable_no_flags() {
- UnlinkedVariable variable =
- serializeVariableText('int i;', variableName: 'i');
- expect(variable.isLate, isFalse);
- expect(variable.isStatic, isFalse);
- expect(variable.isConst, isFalse);
- expect(variable.isFinal, isFalse);
- }
-
- test_variable_non_const() {
- UnlinkedVariable variable =
- serializeVariableText('int i = 0;', variableName: 'i');
- expect(variable.isConst, isFalse);
- }
-
- test_variable_non_final() {
- UnlinkedVariable variable =
- serializeVariableText('int i;', variableName: 'i');
- expect(variable.isFinal, isFalse);
- }
-
- test_variable_non_static() {
- UnlinkedVariable variable =
- serializeClassText('class C { int i; }').fields[0];
- expect(variable.isLate, isFalse);
- expect(variable.isStatic, isFalse);
- }
-
- test_variable_non_static_top_level() {
- // Top level variables are considered non-static.
- UnlinkedVariable variable =
- serializeVariableText('int i;', variableName: 'i');
- expect(variable.isLate, isFalse);
- expect(variable.isStatic, isFalse);
- }
-
- test_variable_private() {
- serializeVariableText('int _i;', variableName: '_i');
- expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
- }
-
- test_variable_static() {
- UnlinkedVariable variable =
- serializeClassText('class C { static int i; }').fields[0];
- expect(variable.isLate, isFalse);
- expect(variable.isStatic, isTrue);
- }
-
- test_variable_type() {
- UnlinkedVariable variable =
- serializeVariableText('int i;', variableName: 'i');
- checkTypeRef(variable.type, 'dart:core', 'int');
- }
-
- /// Assert that serializing the given [expr] of form `(a op= 1 + 2) + 3`
- /// uses the given [expectedAssignOperator].
- void _assertAssignmentOperator(
- String expr, UnlinkedExprAssignOperator expectedAssignOperator) {
- UnlinkedVariable variable = serializeVariableText('''
-int a = 0;
-final v = $expr;
- ''');
- assertUnlinkedConst(variable.initializer.bodyExpr, expr,
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.add,
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.add,
- ],
- assignmentOperators: [expectedAssignOperator],
- ints: [1, 2, 3],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ],
- forTypeInferenceOnly: true);
- }
-
- void _assertCodeRange(CodeRange codeRange, int offset, int length) {
- expect(codeRange, isNotNull);
- expect(codeRange.offset, offset);
- expect(codeRange.length, length);
- }
-
- void _assertParameterVisible(
- String code, UnlinkedParam p, String visibleBegin, String visibleEnd) {
- int expectedVisibleOffset = code.indexOf(visibleBegin);
- int expectedVisibleLength =
- code.indexOf(visibleEnd) - expectedVisibleOffset + 1;
- expect(p.visibleOffset, expectedVisibleOffset);
- expect(p.visibleLength, expectedVisibleLength);
- }
-
- void _assertParameterZeroVisibleRange(UnlinkedParam p) {
- expect(p.visibleOffset, isZero);
- expect(p.visibleLength, isZero);
- }
-
- /// Assert that the [expr] of the form `++a + 2` is serialized with the
- /// [expectedAssignmentOperator].
- void _assertRefPrefixPostfixIncrementDecrement(
- String expr, UnlinkedExprAssignOperator expectedAssignmentOperator) {
- UnlinkedVariable variable = serializeVariableText('''
-int a = 0;
-final v = $expr;
-''');
- assertUnlinkedConst(variable.initializer.bodyExpr, expr,
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.assignToRef,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.add,
- ],
- assignmentOperators: [expectedAssignmentOperator],
- ints: [2],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'a',
- expectedKind: ReferenceKind.topLevelPropertyAccessor)
- ],
- forTypeInferenceOnly: true);
- }
-
- String _normalizeTokenString(String tokenString) {
- // Note: to normalize the token string it's not sufficient to tokenize it
- // and then pass the tokens to `tokensToString`; we also need to parse it
- // because parsing modifies the token stream (splitting up `[]`, `>>`, and
- // `>>>` tokens when circumstances warrant).
- //
- // We wrap the expression in "f() async => ...;" to ensure that the await
- // keyword is properly parsed.
- var sourceText = 'f() async => $tokenString;';
- var errorListener = AnalysisErrorListener.NULL_LISTENER;
- var reader = new CharSequenceReader(sourceText);
- var stringSource = new StringSource(sourceText, null);
- var scanner = new Scanner(stringSource, reader, errorListener)
- ..configureFeatures(featureSet);
- var startToken = scanner.tokenize();
- var parser =
- new Parser(stringSource, errorListener, featureSet: featureSet);
- var compilationUnit = parser.parseCompilationUnit(startToken);
- var f = compilationUnit.declarations[0] as FunctionDeclaration;
- var body = f.functionExpression.body as ExpressionFunctionBody;
- var expression = body.expression;
- return tokensToString(expression.beginToken, expression.endToken);
- }
-}
-
-/// Description of expectations for a prelinked prefix reference.
-class _PrefixExpectation {
- final ReferenceKind kind;
- final String name;
- final String absoluteUri;
- final int numTypeParameters;
-
- _PrefixExpectation(this.kind, this.name,
- {this.absoluteUri, this.numTypeParameters: 0});
-}
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
index 184c0e7..40dd736 100644
--- a/pkg/analyzer/test/src/summary/test_all.dart
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -6,32 +6,22 @@
import 'api_signature_test.dart' as api_signature;
import 'dependency_walker_test.dart' as dependency_walker;
-import 'expr_builder_test.dart' as expr_builder;
import 'flat_buffers_test.dart' as flat_buffers;
import 'in_summary_source_test.dart' as in_summary_source;
-import 'linker_test.dart' as linker;
import 'name_filter_test.dart' as name_filter;
import 'package_bundle_reader_test.dart' as package_bundle_reader;
-import 'prelinker_test.dart' as prelinker;
import 'resynthesize_ast2_test.dart' as resynthesize_ast2;
-import 'resynthesize_ast_test.dart' as resynthesize_ast;
-import 'summarize_ast_strong_test.dart' as summarize_ast_strong;
import 'top_level_inference_test.dart' as top_level_inference;
main() {
defineReflectiveSuite(() {
api_signature.main();
dependency_walker.main();
- expr_builder.main();
flat_buffers.main();
in_summary_source.main();
- linker.main();
name_filter.main();
package_bundle_reader.main();
- prelinker.main();
resynthesize_ast2.main();
- resynthesize_ast.main();
- summarize_ast_strong.main();
top_level_inference.main();
}, name: 'summary');
}
diff --git a/pkg/analyzer/test/src/summary/test_strategies.dart b/pkg/analyzer/test/src/summary/test_strategies.dart
index 7f0aa49..83e49ed 100644
--- a/pkg/analyzer/test/src/summary/test_strategies.dart
+++ b/pkg/analyzer/test/src/summary/test_strategies.dart
@@ -8,33 +8,17 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
-import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/link.dart';
-import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/prelink.dart';
-import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
-import 'package:path/path.dart' show posix;
-import 'package:test/test.dart';
import 'resynthesize_common.dart';
-/// Convert the given Posix style file [path] to the corresponding absolute URI.
-String absUri(String path) {
- String absolutePath = posix.absolute(path);
- return posix.toUri(absolutePath).toString();
-}
-
CompilationUnit parseText(
String text,
FeatureSet featureSet,
@@ -56,40 +40,6 @@
return unit;
}
-/// Verify invariants of the given [linkedLibrary].
-void _validateLinkedLibrary(LinkedLibrary linkedLibrary) {
- for (LinkedUnit unit in linkedLibrary.units) {
- for (LinkedReference reference in unit.references) {
- switch (reference.kind) {
- case ReferenceKind.classOrEnum:
- case ReferenceKind.topLevelPropertyAccessor:
- case ReferenceKind.topLevelFunction:
- case ReferenceKind.typedef:
- // This reference can have either a zero or a nonzero dependency,
- // since it refers to top level element which might or might not be
- // imported from another library.
- break;
- case ReferenceKind.prefix:
- // Prefixes should have a dependency of 0, since they come from the
- // current library.
- expect(reference.dependency, 0,
- reason: 'Nonzero dependency for prefix');
- break;
- case ReferenceKind.unresolved:
- // Unresolved references always have a dependency of 0.
- expect(reference.dependency, 0,
- reason: 'Nonzero dependency for undefined');
- break;
- default:
- // This reference should have a dependency of 0, since it refers to
- // an element that is contained within some other element.
- expect(reference.dependency, 0,
- reason: 'Nonzero dependency for ${reference.kind}');
- }
- }
- }
-}
-
/// Abstract base class for tests of summary resynthesis.
///
/// Test classes should not extend this class directly; they should extend a
@@ -119,14 +69,9 @@
Source addSource(String path, String contents);
Source addTestSource(String code, [Uri uri]);
-
- void checkMinimalResynthesisWork(TestSummaryResynthesizer resynthesizer,
- Uri expectedLibraryUri, List<Uri> expectedUnitUriList);
-
- TestSummaryResynthesizer encodeLibrary(Source source);
}
-/// Implementation of [SummaryBlackBoxTestStrategy] that drives summary
+/// Implementation of [ResynthesizeTestStrategy] that drives summary
/// generation using the old two-phase API.
class ResynthesizeTestStrategyTwoPhase extends AbstractResynthesizeTest
implements ResynthesizeTestStrategy {
@@ -142,129 +87,6 @@
@override
bool get isAstBasedSummary => false;
-
- TestSummaryResynthesizer encodeLibrary(Source source) {
- _serializeLibrary(source);
-
- PackageBundle bundle =
- new PackageBundle.fromBuffer(bundleAssembler.assemble().toBuffer());
-
- Map<String, UnlinkedUnit> unlinkedSummaries = <String, UnlinkedUnit>{};
- for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
- String uri = bundle.unlinkedUnitUris[i];
- unlinkedSummaries[uri] = bundle.unlinkedUnits[i];
- }
-
- LinkedLibrary getDependency(String absoluteUri) {
- Map<String, LinkedLibrary> sdkLibraries =
- SerializedMockSdk.instance.uriToLinkedLibrary;
- LinkedLibrary linkedLibrary = sdkLibraries[absoluteUri];
- if (linkedLibrary == null && !allowMissingFiles) {
- fail('Linker unexpectedly requested LinkedLibrary for "$absoluteUri".'
- ' Libraries available: ${sdkLibraries.keys}');
- }
- return linkedLibrary;
- }
-
- UnlinkedUnit getUnit(String absoluteUri) {
- UnlinkedUnit unit = uriToUnit[absoluteUri] ??
- SerializedMockSdk.instance.uriToUnlinkedUnit[absoluteUri];
- if (unit == null && !allowMissingFiles) {
- fail('Linker unexpectedly requested unit for "$absoluteUri".');
- }
- return unit;
- }
-
- Set<String> nonSdkLibraryUris = serializedSources
- .where((Source source) => !source.isInSystemLibrary)
- .map((Source source) => source.uri.toString())
- .toSet();
-
- var analysisOptions = AnalysisOptionsImpl()..contextFeatures = featureSet;
-
- Map<String, LinkedLibrary> linkedSummaries = link(nonSdkLibraryUris,
- getDependency, getUnit, declaredVariables, analysisOptions);
-
- var synchronousSession =
- SynchronousSession(analysisOptions, declaredVariables);
- var analysisContext = RestrictedAnalysisContext(
- synchronousSession,
- sourceFactory,
- );
-
- return new TestSummaryResynthesizer(
- analysisContext,
- new Map<String, UnlinkedUnit>()
- ..addAll(SerializedMockSdk.instance.uriToUnlinkedUnit)
- ..addAll(unlinkedSummaries),
- new Map<String, LinkedLibrary>()
- ..addAll(SerializedMockSdk.instance.uriToLinkedLibrary)
- ..addAll(linkedSummaries),
- allowMissingFiles);
- }
-
- UnlinkedUnit _getUnlinkedUnit(Source source) {
- if (source == null) {
- return new UnlinkedUnitBuilder();
- }
-
- String uriStr = source.uri.toString();
- {
- UnlinkedUnit unlinkedUnitInSdk =
- SerializedMockSdk.instance.uriToUnlinkedUnit[uriStr];
- if (unlinkedUnitInSdk != null) {
- return unlinkedUnitInSdk;
- }
- }
- return uriToUnit.putIfAbsent(uriStr, () {
- var file = getFile(source.fullName);
-
- String contents;
- if (file.exists) {
- contents = file.readAsStringSync();
- } else {
- // Source does not exist.
- if (!allowMissingFiles) {
- fail('Unexpectedly tried to get unlinked summary for $source');
- }
- contents = '';
- }
-
- CompilationUnit unit = parseText(contents, featureSet);
-
- UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
- bundleAssembler.addUnlinkedUnit(source, unlinkedUnit);
- return unlinkedUnit;
- });
- }
-
- void _serializeLibrary(Source librarySource) {
- if (librarySource == null || librarySource.isInSystemLibrary) {
- return;
- }
- if (!serializedSources.add(librarySource)) {
- return;
- }
-
- UnlinkedUnit getPart(String absoluteUri) {
- Source source = sourceFactory.forUri(absoluteUri);
- return _getUnlinkedUnit(source);
- }
-
- UnlinkedPublicNamespace getImport(String relativeUri) {
- return getPart(relativeUri)?.publicNamespace;
- }
-
- UnlinkedUnit definingUnit = _getUnlinkedUnit(librarySource);
- if (definingUnit != null) {
- LinkedLibraryBuilder linkedLibrary = prelink(librarySource.uri.toString(),
- definingUnit, getPart, getImport, declaredVariables);
- linkedLibrary.dependencies.skip(1).forEach((LinkedDependency d) {
- Source source = sourceFactory.forUri(d.uri);
- _serializeLibrary(source);
- });
- }
- }
}
/// [SerializedMockSdk] is a singleton class representing the result of
@@ -303,355 +125,3 @@
}
}
}
-
-/// Abstract base class for tests involving summaries.
-///
-/// Test classes should not extend this class directly; they should extend a
-/// class that implements this class with methods that drive summary generation.
-/// The tests themselves can then be provided via mixin, allowing summaries to
-/// be tested in a variety of ways.
-abstract class SummaryBaseTestStrategy {
- /// The set of features enabled in this test.
- FeatureSet featureSet;
-
- /// Add the given package bundle as a dependency so that it may be referenced
- /// by the files under test.
- void addBundle(String path, PackageBundle bundle);
-
- /// Add the given source file so that it may be referenced by the file under
- /// test.
- void addNamedSource(String filePath, String contents);
-
- /// Link together the given file, along with any other files passed to
- /// [addNamedSource], to form a package bundle. Reset the state of the
- /// buffers accumulated by [addNamedSource] and [addBundle] so that further
- /// bundles can be created.
- PackageBundleBuilder createPackageBundle(String text,
- {String path: '/test.dart', String uri});
-}
-
-/// Abstract base class for black-box tests of summaries.
-///
-/// Test classes should not extend this class directly; they should extend a
-/// class that implements this class with methods that drive summary generation.
-/// The tests themselves can then be provided via mixin, allowing summaries to
-/// be tested in a variety of ways.
-abstract class SummaryBlackBoxTestStrategy extends SummaryBaseTestStrategy {
- /// A test will set this to `true` if it contains `import`, `export`, or
- /// `part` declarations that deliberately refer to non-existent files.
- void set allowMissingFiles(bool value);
-
- /// Indicates whether the summary contains expressions for non-const fields.
- ///
- /// When one-phase summarization is in use, only const field initializer
- /// expressions are stored in the summary.
- bool get containsNonConstExprs;
-
- /// Get access to the linked summary that results from serializing and
- /// then deserializing the library under test.
- LinkedLibrary get linked;
-
- /// `true` if the linked portion of the summary only contains prelinked data.
- /// This happens because we don't yet have a full linker; only a prelinker.
- bool get skipFullyLinkedData;
-
- /// Get access to the unlinked compilation unit summaries that result from
- /// serializing and deserializing the library under test.
- List<UnlinkedUnit> get unlinkedUnits;
-
- /// Serialize the given library [text], then deserialize it and store its
- /// summary in [lib].
- void serializeLibraryText(String text, {bool allowErrors: false});
-}
-
-/// Implementation of [SummaryBlackBoxTestStrategy] that drives summary
-/// generation using the old two-phase API, and exercises the pre-linker only.
-class SummaryBlackBoxTestStrategyPrelink
- extends _SummaryBlackBoxTestStrategyTwoPhase
- implements SummaryBlackBoxTestStrategy {
- @override
- bool get skipFullyLinkedData => true;
-
- @override
- void serializeLibraryText(String text, {bool allowErrors: false}) {
- super.serializeLibraryText(text, allowErrors: allowErrors);
-
- UnlinkedUnit getPart(String absoluteUri) {
- return _linkerInputs.getUnit(absoluteUri);
- }
-
- UnlinkedPublicNamespace getImport(String absoluteUri) {
- return getPart(absoluteUri)?.publicNamespace;
- }
-
- linked = new LinkedLibrary.fromBuffer(prelink(
- _linkerInputs._testDartUri.toString(),
- _linkerInputs._unlinkedDefiningUnit,
- getPart,
- getImport,
- DeclaredVariables())
- .toBuffer());
- _validateLinkedLibrary(linked);
- }
-}
-
-/// Implementation of [SummaryBlackBoxTestStrategy] that drives summary
-/// generation using the old two-phase API, and exercises full summary
-/// generation.
-class SummaryBlackBoxTestStrategyTwoPhase
- extends _SummaryBlackBoxTestStrategyTwoPhase
- implements SummaryBlackBoxTestStrategy {
- @override
- bool get skipFullyLinkedData => false;
-}
-
-/// Abstract base class for unit tests of the summary linker.
-///
-/// Test classes should not extend this class directly; they should extend a
-/// class that implements this class with methods that drive summary generation.
-/// The tests themselves can then be provided via mixin, allowing summaries to
-/// be tested in a variety of ways.
-abstract class SummaryLinkerTestStrategy extends SummaryBaseTestStrategy {
- Linker get linker;
-
- /// Gets the URI of the main library under test.
- ///
- /// May only be called after [createLinker].
- Uri get testDartUri;
-
- LibraryElementInBuildUnit get testLibrary;
-
- void createLinker(String text, {String path: '/test.dart'});
-}
-
-/// Implementation of [SummaryLinkerTestStrategy] that drives summary generation
-/// using the old two-phase API.
-class SummaryLinkerTestStrategyTwoPhase extends _SummaryBaseTestStrategyTwoPhase
- implements SummaryLinkerTestStrategy {
- LibraryElementInBuildUnit _testLibrary;
-
- @override
- Linker linker;
-
- @override
- Uri get testDartUri => _linkerInputs._testDartUri;
-
- @override
- LibraryElementInBuildUnit get testLibrary =>
- _testLibrary ??= linker.getLibrary(_linkerInputs._testDartUri)
- as LibraryElementInBuildUnit;
-
- @override
- bool get _allowMissingFiles => false;
-
- @override
- void createLinker(String text, {String path: '/test.dart'}) {
- _linkerInputs = _createLinkerInputs(text, path: path);
- Map<String, LinkedLibraryBuilder> linkedLibraries = setupForLink(
- _linkerInputs.linkedLibraries,
- _linkerInputs.getUnit,
- _linkerInputs.declaredVariables);
- linker = new Linker(linkedLibraries, _linkerInputs.getDependency,
- _linkerInputs.getUnit, null, analysisOptions);
- }
-}
-
-/// [_FilesToLink] stores information about a set of files to be linked
-/// together. This information is grouped into a class to allow it to be reset
-/// easily when [_SummaryBaseTestStrategyTwoPhase._createLinkerInputs] is
-/// called.
-///
-/// The generic parameter [U] is the type of information stored for each
-/// compilation unit.
-class _FilesToLink<U> {
- /// Map from absolute URI to the [U] for each compilation unit passed to
- /// [addNamedSource].
- Map<String, U> uriToUnit = <String, U>{};
-
- /// Information about summaries to be included in the link process.
- SummaryDataStore summaryDataStore = new SummaryDataStore([]);
-}
-
-/// Instances of the class [_LinkerInputs] encapsulate the necessary information
-/// to pass to the summary linker.
-class _LinkerInputs {
- final bool _allowMissingFiles;
- final Map<String, UnlinkedUnit> _uriToUnit;
- final Uri _testDartUri;
- final UnlinkedUnit _unlinkedDefiningUnit;
- final Map<String, LinkedLibrary> _dependentLinkedLibraries;
- final Map<String, UnlinkedUnit> _dependentUnlinkedUnits;
-
- _LinkerInputs(
- this._allowMissingFiles,
- this._uriToUnit,
- this._testDartUri,
- this._unlinkedDefiningUnit,
- this._dependentLinkedLibraries,
- this._dependentUnlinkedUnits);
-
- DeclaredVariables get declaredVariables => DeclaredVariables();
-
- Set<String> get linkedLibraries => _uriToUnit.keys.toSet();
-
- LinkedLibrary getDependency(String absoluteUri) {
- Map<String, LinkedLibrary> sdkLibraries =
- SerializedMockSdk.instance.uriToLinkedLibrary;
- LinkedLibrary linkedLibrary =
- sdkLibraries[absoluteUri] ?? _dependentLinkedLibraries[absoluteUri];
- if (linkedLibrary == null && !_allowMissingFiles) {
- Set<String> librariesAvailable = sdkLibraries.keys.toSet();
- librariesAvailable.addAll(_dependentLinkedLibraries.keys);
- fail('Linker unexpectedly requested LinkedLibrary for "$absoluteUri".'
- ' Libraries available: ${librariesAvailable.toList()}');
- }
- return linkedLibrary;
- }
-
- UnlinkedUnit getUnit(String absoluteUri) {
- if (absoluteUri == null) {
- return null;
- }
- UnlinkedUnit unit = _uriToUnit[absoluteUri] ??
- SerializedMockSdk.instance.uriToUnlinkedUnit[absoluteUri] ??
- _dependentUnlinkedUnits[absoluteUri];
- if (unit == null && !_allowMissingFiles) {
- fail('Linker unexpectedly requested unit for "$absoluteUri".');
- }
- return unit;
- }
-}
-
-/// Implementation of [SummaryBaseTestStrategy] that drives summary generation
-/// using the old two-phase API.
-abstract class _SummaryBaseTestStrategyTwoPhase
- implements SummaryBaseTestStrategy {
- /// Information about the files to be linked.
- _FilesToLink<UnlinkedUnitBuilder> _filesToLink =
- new _FilesToLink<UnlinkedUnitBuilder>();
-
- @override
- FeatureSet featureSet = FeatureSet.forTesting();
-
- _LinkerInputs _linkerInputs;
-
- AnalysisOptions get analysisOptions =>
- AnalysisOptionsImpl()..contextFeatures = featureSet;
-
- bool get _allowMissingFiles;
-
- @override
- void addBundle(String path, PackageBundle bundle) {
- _filesToLink.summaryDataStore.addBundle(path, bundle);
- }
-
- @override
- void addNamedSource(String filePath, String contents) {
- CompilationUnit unit = parseText(contents, featureSet);
- UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
- _filesToLink.uriToUnit[absUri(filePath)] = unlinkedUnit;
- }
-
- @override
- PackageBundleBuilder createPackageBundle(String text,
- {String path: '/test.dart', String uri}) {
- PackageBundleAssembler assembler = new PackageBundleAssembler();
- _LinkerInputs linkerInputs =
- _createLinkerInputs(text, path: path, uri: uri);
- Map<String, LinkedLibraryBuilder> linkedLibraries = link(
- linkerInputs.linkedLibraries,
- linkerInputs.getDependency,
- linkerInputs.getUnit,
- linkerInputs.declaredVariables,
- analysisOptions);
- linkedLibraries.forEach(assembler.addLinkedLibrary);
- linkerInputs._uriToUnit.forEach((String uri, UnlinkedUnit unit) {
- assembler.addUnlinkedUnitViaUri(uri, unit);
- });
- return assembler.assemble();
- }
-
- UnlinkedUnitBuilder createUnlinkedSummary(Uri uri, String text) =>
- serializeAstUnlinked(parseText(text, featureSet));
-
- _LinkerInputs _createLinkerInputs(String text,
- {String path: '/test.dart', String uri}) {
- uri ??= absUri(path);
- Uri testDartUri = Uri.parse(uri);
- UnlinkedUnitBuilder unlinkedDefiningUnit =
- createUnlinkedSummary(testDartUri, text);
- _filesToLink.uriToUnit[testDartUri.toString()] = unlinkedDefiningUnit;
- _LinkerInputs linkerInputs = new _LinkerInputs(
- _allowMissingFiles,
- _filesToLink.uriToUnit,
- testDartUri,
- unlinkedDefiningUnit,
- _filesToLink.summaryDataStore.linkedMap,
- _filesToLink.summaryDataStore.unlinkedMap);
- // Reset _filesToLink in case the test needs to start a new package bundle.
- _filesToLink = new _FilesToLink<UnlinkedUnitBuilder>();
- return linkerInputs;
- }
-}
-
-/// Implementation of [SummaryBlackBoxTestStrategy] that drives summary
-/// generation using the old two-phase API.
-///
-/// Not intended to be used directly; instead use a derived class that either
-/// exercises the full summary algorithm or just pre-linking.
-abstract class _SummaryBlackBoxTestStrategyTwoPhase
- extends _SummaryBaseTestStrategyTwoPhase
- implements SummaryBlackBoxTestStrategy {
- @override
- List<UnlinkedUnit> unlinkedUnits;
-
- @override
- LinkedLibrary linked;
-
- @override
- bool _allowMissingFiles = false;
-
- @override
- void set allowMissingFiles(bool value) {
- _allowMissingFiles = value;
- }
-
- @override
- bool get containsNonConstExprs => true;
-
- @override
- void serializeLibraryText(String text, {bool allowErrors: false}) {
- Map<String, UnlinkedUnitBuilder> uriToUnit = this._filesToLink.uriToUnit;
- _linkerInputs = _createLinkerInputs(text);
- linked = link(
- _linkerInputs.linkedLibraries,
- _linkerInputs.getDependency,
- _linkerInputs.getUnit,
- DeclaredVariables(),
- analysisOptions)[_linkerInputs._testDartUri.toString()];
- expect(linked, isNotNull);
- _validateLinkedLibrary(linked);
- unlinkedUnits = <UnlinkedUnit>[_linkerInputs._unlinkedDefiningUnit];
- for (String relativeUriStr
- in _linkerInputs._unlinkedDefiningUnit.publicNamespace.parts) {
- Uri relativeUri;
- try {
- relativeUri = Uri.parse(relativeUriStr);
- } on FormatException {
- unlinkedUnits.add(new UnlinkedUnitBuilder());
- continue;
- }
-
- UnlinkedUnit unit = uriToUnit[
- resolveRelativeUri(_linkerInputs._testDartUri, relativeUri)
- .toString()];
- if (unit == null) {
- if (!_allowMissingFiles) {
- fail('Test referred to unknown unit $relativeUriStr');
- }
- } else {
- unlinkedUnits.add(unit);
- }
- }
- }
-}
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
index f738485..6a7ed96 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -6,7 +6,6 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -719,17 +718,10 @@
import 'a.dart';
var x = new C().f;
''');
- if (AnalysisDriver.useSummary2) {
- checkElementText(library, r'''
+ checkElementText(library, r'''
import 'a.dart';
int x;
''');
- } else {
- checkElementText(library, r'''
-import 'a.dart';
-dynamic x;
-''');
- }
}
test_initializer_extractProperty_implicitlyTyped_sameLibrary() async {
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index db5ceab..2158740 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -6,7 +6,6 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -367,11 +366,7 @@
''');
var v = mainUnit.topLevelVariables[0];
expect(v.type.toString(), 'dynamic');
- if (AnalysisDriver.useSummary2) {
- expect(v.initializer.type.toString(), 'dynamic Function()');
- } else {
- expect(v.initializer.type.toString(), 'Null Function()');
- }
+ expect(v.initializer.type.toString(), 'dynamic Function()');
}
test_bottom_inClosure() async {
@@ -2416,8 +2411,7 @@
}
test_infer_use_of_void() async {
- if (AnalysisDriver.useSummary2) {
- await checkFileElement('''
+ await checkFileElement('''
class B {
void f() {}
}
@@ -2426,17 +2420,6 @@
}
var x = /*error:TOP_LEVEL_INSTANCE_METHOD*/new C().f();
''');
- } else {
- await checkFileElement('''
-class B {
- void f() {}
-}
-class C extends B {
- f() {}
-}
-var x = /*error:TOP_LEVEL_INSTANCE_METHOD*/new C()./*error:USE_OF_VOID_RESULT*/f();
-''');
- }
}
test_inferConstsTransitively() async {
diff --git a/pkg/analyzer/tool/experiments/generate.dart b/pkg/analyzer/tool/experiments/generate.dart
index 4846520..ac968f5 100644
--- a/pkg/analyzer/tool/experiments/generate.dart
+++ b/pkg/analyzer/tool/experiments/generate.dart
@@ -9,16 +9,16 @@
import 'package:path/path.dart';
import 'package:yaml/yaml.dart' show YamlMap, loadYaml;
-import '../../test/utils/package_root.dart' as pkgRoot;
+import '../../test/utils/package_root.dart' as pkg_root;
main() async {
await GeneratedContent.generateAll(
- normalize(join(pkgRoot.packageRoot, 'analyzer')), allTargets);
+ normalize(join(pkg_root.packageRoot, 'analyzer')), allTargets);
}
List<GeneratedContent> get allTargets {
Map<dynamic, dynamic> experimentsYaml = loadYaml(new File(join(
- normalize(join(pkgRoot.packageRoot, '../tools')),
+ normalize(join(pkg_root.packageRoot, '../tools')),
'experimental_features.yaml'))
.readAsStringSync());
diff --git a/pkg/analyzer/tool/messages/generate.dart b/pkg/analyzer/tool/messages/generate.dart
index e35adc8..1a20e92 100644
--- a/pkg/analyzer/tool/messages/generate.dart
+++ b/pkg/analyzer/tool/messages/generate.dart
@@ -14,18 +14,18 @@
*/
import 'dart:io';
-import 'package:analyzer/error/error.dart';
import 'package:analysis_tool/tools.dart';
+import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:front_end/src/fasta/scanner.dart';
import 'package:path/path.dart';
import 'package:yaml/yaml.dart' show loadYaml;
-import '../../test/utils/package_root.dart' as pkgRoot;
+import '../../test/utils/package_root.dart' as pkg_root;
main() async {
- String analyzerPkgPath = normalize(join(pkgRoot.packageRoot, 'analyzer'));
- String frontEndPkgPath = normalize(join(pkgRoot.packageRoot, 'front_end'));
+ String analyzerPkgPath = normalize(join(pkg_root.packageRoot, 'analyzer'));
+ String frontEndPkgPath = normalize(join(pkg_root.packageRoot, 'front_end'));
Map<dynamic, dynamic> messagesYaml = loadYaml(
new File(join(frontEndPkgPath, 'messages.yaml')).readAsStringSync());
@@ -179,6 +179,10 @@
if (tip is String) {
out.writeln(',correction: "$tip"');
}
+ final hasPublishedDocs = entry['hasPublishedDocs'];
+ if (hasPublishedDocs is bool && hasPublishedDocs) {
+ out.writeln(',hasPublishedDocs:true');
+ }
out.writeln(');');
}
}
diff --git a/pkg/analyzer/tool/summary/dump_inferred_types.dart b/pkg/analyzer/tool/summary/dump_inferred_types.dart
deleted file mode 100644
index ee6bb64..0000000
--- a/pkg/analyzer/tool/summary/dump_inferred_types.dart
+++ /dev/null
@@ -1,341 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:convert';
-
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/summary/base.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/link.dart';
-import 'package:analyzer/src/summary/package_bundle_reader.dart';
-
-/**
- * Collect the inferred types from all the summary files listed in [args] and
- * print them in alphabetical order.
- */
-main(List<String> args) {
- SummaryDataStore summaryDataStore = new SummaryDataStore(args);
- InferredTypeCollector collector = new InferredTypeCollector(
- (String uri) => summaryDataStore.linkedMap[uri],
- (String uri) => summaryDataStore.unlinkedMap[uri]);
- collector.visitSummaryDataStore(summaryDataStore);
- collector.dumpCollectedTypes();
-}
-
-/**
- * Visitor class that visits the contents of a summary file and collects the
- * inferred types in it.
- */
-class InferredTypeCollector {
- UnlinkedUnit unlinkedUnit;
- LinkedUnit linkedUnit;
- CompilationUnitElementForLink unitForLink;
- final Map<String, String> inferredTypes = <String, String>{};
- List<String> typeParamsInScope = <String>[];
- final Linker _linker;
-
- InferredTypeCollector(
- GetDependencyCallback getDependency, GetUnitCallback getUnit)
- : _linker =
- new Linker({}, getDependency, getUnit, null, AnalysisOptionsImpl());
-
- /**
- * If an inferred type exists matching the given [slot], record that it is the
- * type of the entity reachable via [path].
- */
- void collectInferredType(int slot, String path) {
- for (EntityRef type in linkedUnit.types) {
- if (type.slot == slot) {
- inferredTypes[path] = formatType(type);
- return;
- }
- }
- }
-
- /**
- * Collect the inferred type in summary object [obj] (if any), which is
- * reachable via [path].
- *
- * This method may modify [properties] in order to affect how sub-elements
- * are visited.
- */
- void collectInferredTypes(
- SummaryClass obj, Map<String, Object> properties, String path) {
- if (obj is UnlinkedVariable) {
- collectInferredType(obj.inferredTypeSlot, path);
- // As a temporary measure, prevent recursion into the variable's
- // initializer, since AST-based type inference doesn't infer its type
- // correctly yet. TODO(paulberry): fix.
- properties.remove('initializer');
- } else if (obj is UnlinkedExecutable) {
- collectInferredType(obj.inferredReturnTypeSlot, path);
- // As a temporary measure, prevent recursion into the executable's local
- // variables and local functions, since AST-based type inference doesn't
- // infer locals correctly yet. TODO(paulberry): fix if necessary.
- properties.remove('localFunctions');
- properties.remove('localVariables');
- } else if (obj is UnlinkedParam) {
- collectInferredType(obj.inferredTypeSlot, path);
- // As a temporary measure, prevent recursion into the parameter's
- // initializer, since AST-based type inference doesn't infer its type
- // correctly yet. TODO(paulberry): fix.
- properties.remove('initializer');
- }
- }
-
- /**
- * Print out all the inferred types collected so far, in alphabetical order.
- */
- void dumpCollectedTypes() {
- print('Collected types (${inferredTypes.length}):');
- List<String> paths = inferredTypes.keys.toList();
- paths.sort();
- for (String path in paths) {
- print('$path -> ${inferredTypes[path]}');
- }
- }
-
- /**
- * Format the given [type] as a string. Unlike the type's [toString] method,
- * this formats types using their complete URI to avoid ambiguity.
- */
- String formatDartType(DartType type) {
- if (type is FunctionType) {
- List<String> argStrings =
- type.normalParameterTypes.map(formatDartType).toList();
- List<DartType> optionalParameterTypes = type.optionalParameterTypes;
- if (optionalParameterTypes.isNotEmpty) {
- List<String> optionalArgStrings =
- optionalParameterTypes.map(formatDartType).toList();
- argStrings.add('[${optionalArgStrings.join(', ')}]');
- }
- Map<String, DartType> namedParameterTypes = type.namedParameterTypes;
- if (namedParameterTypes.isNotEmpty) {
- List<String> namedArgStrings = <String>[];
- namedParameterTypes.forEach((String name, DartType type) {
- namedArgStrings.add('$name: ${formatDartType(type)}');
- });
- argStrings.add('{${namedArgStrings.join(', ')}}');
- }
- return '(${argStrings.join(', ')}) → ${formatDartType(type.returnType)}';
- } else if (type is InterfaceType) {
- if (type.typeArguments.isNotEmpty) {
- // TODO(paulberry): implement.
- throw new UnimplementedError('type args');
- }
- return formatElement(type.element);
- } else if (type is DynamicTypeImpl) {
- return type.toString();
- } else {
- // TODO(paulberry): implement.
- throw new UnimplementedError(
- "Don't know how to format type of type ${type.runtimeType}");
- }
- }
-
- /**
- * Format the given [element] as a string, assuming it represents a type.
- * Unlike the element's [toString] method, this formats elements using their
- * complete URI to avoid ambiguity.
- */
- String formatElement(Element element) {
- if (element is ClassElementForLink_Class ||
- element is MethodElementForLink ||
- element is ClassElementForLink_Enum ||
- element is SpecialTypeElementForLink ||
- element is FunctionTypeAliasElementForLink ||
- element is TopLevelFunctionElementForLink) {
- return element.toString();
- } else if (element is FunctionElementForLink_Local_NonSynthetic) {
- return formatDartType(element.type);
- } else if (element is UndefinedElementForLink) {
- return '???';
- } else {
- throw new UnimplementedError(
- "Don't know how to format reference of type ${element.runtimeType}");
- }
- }
-
- /**
- * Interpret the given [param] as a parameter in a synthetic typedef, and
- * format it as a string.
- */
- String formatParam(UnlinkedParam param) {
- if (param.isFunctionTyped) {
- // TODO(paulberry): fix this case.
- return 'BAD(${json.encode(param)})';
- }
- String result;
- if (param.type != null) {
- result = '${formatType(param.type)} ${param.name}';
- } else {
- result = param.name;
- }
- if (param.kind == UnlinkedParamKind.optionalNamed) {
- result = '{$result}';
- } else if (param.kind == UnlinkedParamKind.optionalPositional) {
- result = '[$result]';
- }
- return result;
- }
-
- /**
- * Convert the reference with index [index] into a string. If [typeOf] is
- * `true`, the reference is being used in the context of naming a type, so
- * if the entity being referenced is not a type, it will be enclosed in
- * `typeof()` for clarity.
- */
- String formatReference(int index, {bool typeOf: false}) {
- ReferenceableElementForLink element = unitForLink.resolveRef(index);
- return formatElement(element);
- }
-
- /**
- * Interpret the given [entityRef] as a reference to a type, and format it as
- * a string.
- */
- String formatType(EntityRef entityRef) {
- List<int> implicitFunctionTypeIndices =
- entityRef.implicitFunctionTypeIndices;
- if (entityRef.syntheticReturnType != null) {
- String params = entityRef.syntheticParams.map(formatParam).join(', ');
- String retType = formatType(entityRef.syntheticReturnType);
- return '($params) -> $retType';
- }
- if (entityRef.paramReference != 0) {
- return typeParamsInScope[
- typeParamsInScope.length - entityRef.paramReference];
- }
- String result = formatReference(entityRef.reference, typeOf: true);
- List<EntityRef> typeArguments = entityRef.typeArguments.toList();
- while (typeArguments.isNotEmpty && isDynamic(typeArguments.last)) {
- typeArguments.removeLast();
- }
- if (typeArguments.isNotEmpty) {
- result += '<${typeArguments.map(formatType).join(', ')}>';
- }
- if (implicitFunctionTypeIndices.isNotEmpty) {
- result =
- 'parameterOf($result, ${implicitFunctionTypeIndices.join(', ')})';
- }
- return result;
- }
-
- /**
- * Determine if the given [entityRef] represents the pseudo-type `dynamic`.
- */
- bool isDynamic(EntityRef entityRef) {
- if (entityRef.syntheticReturnType != null ||
- entityRef.paramReference != 0) {
- return false;
- }
- return formatReference(entityRef.reference, typeOf: true) == 'dynamic';
- }
-
- /**
- * Collect all the inferred types contained in [obj], which is reachable via
- * [path]. [properties] is the result of calling `obj.toMap()`, and may be
- * modified before returning.
- */
- void visit(SummaryClass obj, Map<String, Object> properties, String path) {
- List<String> oldTypeParamsInScope = typeParamsInScope;
- Object newTypeParams = properties['typeParameters'];
- if (newTypeParams is List && newTypeParams.isNotEmpty) {
- typeParamsInScope = typeParamsInScope.toList();
- for (Object typeParam in newTypeParams) {
- if (typeParam is UnlinkedTypeParam) {
- typeParamsInScope.add(typeParam.name);
- } else {
- throw new StateError(
- 'Unexpected type param type: ${typeParam.runtimeType}');
- }
- }
- }
- collectInferredTypes(obj, properties, path);
- properties.forEach((String key, Object value) {
- if (value is SummaryClass) {
- visit(value, value.toMap(), '$path.$key');
- } else if (value is List) {
- for (int i = 0; i < value.length; i++) {
- Object item = value[i];
- if (item is SummaryClass) {
- Map<String, Object> itemProperties = item.toMap();
- String indexOrName = itemProperties['name'] ?? i.toString();
- visit(item, itemProperties, '$path.$key[$indexOrName]');
- }
- }
- }
- });
- typeParamsInScope = oldTypeParamsInScope;
- }
-
- /**
- * Collect all the inferred types contained in [summaryDataStore].
- */
- void visitSummaryDataStore(SummaryDataStore summaryDataStore) {
- // Figure out which unlinked units are a part of another library so we won't
- // visit them redundantly.
- Set<String> partOfUris = new Set<String>();
- summaryDataStore.unlinkedMap
- .forEach((String unitUriString, UnlinkedUnit unlinkedUnit) {
- Uri unitUri = Uri.parse(unitUriString);
- for (String relativePartUriString in unlinkedUnit.publicNamespace.parts) {
- partOfUris.add(
- resolveRelativeUri(unitUri, Uri.parse(relativePartUriString))
- .toString());
- }
- });
- summaryDataStore.linkedMap
- .forEach((String libraryUriString, LinkedLibrary linkedLibrary) {
- if (partOfUris.contains(libraryUriString)) {
- return;
- }
- if (libraryUriString.startsWith('dart:')) {
- // Don't bother dumping inferred types from the SDK.
- return;
- }
- Uri libraryUri = Uri.parse(libraryUriString);
- UnlinkedUnit definingUnlinkedUnit =
- summaryDataStore.unlinkedMap[libraryUriString];
- if (definingUnlinkedUnit != null) {
- visitUnit(
- definingUnlinkedUnit, linkedLibrary.units[0], libraryUriString, 0);
- for (int i = 0;
- i < definingUnlinkedUnit.publicNamespace.parts.length;
- i++) {
- Uri relativePartUri =
- Uri.parse(definingUnlinkedUnit.publicNamespace.parts[i]);
- String unitUriString =
- resolveRelativeUri(libraryUri, relativePartUri).toString();
- UnlinkedUnit unlinkedUnit =
- summaryDataStore.unlinkedMap[unitUriString];
- if (unlinkedUnit != null) {
- visitUnit(unlinkedUnit, linkedLibrary.units[i + 1],
- libraryUriString, i + 1);
- }
- }
- }
- });
- }
-
- /**
- * Collect all the inferred types contained in the compilation unit described
- * by [unlinkedUnit] and [linkedUnit], which has URI [libraryUriString].
- */
- void visitUnit(UnlinkedUnit unlinkedUnit, LinkedUnit linkedUnit,
- String libraryUriString, int unitNum) {
- this.unlinkedUnit = unlinkedUnit;
- this.linkedUnit = linkedUnit;
- this.unitForLink =
- _linker.getLibrary(Uri.parse(libraryUriString)).units[unitNum];
- visit(unlinkedUnit, unlinkedUnit.toMap(), libraryUriString);
- this.unlinkedUnit = null;
- this.linkedUnit = null;
- this.unitForLink = null;
- }
-}
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index 5d6ad0b..dd44327 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -22,7 +22,7 @@
import 'package:front_end/src/fasta/scanner.dart';
import 'package:front_end/src/scanner/token.dart' show Token;
-import 'idl_model.dart' as idlModel;
+import 'idl_model.dart' as idl_model;
import 'mini_ast.dart';
main(List<String> args) async {
@@ -59,7 +59,7 @@
"throw new UnimplementedError('attempt to access deprecated field')";
/// Semantic model of the "IDL" input file.
- final idlModel.Idl _idl;
+ final idl_model.Idl _idl;
/// Buffer in which generated code is accumulated.
final StringBuffer _outBuffer;
@@ -74,11 +74,11 @@
///
/// If [builder] is `true`, the returned type should be appropriate for use in
/// a builder class.
- String defaultValue(idlModel.FieldType type, bool builder) {
+ String defaultValue(idl_model.FieldType type, bool builder) {
if (type.isList) {
if (builder) {
- idlModel.FieldType elementType =
- new idlModel.FieldType(type.typeName, false);
+ idl_model.FieldType elementType =
+ new idl_model.FieldType(type.typeName, false);
return '<${encodedType(elementType)}>[]';
} else {
return 'const <${idlPrefix(type.typeName)}>[]';
@@ -101,7 +101,7 @@
/// Generate a string representing the Dart type which should be used to
/// represent [type] while building a serialized data structure.
- String encodedType(idlModel.FieldType type) {
+ String encodedType(idl_model.FieldType type) {
String typeStr;
if (_idl.classes.containsKey(type.typeName)) {
typeStr = '${type.typeName}Builder';
@@ -161,7 +161,7 @@
return json.encode(s);
}
- List<String> _computeVariants(idlModel.ClassDeclaration cls) {
+ List<String> _computeVariants(idl_model.ClassDeclaration cls) {
var allVariants = Set<String>();
for (var field in cls.fields) {
var logicalFields = field.logicalProperties?.values;
@@ -175,8 +175,8 @@
}
String _variantAssertStatement(
- idlModel.ClassDeclaration class_,
- idlModel.LogicalProperty property,
+ idl_model.ClassDeclaration class_,
+ idl_model.LogicalProperty property,
) {
var assertCondition = property.variants
?.map((key) => '${class_.variantField} == idl.$key')
@@ -186,10 +186,10 @@
}
class _BuilderGenerator extends _BaseGenerator {
- final idlModel.ClassDeclaration cls;
+ final idl_model.ClassDeclaration cls;
List<String> constructorParams = <String>[];
- _BuilderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+ _BuilderGenerator(idl_model.Idl idl, StringBuffer outBuffer, this.cls)
: super(idl, outBuffer);
String get builderName => name + 'Builder';
@@ -218,7 +218,7 @@
out('/// Accumulate non-[informative] data into [signature].');
out('void collectApiSignature(api_sig.ApiSignature signature) {');
- void writeField(String name, idlModel.FieldType type, bool isInformative) {
+ void writeField(String name, idl_model.FieldType type, bool isInformative) {
if (isInformative) {
return;
}
@@ -244,8 +244,8 @@
}
indent(() {
- List<idlModel.FieldDeclaration> sortedFields = cls.fields.toList()
- ..sort((idlModel.FieldDeclaration a, idlModel.FieldDeclaration b) =>
+ List<idl_model.FieldDeclaration> sortedFields = cls.fields.toList()
+ ..sort((idl_model.FieldDeclaration a, idl_model.FieldDeclaration b) =>
a.id.compareTo(b.id));
if (cls.variantField != null) {
var firstVariant = true;
@@ -278,7 +278,7 @@
out('}');
}
} else {
- for (idlModel.FieldDeclaration field in sortedFields) {
+ for (idl_model.FieldDeclaration field in sortedFields) {
writeField('_${field.name}', field.type, field.isInformative);
}
}
@@ -326,9 +326,9 @@
}
} else {
out('$builderName({${constructorParams.join(', ')}})');
- List<idlModel.FieldDeclaration> fields = cls.fields.toList();
+ List<idl_model.FieldDeclaration> fields = cls.fields.toList();
for (int i = 0; i < fields.length; i++) {
- idlModel.FieldDeclaration field = fields[i];
+ idl_model.FieldDeclaration field = fields[i];
String prefix = i == 0 ? ' : ' : ' ';
String suffix = i == fields.length - 1 ? ';' : ',';
out('${prefix}_${field.name} = ${field.name}$suffix');
@@ -337,9 +337,9 @@
}
void _generateFields() {
- for (idlModel.FieldDeclaration field in cls.fields) {
+ for (idl_model.FieldDeclaration field in cls.fields) {
String fieldName = field.name;
- idlModel.FieldType type = field.type;
+ idl_model.FieldType type = field.type;
String typeStr = encodedType(type);
out('$typeStr _$fieldName;');
}
@@ -350,8 +350,8 @@
out('fb.Offset finish(fb.Builder fbBuilder) {');
indent(() {
// Write objects and remember Offset(s).
- for (idlModel.FieldDeclaration field in cls.fields) {
- idlModel.FieldType fieldType = field.type;
+ for (idl_model.FieldDeclaration field in cls.fields) {
+ idl_model.FieldType fieldType = field.type;
String offsetName = 'offset_' + field.name;
if (fieldType.isList ||
fieldType.typeName == 'String' ||
@@ -360,8 +360,8 @@
}
}
- for (idlModel.FieldDeclaration field in cls.fields) {
- idlModel.FieldType fieldType = field.type;
+ for (idl_model.FieldDeclaration field in cls.fields) {
+ idl_model.FieldType fieldType = field.type;
String valueName = '_' + field.name;
String offsetName = 'offset_' + field.name;
String condition;
@@ -408,9 +408,9 @@
// Write the table.
out('fbBuilder.startTable();');
- for (idlModel.FieldDeclaration field in cls.fields) {
+ for (idl_model.FieldDeclaration field in cls.fields) {
int index = field.id;
- idlModel.FieldType fieldType = field.type;
+ idl_model.FieldType fieldType = field.type;
String valueName = '_' + field.name;
String condition = '$valueName != null';
String writeCode;
@@ -452,7 +452,7 @@
out('/// Flush [informative] data recursively.');
out('void flushInformative() {');
- void writeField(String name, idlModel.FieldType type, bool isInformative) {
+ void writeField(String name, idl_model.FieldType type, bool isInformative) {
if (isInformative) {
out('$name = null;');
} else if (_idl.classes.containsKey(type.typeName)) {
@@ -496,7 +496,7 @@
out('}');
}
} else {
- for (idlModel.FieldDeclaration field in cls.fields) {
+ for (idl_model.FieldDeclaration field in cls.fields) {
writeField('_${field.name}', field.type, field.isInformative);
}
}
@@ -505,9 +505,9 @@
}
void _generateGettersSetters() {
- for (idlModel.FieldDeclaration field in cls.allFields) {
+ for (idl_model.FieldDeclaration field in cls.allFields) {
String fieldName = field.name;
- idlModel.FieldType fieldType = field.type;
+ idl_model.FieldType fieldType = field.type;
String typeStr = encodedType(fieldType);
String def = defaultValue(fieldType, true);
String defSuffix = def == null ? '' : ' ??= $def';
@@ -562,7 +562,7 @@
}
}
- void _generateNonNegativeInt(idlModel.FieldType fieldType) {
+ void _generateNonNegativeInt(idl_model.FieldType fieldType) {
if (fieldType.typeName == 'int') {
if (!fieldType.isList) {
out('assert(value == null || value >= 0);');
@@ -640,7 +640,7 @@
final StringBuffer _outBuffer = new StringBuffer();
/// Semantic model of the "IDL" input file.
- idlModel.Idl _idl;
+ idl_model.Idl _idl;
_CodeGenerator(String idlPath) {
// Parse the input "IDL" file.
@@ -659,7 +659,7 @@
/// Perform basic sanity checking of the IDL (over and above that done by
/// [extractIdl]).
void checkIdl() {
- _idl.classes.forEach((String name, idlModel.ClassDeclaration cls) {
+ _idl.classes.forEach((String name, idl_model.ClassDeclaration cls) {
if (cls.fileIdentifier != null) {
if (cls.fileIdentifier.length != 4) {
throw new Exception('$name: file identifier must be 4 characters');
@@ -672,9 +672,9 @@
}
}
Map<int, String> idsUsed = <int, String>{};
- for (idlModel.FieldDeclaration field in cls.allFields) {
+ for (idl_model.FieldDeclaration field in cls.allFields) {
String fieldName = field.name;
- idlModel.FieldType type = field.type;
+ idl_model.FieldType type = field.type;
if (type.isList) {
if (_idl.classes.containsKey(type.typeName)) {
// List of classes is ok
@@ -710,7 +710,7 @@
/// Process the AST in [idlParsed] and store the resulting semantic model in
/// [_idl]. Also perform some error checking.
void extractIdl(CompilationUnit idlParsed) {
- _idl = new idlModel.Idl();
+ _idl = new idl_model.Idl();
for (CompilationUnitMember decl in idlParsed.declarations) {
if (decl is ClassDeclaration) {
bool isTopLevel = false;
@@ -759,7 +759,7 @@
}
}
}
- idlModel.ClassDeclaration cls = new idlModel.ClassDeclaration(
+ idl_model.ClassDeclaration cls = new idl_model.ClassDeclaration(
documentation: _getNodeDoc(decl),
name: clsName,
isTopLevel: isTopLevel,
@@ -786,13 +786,13 @@
}
} else if (decl is EnumDeclaration) {
String doc = _getNodeDoc(decl);
- idlModel.EnumDeclaration enm =
- new idlModel.EnumDeclaration(doc, decl.name);
+ idl_model.EnumDeclaration enm =
+ new idl_model.EnumDeclaration(doc, decl.name);
_idl.enums[enm.name] = enm;
for (EnumConstantDeclaration constDecl in decl.constants) {
String doc = _getNodeDoc(constDecl);
enm.values
- .add(new idlModel.EnumValueDeclaration(doc, constDecl.name));
+ .add(new idl_model.EnumValueDeclaration(doc, constDecl.name));
}
} else {
throw new Exception('Unexpected declaration `$decl`');
@@ -818,11 +818,11 @@
out();
out("import 'idl.dart' as idl;");
out();
- for (idlModel.EnumDeclaration enum_ in _idl.enums.values) {
+ for (idl_model.EnumDeclaration enum_ in _idl.enums.values) {
_EnumReaderGenerator(_idl, _outBuffer, enum_).generate();
out();
}
- for (idlModel.ClassDeclaration cls in _idl.classes.values) {
+ for (idl_model.ClassDeclaration cls in _idl.classes.values) {
if (!cls.isDeprecated) {
_BuilderGenerator(_idl, _outBuffer, cls).generate();
out();
@@ -860,7 +860,7 @@
}
void _addFieldForGetter(
- idlModel.ClassDeclaration cls,
+ idl_model.ClassDeclaration cls,
MethodDeclaration getter,
) {
var desc = '${cls.name}.${getter.name}';
@@ -964,10 +964,10 @@
throw new Exception('Missing @id annotation ($desc)');
}
- var fieldType = new idlModel.FieldType(type.name, isList);
+ var fieldType = new idl_model.FieldType(type.name, isList);
String name = getter.name;
- Map<String, idlModel.LogicalProperty> logicalProperties;
+ Map<String, idl_model.LogicalProperty> logicalProperties;
if (variants != null) {
var fieldsWithSameId =
cls.allFields.where((field) => field.id == id).toList();
@@ -999,7 +999,7 @@
);
}
- map[getter.name] = idlModel.LogicalProperty(
+ map[getter.name] = idl_model.LogicalProperty(
isDeprecated: isDeprecated,
isInformative: isInformative,
variants: variants,
@@ -1007,8 +1007,8 @@
return;
} else {
name = 'variantField_$id';
- logicalProperties = <String, idlModel.LogicalProperty>{
- getter.name: idlModel.LogicalProperty(
+ logicalProperties = <String, idl_model.LogicalProperty>{
+ getter.name: idl_model.LogicalProperty(
isDeprecated: isDeprecated,
isInformative: isInformative,
variants: variants,
@@ -1018,7 +1018,7 @@
}
cls.allFields.add(
- idlModel.FieldDeclaration(
+ idl_model.FieldDeclaration(
documentation: _getNodeDoc(getter),
name: name,
type: fieldType,
@@ -1055,9 +1055,9 @@
}
class _EnumReaderGenerator extends _BaseGenerator {
- final idlModel.EnumDeclaration enum_;
+ final idl_model.EnumDeclaration enum_;
- _EnumReaderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.enum_)
+ _EnumReaderGenerator(idl_model.Idl idl, StringBuffer outBuffer, this.enum_)
: super(idl, outBuffer);
void generate() {
@@ -1085,17 +1085,17 @@
}
class _FlatBufferSchemaGenerator extends _BaseGenerator {
- _FlatBufferSchemaGenerator(idlModel.Idl idl, StringBuffer outBuffer)
+ _FlatBufferSchemaGenerator(idl_model.Idl idl, StringBuffer outBuffer)
: super(idl, outBuffer);
void generate() {
- for (idlModel.EnumDeclaration enm in _idl.enums.values) {
+ for (idl_model.EnumDeclaration enm in _idl.enums.values) {
out();
outDoc(enm.documentation);
out('enum ${enm.name} : byte {');
indent(() {
for (int i = 0; i < enm.values.length; i++) {
- idlModel.EnumValueDeclaration value = enm.values[i];
+ idl_model.EnumValueDeclaration value = enm.values[i];
if (i != 0) {
out();
}
@@ -1106,13 +1106,13 @@
});
out('}');
}
- for (idlModel.ClassDeclaration cls in _idl.classes.values) {
+ for (idl_model.ClassDeclaration cls in _idl.classes.values) {
out();
outDoc(cls.documentation);
out('table ${cls.name} {');
indent(() {
for (int i = 0; i < cls.allFields.length; i++) {
- idlModel.FieldDeclaration field = cls.allFields[i];
+ idl_model.FieldDeclaration field = cls.allFields[i];
if (i != 0) {
out();
}
@@ -1131,7 +1131,7 @@
// Standard flatbuffers only support one root type. We support multiple
// root types. For now work around this by forcing PackageBundle to be the
// root type. TODO(paulberry): come up with a better solution.
- idlModel.ClassDeclaration rootType = _idl.classes['PackageBundle'];
+ idl_model.ClassDeclaration rootType = _idl.classes['PackageBundle'];
out('root_type ${rootType.name};');
if (rootType.fileIdentifier != null) {
out();
@@ -1141,7 +1141,7 @@
/// Generate a string representing the FlatBuffer schema type which should be
/// used to represent [type].
- String _fbsType(idlModel.FieldType type) {
+ String _fbsType(idl_model.FieldType type) {
String typeStr;
switch (type.typeName) {
case 'bool':
@@ -1175,9 +1175,9 @@
}
class _ImplGenerator extends _BaseGenerator {
- final idlModel.ClassDeclaration cls;
+ final idl_model.ClassDeclaration cls;
- _ImplGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+ _ImplGenerator(idl_model.Idl idl, StringBuffer outBuffer, this.cls)
: super(idl, outBuffer);
void generate() {
@@ -1193,16 +1193,16 @@
out('$implName(this._bc, this._bcOffset);');
out();
// Write cache fields.
- for (idlModel.FieldDeclaration field in cls.fields) {
+ for (idl_model.FieldDeclaration field in cls.fields) {
String returnType = _dartType(field.type);
String fieldName = field.name;
out('$returnType _$fieldName;');
}
// Write getters.
- for (idlModel.FieldDeclaration field in cls.allFields) {
+ for (idl_model.FieldDeclaration field in cls.allFields) {
int index = field.id;
String fieldName = field.name;
- idlModel.FieldType type = field.type;
+ idl_model.FieldType type = field.type;
String typeName = type.typeName;
// Prepare "readCode" + "def"
String readCode;
@@ -1280,7 +1280,7 @@
/// Generate a string representing the Dart type which should be used to
/// represent [type] when deserialized.
- String _dartType(idlModel.FieldType type) {
+ String _dartType(idl_model.FieldType type) {
String baseType = idlPrefix(type.typeName);
if (type.isList) {
return 'List<$baseType>';
@@ -1291,9 +1291,9 @@
}
class _MixinGenerator extends _BaseGenerator {
- final idlModel.ClassDeclaration cls;
+ final idl_model.ClassDeclaration cls;
- _MixinGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+ _MixinGenerator(idl_model.Idl idl, StringBuffer outBuffer, this.cls)
: super(idl, outBuffer);
void generate() {
@@ -1301,7 +1301,7 @@
String mixinName = '_${name}Mixin';
out('abstract class $mixinName implements ${idlPrefix(name)} {');
indent(() {
- String jsonCondition(idlModel.FieldType type, String name) {
+ String jsonCondition(idl_model.FieldType type, String name) {
if (type.isList) {
return '$name.isNotEmpty';
} else {
@@ -1309,7 +1309,7 @@
}
}
- String jsonStore(idlModel.FieldType type, String name) {
+ String jsonStore(idl_model.FieldType type, String name) {
_StringToString convertItem;
if (_idl.classes.containsKey(type.typeName)) {
convertItem = (String name) => '$name.toJson()';
@@ -1341,7 +1341,7 @@
if (cls.variantField != null) {
indent(() {
- for (idlModel.FieldDeclaration field in cls.fields) {
+ for (idl_model.FieldDeclaration field in cls.fields) {
if (field.logicalProperties == null) {
var condition = jsonCondition(field.type, field.name);
var storeField = jsonStore(field.type, field.name);
@@ -1351,7 +1351,7 @@
for (var variant in _computeVariants(cls)) {
out('if (${cls.variantField} == idl.$variant) {');
indent(() {
- for (idlModel.FieldDeclaration field in cls.fields) {
+ for (idl_model.FieldDeclaration field in cls.fields) {
var logicalProperties = field.logicalProperties;
if (logicalProperties != null) {
for (var logicalName in logicalProperties.keys) {
@@ -1370,7 +1370,7 @@
});
} else {
indent(() {
- for (idlModel.FieldDeclaration field in cls.fields) {
+ for (idl_model.FieldDeclaration field in cls.fields) {
String condition = jsonCondition(field.type, field.name);
String storeField = jsonStore(field.type, field.name);
out('if ($condition) $storeField;');
@@ -1391,7 +1391,7 @@
out('if (${cls.variantField} == idl.$variant) {');
indent(() {
out('return {');
- for (idlModel.FieldDeclaration field in cls.fields) {
+ for (idl_model.FieldDeclaration field in cls.fields) {
if (field.logicalProperties != null) {
for (var logicalName in field.logicalProperties.keys) {
var logicalProperty = field.logicalProperties[logicalName];
@@ -1413,7 +1413,7 @@
} else {
out('Map<String, Object> toMap() => {');
indent(() {
- for (idlModel.FieldDeclaration field in cls.fields) {
+ for (idl_model.FieldDeclaration field in cls.fields) {
String fieldName = field.name;
out('${quoted(fieldName)}: $fieldName,');
}
@@ -1430,9 +1430,9 @@
}
class _ReaderGenerator extends _BaseGenerator {
- final idlModel.ClassDeclaration cls;
+ final idl_model.ClassDeclaration cls;
- _ReaderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+ _ReaderGenerator(idl_model.Idl idl, StringBuffer outBuffer, this.cls)
: super(idl, outBuffer);
void generateReader() {
diff --git a/pkg/analyzer_cli/analysis_options.yaml b/pkg/analyzer_cli/analysis_options.yaml
index 4341996..87f2d3b 100644
--- a/pkg/analyzer_cli/analysis_options.yaml
+++ b/pkg/analyzer_cli/analysis_options.yaml
@@ -1,6 +1,9 @@
analyzer:
strong-mode:
implicit-casts: false
+ errors:
+ # Increase the severity of the unused_import hint.
+ unused_import: warning
exclude:
- test/data/**
linter:
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index a4363fc..57bedb4 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -27,9 +27,7 @@
import 'package:analyzer/src/source/source_resource.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/link.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
import 'package:analyzer/src/summary2/link.dart' as summary2;
@@ -193,7 +191,6 @@
AnalysisDriver analysisDriver;
PackageBundleAssembler assembler;
- final Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
final Map<String, ParsedUnitResult> inputParsedUnitResults = {};
summary2.LinkedElementFactory elementFactory;
@@ -270,27 +267,12 @@
// Prepare all unlinked units.
await logger.runAsync('Prepare unlinked units', () async {
for (var src in explicitSources) {
- await _prepareUnlinkedUnit('${src.uri}');
+ await _prepareUnit('${src.uri}');
}
});
// Build and assemble linked libraries.
- if (AnalysisDriver.useSummary2) {
- _computeLinkedLibraries2();
- } else {
- if (!options.buildSummaryOnlyUnlinked) {
- // Prepare URIs of unlinked units that should be linked.
- var unlinkedUris = new Set<String>();
- for (var bundle in unlinkedBundles) {
- unlinkedUris.addAll(bundle.unlinkedUnitUris);
- }
- for (var src in explicitSources) {
- unlinkedUris.add('${src.uri}');
- }
- // Perform linking.
- _computeLinkedLibraries(unlinkedUris);
- }
- }
+ _computeLinkedLibraries2();
// Write the whole package bundle.
PackageBundleBuilder bundle = assembler.assemble();
@@ -332,43 +314,6 @@
}
/**
- * Compute linked libraries for the given [libraryUris] using the linked
- * libraries of the [summaryDataStore] and unlinked units in [uriToUnit], and
- * add them to the [assembler].
- */
- void _computeLinkedLibraries(Set<String> libraryUris) {
- logger.run('Link output summary', () {
- void trackDependency(String absoluteUri) {
- if (dependencyTracker != null) {
- var summaryUri = summaryDataStore.uriToSummaryPath[absoluteUri];
- if (summaryUri != null) {
- dependencyTracker.record(summaryUri);
- }
- }
- }
-
- LinkedLibrary getDependency(String absoluteUri) {
- trackDependency(absoluteUri);
- return summaryDataStore.linkedMap[absoluteUri];
- }
-
- UnlinkedUnit getUnit(String absoluteUri) {
- trackDependency(absoluteUri);
- return summaryDataStore.unlinkedMap[absoluteUri] ??
- uriToUnit[absoluteUri];
- }
-
- Map<String, LinkedLibraryBuilder> linkResult = link(
- libraryUris,
- getDependency,
- getUnit,
- analysisDriver.declaredVariables,
- analysisOptions);
- linkResult.forEach(assembler.addLinkedLibrary);
- });
- }
-
- /**
* Use [elementFactory] filled with input summaries, and link prepared
* [inputParsedUnitResults] to produce linked libraries in [assembler].
*/
@@ -539,9 +484,7 @@
declaredVariables = new DeclaredVariables.fromMap(options.definedVariables);
analysisDriver.declaredVariables = declaredVariables;
- if (AnalysisDriver.useSummary2) {
- _createLinkedElementFactory();
- }
+ _createLinkedElementFactory();
scheduler.start();
}
@@ -590,13 +533,11 @@
}
/**
- * Ensure that the [UnlinkedUnit] for [absoluteUri] is available.
+ * Ensure that the parsed unit for [absoluteUri] is available.
*
* If the unit is in the input [summaryDataStore], do nothing.
- *
- * Otherwise compute it and store into the [uriToUnit] and [assembler].
*/
- Future<void> _prepareUnlinkedUnit(String absoluteUri) async {
+ Future<void> _prepareUnit(String absoluteUri) async {
// Maybe an input package contains the source.
if (summaryDataStore.unlinkedMap[absoluteUri] != null) {
return;
@@ -610,13 +551,7 @@
return;
}
var result = await analysisDriver.parseFile(source.fullName);
- if (AnalysisDriver.useSummary2) {
- inputParsedUnitResults[result.path] = result;
- } else {
- UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(result.unit);
- uriToUnit[absoluteUri] = unlinkedUnit;
- assembler.addUnlinkedUnit(source, unlinkedUnit);
- }
+ inputParsedUnitResults[result.path] = result;
}
/**
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 526bc26..931c9ad 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -7,7 +7,6 @@
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/command_line/arguments.dart';
import 'package:analyzer/src/context/builder.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer_cli/src/ansi.dart' as ansi;
@@ -270,23 +269,8 @@
}
if (options.buildSummaryOnlyUnlinked) {
- if (AnalysisDriver.useSummary2) {
- printAndFail('The option --build-summary-only-unlinked can not be used '
- 'together with summary2.');
- return null; // Only reachable in testing.
- }
- if (!options.buildSummaryOnly) {
- printAndFail(
- 'The option --build-summary-only-unlinked can be used only '
- 'together with --build-summary-only.');
- return null; // Only reachable in testing.
- }
- if (options.buildSummaryInputs.isNotEmpty ||
- options.buildSummaryUnlinkedInputs.isNotEmpty) {
- printAndFail('No summaries should be provided in combination with '
- '--build-summary-only-unlinked, they aren\'t needed.');
- return null; // Only reachable in testing.
- }
+ printAndFail('The option --build-summary-only-unlinked is deprecated.');
+ return null; // Only reachable in testing.
}
return options;
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index 705be26..4232985 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/error_processor.dart';
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -489,122 +488,18 @@
PackageBundle bundle =
new PackageBundle.fromBuffer(await output.readAsBytes());
var testFileUri = 'file:///test_file.dart';
- if (AnalysisDriver.useSummary2) {
- var bundle2 = bundle.bundle2;
- expect(_linkedLibraryUriList(bundle2), [testFileUri]);
- expect(
- _linkedLibraryUnitUriList(bundle2, testFileUri),
- [testFileUri],
- );
- } else {
- expect(bundle.unlinkedUnitUris, equals([testFileUri]));
- expect(bundle.linkedLibraryUris, equals([testFileUri]));
- }
+
+ var bundle2 = bundle.bundle2;
+ expect(_linkedLibraryUriList(bundle2), [testFileUri]);
+ expect(
+ _linkedLibraryUnitUriList(bundle2, testFileUri),
+ [testFileUri],
+ );
+
expect(exitCode, 0);
});
}
- test_buildLinked_buildSummaryOutputSemantic() async {
- // All informative data is stored separately when summary2.
- if (AnalysisDriver.useSummary2) {
- return;
- }
-
- await withTempDirAsync((tempDir) async {
- var testDart = path.join(tempDir, 'test.dart');
- var testSumFull = path.join(tempDir, 'test.sum.full');
- var testSumSemantic = path.join(tempDir, 'test.sum.sem');
-
- new File(testDart).writeAsStringSync('var v = 42;');
-
- await _doDrive(testDart, additionalArgs: [
- '--build-summary-only',
- '--build-summary-output=$testSumFull',
- '--build-summary-output-semantic=$testSumSemantic',
- ]);
- expect(exitCode, 0);
-
- // The full summary is produced.
- {
- var file = new File(testSumFull);
- expect(file.existsSync(), isTrue);
- var bytes = file.readAsBytesSync();
- var bundle = new PackageBundle.fromBuffer(bytes);
- var v = bundle.unlinkedUnits[0].variables[0];
- expect(v.name, 'v');
- expect(v.nameOffset, 4);
- }
-
- // The semantic summary is produced.
- {
- var file = new File(testSumSemantic);
- expect(file.existsSync(), isTrue);
- var bytes = file.readAsBytesSync();
- var bundle = new PackageBundle.fromBuffer(bytes);
- var v = bundle.unlinkedUnits[0].variables[0];
- expect(v.name, 'v');
- expect(v.nameOffset, 0);
- }
- });
- }
-
- test_buildLinked_fromUnlinked() async {
- // We don't use unlinked units with summary2.
- if (AnalysisDriver.useSummary2) {
- return;
- }
-
- await withTempDirAsync((tempDir) async {
- var aDart = path.join(tempDir, 'a.dart');
- var bDart = path.join(tempDir, 'b.dart');
-
- var aUri = 'package:aaa/a.dart';
- var bUri = 'package:bbb/b.dart';
-
- var aUnlinked = path.join(tempDir, 'a.unlinked');
- var bUnlinked = path.join(tempDir, 'b.unlinked');
- var abLinked = path.join(tempDir, 'ab.linked');
-
- new File(aDart).writeAsStringSync('var a = 1;');
- new File(bDart).writeAsStringSync('''
-import 'package:aaa/a.dart';
-var b = a;
-''');
-
- Future<void> buildUnlinked(String uri, String path, String output) async {
- await _doDrive(path, uri: uri, additionalArgs: [
- '--build-summary-only',
- '--build-summary-only-unlinked',
- '--build-summary-output=$output'
- ]);
- expect(exitCode, 0);
- expect(new File(output).existsSync(), isTrue);
- }
-
- await buildUnlinked(aUri, aDart, aUnlinked);
- await buildUnlinked(bUri, bDart, bUnlinked);
-
- await new Driver(isTesting: true).start([
- '--dart-sdk',
- _findSdkDirForSummaries(),
- '--build-mode',
- '--build-summary-unlinked-input=$aUnlinked,$bUnlinked',
- '--build-summary-output=$abLinked'
- ]);
- expect(exitCode, 0);
- var bytes = new File(abLinked).readAsBytesSync();
- var bundle = new PackageBundle.fromBuffer(bytes);
-
- // Only linked information.
- expect(bundle.unlinkedUnitUris, isEmpty);
- expect(bundle.linkedLibraryUris, unorderedEquals([aUri, bUri]));
-
- // Strong mode type inference was performed.
- expect(bundle.linkedLibraries[0].units[0].types, isNotEmpty);
- expect(bundle.linkedLibraries[1].units[0].types, isNotEmpty);
- });
- }
-
test_buildLinked_invalidPartUri() async {
await withTempDirAsync((tempDir) async {
var aDart = path.join(tempDir, 'a.dart');
@@ -622,14 +517,9 @@
expect(exitCode, ErrorSeverity.ERROR.ordinal);
var bytes = new File(aSum).readAsBytesSync();
var bundle = new PackageBundle.fromBuffer(bytes);
- if (AnalysisDriver.useSummary2) {
- var bundle2 = bundle.bundle2;
- expect(_linkedLibraryUriList(bundle2), [aUri]);
- expect(_linkedLibraryUnitUriList(bundle2, aUri), [aUri, '']);
- } else {
- expect(bundle.unlinkedUnitUris, equals([aUri]));
- expect(bundle.linkedLibraryUris, equals([aUri]));
- }
+ var bundle2 = bundle.bundle2;
+ expect(_linkedLibraryUriList(bundle2), [aUri]);
+ expect(_linkedLibraryUnitUriList(bundle2, aUri), [aUri, '']);
});
}
@@ -645,31 +535,6 @@
expect(exitCode, 0);
}
- test_buildUnlinked() async {
- // We don't use unlinked units with summary2.
- if (AnalysisDriver.useSummary2) {
- return;
- }
-
- await withTempDirAsync((tempDir) async {
- var outputPath = path.join(tempDir, 'test_file.dart.sum');
- await _doDrive(path.join('data', 'test_file.dart'), additionalArgs: [
- '--build-summary-only',
- '--build-summary-only-unlinked',
- '--build-summary-output=$outputPath'
- ]);
- var output = new File(outputPath);
- expect(output.existsSync(), isTrue);
- PackageBundle bundle =
- new PackageBundle.fromBuffer(await output.readAsBytes());
- var testFileUri = 'file:///test_file.dart';
- expect(bundle.unlinkedUnits.length, 1);
- expect(bundle.unlinkedUnitUris, equals([testFileUri]));
- expect(bundle.linkedLibraryUris, isEmpty);
- expect(exitCode, 0);
- });
- }
-
test_consumeLinked() async {
await withTempDirAsync((tempDir) async {
var aDart = path.join(tempDir, 'a.dart');
@@ -702,14 +567,9 @@
expect(exitCode, 0);
var bytes = new File(aSum).readAsBytesSync();
var bundle = new PackageBundle.fromBuffer(bytes);
- if (AnalysisDriver.useSummary2) {
- var bundle2 = bundle.bundle2;
- expect(_linkedLibraryUriList(bundle2), [aUri]);
- expect(_linkedLibraryUnitUriList(bundle2, aUri), [aUri]);
- } else {
- expect(bundle.unlinkedUnitUris, equals([aUri]));
- expect(bundle.linkedLibraryUris, equals([aUri]));
- }
+ var bundle2 = bundle.bundle2;
+ expect(_linkedLibraryUriList(bundle2), [aUri]);
+ expect(_linkedLibraryUnitUriList(bundle2, aUri), [aUri]);
}
// Analyze package:bbb/b.dart and compute summary.
@@ -721,14 +581,9 @@
expect(exitCode, 0);
var bytes = new File(bSum).readAsBytesSync();
var bundle = new PackageBundle.fromBuffer(bytes);
- if (AnalysisDriver.useSummary2) {
- var bundle2 = bundle.bundle2;
- expect(_linkedLibraryUriList(bundle2), [bUri]);
- expect(_linkedLibraryUnitUriList(bundle2, bUri), [bUri]);
- } else {
- expect(bundle.unlinkedUnitUris, equals([bUri]));
- expect(bundle.linkedLibraryUris, equals([bUri]));
- }
+ var bundle2 = bundle.bundle2;
+ expect(_linkedLibraryUriList(bundle2), [bUri]);
+ expect(_linkedLibraryUnitUriList(bundle2, bUri), [bUri]);
}
// Analyze package:ccc/c.dart and compute summary.
@@ -740,14 +595,9 @@
expect(exitCode, 0);
var bytes = new File(cSum).readAsBytesSync();
var bundle = new PackageBundle.fromBuffer(bytes);
- if (AnalysisDriver.useSummary2) {
- var bundle2 = bundle.bundle2;
- expect(_linkedLibraryUriList(bundle2), [cUri]);
- expect(_linkedLibraryUnitUriList(bundle2, cUri), [cUri]);
- } else {
- expect(bundle.unlinkedUnitUris, equals([cUri]));
- expect(bundle.linkedLibraryUris, equals([cUri]));
- }
+ var bundle2 = bundle.bundle2;
+ expect(_linkedLibraryUriList(bundle2), [cUri]);
+ expect(_linkedLibraryUnitUriList(bundle2, cUri), [cUri]);
}
});
}
@@ -774,47 +624,6 @@
});
}
- test_error_linkedAsUnlinked() async {
- // We don't use unlinked units with summary2.
- if (AnalysisDriver.useSummary2) {
- return;
- }
-
- await withTempDirAsync((tempDir) async {
- var aDart = path.join(tempDir, 'a.dart');
- var bDart = path.join(tempDir, 'b.dart');
-
- var aUri = 'package:aaa/a.dart';
- var bUri = 'package:bbb/b.dart';
-
- var aSum = path.join(tempDir, 'a.sum');
- var bSum = path.join(tempDir, 'b.sum');
-
- new File(aDart).writeAsStringSync('class A {}');
-
- // Build linked a.sum
- await _doDrive(aDart, uri: aUri, additionalArgs: [
- '--build-summary-only',
- '--build-summary-output=$aSum'
- ]);
- expect(new File(aSum).existsSync(), isTrue);
-
- // Try to consume linked a.sum as unlinked.
- try {
- await _doDrive(bDart, uri: bUri, additionalArgs: [
- '--build-summary-unlinked-input=$aSum',
- '--build-summary-output=$bSum'
- ]);
- fail('ArgumentError expected.');
- } on ArgumentError catch (e) {
- expect(
- e.message,
- contains(
- 'Got a linked summary for --build-summary-input-unlinked'));
- }
- });
- }
-
test_error_notUriPipePath() async {
await withTempDirAsync((tempDir) async {
var testDart = path.join(tempDir, 'test.dart');
@@ -826,46 +635,6 @@
});
}
- test_error_unlinkedAsLinked() async {
- // We don't use unlinked units with summary2.
- if (AnalysisDriver.useSummary2) {
- return;
- }
-
- await withTempDirAsync((tempDir) async {
- var aDart = path.join(tempDir, 'a.dart');
- var bDart = path.join(tempDir, 'b.dart');
-
- var aUri = 'package:aaa/a.dart';
- var bUri = 'package:bbb/b.dart';
-
- var aSum = path.join(tempDir, 'a.sum');
- var bSum = path.join(tempDir, 'b.sum');
-
- new File(aDart).writeAsStringSync('class A {}');
-
- // Build unlinked a.sum
- await _doDrive(aDart, uri: aUri, additionalArgs: [
- '--build-summary-only',
- '--build-summary-only-unlinked',
- '--build-summary-output=$aSum'
- ]);
- expect(new File(aSum).existsSync(), isTrue);
-
- // Try to consume unlinked a.sum as linked.
- try {
- await _doDrive(bDart, uri: bUri, additionalArgs: [
- '--build-summary-input=$aSum',
- '--build-summary-output=$bSum'
- ]);
- fail('ArgumentError expected.');
- } on ArgumentError catch (e) {
- expect(e.message,
- contains('Got an unlinked summary for --build-summary-input'));
- }
- });
- }
-
test_fail_whenHasError() async {
await _doDrive(path.join('data', 'file_with_error.dart'));
expect(exitCode, isNot(0));
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index ea5d4d4..040710e 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -7,7 +7,6 @@
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/experiments_impl.dart'
show overrideKnownFeatures;
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer_cli/src/driver.dart';
import 'package:analyzer_cli/src/options.dart';
import 'package:telemetry/telemetry.dart' as telemetry;
@@ -419,19 +418,12 @@
'--build-summary-only-unlinked',
'package:p/foo.dart|/path/to/p/lib/foo.dart'
]);
- if (AnalysisDriver.useSummary2) {
- expect(
- errorStringBuffer.toString(),
- contains(
- 'The option --build-summary-only-unlinked can not be used '
- 'together with summary2.',
- ),
- );
- } else {
- expect(options.buildMode, isTrue);
- expect(options.buildSummaryOnly, isTrue);
- expect(options.buildSummaryOnlyUnlinked, isTrue);
- }
+ expect(
+ errorStringBuffer.toString(),
+ contains(
+ 'The option --build-summary-only-unlinked is deprecated.',
+ ),
+ );
}
test_buildSummaryOutput() {
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index b7b473f..0fe28a95 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -8,7 +8,7 @@
sdk: '>=2.0.0 <3.0.0'
dependencies:
- analyzer: '>=0.35.3 <0.38.0'
+ analyzer: '>=0.35.3 <0.39.0'
charcode: '^1.1.0'
dart_style: '^1.2.0'
html: '>=0.13.1 <0.15.0'
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index 5b4985f..64cba71 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -9,7 +9,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -1238,9 +1237,6 @@
}
test_writeType_function_generic() async {
- // TODO(scheglov) Fails because T/U are considered invisible.
- if (!AnalysisDriver.useSummary2) return;
-
await _assertWriteType('T Function<T, U>(T a, U b)');
}
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
index ecb9b52..02c690d 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
@@ -46,8 +46,9 @@
/// Returns a [jsAst.Literal] representing [supertypeArgument] to be evaluated
/// against a [FullTypeEnvironmentStructure] representing [declaringType]. Any
/// [TypeVariableType]s appearing in [supertypeArgument] which are declared by
- /// [declaringType] are always encoded as indices.
- jsAst.Literal encodeDirectSupertypeRecipe(ModularEmitter emitter,
+ /// [declaringType] are always encoded as indices and type variables are
+ /// assumed to never be erased.
+ jsAst.Literal encodeMetadataRecipe(ModularEmitter emitter,
InterfaceType declaringType, DartType supertypeArgument);
/// Converts a recipe into a fragment of code that accesses the evaluated
@@ -94,14 +95,14 @@
}
@override
- jsAst.Literal encodeDirectSupertypeRecipe(ModularEmitter emitter,
+ jsAst.Literal encodeMetadataRecipe(ModularEmitter emitter,
InterfaceType declaringType, DartType supertypeArgument) {
return _RecipeGenerator(
this,
emitter,
FullTypeEnvironmentStructure(classType: declaringType),
TypeExpressionRecipe(supertypeArgument),
- indexTypeVariablesOnDeclaringClass: true)
+ metadata: true)
.run()
.recipe;
}
@@ -130,7 +131,7 @@
final ModularEmitter _emitter;
final TypeEnvironmentStructure _environment;
final TypeRecipe _recipe;
- final bool indexTypeVariablesOnDeclaringClass;
+ final bool metadata;
final bool hackTypeVariablesToAny;
final List<FunctionTypeVariable> functionTypeVariables = [];
@@ -140,10 +141,11 @@
final List<jsAst.Literal> _fragments = [];
final List<int> _codes = [];
+ RuntimeTypesNeed get _rtiNeed => _encoder._rtiNeed;
+
_RecipeGenerator(
this._encoder, this._emitter, this._environment, this._recipe,
- {this.indexTypeVariablesOnDeclaringClass = false,
- this.hackTypeVariablesToAny = false});
+ {this.metadata = false, this.hackTypeVariablesToAny = false});
JClosedWorld get _closedWorld => _encoder._closedWorld;
NativeBasicData get _nativeData => _encoder._nativeData;
@@ -268,6 +270,11 @@
int index = _indexIntoClassTypeVariables(type);
if (index != null) {
+ // We should only observe erased type arguments if we're generating
+ // subtype metadata.
+ assert(metadata ||
+ _rtiNeed.classNeedsTypeArguments(environment.classType.element));
+
// Indexed class type variables come after the bound function type
// variables.
_emitInteger(1 + environment.bindings.length + index);
@@ -287,7 +294,7 @@
TypeVariableEntity element = variable.element;
ClassEntity cls = element.typeDeclaration;
- if (indexTypeVariablesOnDeclaringClass) {
+ if (metadata) {
TypeEnvironmentStructure environment = _environment;
if (environment is FullTypeEnvironmentStructure) {
if (identical(environment.classType.element, cls)) {
@@ -486,12 +493,17 @@
}
class Ruleset {
+ Map<ClassEntity, ClassEntity> _redirections;
Map<InterfaceType, _RulesetEntry> _entries;
- Ruleset(this._entries);
- Ruleset.empty() : this({});
+ Ruleset(this._redirections, this._entries);
+ Ruleset.empty() : this({}, {});
- void add(InterfaceType targetType, Iterable<InterfaceType> supertypes,
+ void addRedirection(ClassEntity targetClass, ClassEntity redirection) {
+ _redirections[targetClass] = redirection;
+ }
+
+ void addEntry(InterfaceType targetType, Iterable<InterfaceType> supertypes,
Map<TypeVariableType, DartType> typeVariables) {
_RulesetEntry entry = _entries[targetType] ??= _RulesetEntry();
entry.addAll(supertypes, typeVariables);
@@ -518,6 +530,8 @@
bool _isObject(InterfaceType type) => identical(type.element, _objectClass);
+ bool _isSyntheticClosure(InterfaceType type) => type.element.isClosure;
+
void _preprocessEntry(InterfaceType targetType, _RulesetEntry entry) {
entry._supertypes.removeWhere((InterfaceType supertype) =>
_isObject(supertype) ||
@@ -525,8 +539,8 @@
}
void _preprocessRuleset(Ruleset ruleset) {
- ruleset._entries
- .removeWhere((InterfaceType targetType, _) => _isObject(targetType));
+ ruleset._entries.removeWhere((InterfaceType targetType, _) =>
+ _isObject(targetType) || _isSyntheticClosure(targetType));
ruleset._entries.forEach(_preprocessEntry);
ruleset._entries.removeWhere((_, _RulesetEntry entry) => entry.isEmpty);
}
@@ -543,11 +557,22 @@
js.concatenateStrings([
_quote,
_leftBrace,
- ...js.joinLiterals(ruleset._entries.entries.map(_encodeEntry), _comma),
+ ...js.joinLiterals([
+ ...ruleset._redirections.entries.map(_encodeRedirection),
+ ...ruleset._entries.entries.map(_encodeEntry),
+ ], _comma),
_rightBrace,
_quote,
]);
+ jsAst.StringConcatenation _encodeRedirection(
+ MapEntry<ClassEntity, ClassEntity> redirection) =>
+ js.concatenateStrings([
+ js.quoteName(_emitter.typeAccessNewRti(redirection.key)),
+ _colon,
+ js.quoteName(_emitter.typeAccessNewRti(redirection.value)),
+ ]);
+
jsAst.StringConcatenation _encodeEntry(
MapEntry<InterfaceType, _RulesetEntry> entry) =>
js.concatenateStrings([
@@ -586,6 +611,6 @@
jsAst.Literal _encodeSupertypeArgument(
InterfaceType targetType, DartType supertypeArgument) =>
- _recipeEncoder.encodeDirectSupertypeRecipe(
+ _recipeEncoder.encodeMetadataRecipe(
_emitter, targetType, supertypeArgument);
}
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 871cdd2..91d8954 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -988,12 +988,23 @@
js.Expression _generateFunctionType(ClassEntity /*?*/ enclosingClass,
FunctionType type, OutputUnit outputUnit) {
+ InterfaceType enclosingType;
+ if (enclosingClass != null && type.containsTypeVariables) {
+ enclosingType = _elementEnvironment.getThisType(enclosingClass);
+ if (!_rtiNeed.classNeedsTypeArguments(enclosingClass)) {
+ // Erase type arguments.
+ List<DartType> typeArguments = enclosingType.typeArguments;
+ type = type.subst(
+ List<DartType>.filled(typeArguments.length, const DynamicType()),
+ typeArguments);
+ }
+ }
+
if (type.containsTypeVariables) {
if (_options.experimentNewRti) {
RecipeEncoding encoding = _rtiRecipeEncoder.encodeRecipe(
_task.emitter,
- FullTypeEnvironmentStructure(
- classType: _elementEnvironment.getThisType(enclosingClass)),
+ FullTypeEnvironmentStructure(classType: enclosingType),
TypeExpressionRecipe(type));
_lateNamedTypeVariablesNewRti.addAll(encoding.typeVariables);
return encoding.recipe;
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index 288e35b..aaea216 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -17,6 +17,7 @@
import '../js_backend/runtime_types_codegen.dart'
show ClassChecks, ClassFunctionType, Substitution, TypeCheck;
import '../js_emitter/sorter.dart';
+import '../options.dart';
import '../util/util.dart' show Setlet;
import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;
@@ -93,6 +94,8 @@
final RuntimeTypesEncoder _rtiEncoder;
final _TypeContainedInOutputUnitVisitor _outputUnitVisitor;
+ CompilerOptions get _options => emitterTask.options;
+
RuntimeTypeGenerator(this._commonElements, this._outputUnitData,
this.emitterTask, this._namer, this._rtiChecks, this._rtiEncoder)
: _outputUnitVisitor = new _TypeContainedInOutputUnitVisitor(
@@ -181,7 +184,7 @@
checkedClass, _namer.operatorIs(checkedClass), js('1'));
}
Substitution substitution = check.substitution;
- if (substitution != null) {
+ if (substitution != null && !_options.experimentNewRti) {
jsAst.Expression body =
_getSubstitutionCode(emitterTask.emitter, substitution);
result.addSubstitution(
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 17d454c..441ab87 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -1945,6 +1945,10 @@
js.Statement emitTypeRules(Fragment fragment) {
if (!_options.experimentNewRti) return js.EmptyStatement();
+ bool addJsObjectRedirections = false;
+ ClassEntity jsObjectClass = _commonElements.jsJavaScriptObjectClass;
+ InterfaceType jsObjectType = _elementEnvironment.getThisType(jsObjectClass);
+
Ruleset ruleset = Ruleset.empty();
Iterable<Class> classes =
fragment.libraries.expand((Library library) => library.classes);
@@ -1971,17 +1975,21 @@
}
if (isInterop) {
- _classHierarchy
- .subtypesOf(_commonElements.jsJavaScriptObjectClass)
- .forEach((ClassEntity interceptor) {
- ruleset.add(_elementEnvironment.getThisType(interceptor), supertypes,
- typeVariables);
- });
+ ruleset.addEntry(jsObjectType, supertypes, typeVariables);
+ addJsObjectRedirections = true;
} else {
- ruleset.add(targetType, supertypes, typeVariables);
+ ruleset.addEntry(targetType, supertypes, typeVariables);
}
});
+ if (addJsObjectRedirections) {
+ _classHierarchy
+ .strictSubtypesOf(jsObjectClass)
+ .forEach((ClassEntity subtype) {
+ ruleset.addRedirection(subtype, jsObjectClass);
+ });
+ }
+
FunctionEntity method = _closedWorld.commonElements.rtiAddRulesMethod;
return js.js.statement('#(init.#,JSON.parse(#));', [
_emitter.staticFunctionAccess(method),
diff --git a/pkg/dartfix/analysis_options.yaml b/pkg/dartfix/analysis_options.yaml
index 1d96fdd..0012141 100644
--- a/pkg/dartfix/analysis_options.yaml
+++ b/pkg/dartfix/analysis_options.yaml
@@ -3,6 +3,9 @@
analyzer:
strong-mode:
implicit-casts: false
+ errors:
+ # Increase the severity of the unused_import hint.
+ unused_import: warning
linter:
rules:
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index bea1563..ad3e479 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -19,7 +19,6 @@
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/resynthesize.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:meta/meta.dart';
@@ -56,18 +55,6 @@
ExtensionTypeSet _extensionTypes;
- CompilerAnalysisDriver._(this.dartSdk, this._summaryPaths, this.summaryData,
- this.analysisOptions, this._resourceProvider, this._dartSdkSummaryPath) {
- var bundle = dartSdk.getLinkedBundle();
- if (bundle != null) summaryData.addBundle(null, bundle);
- }
-
- /// Information about native extension types.
- ///
- /// This will be `null` until [linkLibraries] has been called (because we
- /// could be compiling the Dart SDK, so it would not be available yet).
- ExtensionTypeSet get extensionTypes => _extensionTypes;
-
factory CompilerAnalysisDriver(AnalyzerOptions options,
{SummaryDataStore summaryData,
List<String> summaryPaths = const [],
@@ -93,6 +80,18 @@
analysisOptions, resourceProvider, options.dartSdkSummaryPath);
}
+ CompilerAnalysisDriver._(this.dartSdk, this._summaryPaths, this.summaryData,
+ this.analysisOptions, this._resourceProvider, this._dartSdkSummaryPath) {
+ var bundle = dartSdk.getLinkedBundle();
+ if (bundle != null) summaryData.addBundle(null, bundle);
+ }
+
+ /// Information about native extension types.
+ ///
+ /// This will be `null` until [linkLibraries] has been called (because we
+ /// could be compiling the Dart SDK, so it would not be available yet).
+ ExtensionTypeSet get extensionTypes => _extensionTypes;
+
/// Whether this driver can be reused for the given [dartSdkSummaryPath] and
/// [summaryPaths].
bool isCompatibleWith(AnalyzerOptions options, List<String> summaryPaths) {
@@ -130,13 +129,11 @@
_extensionTypes ??= ExtensionTypeSet(
resynthesizerBuilder.context.typeProvider,
- resynthesizerBuilder.resynthesizer,
resynthesizerBuilder.elementFactory,
);
return LinkedAnalysisDriver(
analysisOptions,
- resynthesizerBuilder.resynthesizer,
resynthesizerBuilder.elementFactory,
sourceFactory,
resynthesizerBuilder.libraryUris,
@@ -175,7 +172,6 @@
/// sources, produced by [CompilerAnalysisDriver.linkLibraries].
class LinkedAnalysisDriver {
final AnalysisOptions analysisOptions;
- final SummaryResynthesizer resynthesizer;
final LinkedElementFactory elementFactory;
final SourceFactory sourceFactory;
final List<String> libraryUris;
@@ -190,7 +186,6 @@
LinkedAnalysisDriver(
this.analysisOptions,
- this.resynthesizer,
this.elementFactory,
this.sourceFactory,
this.libraryUris,
@@ -200,21 +195,7 @@
this._resourceProvider);
TypeProvider get typeProvider {
- if (resynthesizer != null) {
- return resynthesizer.typeProvider;
- } else {
- return elementFactory.analysisContext.typeProvider;
- }
- }
-
- /// True if [uri] refers to a Dart library (i.e. a Dart source file exists
- /// with this uri, and it is not a part file).
- bool _isLibraryUri(String uri) {
- if (resynthesizer != null) {
- return resynthesizer.hasLibrarySummary(uri);
- } else {
- return elementFactory.isLibraryUri(uri);
- }
+ return elementFactory.analysisContext.typeProvider;
}
/// Analyzes the library at [uri] and returns the results of analysis for all
@@ -224,13 +205,7 @@
throw ArgumentError('"$libraryUri" is not a library');
}
- AnalysisContext analysisContext;
- if (resynthesizer != null) {
- analysisContext = resynthesizer.context;
- } else {
- analysisContext = elementFactory.analysisContext;
- }
-
+ var analysisContext = elementFactory.analysisContext;
var libraryFile = _fsState.getFileForUri(Uri.parse(libraryUri));
var analyzer = LibraryAnalyzer(
analysisOptions as AnalysisOptionsImpl,
@@ -238,7 +213,6 @@
sourceFactory,
(uri) => _isLibraryUri('$uri'),
analysisContext,
- resynthesizer,
elementFactory,
InheritanceManager3(analysisContext.typeSystem),
libraryFile,
@@ -256,10 +230,12 @@
}
LibraryElement getLibrary(String uri) {
- if (resynthesizer != null) {
- return resynthesizer.getLibraryElement(uri);
- } else {
- return elementFactory.libraryOfUri(uri);
- }
+ return elementFactory.libraryOfUri(uri);
+ }
+
+ /// True if [uri] refers to a Dart library (i.e. a Dart source file exists
+ /// with this uri, and it is not a part file).
+ bool _isLibraryUri(String uri) {
+ return elementFactory.isLibraryUri(uri);
}
}
diff --git a/pkg/dev_compiler/lib/src/analyzer/extension_types.dart b/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
index 0175913..9f3399e 100644
--- a/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
@@ -8,7 +8,6 @@
show ClassElement, CompilationUnitElement, Element, LibraryElement;
import 'package:analyzer/dart/element/type.dart' show DartType, InterfaceType;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/summary/resynthesize.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'element_helpers.dart' show getAnnotationName, isBuiltinAnnotation;
@@ -32,7 +31,6 @@
/// This will provide the [Iterable.first] property, without needing to add
/// `first` to the `Array.prototype`.
class ExtensionTypeSet {
- final SummaryResynthesizer _resynthesizer;
final LinkedElementFactory _elementFactory;
// Abstract types that may be implemented by both native and non-native
@@ -43,8 +41,7 @@
final _nativeTypes = HashSet<ClassElement>();
final _pendingLibraries = HashSet<String>();
- ExtensionTypeSet(
- TypeProvider types, this._resynthesizer, this._elementFactory) {
+ ExtensionTypeSet(TypeProvider types, this._elementFactory) {
// TODO(vsm): Eventually, we want to make this extensible - i.e., find
// annotations in user code as well. It would need to be summarized in
// the element model - not searched this way on every compile. To make this
@@ -75,25 +72,30 @@
_addPendingExtensionTypes('dart:web_sql');
}
- void _visitCompilationUnit(CompilationUnitElement unit) {
- unit.types.forEach(_visitClass);
+ /// Gets the JS peer for this Dart type if any, otherwise null.
+ ///
+ /// For example for dart:_interceptors `JSArray` this will return "Array",
+ /// referring to the JavaScript built-in `Array` type.
+ List<String> getNativePeers(ClassElement classElem) {
+ if (classElem.isDartCoreObject) return ['Object'];
+ var names = getAnnotationName(
+ classElem,
+ (a) =>
+ isBuiltinAnnotation(a, '_js_helper', 'JsPeerInterface') ||
+ isBuiltinAnnotation(a, '_js_helper', 'Native'));
+ if (names == null) return [];
+
+ // Omit the special name "!nonleaf" and any future hacks starting with "!"
+ return names.split(',').where((peer) => !peer.startsWith("!")).toList();
}
- void _visitClass(ClassElement element) {
- if (_isNative(element)) {
- _addExtensionType(getLegacyRawClassType(element), true);
- }
- }
+ bool hasNativeSubtype(DartType type) =>
+ isNativeInterface(type.element) || isNativeClass(type.element);
- bool _isNative(ClassElement element) {
- for (var metadata in element.metadata) {
- var e = metadata.element?.enclosingElement;
- if (e.name == 'Native' || e.name == 'JsPeerInterface') {
- if (e.source.isInSystemLibrary) return true;
- }
- }
- return false;
- }
+ bool isNativeClass(Element element) => _setContains(_nativeTypes, element);
+
+ bool isNativeInterface(Element element) =>
+ _setContains(_extensibleTypes, element);
void _addExtensionType(InterfaceType t, [bool mustBeNative = false]) {
if (t.isObject) return;
@@ -113,6 +115,12 @@
if (supertype != null) _addExtensionType(element.supertype);
}
+ void _addExtensionTypes(String libraryUri) {
+ var library = _getLibraryByUri(libraryUri);
+ _visitCompilationUnit(library.definingCompilationUnit);
+ library.parts.forEach(_visitCompilationUnit);
+ }
+
void _addExtensionTypesForLibrary(String libraryUri, List<String> typeNames) {
var library = _getLibraryByUri(libraryUri);
for (var typeName in typeNames) {
@@ -120,22 +128,22 @@
}
}
- void _addExtensionTypes(String libraryUri) {
- var library = _getLibraryByUri(libraryUri);
- _visitCompilationUnit(library.definingCompilationUnit);
- library.parts.forEach(_visitCompilationUnit);
- }
-
void _addPendingExtensionTypes(String libraryUri) {
_pendingLibraries.add(libraryUri);
}
LibraryElement _getLibraryByUri(String uriStr) {
- if (_resynthesizer != null) {
- return _resynthesizer.getLibraryElement(uriStr);
- } else {
- return _elementFactory.libraryOfUri(uriStr);
+ return _elementFactory.libraryOfUri(uriStr);
+ }
+
+ bool _isNative(ClassElement element) {
+ for (var metadata in element.metadata) {
+ var e = metadata.element?.enclosingElement;
+ if (e.name == 'Native' || e.name == 'JsPeerInterface') {
+ if (e.source.isInSystemLibrary) return true;
+ }
}
+ return false;
}
bool _processPending(Element element) {
@@ -157,28 +165,13 @@
_processPending(element) && set.contains(element);
}
- bool isNativeClass(Element element) => _setContains(_nativeTypes, element);
+ void _visitClass(ClassElement element) {
+ if (_isNative(element)) {
+ _addExtensionType(getLegacyRawClassType(element), true);
+ }
+ }
- bool isNativeInterface(Element element) =>
- _setContains(_extensibleTypes, element);
-
- bool hasNativeSubtype(DartType type) =>
- isNativeInterface(type.element) || isNativeClass(type.element);
-
- /// Gets the JS peer for this Dart type if any, otherwise null.
- ///
- /// For example for dart:_interceptors `JSArray` this will return "Array",
- /// referring to the JavaScript built-in `Array` type.
- List<String> getNativePeers(ClassElement classElem) {
- if (classElem.isDartCoreObject) return ['Object'];
- var names = getAnnotationName(
- classElem,
- (a) =>
- isBuiltinAnnotation(a, '_js_helper', 'JsPeerInterface') ||
- isBuiltinAnnotation(a, '_js_helper', 'Native'));
- if (names == null) return [];
-
- // Omit the special name "!nonleaf" and any future hacks starting with "!"
- return names.split(',').where((peer) => !peer.startsWith("!")).toList();
+ void _visitCompilationUnit(CompilationUnitElement unit) {
+ unit.types.forEach(_visitClass);
}
}
diff --git a/pkg/dev_compiler/lib/src/compiler/js_names.dart b/pkg/dev_compiler/lib/src/compiler/js_names.dart
index ba120a3..54c1f23 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_names.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_names.dart
@@ -405,3 +405,32 @@
'[]=': '_set',
'unary-': '_negate',
};
+
+// Invalid characters for identifiers, which would need to be escaped.
+final _invalidCharInIdentifier = RegExp(r'[^A-Za-z_$0-9]');
+
+/// Escape [name] to make it into a valid identifier.
+String toJSIdentifier(String name) {
+ if (name.isEmpty) return r'$';
+
+ // Escape any invalid characters
+ StringBuffer buffer;
+ for (int i = 0; i < name.length; i++) {
+ var ch = name[i];
+ var needsEscape = ch == r'$' || _invalidCharInIdentifier.hasMatch(ch);
+ if (needsEscape && buffer == null) {
+ buffer = StringBuffer(name.substring(0, i));
+ }
+ if (buffer != null) {
+ buffer.write(needsEscape ? '\$${ch.codeUnits.join("")}' : ch);
+ }
+ }
+
+ var result = buffer != null ? '$buffer' : name;
+ // Ensure the identifier first character is not numeric and that the whole
+ // identifier is not a keyword.
+ if (result.startsWith(RegExp('[0-9]')) || invalidVariableName(result)) {
+ return '\$$result';
+ }
+ return result;
+}
diff --git a/pkg/dev_compiler/lib/src/compiler/module_builder.dart b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
index 208ca81..ec1ea4a 100644
--- a/pkg/dev_compiler/lib/src/compiler/module_builder.dart
+++ b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
@@ -359,34 +359,5 @@
.replaceAll('-', '_'));
}
-/// Escape [name] to make it into a valid identifier.
-String toJSIdentifier(String name) {
- if (name.isEmpty) return r'$';
-
- // Escape any invalid characters
- StringBuffer buffer;
- for (int i = 0; i < name.length; i++) {
- var ch = name[i];
- var needsEscape = ch == r'$' || _invalidCharInIdentifier.hasMatch(ch);
- if (needsEscape && buffer == null) {
- buffer = StringBuffer(name.substring(0, i));
- }
- if (buffer != null) {
- buffer.write(needsEscape ? '\$${ch.codeUnits.join("")}' : ch);
- }
- }
-
- var result = buffer != null ? '$buffer' : name;
- // Ensure the identifier first character is not numeric and that the whole
- // identifier is not a keyword.
- if (result.startsWith(RegExp('[0-9]')) || invalidVariableName(result)) {
- return '\$$result';
- }
- return result;
-}
-
-// Invalid characters for identifiers, which would need to be escaped.
-final _invalidCharInIdentifier = RegExp(r'[^A-Za-z_$0-9]');
-
// Replacement string for path separators (i.e., '/', '\', '..').
final encodedSeparator = "__";
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_command.dart b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
index e75a067..be32b50 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_command.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
@@ -503,7 +503,7 @@
/// Preprocess arguments to determine whether DDK is used in batch mode or as a
/// persistent worker.
///
- /// When used in batch mode, we expect a `--batch` parameter last.
+ /// When used in batch mode, we expect a `--batch` parameter.
///
/// When used as a persistent bazel worker, the `--persistent_worker` might be
/// present, and an argument of the form `@path/to/file` might be provided. The
@@ -518,19 +518,19 @@
bool isKernel = false;
bool reuseResult = false;
bool useIncrementalCompiler = false;
- var len = args.length;
- for (int i = 0; i < len; i++) {
- var arg = args[i];
- var isLastArg = i == len - 1;
- if (isLastArg && arg.startsWith('@')) {
- var extra = _readLines(arg.substring(1)).toList();
- if (extra.remove('--kernel') || extra.remove('-k')) {
- isKernel = true;
- }
- newArgs.addAll(extra);
- } else if (arg == '--persistent_worker') {
+
+ Iterable<String> argsToParse = args;
+
+ // Expand `@path/to/file`
+ if (args.last.startsWith('@')) {
+ var extra = _readLines(args.last.substring(1));
+ argsToParse = args.take(args.length - 1).followedBy(extra);
+ }
+
+ for (var arg in argsToParse) {
+ if (arg == '--persistent_worker') {
isWorker = true;
- } else if (isLastArg && arg == '--batch') {
+ } else if (arg == '--batch') {
isBatch = true;
} else if (arg == '--kernel' || arg == '-k') {
isKernel = true;
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
index 7b9408a..87caa77 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -9,6 +9,8 @@
import 'package:analyzer/dart/element/type.dart' as a;
import 'package:analyzer/file_system/physical_file_system.dart' as a;
import 'package:analyzer/src/context/context.dart' as a;
+import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart'
+ as a;
import 'package:analyzer/src/dart/element/element.dart' as a;
import 'package:analyzer/src/dart/element/member.dart' as a;
import 'package:analyzer/src/dart/element/type.dart' as a;
@@ -21,6 +23,9 @@
import 'package:analyzer/src/summary/idl.dart' as a;
import 'package:analyzer/src/summary/package_bundle_reader.dart' as a;
import 'package:analyzer/src/summary/summary_sdk.dart' as a;
+import 'package:analyzer/src/summary2/linked_bundle_context.dart' as a;
+import 'package:analyzer/src/summary2/linked_element_factory.dart' as a;
+import 'package:analyzer/src/summary2/reference.dart' as a;
import 'package:front_end/src/api_unstable/ddc.dart'
show RedirectingFactoryBody;
import 'package:kernel/kernel.dart';
@@ -72,7 +77,7 @@
/// Analyzer and modify it to resynthesize directly into Kernel trees, if we
/// ever need to support a mix of Kernel and Analyzer summary files.
class AnalyzerToKernel {
- final a.StoreBasedSummaryResynthesizer _resynth;
+ final a.LinkedElementFactory _resynth;
final a.SummaryDataStore _summaryData;
final a.TypeProvider types;
final a.Dart2TypeSystem rules;
@@ -82,8 +87,8 @@
final _namespaceBuilder = a.NamespaceBuilder();
AnalyzerToKernel._(this._resynth, this._summaryData)
- : types = _resynth.typeProvider,
- rules = _resynth.typeSystem as a.Dart2TypeSystem;
+ : types = _resynth.analysisContext.typeProvider,
+ rules = _resynth.analysisContext.typeSystem as a.Dart2TypeSystem;
/// Create an Analyzer summary to Kernel tree converter, using the provided
/// [analyzerSdkSummary] and [summaryPaths].
@@ -155,13 +160,12 @@
}
for (var uri in bundle.unlinkedUnitUris) {
- var unitInfo = _resynth.getUnlinkedSummary(uri);
- if (unitInfo.isPartOf) {
+ if (_summaryData.isPartUnit(uri)) {
// Library parts are handled by their corresponding library.
continue;
}
- var element = _resynth.getLibraryElement(uri);
+ var element = _resynth.libraryOfUri(uri);
libraries.add(visitLibraryElement(element));
addCompilationUnit(element.definingCompilationUnit);
element.parts.forEach(addCompilationUnit);
@@ -872,14 +876,23 @@
: (e.isAsynchronous ? AsyncMarker.Async : AsyncMarker.Sync);
}
-a.StoreBasedSummaryResynthesizer _createSummaryResynthesizer(
+a.LinkedElementFactory _createSummaryResynthesizer(
a.SummaryDataStore summaryData, String dartSdkPath) {
var context = _createContextForSummaries(summaryData, dartSdkPath);
- var resynthesizer = a.StoreBasedSummaryResynthesizer(
- context, null, context.sourceFactory, /*strongMode*/ true, summaryData);
- resynthesizer.finishCoreAsyncLibraries();
- context.typeProvider = resynthesizer.typeProvider;
- return resynthesizer;
+
+ var elementFactory = a.LinkedElementFactory(
+ context,
+ null,
+ a.Reference.root(),
+ );
+
+ for (var bundle in summaryData.bundles) {
+ elementFactory.addBundle(
+ a.LinkedBundleContext(elementFactory, bundle.bundle2),
+ );
+ }
+
+ return elementFactory;
}
/// Creates a dummy Analyzer context so we can use summary resynthesizer.
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 2539d4a..57b2fe0 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -505,10 +505,10 @@
}
static js_ast.Identifier _emitIdentifier(String name) =>
- js_ast.Identifier(escapeIdentifier(name));
+ js_ast.Identifier(js_ast.toJSIdentifier(name));
static js_ast.TemporaryId _emitTemporaryId(String name) =>
- js_ast.TemporaryId(escapeIdentifier(name));
+ js_ast.TemporaryId(js_ast.toJSIdentifier(name));
js_ast.Statement _emitClassDeclaration(Class c) {
// Mixins are unrolled in _defineClass.
diff --git a/pkg/dev_compiler/test/modular_ddc_suite.dart b/pkg/dev_compiler/test/modular_ddc_suite.dart
index f537492..fac2975 100644
--- a/pkg/dev_compiler/test/modular_ddc_suite.dart
+++ b/pkg/dev_compiler/test/modular_ddc_suite.dart
@@ -19,12 +19,12 @@
String _test_package = 'ddc_modular_test';
Uri sdkRoot = Platform.script.resolve("../../../");
-bool _nnbd = false;
Options _options;
String _dartdevcScript;
String _buildSdkScript;
String _patchSdkScript;
String _sdkDevRuntime;
+String _sdkDevRuntimeNnbd;
main(List<String> args) async {
_options = Options.parse(args);
@@ -69,8 +69,8 @@
ProcessResult result;
- _nnbd = flags.contains('non-nullable');
- bool allowErrors = _nnbd && _nnbdOptOut.contains(module.name);
+ bool nnbd = flags.contains('non-nullable');
+ bool allowErrors = nnbd && _nnbdOptOut.contains(module.name);
if (module.isSdk) {
assert(transitiveDependencies.isEmpty);
@@ -81,9 +81,9 @@
[
_patchSdkScript,
sdkRoot.toFilePath(),
- _sdkDevRuntime,
+ if (nnbd) _sdkDevRuntimeNnbd else _sdkDevRuntime,
'patched_sdk',
- if (_nnbd) 'sdk_nnbd'
+ if (nnbd) 'sdk_nnbd'
],
root.toFilePath());
_checkExitCode(result, this, module);
@@ -310,8 +310,6 @@
'pkg/dev_compiler/bin/dartdevc.dart', 'snapshots/dartdevc.dart.snapshot');
_buildSdkScript = await resolve('pkg/dev_compiler/tool/build_sdk.dart');
_patchSdkScript = await resolve('pkg/dev_compiler/tool/patch_sdk.dart');
- _sdkDevRuntime = await resolve(_nnbd
- ? 'sdk_nnbd'
- : 'sdk'
- '/lib/_internal/js_dev_runtime');
+ _sdkDevRuntime = await resolve('sdk/lib/_internal/js_dev_runtime');
+ _sdkDevRuntimeNnbd = await resolve('sdk_nnbd/lib/_internal/js_dev_runtime');
}
diff --git a/pkg/front_end/analysis_options_no_lints.yaml b/pkg/front_end/analysis_options_no_lints.yaml
index 63c5c24..5317b91 100644
--- a/pkg/front_end/analysis_options_no_lints.yaml
+++ b/pkg/front_end/analysis_options_no_lints.yaml
@@ -9,6 +9,7 @@
- test/flow_analysis/nullability/data/**
- test/flow_analysis/reachability/data/**
- test/flow_analysis/type_promotion/data/**
+ - parser_testcases/**
- testcases/**
- test/id_testing/data/**
- test/language_versioning/data/**
diff --git a/pkg/front_end/lib/src/base/errors.dart b/pkg/front_end/lib/src/base/errors.dart
index 735fa5d..feda572 100644
--- a/pkg/front_end/lib/src/base/errors.dart
+++ b/pkg/front_end/lib/src/base/errors.dart
@@ -76,7 +76,12 @@
* Return a URL that can be used to access documentation for diagnostics with
* this code, or `null` if there is no published documentation.
*/
- String get url => null;
+ String get url {
+ if (hasPublishedDocs) {
+ return 'https://dart.dev/tools/diagnostic-messages#${name.toLowerCase()}';
+ }
+ return null;
+ }
@override
String toString() => uniqueName;
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 3f1df47..ad6ebd4 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -1395,7 +1395,7 @@
_constant)> templateConstEvalInvalidMethodInvocation = const Template<
Message Function(String string, Constant _constant)>(
messageTemplate:
- r"""The method '#string' can't be invoked on '#constant' within a const context.""",
+ r"""The method '#string' can't be invoked on '#constant' in a constant expression.""",
withArguments: _withArgumentsConstEvalInvalidMethodInvocation);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1415,7 +1415,7 @@
String constant = constantParts.join();
return new Message(codeConstEvalInvalidMethodInvocation,
message:
- """The method '${string}' can't be invoked on '${constant}' within a const context.""" +
+ """The method '${string}' can't be invoked on '${constant}' in a constant expression.""" +
labeler.originMessages,
arguments: {'string': string, 'constant': _constant});
}
@@ -1428,7 +1428,7 @@
_constant)> templateConstEvalInvalidPropertyGet = const Template<
Message Function(String string, Constant _constant)>(
messageTemplate:
- r"""The property '#string' can't be accessed on '#constant' within a const context.""",
+ r"""The property '#string' can't be accessed on '#constant' in a constant expression.""",
withArguments: _withArgumentsConstEvalInvalidPropertyGet);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1447,7 +1447,7 @@
String constant = constantParts.join();
return new Message(codeConstEvalInvalidPropertyGet,
message:
- """The property '${string}' can't be accessed on '${constant}' within a const context.""" +
+ """The property '${string}' can't be accessed on '${constant}' in a constant expression.""" +
labeler.originMessages,
arguments: {'string': string, 'constant': _constant});
}
@@ -1459,7 +1459,7 @@
name)> templateConstEvalInvalidStaticInvocation = const Template<
Message Function(String name)>(
messageTemplate:
- r"""The invocation of '#name' is not allowed within a const context.""",
+ r"""The invocation of '#name' is not allowed in a constant expression.""",
withArguments: _withArgumentsConstEvalInvalidStaticInvocation);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1475,7 +1475,7 @@
name = demangleMixinApplicationName(name);
return new Message(codeConstEvalInvalidStaticInvocation,
message:
- """The invocation of '${name}' is not allowed within a const context.""",
+ """The invocation of '${name}' is not allowed in a constant expression.""",
arguments: {'name': name});
}
@@ -1484,7 +1484,8 @@
templateConstEvalInvalidStringInterpolationOperand =
const Template<Message Function(Constant _constant)>(
messageTemplate:
- r"""The '#constant' can't be used as part of a string interpolation within a const context, only values of type 'null', 'bool', 'int', 'double', or 'String' can be used.""",
+ r"""The constant value '#constant' can't be used as part of a string interpolation in a constant expression.
+Only values of type 'null', 'bool', 'int', 'double', or 'String' can be used.""",
withArguments:
_withArgumentsConstEvalInvalidStringInterpolationOperand);
@@ -1504,7 +1505,8 @@
String constant = constantParts.join();
return new Message(codeConstEvalInvalidStringInterpolationOperand,
message:
- """The '${constant}' can't be used as part of a string interpolation within a const context, only values of type 'null', 'bool', 'int', 'double', or 'String' can be used.""" +
+ """The constant value '${constant}' can't be used as part of a string interpolation in a constant expression.
+Only values of type 'null', 'bool', 'int', 'double', or 'String' can be used.""" +
labeler.originMessages,
arguments: {'constant': _constant});
}
@@ -1641,31 +1643,6 @@
const Template<
Message Function(
String
- string)> templateConstEvalNonConstantLiteral = const Template<
- Message Function(String string)>(
- messageTemplate:
- r"""Can't have a non-constant #string literal within a const context.""",
- withArguments: _withArgumentsConstEvalNonConstantLiteral);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)> codeConstEvalNonConstantLiteral =
- const Code<Message Function(String string)>(
- "ConstEvalNonConstantLiteral", templateConstEvalNonConstantLiteral,
- analyzerCodes: <String>["NON_CONSTANT_DEFAULT_VALUE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalNonConstantLiteral(String string) {
- if (string.isEmpty) throw 'No string provided';
- return new Message(codeConstEvalNonConstantLiteral,
- message:
- """Can't have a non-constant ${string} literal within a const context.""",
- arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
- Message Function(
- String
string)> templateConstEvalNonConstantVariableGet = const Template<
Message Function(String string)>(
messageTemplate:
diff --git a/pkg/front_end/lib/src/fasta/flow_analysis/flow_analysis.dart b/pkg/front_end/lib/src/fasta/flow_analysis/flow_analysis.dart
index aa2b361..765b78e 100644
--- a/pkg/front_end/lib/src/fasta/flow_analysis/flow_analysis.dart
+++ b/pkg/front_end/lib/src/fasta/flow_analysis/flow_analysis.dart
@@ -130,12 +130,6 @@
}
class FlowAnalysis<Statement, Expression, Variable, Type> {
- static bool get _assertionsEnabled {
- bool result = false;
- assert(result = true);
- return result;
- }
-
/// The [NodeOperations], used to manipulate expressions.
final NodeOperations<Expression> nodeOperations;
@@ -154,9 +148,6 @@
/// states.
final Map<Statement, int> _statementToStackIndex = {};
- /// List of all variables passed to [add].
- final List<Variable> _addedVariables = [];
-
FlowModel<Variable, Type> _current;
/// The last boolean condition, for [_conditionTrue] and [_conditionFalse].
@@ -168,19 +159,6 @@
/// The state when [_condition] evaluates to `false`.
FlowModel<Variable, Type> _conditionFalse;
- /// If assertions are enabled, keeps track of all variables that have been
- /// passed into the API (other than through a call to [add]). The [finish]
- /// method uses this to verify that the caller doesn't forget to pass a
- /// variable to [add].
- ///
- /// Note: the reason we have to keep track of this set (rather than simply
- /// checking each variable at the time it is passed into the API) is because
- /// the client doesn't call `add` until a variable is declared, and in
- /// erroneous code, it's possible that a variable might be used before its
- /// declaration.
- final Set<Variable> _referencedVariables =
- _assertionsEnabled ? new Set<Variable>() : null;
-
factory FlowAnalysis(
NodeOperations<Expression> nodeOperations,
TypeOperations<Variable, Type> typeOperations,
@@ -196,12 +174,6 @@
/// Return `true` if the current state is reachable.
bool get isReachable => _current.reachable;
- /// Add a new [variable], which might be already [assigned].
- void add(Variable variable, {bool assigned: false}) {
- _addedVariables.add(variable);
- _current = _current.add(variable, assigned: assigned);
- }
-
void booleanLiteral(Expression expression, bool value) {
_condition = expression;
if (value) {
@@ -260,7 +232,6 @@
/// `null`.
void conditionEqNull(Expression binaryExpression, Variable variable,
{bool notEqual: false}) {
- _variableReferenced(variable);
if (functionBody.isPotentiallyMutatedInClosure(variable)) {
return;
}
@@ -279,7 +250,7 @@
void doStatement_bodyBegin(
Statement doStatement, Iterable<Variable> loopAssigned) {
- _current = _current.removePromotedAll(loopAssigned, _referencedVariables);
+ _current = _current.removePromotedAll(loopAssigned);
_statementToStackIndex[doStatement] = _stack.length;
_stack.add(null); // break
@@ -308,13 +279,6 @@
/// level function or method. Performs assertion checks.
void finish() {
assert(_stack.isEmpty);
- assert(() {
- Set<Variable> variablesNotAdded = _referencedVariables
- .difference(new Set<Variable>.from(_addedVariables));
- assert(variablesNotAdded.isEmpty,
- 'Variables not passed to add: $variablesNotAdded');
- return true;
- }());
}
/// Call this method just before visiting the body of a conventional "for"
@@ -373,7 +337,7 @@
/// [loopAssigned] should be the set of variables that are assigned anywhere
/// in the loop's condition, updaters, or body.
void for_conditionBegin(Set<Variable> loopAssigned) {
- _current = _current.removePromotedAll(loopAssigned, _referencedVariables);
+ _current = _current.removePromotedAll(loopAssigned);
}
/// Call this method just after visiting the updaters of a conventional "for"
@@ -411,10 +375,10 @@
/// local variable, or `null` otherwise.
void forEach_bodyBegin(Set<Variable> loopAssigned, Variable loopVariable) {
_stack.add(_current);
- _current = _current.removePromotedAll(loopAssigned, _referencedVariables);
+ _current = _current.removePromotedAll(loopAssigned);
if (loopVariable != null) {
assert(loopAssigned.contains(loopVariable));
- _current = _current.write(typeOperations, loopVariable);
+ _current = _current.write(loopVariable);
}
}
@@ -440,7 +404,7 @@
}
if (notPromoted.isNotEmpty) {
- _current = _current.removePromotedAll(notPromoted, null);
+ _current = _current.removePromotedAll(notPromoted);
}
}
@@ -510,22 +474,11 @@
/// Return whether the [variable] is definitely assigned in the current state.
bool isAssigned(Variable variable) {
- _variableReferenced(variable);
- VariableModel<Type> variableInfo = _current.variableInfo[variable];
- if (variableInfo == null) {
- // In error-free code, variables should always be registered with flow
- // analysis before they're used. But this can't be relied on when the
- // analyzer is doing error recovery. So if we encounter a variable that
- // hasn't been registered with flow analysis yet, assume it's unassigned.
- return false;
- } else {
- return variableInfo.assigned;
- }
+ return _current.infoFor(variable).assigned;
}
void isExpression_end(
Expression isExpression, Variable variable, bool isNot, Type type) {
- _variableReferenced(variable);
if (functionBody.isPotentiallyMutatedInClosure(variable)) {
return;
}
@@ -597,8 +550,7 @@
/// Retrieves the type that the [variable] is promoted to, if the [variable]
/// is currently promoted. Otherwise returns `null`.
Type promotedType(Variable variable) {
- _variableReferenced(variable);
- return _current.variableInfo[variable]?.promotedType;
+ return _current.infoFor(variable).promotedType;
}
/// Call this method just before visiting one of the cases in the body of a
@@ -611,8 +563,7 @@
void switchStatement_beginCase(
bool hasLabel, Iterable<Variable> notPromoted) {
if (hasLabel) {
- _current =
- _stack.last.removePromotedAll(notPromoted, _referencedVariables);
+ _current = _stack.last.removePromotedAll(notPromoted);
} else {
_current = _stack.last;
}
@@ -663,7 +614,7 @@
void tryCatchStatement_bodyEnd(Iterable<Variable> assignedInBody) {
FlowModel<Variable, Type> beforeBody = _stack.removeLast();
FlowModel<Variable, Type> beforeCatch =
- beforeBody.removePromotedAll(assignedInBody, _referencedVariables);
+ beforeBody.removePromotedAll(assignedInBody);
_stack.add(beforeCatch);
_stack.add(_current); // afterBodyAndCatches
// Tail of the stack: beforeCatch, afterBodyAndCatches
@@ -690,7 +641,6 @@
}
void tryFinallyStatement_end(Set<Variable> assignedInFinally) {
- _variablesReferenced(assignedInFinally);
FlowModel<Variable, Type> afterBody = _stack.removeLast();
_current = _current.restrict(typeOperations, afterBody, assignedInFinally);
}
@@ -699,8 +649,7 @@
FlowModel<Variable, Type> beforeTry = _stack.removeLast();
FlowModel<Variable, Type> afterBody = _current;
_stack.add(afterBody);
- _current = _join(afterBody,
- beforeTry.removePromotedAll(assignedInBody, _referencedVariables));
+ _current = _join(afterBody, beforeTry.removePromotedAll(assignedInBody));
}
void whileStatement_bodyBegin(
@@ -718,7 +667,7 @@
}
void whileStatement_conditionBegin(Iterable<Variable> loopAssigned) {
- _current = _current.removePromotedAll(loopAssigned, _referencedVariables);
+ _current = _current.removePromotedAll(loopAssigned);
}
void whileStatement_end() {
@@ -731,8 +680,7 @@
/// Register write of the given [variable] in the current state.
void write(Variable variable) {
- _variableReferenced(variable);
- _current = _current.write(typeOperations, variable);
+ _current = _current.write(variable);
}
void _conditionalEnd(Expression condition) {
@@ -749,26 +697,6 @@
FlowModel<Variable, Type> _join(
FlowModel<Variable, Type> first, FlowModel<Variable, Type> second) =>
FlowModel.join(typeOperations, first, second);
-
- /// If assertions are enabled, records that the given variable has been
- /// referenced. The [finish] method will verify that all referenced variables
- /// were eventually passed to [add].
- void _variableReferenced(Variable variable) {
- assert(() {
- _referencedVariables.add(variable);
- return true;
- }());
- }
-
- /// If assertions are enabled, records that the given variables have been
- /// referenced. The [finish] method will verify that all referenced variables
- /// were eventually passed to [add].
- void _variablesReferenced(Iterable<Variable> variables) {
- assert(() {
- _referencedVariables.addAll(variables);
- return true;
- }());
- }
}
/// An instance of the [FlowModel] class represents the information gathered by
@@ -795,6 +723,9 @@
/// variable that is no longer in scope.
final Map<Variable, VariableModel<Type> /*!*/ > variableInfo;
+ /// Variable model for variables that have never been seen before.
+ final VariableModel<Type> _freshVariableInfo;
+
/// Creates a state object with the given [reachable] status. All variables
/// are assumed to be unpromoted and already assigned, so joining another
/// state with this one will have no effect on it.
@@ -804,7 +735,8 @@
const {},
);
- FlowModel._(this.reachable, this.variableInfo) {
+ FlowModel._(this.reachable, this.variableInfo)
+ : _freshVariableInfo = new VariableModel.fresh() {
assert(() {
for (VariableModel<Type> value in variableInfo.values) {
assert(value != null);
@@ -813,16 +745,9 @@
}());
}
- /// Updates the state to track a newly declared local [variable]. The
- /// optional [assigned] boolean indicates whether the variable is assigned at
- /// the point of declaration.
- FlowModel<Variable, Type> add(Variable variable, {bool assigned: false}) {
- Map<Variable, VariableModel<Type>> newVariableInfo =
- new Map<Variable, VariableModel<Type>>.from(variableInfo);
- newVariableInfo[variable] = new VariableModel<Type>(null, assigned);
-
- return new FlowModel<Variable, Type>._(reachable, newVariableInfo);
- }
+ /// Gets the info for the given [variable], creating it if it doesn't exist.
+ VariableModel<Type> infoFor(Variable variable) =>
+ variableInfo[variable] ?? _freshVariableInfo;
/// Updates the state to indicate that the given [variable] has been
/// determined to contain a non-null value.
@@ -831,7 +756,7 @@
/// assigned? Does it matter?
FlowModel<Variable, Type> markNonNullable(
TypeOperations<Variable, Type> typeOperations, Variable variable) {
- VariableModel<Type> info = variableInfo[variable];
+ VariableModel<Type> info = infoFor(variable);
Type previousType = info.promotedType;
previousType ??= typeOperations.variableType(variable);
Type type = typeOperations.promoteToNonNull(previousType);
@@ -853,7 +778,7 @@
Variable variable,
Type type,
) {
- VariableModel<Type> info = variableInfo[variable];
+ VariableModel<Type> info = infoFor(variable);
Type previousType = info.promotedType;
previousType ??= typeOperations.variableType(variable);
@@ -867,10 +792,6 @@
/// Updates the state to indicate that the given [variables] are no longer
/// promoted; they are presumed to have their declared types.
///
- /// If assertions are enabled and [referencedVariables] is not `null`, all
- /// variables in [variables] will be stored in [referencedVariables] as a side
- /// effect of this call.
- ///
/// This is used at the top of loops to conservatively cancel the promotion of
/// variables that are modified within the loop, so that we correctly analyze
/// code like the following:
@@ -887,16 +808,11 @@
/// and only remove promotions if it can be shown that they aren't restored
/// later in the loop body. If we switch to a fixed point analysis, we should
/// be able to remove this method.
- FlowModel<Variable, Type> removePromotedAll(
- Iterable<Variable> variables, Set<Variable> referencedVariables) {
+ FlowModel<Variable, Type> removePromotedAll(Iterable<Variable> variables) {
Map<Variable, VariableModel<Type>> newVariableInfo;
for (Variable variable in variables) {
- assert(() {
- referencedVariables?.add(variable);
- return true;
- }());
- VariableModel<Type> info = variableInfo[variable];
- if (info?.promotedType != null) {
+ VariableModel<Type> info = infoFor(variable);
+ if (info.promotedType != null) {
(newVariableInfo ??= new Map<Variable, VariableModel<Type>>.from(
variableInfo))[variable] = info.withPromotedType(null);
}
@@ -934,16 +850,32 @@
Map<Variable, VariableModel<Type>> newVariableInfo =
<Variable, VariableModel<Type>>{};
bool variableInfoMatchesThis = true;
- bool variableInfoMatchesOther =
- other.variableInfo.length == variableInfo.length;
+ bool variableInfoMatchesOther = true;
for (MapEntry<Variable, VariableModel<Type>> entry
in variableInfo.entries) {
Variable variable = entry.key;
- VariableModel<Type> otherModel = other.variableInfo[variable];
- VariableModel<Type> restricted = entry.value
- .restrict(typeOperations, otherModel, unsafe.contains(variable));
- newVariableInfo[variable] = restricted;
- if (!identical(restricted, entry.value)) variableInfoMatchesThis = false;
+ VariableModel<Type> thisModel = entry.value;
+ VariableModel<Type> otherModel = other.infoFor(variable);
+ VariableModel<Type> restricted = thisModel.restrict(
+ typeOperations, otherModel, unsafe.contains(variable));
+ if (!identical(restricted, _freshVariableInfo)) {
+ newVariableInfo[variable] = restricted;
+ }
+ if (!identical(restricted, thisModel)) variableInfoMatchesThis = false;
+ if (!identical(restricted, otherModel)) variableInfoMatchesOther = false;
+ }
+ for (MapEntry<Variable, VariableModel<Type>> entry
+ in other.variableInfo.entries) {
+ Variable variable = entry.key;
+ if (variableInfo.containsKey(variable)) continue;
+ VariableModel<Type> thisModel = _freshVariableInfo;
+ VariableModel<Type> otherModel = entry.value;
+ VariableModel<Type> restricted = thisModel.restrict(
+ typeOperations, otherModel, unsafe.contains(variable));
+ if (!identical(restricted, _freshVariableInfo)) {
+ newVariableInfo[variable] = restricted;
+ }
+ if (!identical(restricted, thisModel)) variableInfoMatchesThis = false;
if (!identical(restricted, otherModel)) variableInfoMatchesOther = false;
}
assert(variableInfoMatchesThis ==
@@ -975,9 +907,8 @@
/// previous type promotion is removed.
///
/// TODO(paulberry): allow for writes that preserve type promotions.
- FlowModel<Variable, Type> write(
- TypeOperations<Variable, Type> typeOperations, Variable variable) {
- VariableModel<Type> infoForVar = variableInfo[variable];
+ FlowModel<Variable, Type> write(Variable variable) {
+ VariableModel<Type> infoForVar = infoFor(variable);
VariableModel<Type> newInfoForVar = infoForVar.write();
if (identical(newInfoForVar, infoForVar)) return this;
return _updateVariableInfo(variable, newInfoForVar);
@@ -1110,9 +1041,6 @@
/// Operations on types, abstracted from concrete type interfaces.
abstract class TypeOperations<Variable, Type> {
- /// Return `true` if the [variable] is a local variable, not a parameter.
- bool isLocalVariable(Variable variable);
-
/// Returns `true` if [type1] and [type2] are the same type.
bool isSameType(Type type1, Type type2);
@@ -1146,6 +1074,12 @@
VariableModel(this.promotedType, this.assigned);
+ /// Creates a [VariableModel] representing a variable that's never been seen
+ /// before.
+ VariableModel.fresh()
+ : promotedType = null,
+ assigned = false;
+
@override
bool operator ==(Object other) {
return other is VariableModel<Type> &&
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index f1d6340..656b1ae 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -10,6 +10,8 @@
import '../builder/declaration_builder.dart';
+import '../builder/extension_builder.dart';
+
import '../constant_context.dart' show ConstantContext;
import '../dill/dill_library_builder.dart' show DillLibraryBuilder;
@@ -23,8 +25,7 @@
import '../modifier.dart'
show Modifier, constMask, covariantMask, finalMask, lateMask;
-import '../names.dart'
- show callName, emptyName, indexGetName, indexSetName, minusName, plusName;
+import '../names.dart' show callName, emptyName, minusName, plusName;
import '../parser.dart'
show
@@ -1869,11 +1870,19 @@
}
return new ThisPropertyAccessGenerator(this, token, n, getter, setter);
} else if (declaration.isExtensionInstanceMember) {
+ ExtensionBuilder extensionBuilder = declarationBuilder;
Builder setter =
_getCorrespondingSetterBuilder(scope, declaration, name, charOffset);
// TODO(johnniwinther): Check for constantContext like below?
- return new ExtensionInstanceAccessGenerator.fromBuilder(this, name,
- extensionThis, extensionTypeParameters, declaration, token, setter);
+ return new ExtensionInstanceAccessGenerator.fromBuilder(
+ this,
+ extensionBuilder.extension,
+ name,
+ extensionThis,
+ extensionTypeParameters,
+ declaration,
+ token,
+ setter);
} else if (declaration.isRegularMethod) {
assert(declaration.isStatic || declaration.isTopLevel);
return new StaticAccessGenerator(
@@ -3247,17 +3256,21 @@
@override
void handleIndexedExpression(
Token openSquareBracket, Token closeSquareBracket) {
+ assert(checkState(openSquareBracket, [
+ unionOfKinds([ValueKind.Expression, ValueKind.Generator]),
+ unionOfKinds(
+ [ValueKind.Expression, ValueKind.Generator, ValueKind.Initializer])
+ ]));
debugEvent("IndexedExpression");
Expression index = popForValue();
Object receiver = pop();
- if (receiver is ThisAccessGenerator && receiver.isSuper) {
- push(new SuperIndexedAccessGenerator(
- this,
- openSquareBracket,
- index,
- lookupInstanceMember(indexGetName, isSuper: true),
- lookupInstanceMember(indexSetName, isSuper: true)));
+ if (receiver is Generator) {
+ push(receiver.buildIndexedAccess(index, openSquareBracket));
+ } else if (receiver is Expression) {
+ push(IndexedAccessGenerator.make(
+ this, openSquareBracket, receiver, index, null, null));
} else {
+ assert(receiver is Initializer);
push(IndexedAccessGenerator.make(
this, openSquareBracket, toValue(receiver), index, null, null));
}
@@ -3502,8 +3515,8 @@
}
Expression buildExtensionMethodInvocation(
- int fileOffset, Procedure target, Arguments arguments) {
- // TODO(johnniwinther): Check type argument count.
+ int fileOffset, Procedure target, Arguments arguments,
+ {bool isTearOff}) {
List<TypeParameter> typeParameters = target.function.typeParameters;
LocatedMessage argMessage = checkArgumentsForFunction(
target.function, arguments, fileOffset, typeParameters);
@@ -3517,10 +3530,13 @@
message: argMessage);
}
- StaticInvocation node = new StaticInvocation(target, arguments)
- ..fileOffset = fileOffset;
- // TODO(johnniwinther): Check type argument bounds.
- //libraryBuilder.checkBoundsInStaticInvocation(node, typeEnvironment, uri);
+ Expression node;
+ if (isTearOff) {
+ node = new ExtensionTearOff(target, arguments);
+ } else {
+ node = new StaticInvocation(target, arguments);
+ }
+ node.fileOffset = fileOffset;
return node;
}
@@ -4751,7 +4767,8 @@
}
@override
- void endTypeVariable(Token token, int index, Token extendsOrSuper) {
+ void endTypeVariable(
+ Token token, int index, Token extendsOrSuper, Token variance) {
debugEvent("TypeVariable");
UnresolvedType bound = pop();
// Peek to leave type parameters on top of stack.
@@ -4759,6 +4776,9 @@
TypeVariableBuilder variable = typeVariables[index];
variable.bound = bound?.builder;
+ if (variance != null) {
+ variable.variance = Variance.fromString(variance.lexeme);
+ }
}
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 539b86f..0821f5e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -60,7 +60,6 @@
templateConstEvalInvalidStringInterpolationOperand,
templateConstEvalInvalidSymbolName,
templateConstEvalKeyImplementsEqual,
- templateConstEvalNonConstantLiteral,
templateConstEvalNonConstantVariableGet,
templateConstEvalZeroDivisor;
@@ -820,8 +819,7 @@
@override
Constant visitListLiteral(ListLiteral node) {
if (!node.isConst) {
- return report(
- node, templateConstEvalNonConstantLiteral.withArguments('List'));
+ return reportInvalid(node, "Non-constant list literal");
}
final ListConstantBuilder builder =
new ListConstantBuilder(node, node.typeArgument, this);
@@ -844,8 +842,7 @@
@override
Constant visitSetLiteral(SetLiteral node) {
if (!node.isConst) {
- return report(
- node, templateConstEvalNonConstantLiteral.withArguments('Set'));
+ return reportInvalid(node, "Non-constant set literal");
}
final SetConstantBuilder builder =
new SetConstantBuilder(node, node.typeArgument, this);
@@ -868,8 +865,7 @@
@override
Constant visitMapLiteral(MapLiteral node) {
if (!node.isConst) {
- return report(
- node, templateConstEvalNonConstantLiteral.withArguments('Map'));
+ return reportInvalid(node, "Non-constant map literal");
}
final MapConstantBuilder builder =
new MapConstantBuilder(node, node.keyType, node.valueType, this);
@@ -891,8 +887,7 @@
@override
Constant visitFunctionExpression(FunctionExpression node) {
- return report(
- node, templateConstEvalNonConstantLiteral.withArguments('Function'));
+ return reportInvalid(node, "Function literal");
}
@override
@@ -1714,12 +1709,6 @@
}
}
- // TODO(kmillikin) For an invalid factory invocation we should adopt a
- // better message. This will show something like:
- //
- // "The invocation of 'List' is not allowed within a const context."
- //
- // Which is not quite right when the code was "new List()".
String name = target.name.name;
if (target is Procedure && target.isFactory) {
if (name.isEmpty) {
@@ -1728,8 +1717,7 @@
name = '${target.enclosingClass.name}.${name}';
}
}
- return report(
- node, templateConstEvalInvalidStaticInvocation.withArguments(name));
+ return reportInvalid(node, "Invocation of $name");
}
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart b/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart
index e28900f..9bd4a18 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart
@@ -10,10 +10,7 @@
import 'constant_evaluator.dart';
import '../fasta_codes.dart'
- show
- templateConstEvalInvalidMethodInvocation,
- templateConstEvalNegativeShift,
- templateConstEvalZeroDivisor;
+ show templateConstEvalNegativeShift, templateConstEvalZeroDivisor;
abstract class ConstantIntFolder {
final ConstantEvaluator evaluator;
@@ -73,10 +70,7 @@
case '~':
return new IntConstant(~operand.value);
default:
- return evaluator.report(
- node,
- templateConstEvalInvalidMethodInvocation.withArguments(
- op, operand));
+ return evaluator.reportInvalid(node, "Invalid unary operator $op");
}
}
@@ -121,8 +115,7 @@
case '>':
return evaluator.makeBoolConstant(a > b);
default:
- return evaluator.report(node,
- templateConstEvalInvalidMethodInvocation.withArguments(op, left));
+ return evaluator.reportInvalid(node, "Invalid binary operator $op");
}
}
@@ -171,10 +164,7 @@
int intValue = _toUint32(operand.value);
return new DoubleConstant(_truncate32(~intValue).toDouble());
default:
- return evaluator.report(
- node,
- templateConstEvalInvalidMethodInvocation.withArguments(
- op, operand));
+ return evaluator.reportInvalid(node, "Invalid unary operator $op");
}
}
@@ -225,8 +215,7 @@
case '>':
return evaluator.makeBoolConstant(a > b);
default:
- return evaluator.report(node,
- templateConstEvalInvalidMethodInvocation.withArguments(op, left));
+ return evaluator.reportInvalid(node, "Invalid binary operator $op");
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 89098b2..e1f4092 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -82,8 +82,6 @@
import 'kernel_shadow_ast.dart';
-import '../type_inference/type_inferrer.dart';
-
/// A generator represents a subexpression for which we can't yet build an
/// expression because we don't yet know the context in which it's used.
///
@@ -178,6 +176,11 @@
bool voidContext: false,
Procedure interfaceTarget});
+ /// Returns a [Generator] or [Expression] representing an index access
+ /// (e.g. `a[b]`) with the generator on the receiver and [index] as the
+ /// index expression.
+ Generator buildIndexedAccess(Expression index, Token token);
+
/// Returns a [Expression] representing a compile-time error.
///
/// At runtime, an exception will be thrown.
@@ -413,6 +416,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", variable: ");
@@ -451,9 +460,6 @@
final Member setter;
- /// Synthetic variable created for [receiver] if need.
- VariableDeclaration _receiverVariable;
-
PropertyAccessGenerator(ExpressionGeneratorHelper helper, Token token,
this.receiver, this.name, this.getter, this.setter)
: super(helper, token);
@@ -464,11 +470,6 @@
@override
String get _plainNameForRead => name.name;
- receiverAccess() {
- _receiverVariable ??= new VariableDeclaration.forValue(receiver);
- return new VariableGet(_receiverVariable)..fileOffset = fileOffset;
- }
-
@override
Expression doInvocation(int offset, Arguments arguments) {
return _helper.buildMethodInvocation(receiver, name, arguments, offset);
@@ -477,8 +478,6 @@
@override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
- sink.write(", _receiverVariable: ");
- printNodeOn(_receiverVariable, sink, syntheticNames: syntheticNames);
sink.write(", receiver: ");
printNodeOn(receiver, sink, syntheticNames: syntheticNames);
sink.write(", name: ");
@@ -576,6 +575,12 @@
return new PropertyPostIncDec(variable, read, write)..fileOffset = offset;
}
+ @override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
/// Creates a [Generator] for the access of property [name] on [receiver].
static Generator make(
ExpressionGeneratorHelper helper,
@@ -749,6 +754,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", name: ");
@@ -864,6 +875,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", receiver: ");
@@ -996,6 +1013,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", name: ");
@@ -1097,6 +1120,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", receiver: ");
@@ -1222,6 +1251,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", index: ");
@@ -1324,6 +1359,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", index: ");
@@ -1531,6 +1572,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", targetName: ");
@@ -1561,6 +1608,8 @@
///
/// These can only occur within an extension instance member.
class ExtensionInstanceAccessGenerator extends Generator {
+ final Extension extension;
+
/// The original name of the target.
final String targetName;
@@ -1600,6 +1649,7 @@
ExtensionInstanceAccessGenerator(
ExpressionGeneratorHelper helper,
Token token,
+ this.extension,
this.targetName,
this.readTarget,
this.invokeTarget,
@@ -1613,6 +1663,7 @@
factory ExtensionInstanceAccessGenerator.fromBuilder(
ExpressionGeneratorHelper helper,
+ Extension extension,
String targetName,
VariableDeclaration extensionThis,
List<TypeParameter> extensionTypeParameters,
@@ -1648,6 +1699,7 @@
return new ExtensionInstanceAccessGenerator(
helper,
token,
+ extension,
targetName,
readTarget,
invokeTarget,
@@ -1694,7 +1746,8 @@
_extensionTypeParameterCount,
0,
_helper.createVariableGet(extensionThis, fileOffset),
- extensionTypeArguments: _createExtensionTypeArguments()));
+ extensionTypeArguments: _createExtensionTypeArguments()),
+ isTearOff: invokeTarget != null);
}
return read;
}
@@ -1710,9 +1763,10 @@
write = _makeInvalidWrite(value);
} else {
write = new ExtensionSet(
+ extension,
+ _createExtensionTypeArguments(),
_helper.createVariableGet(extensionThis, fileOffset),
- new ExtensionAccessTarget(writeTarget, null, ProcedureKind.Setter,
- _createExtensionTypeArguments()),
+ writeTarget,
value,
forEffect: forEffect,
readOnlyReceiver: true);
@@ -1788,7 +1842,8 @@
extensionTypeArguments: _createExtensionTypeArguments(),
typeArguments: arguments.types,
positionalArguments: arguments.positional,
- namedArguments: arguments.named));
+ namedArguments: arguments.named),
+ isTearOff: false);
} else {
return _helper.buildMethodInvocation(buildSimpleRead(), callName,
arguments, adjustForImplicitCall(_plainNameForRead, offset),
@@ -1797,6 +1852,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", targetName: ");
@@ -1830,6 +1891,8 @@
/// }
///
class ExplicitExtensionInstanceAccessGenerator extends Generator {
+ final Extension extension;
+
/// The name of the original target;
final String targetName;
@@ -1873,6 +1936,7 @@
ExplicitExtensionInstanceAccessGenerator(
ExpressionGeneratorHelper helper,
Token token,
+ this.extension,
this.targetName,
this.readTarget,
this.invokeTarget,
@@ -1890,6 +1954,7 @@
factory ExplicitExtensionInstanceAccessGenerator.fromBuilder(
ExpressionGeneratorHelper helper,
Token token,
+ Extension extension,
Builder getterBuilder,
Builder setterBuilder,
Expression receiver,
@@ -1934,6 +1999,7 @@
return new ExplicitExtensionInstanceAccessGenerator(
helper,
token,
+ extension,
targetName,
readTarget,
invokeTarget,
@@ -1945,7 +2011,7 @@
}
@override
- String get _debugName => "InstanceExtensionAccessGenerator";
+ String get _debugName => "ExplicitExtensionIndexedAccessGenerator";
@override
String get _plainNameForRead => targetName;
@@ -1954,6 +2020,13 @@
return explicitTypeArguments ?? const <DartType>[];
}
+ /// Returns `true` if performing a read operation is a tear off.
+ ///
+ /// This is the case if [invokeTarget] is non-null, since extension methods
+ /// have both a [readTarget] and an [invokeTarget], whereas extension getters
+ /// only have a [readTarget].
+ bool get isReadTearOff => invokeTarget != null;
+
@override
Expression buildSimpleRead() {
if (isNullAware) {
@@ -1977,7 +2050,8 @@
readTarget,
_helper.forest.createArgumentsForExtensionMethod(
fileOffset, extensionTypeParameterCount, 0, receiver,
- extensionTypeArguments: _createExtensionTypeArguments()));
+ extensionTypeArguments: _createExtensionTypeArguments()),
+ isTearOff: isReadTearOff);
}
return read;
}
@@ -2006,12 +2080,8 @@
write = _makeInvalidWrite(value);
} else {
write = new ExtensionSet(
- receiver,
- new ExtensionAccessTarget(writeTarget, null, ProcedureKind.Setter,
- _createExtensionTypeArguments()),
- value,
- readOnlyReceiver: readOnlyReceiver,
- forEffect: forEffect);
+ extension, explicitTypeArguments, receiver, writeTarget, value,
+ readOnlyReceiver: readOnlyReceiver, forEffect: forEffect);
}
write.fileOffset = offset;
return write;
@@ -2174,7 +2244,8 @@
extensionTypeArguments: _createExtensionTypeArguments(),
typeArguments: arguments.types,
positionalArguments: arguments.positional,
- namedArguments: arguments.named));
+ namedArguments: arguments.named),
+ isTearOff: false);
} else {
invocation = _helper.buildMethodInvocation(
_createRead(receiverExpression),
@@ -2193,6 +2264,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", targetName: ");
@@ -2204,8 +2281,204 @@
}
}
+class ExplicitExtensionIndexedAccessGenerator extends Generator {
+ final Extension extension;
+
+ /// The static [Member] generated for the [] operation.
+ ///
+ /// This can be `null` if the extension doesn't have an [] method.
+ final Procedure readTarget;
+
+ /// The static [Member] generated for the []= operation.
+ ///
+ /// This can be `null` if the extension doesn't have an []= method.
+ final Procedure writeTarget;
+
+ /// The expression holding the receiver value for the explicit extension
+ /// access, that is, `a` in `Extension<int>(a)[index]`.
+ final Expression receiver;
+
+ /// The index expression;
+ final Expression index;
+
+ /// The type arguments explicitly passed to the explicit extension access,
+ /// like `<int>` in `Extension<int>(a)[b]`.
+ final List<DartType> explicitTypeArguments;
+
+ /// The number of type parameters declared on the extension declaration.
+ final int extensionTypeParameterCount;
+
+ ExplicitExtensionIndexedAccessGenerator(
+ ExpressionGeneratorHelper helper,
+ Token token,
+ this.extension,
+ this.readTarget,
+ this.writeTarget,
+ this.receiver,
+ this.index,
+ this.explicitTypeArguments,
+ this.extensionTypeParameterCount)
+ : assert(readTarget != null || writeTarget != null),
+ assert(receiver != null),
+ super(helper, token);
+
+ factory ExplicitExtensionIndexedAccessGenerator.fromBuilder(
+ ExpressionGeneratorHelper helper,
+ Token token,
+ Extension extension,
+ Builder getterBuilder,
+ Builder setterBuilder,
+ Expression receiver,
+ Expression index,
+ List<DartType> explicitTypeArguments,
+ int extensionTypeParameterCount) {
+ Procedure readTarget;
+ if (getterBuilder != null) {
+ if (getterBuilder is AccessErrorBuilder) {
+ AccessErrorBuilder error = getterBuilder;
+ getterBuilder = error.builder;
+ // We should only see an access error here if we've looked up a setter
+ // when not explicitly looking for a setter.
+ assert(getterBuilder is MemberBuilder);
+ } else if (getterBuilder is MemberBuilder) {
+ MemberBuilder procedureBuilder = getterBuilder;
+ readTarget = procedureBuilder.member;
+ } else {
+ return unhandled(
+ "${getterBuilder.runtimeType}",
+ "InstanceExtensionAccessGenerator.fromBuilder",
+ offsetForToken(token),
+ helper.uri);
+ }
+ }
+ Procedure writeTarget;
+ if (setterBuilder is MemberBuilder) {
+ MemberBuilder memberBuilder = setterBuilder;
+ writeTarget = memberBuilder.member;
+ }
+ return new ExplicitExtensionIndexedAccessGenerator(
+ helper,
+ token,
+ extension,
+ readTarget,
+ writeTarget,
+ receiver,
+ index,
+ explicitTypeArguments,
+ extensionTypeParameterCount);
+ }
+
+ List<DartType> _createExtensionTypeArguments() {
+ return explicitTypeArguments ?? const <DartType>[];
+ }
+
+ String get _plainNameForRead => "[]";
+
+ String get _debugName => "ExplicitExtensionIndexedAccessGenerator";
+
+ @override
+ Expression buildSimpleRead() {
+ if (readTarget == null) {
+ return _makeInvalidRead();
+ }
+ return _helper.buildExtensionMethodInvocation(
+ fileOffset,
+ readTarget,
+ _forest.createArgumentsForExtensionMethod(
+ fileOffset, extensionTypeParameterCount, 0, receiver,
+ extensionTypeArguments: _createExtensionTypeArguments(),
+ positionalArguments: <Expression>[index]),
+ isTearOff: false);
+ }
+
+ @override
+ Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ if (writeTarget == null) {
+ return _makeInvalidWrite(value);
+ }
+ if (voidContext) {
+ return _helper.buildExtensionMethodInvocation(
+ fileOffset,
+ writeTarget,
+ _forest.createArgumentsForExtensionMethod(
+ fileOffset, extensionTypeParameterCount, 0, receiver,
+ extensionTypeArguments: _createExtensionTypeArguments(),
+ positionalArguments: <Expression>[index, value]),
+ isTearOff: false);
+ } else {
+ return new ExtensionIndexSet(
+ extension, explicitTypeArguments, receiver, writeTarget, index, value)
+ ..fileOffset = fileOffset;
+ }
+ }
+
+ @override
+ Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+ {bool voidContext: false}) {
+ return new IfNullExtensionIndexSet(extension, explicitTypeArguments,
+ receiver, readTarget, writeTarget, index, value,
+ readOffset: fileOffset,
+ testOffset: offset,
+ writeOffset: fileOffset,
+ forEffect: voidContext)
+ ..fileOffset = offset;
+ }
+
+ Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+ {int offset: TreeNode.noOffset,
+ bool voidContext: false,
+ Procedure interfaceTarget,
+ bool isPreIncDec: false,
+ bool isPostIncDec: false}) {
+ return new CompoundExtensionIndexSet(extension, explicitTypeArguments,
+ receiver, readTarget, writeTarget, index, binaryOperator, value,
+ readOffset: fileOffset,
+ binaryOffset: offset,
+ writeOffset: fileOffset,
+ forEffect: voidContext,
+ forPostIncDec: isPostIncDec);
+ }
+
+ @override
+ Expression buildPostfixIncrement(Name binaryOperator,
+ {int offset = TreeNode.noOffset,
+ bool voidContext = false,
+ Procedure interfaceTarget}) {
+ Expression value = _forest.createIntLiteral(1, null)..fileOffset = offset;
+ return buildCompoundAssignment(binaryOperator, value,
+ offset: offset,
+ voidContext: voidContext,
+ interfaceTarget: interfaceTarget,
+ isPostIncDec: true);
+ }
+
+ @override
+ Expression doInvocation(int offset, Arguments arguments) {
+ return _helper.buildMethodInvocation(
+ buildSimpleRead(), callName, arguments, offset,
+ isImplicitCall: true);
+ }
+
+ @override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
+ void printOn(StringSink sink) {
+ NameSystem syntheticNames = new NameSystem();
+ sink.write(", index: ");
+ printNodeOn(index, sink, syntheticNames: syntheticNames);
+ sink.write(", readTarget: ");
+ printQualifiedNameOn(readTarget, sink, syntheticNames: syntheticNames);
+ sink.write(", writeTarget: ");
+ printQualifiedNameOn(writeTarget, sink, syntheticNames: syntheticNames);
+ }
+}
+
/// A [ExplicitExtensionAccessGenerator] represents a subexpression whose
-/// prefix is a forced extension resolution.
+/// prefix is an explicit extension application.
///
/// For instance
///
@@ -2281,28 +2554,33 @@
return _makeInvalidRead();
}
+ Generator _createInstanceAccess(Name name, {bool isNullAware}) {
+ Builder getter = extensionBuilder.lookupLocalMember(name.name);
+ Builder setter =
+ extensionBuilder.lookupLocalMember(name.name, setter: true);
+ if (getter == null && setter == null) {
+ return new UnresolvedNameGenerator(_helper, token, name);
+ }
+ return new ExplicitExtensionInstanceAccessGenerator.fromBuilder(
+ _helper,
+ token,
+ extensionBuilder.extension,
+ getter,
+ setter,
+ receiver,
+ explicitTypeArguments,
+ extensionBuilder.typeParameters?.length ?? 0,
+ isNullAware: isNullAware);
+ }
+
/* Expression | Generator */ buildPropertyAccess(
IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
if (_helper.constantContext != ConstantContext.none) {
_helper.addProblem(
messageNotAConstantExpression, fileOffset, token.length);
}
- Builder getter = extensionBuilder.lookupLocalMember(send.name.name);
- Builder setter =
- extensionBuilder.lookupLocalMember(send.name.name, setter: true);
- if (getter == null && setter == null) {
- return new UnresolvedNameGenerator(_helper, token, send.name);
- }
Generator generator =
- new ExplicitExtensionInstanceAccessGenerator.fromBuilder(
- _helper,
- token,
- getter,
- setter,
- receiver,
- explicitTypeArguments,
- extensionBuilder.typeParameters?.length ?? 0,
- isNullAware: isNullAware);
+ _createInstanceAccess(send.name, isNullAware: isNullAware);
if (send.arguments != null) {
return generator.doInvocation(offsetForToken(send.token), send.arguments);
} else {
@@ -2312,8 +2590,8 @@
@override
doInvocation(int offset, Arguments arguments) {
- return unimplemented(
- "ExplicitExtensionAccessGenerator.doInvocation", fileOffset, _uri);
+ Generator generator = _createInstanceAccess(callName, isNullAware: false);
+ return generator.doInvocation(offset, arguments);
}
@override
@@ -2329,6 +2607,26 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ Builder getter = extensionBuilder.lookupLocalMember(indexGetName.name);
+ Builder setter = extensionBuilder.lookupLocalMember(indexSetName.name);
+ if (getter == null && setter == null) {
+ return new UnresolvedNameGenerator(_helper, token, indexGetName);
+ }
+
+ return new ExplicitExtensionIndexedAccessGenerator.fromBuilder(
+ _helper,
+ token,
+ extensionBuilder.extension,
+ getter,
+ setter,
+ receiver,
+ index,
+ explicitTypeArguments,
+ extensionBuilder.typeParameters?.length ?? 0);
+ }
+
+ @override
void printOn(StringSink sink) {
sink.write(", extensionBuilder: ");
sink.write(extensionBuilder);
@@ -2413,6 +2711,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
sink.write(", builder: ");
sink.write(builder);
@@ -2559,6 +2863,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
sink.write(", prefixGenerator: ");
sink.write(prefixGenerator);
@@ -2878,6 +3188,14 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ // TODO(johnniwinther): The read-only quality of the variable should be
+ // passed on to the generator.
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
NameSystem syntheticNames = new NameSystem();
sink.write(", expression: ");
@@ -3001,6 +3319,12 @@
}
return buildError(arguments);
}
+
+ @override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
}
class UnresolvedNameGenerator extends ErroneousExpressionGenerator {
@@ -3077,6 +3401,12 @@
return buildError(_forest.createArguments(fileOffset, <Expression>[value]),
isSetter: true);
}
+
+ @override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
}
class UnlinkedGenerator extends Generator {
@@ -3196,6 +3526,12 @@
Expression doInvocation(int offset, Arguments arguments) {
return unsupported("doInvocation", offset, _uri);
}
+
+ @override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
}
abstract class ContextAwareGenerator extends Generator {
@@ -3258,6 +3594,12 @@
return _helper.buildProblem(messageIllegalAssignmentToNonAssignable,
fileOffset, lengthForToken(token));
}
+
+ @override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
}
class DelayedAssignment extends ContextAwareGenerator {
@@ -3499,6 +3841,12 @@
Expression _makeInvalidWrite(Expression value) => _makeInvalidRead();
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
sink.write(", prefix: ");
sink.write(prefix.name);
@@ -3587,6 +3935,12 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
+
+ @override
void printOn(StringSink sink) {
sink.write(", prefixGenerator: ");
prefixGenerator.printOn(sink);
@@ -3688,6 +4042,12 @@
Constness constness) {
return buildProblem();
}
+
+ @override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return new IndexedAccessGenerator(
+ _helper, token, buildSimpleRead(), index, null, null);
+ }
}
/// A [ThisAccessGenerator] represents a subexpression whose prefix is `this`
@@ -3910,6 +4270,20 @@
return buildAssignmentError();
}
+ @override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ if (isSuper) {
+ return new SuperIndexedAccessGenerator(
+ _helper,
+ token,
+ index,
+ _helper.lookupInstanceMember(indexGetName, isSuper: true),
+ _helper.lookupInstanceMember(indexSetName, isSuper: true));
+ } else {
+ return new ThisIndexedAccessGenerator(_helper, token, index, null, null);
+ }
+ }
+
Expression buildAssignmentError() {
return _helper.buildProblem(
isSuper ? messageCannotAssignToSuper : messageNotAnLvalue,
@@ -4045,6 +4419,11 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return unsupported("buildIndexedAccess", offsetForToken(token), _uri);
+ }
+
+ @override
void printOn(StringSink sink) {
sink.write(", name: ");
sink.write(name.name);
@@ -4119,6 +4498,11 @@
}
@override
+ Generator buildIndexedAccess(Expression index, Token token) {
+ return unsupported("buildIndexedAccess", offsetForToken(token), _uri);
+ }
+
+ @override
void printOn(StringSink sink) {
sink.write(", name: ");
sink.write(name.name);
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index 3231dc7..a6d6421 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -82,7 +82,8 @@
{Constness constness, int charOffset});
Expression buildExtensionMethodInvocation(
- int fileOffset, Procedure target, Arguments arguments);
+ int fileOffset, Procedure target, Arguments arguments,
+ {bool isTearOff});
Expression throwNoSuchMethodError(
Expression receiver, String name, Arguments arguments, int offset,
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index b761c58..816cc1e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -41,6 +41,8 @@
switch (node.kind) {
case InternalExpressionKind.Cascade:
return visitCascade(node, typeContext);
+ case InternalExpressionKind.CompoundExtensionIndexSet:
+ return visitCompoundExtensionIndexSet(node, typeContext);
case InternalExpressionKind.CompoundIndexSet:
return visitCompoundIndexSet(node, typeContext);
case InternalExpressionKind.CompoundPropertySet:
@@ -49,10 +51,16 @@
return visitCompoundSuperIndexSet(node, typeContext);
case InternalExpressionKind.DeferredCheck:
return visitDeferredCheck(node, typeContext);
+ case InternalExpressionKind.ExtensionIndexSet:
+ return visitExtensionIndexSet(node, typeContext);
+ case InternalExpressionKind.ExtensionTearOff:
+ return visitExtensionTearOff(node, typeContext);
case InternalExpressionKind.ExtensionSet:
return visitExtensionSet(node, typeContext);
case InternalExpressionKind.IfNull:
return visitIfNull(node, typeContext);
+ case InternalExpressionKind.IfNullExtensionIndexSet:
+ return visitIfNullExtensionIndexSet(node, typeContext);
case InternalExpressionKind.IfNullIndexSet:
return visitIfNullIndexSet(node, typeContext);
case InternalExpressionKind.IfNullPropertySet:
@@ -381,16 +389,50 @@
// No inference needs to be done.
}
+ ExpressionInferenceResult visitExtensionTearOff(
+ ExtensionTearOff node, DartType typeContext) {
+ FunctionType calleeType = node.target != null
+ ? node.target.function.functionType
+ : new FunctionType([], const DynamicType());
+ bool hadExplicitTypeArguments =
+ getExplicitTypeArguments(node.arguments) != null;
+ DartType inferredType = inferrer.inferInvocation(typeContext,
+ node.fileOffset, calleeType, calleeType.returnType, node.arguments);
+ Expression replacement = new StaticInvocation(node.target, node.arguments);
+ if (!inferrer.isTopLevel &&
+ !hadExplicitTypeArguments &&
+ node.target != null) {
+ inferrer.library.checkBoundsInStaticInvocation(
+ replacement, inferrer.typeSchemaEnvironment, inferrer.helper.uri,
+ inferred: true);
+ }
+ node.replaceWith(replacement);
+ inferredType =
+ inferrer.instantiateTearOff(inferredType, typeContext, replacement);
+ return new ExpressionInferenceResult(inferredType);
+ }
+
ExpressionInferenceResult visitExtensionSet(
ExtensionSet node, DartType typeContext) {
- // Since the variable is not used in the body we don't need to type infer
- // it. We can just type infer the body.
ExpressionInferenceResult receiverResult = inferrer.inferExpression(
node.receiver, const UnknownType(), true,
isVoidAllowed: false);
+ List<DartType> extensionTypeArguments =
+ inferrer.computeExtensionTypeArgument(node.extension,
+ node.explicitTypeArguments, receiverResult.inferredType);
+
+ DartType receiverType = inferrer.getExtensionReceiverType(
+ node.extension, extensionTypeArguments);
+
+ inferrer.ensureAssignable(receiverType, receiverResult.inferredType,
+ node.receiver, node.receiver.fileOffset);
+
+ ObjectAccessTarget target = new ExtensionAccessTarget(
+ node.target, null, ProcedureKind.Setter, extensionTypeArguments);
+
DartType valueType =
- inferrer.getSetterType(node.target, receiverResult.inferredType);
+ inferrer.getSetterType(target, receiverResult.inferredType);
ExpressionInferenceResult valueResult = inferrer.inferExpression(
node.value, const UnknownType(), true,
@@ -417,9 +459,9 @@
receiver = createVariableGet(receiverVariable);
}
Expression assignment = new StaticInvocation(
- node.target.member,
+ node.target,
new Arguments(<Expression>[receiver, value],
- types: node.target.inferredExtensionTypeArguments)
+ types: extensionTypeArguments)
..fileOffset = node.fileOffset)
..fileOffset = node.fileOffset;
@@ -2268,9 +2310,9 @@
Expression assignment;
if (indexSetTarget.isMissing) {
assignment = inferrer.helper.buildProblem(
- templateSuperclassHasNoMethod.withArguments('[]='),
+ templateSuperclassHasNoMethod.withArguments(indexSetName.name),
node.fileOffset,
- '[]='.length);
+ noLength);
} else {
assert(indexSetTarget.isInstanceMember);
inferrer.instrumentation?.record(inferrer.uri, node.fileOffset, 'target',
@@ -2295,6 +2337,85 @@
return new ExpressionInferenceResult(inferredType, replacement);
}
+ ExpressionInferenceResult visitExtensionIndexSet(
+ ExtensionIndexSet node, DartType typeContext) {
+ ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+ node.receiver, const UnknownType(), true,
+ isVoidAllowed: false);
+
+ List<DartType> extensionTypeArguments =
+ inferrer.computeExtensionTypeArgument(node.extension,
+ node.explicitTypeArguments, receiverResult.inferredType);
+
+ DartType receiverType = inferrer.getExtensionReceiverType(
+ node.extension, extensionTypeArguments);
+
+ inferrer.ensureAssignable(receiverType, receiverResult.inferredType,
+ node.receiver, node.receiver.fileOffset);
+
+ VariableDeclaration receiverVariable =
+ createVariable(node.receiver, receiverType);
+
+ ObjectAccessTarget target = new ExtensionAccessTarget(
+ node.setter, null, ProcedureKind.Operator, extensionTypeArguments);
+
+ DartType indexType = inferrer.getIndexKeyType(target, receiverType);
+ DartType valueType = inferrer.getIndexSetValueType(target, receiverType);
+
+ ExpressionInferenceResult indexResult = inferrer
+ .inferExpression(node.index, indexType, true, isVoidAllowed: true);
+
+ inferrer.ensureAssignable(
+ indexType, indexResult.inferredType, node.index, node.index.fileOffset);
+
+ VariableDeclaration indexVariable =
+ createVariable(node.index, indexResult.inferredType);
+
+ ExpressionInferenceResult valueResult = inferrer
+ .inferExpression(node.value, valueType, true, isVoidAllowed: true);
+ inferrer.ensureAssignable(
+ valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+ VariableDeclaration valueVariable =
+ createVariable(node.value, valueResult.inferredType);
+
+ // The inferred type is that inferred type of the value expression and not
+ // the type of the value parameter.
+ DartType inferredType = valueResult.inferredType;
+
+ Expression replacement;
+ Expression assignment;
+ if (target.isMissing) {
+ assignment = inferrer.helper.buildProblem(
+ templateUndefinedMethod.withArguments(
+ indexSetName.name, receiverType),
+ node.fileOffset,
+ noLength);
+ } else {
+ assert(target.isExtensionMember);
+ assignment = new StaticInvocation(
+ target.member,
+ new Arguments(<Expression>[
+ createVariableGet(receiverVariable),
+ createVariableGet(indexVariable),
+ createVariableGet(valueVariable)
+ ], types: target.inferredExtensionTypeArguments)
+ ..fileOffset = node.fileOffset)
+ ..fileOffset = node.fileOffset;
+ }
+ VariableDeclaration assignmentVariable =
+ createVariable(assignment, const VoidType());
+ node.replaceWith(replacement = new Let(
+ receiverVariable,
+ createLet(
+ indexVariable,
+ createLet(
+ valueVariable,
+ createLet(
+ assignmentVariable, createVariableGet(valueVariable)))))
+ ..fileOffset = node.fileOffset);
+ return new ExpressionInferenceResult(inferredType, replacement);
+ }
+
ExpressionInferenceResult visitIfNullIndexSet(
IfNullIndexSet node, DartType typeContext) {
ExpressionInferenceResult receiverResult = inferrer.inferExpression(
@@ -2436,18 +2557,18 @@
Expression inner;
if (node.forEffect) {
- // Encode `o[a] ??= b`, if `node.readOnlyReceiver` is false, as:
+ // Encode `Extension(o)[a] ??= b`, if `node.readOnlyReceiver` is false,
+ // as:
//
- // let v1 = o in
- // let v2 = a in
- // let v3 = v1[v2] in
- // v3 == null ? v1.[]=(v2, b) : null
+ // let receiverVariable = o in
+ // let indexVariable = a in
+ // receiverVariable[indexVariable] == null
+ // ? receiverVariable.[]=(indexVariable, b) : null
//
// and if `node.readOnlyReceiver` is true as:
//
- // let v2 = a in
- // let v3 = o[v2] in
- // v3 == null ? o.[]=(v2, b) : null
+ // let indexVariable = a in
+ // o[indexVariable] == null ? o.[]=(indexVariable, b) : null
//
MethodInvocation equalsNull =
createEqualsNull(node.testOffset, read, equalsMember);
@@ -2456,26 +2577,28 @@
..fileOffset = node.testOffset;
inner = createLet(indexVariable, conditional);
} else {
- // Encode `o[a] ??= b` as, if `node.readOnlyReceiver` is false, as:
+ // Encode `Extension(o)[a] ??= b` as, if `node.readOnlyReceiver` is false,
+ // as:
//
- // let v1 = o in
- // let v2 = a in
- // let v3 = v1[v2] in
- // v3 == null
- // ? (let v4 = b in
- // let _ = v1.[]=(v2, v4) in
- // v4)
- // : v3
+ // let receiverVariable = o in
+ // let indexVariable = a in
+ // let readVariable = receiverVariable[indexVariable] in
+ // readVariable == null
+ // ? (let valueVariable = b in
+ // let writeVariable =
+ // receiverVariable.[]=(indexVariable, valueVariable) in
+ // valueVariable)
+ // : readVariable
//
// and if `node.readOnlyReceiver` is true as:
//
- // let v2 = a in
- // let v3 = o[v2] in
- // v3 == null
- // ? (let v4 = b in
- // let _ = o.[]=(v2, v4) in
- // v4)
- // : v3
+ // let indexVariable = a in
+ // let readVariable = o[indexVariable] in
+ // readVariable == null
+ // ? (let valueVariable = b in
+ // let writeVariable = o.[]=(indexVariable, valueVariable) in
+ // valueVariable)
+ // : readVariable
//
//
assert(valueVariable != null);
@@ -2646,6 +2769,171 @@
return new ExpressionInferenceResult(inferredType, replacement);
}
+ ExpressionInferenceResult visitIfNullExtensionIndexSet(
+ IfNullExtensionIndexSet node, DartType typeContext) {
+ ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+ node.receiver, const UnknownType(), true,
+ isVoidAllowed: false);
+
+ List<DartType> extensionTypeArguments =
+ inferrer.computeExtensionTypeArgument(node.extension,
+ node.explicitTypeArguments, receiverResult.inferredType);
+
+ DartType receiverType = inferrer.getExtensionReceiverType(
+ node.extension, extensionTypeArguments);
+
+ inferrer.ensureAssignable(receiverType, receiverResult.inferredType,
+ node.receiver, node.receiver.fileOffset);
+
+ VariableDeclaration receiverVariable =
+ createVariable(node.receiver, receiverType);
+
+ ObjectAccessTarget readTarget = node.getter != null
+ ? new ExtensionAccessTarget(
+ node.getter, null, ProcedureKind.Operator, extensionTypeArguments)
+ : const ObjectAccessTarget.missing();
+
+ DartType readType = inferrer.getReturnType(readTarget, receiverType);
+ DartType readIndexType = inferrer.getIndexKeyType(readTarget, receiverType);
+
+ Member equalsMember = inferrer
+ .findInterfaceMember(readType, equalsName, node.testOffset)
+ .member;
+
+ ObjectAccessTarget writeTarget = node.setter != null
+ ? new ExtensionAccessTarget(
+ node.setter, null, ProcedureKind.Operator, extensionTypeArguments)
+ : const ObjectAccessTarget.missing();
+
+ DartType writeIndexType =
+ inferrer.getIndexKeyType(writeTarget, receiverType);
+ DartType valueType =
+ inferrer.getIndexSetValueType(writeTarget, receiverType);
+
+ ExpressionInferenceResult indexResult = inferrer
+ .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
+
+ VariableDeclaration indexVariable =
+ createVariable(node.index, indexResult.inferredType);
+
+ VariableGet readIndex = createVariableGet(indexVariable);
+ inferrer.ensureAssignable(readIndexType, indexResult.inferredType,
+ readIndex, readIndex.fileOffset);
+
+ VariableGet writeIndex = createVariableGet(indexVariable);
+ inferrer.ensureAssignable(writeIndexType, indexResult.inferredType,
+ writeIndex, writeIndex.fileOffset);
+
+ ExpressionInferenceResult valueResult = inferrer
+ .inferExpression(node.value, valueType, true, isVoidAllowed: true);
+ inferrer.ensureAssignable(
+ valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+
+ DartType inferredType = inferrer.typeSchemaEnvironment
+ .getStandardUpperBound(readType, valueResult.inferredType);
+
+ Expression read;
+
+ if (readTarget.isMissing) {
+ read = inferrer.helper.buildProblem(
+ templateUndefinedMethod.withArguments(
+ indexGetName.name, receiverType),
+ node.readOffset,
+ noLength);
+ } else {
+ assert(readTarget.isExtensionMember);
+ read = new StaticInvocation(
+ readTarget.member,
+ new Arguments(<Expression>[
+ createVariableGet(receiverVariable),
+ readIndex,
+ ], types: readTarget.inferredExtensionTypeArguments)
+ ..fileOffset = node.readOffset)
+ ..fileOffset = node.readOffset;
+ }
+
+ VariableDeclaration valueVariable;
+ Expression valueExpression;
+ if (node.forEffect) {
+ valueExpression = node.value;
+ } else {
+ valueVariable = createVariable(node.value, valueResult.inferredType);
+ valueExpression = createVariableGet(valueVariable);
+ }
+
+ Expression write;
+
+ if (writeTarget.isMissing) {
+ write = inferrer.helper.buildProblem(
+ templateUndefinedMethod.withArguments(
+ indexSetName.name, receiverType),
+ node.writeOffset,
+ noLength);
+ } else {
+ assert(writeTarget.isExtensionMember);
+ write = new StaticInvocation(
+ writeTarget.member,
+ new Arguments(<Expression>[
+ createVariableGet(receiverVariable),
+ writeIndex,
+ valueExpression
+ ], types: writeTarget.inferredExtensionTypeArguments)
+ ..fileOffset = node.writeOffset)
+ ..fileOffset = node.writeOffset;
+ }
+
+ Expression inner;
+ if (node.forEffect) {
+ // Encode `Extension(o)[a] ??= b` as:
+ //
+ // let receiverVariable = o;
+ // let indexVariable = a in
+ // receiverVariable[indexVariable] == null
+ // ? receiverVariable.[]=(indexVariable, b) : null
+ //
+ MethodInvocation equalsNull =
+ createEqualsNull(node.testOffset, read, equalsMember);
+ ConditionalExpression conditional = new ConditionalExpression(equalsNull,
+ write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
+ ..fileOffset = node.testOffset;
+ inner = createLet(indexVariable, conditional);
+ } else {
+ // Encode `Extension(o)[a] ??= b` as:
+ //
+ // let receiverVariable = o;
+ // let indexVariable = a in
+ // let readVariable = receiverVariable[indexVariable] in
+ // readVariable == null
+ // ? (let valueVariable = b in
+ // let writeVariable =
+ // receiverVariable.[]=(indexVariable, valueVariable) in
+ // valueVariable)
+ // : readVariable
+ //
+ assert(valueVariable != null);
+
+ VariableDeclaration readVariable = createVariable(read, readType);
+ MethodInvocation equalsNull = createEqualsNull(
+ node.testOffset, createVariableGet(readVariable), equalsMember);
+ VariableDeclaration writeVariable =
+ createVariable(write, const VoidType());
+ ConditionalExpression conditional = new ConditionalExpression(
+ equalsNull,
+ createLet(valueVariable,
+ createLet(writeVariable, createVariableGet(valueVariable))),
+ createVariableGet(readVariable),
+ inferredType)
+ ..fileOffset = node.fileOffset;
+ inner = createLet(indexVariable, createLet(readVariable, conditional));
+ }
+
+ Expression replacement = new Let(receiverVariable, inner)
+ ..fileOffset = node.fileOffset;
+
+ node.replaceWith(replacement);
+ return new ExpressionInferenceResult(inferredType, replacement);
+ }
+
ExpressionInferenceResult visitCompoundIndexSet(
CompoundIndexSet node, DartType typeContext) {
ExpressionInferenceResult receiverResult = inferrer.inferExpression(
@@ -3368,6 +3656,247 @@
node.forPostIncDec ? readType : binaryType, replacement);
}
+ ExpressionInferenceResult visitCompoundExtensionIndexSet(
+ CompoundExtensionIndexSet node, DartType typeContext) {
+ ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+ node.receiver, const UnknownType(), true,
+ isVoidAllowed: false);
+
+ List<DartType> extensionTypeArguments =
+ inferrer.computeExtensionTypeArgument(node.extension,
+ node.explicitTypeArguments, receiverResult.inferredType);
+
+ ObjectAccessTarget readTarget = node.getter != null
+ ? new ExtensionAccessTarget(
+ node.getter, null, ProcedureKind.Operator, extensionTypeArguments)
+ : const ObjectAccessTarget.missing();
+
+ DartType receiverType = inferrer.getPositionalParameterTypeForTarget(
+ readTarget, receiverResult.inferredType, 0);
+
+ inferrer.ensureAssignable(receiverType, receiverResult.inferredType,
+ node.receiver, node.receiver.fileOffset);
+
+ VariableDeclaration receiverVariable =
+ createVariable(node.receiver, receiverType);
+
+ DartType readType = inferrer.getReturnType(readTarget, receiverType);
+ DartType readIndexType = inferrer.getPositionalParameterTypeForTarget(
+ readTarget, receiverType, 0);
+
+ ExpressionInferenceResult indexResult = inferrer
+ .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
+ VariableDeclaration indexVariable =
+ createVariable(node.index, indexResult.inferredType);
+
+ Expression readIndex = createVariableGet(indexVariable);
+ Expression readIndexReplacement = inferrer.ensureAssignable(readIndexType,
+ indexResult.inferredType, readIndex, readIndex.fileOffset);
+ if (readIndexReplacement != null) {
+ readIndex = readIndexReplacement;
+ }
+
+ Expression read;
+ if (readTarget.isMissing) {
+ read = inferrer.helper.buildProblem(
+ templateUndefinedMethod.withArguments(
+ indexGetName.name, receiverType),
+ node.readOffset,
+ noLength);
+ } else {
+ assert(readTarget.isExtensionMember);
+ read = new StaticInvocation(
+ readTarget.member,
+ new Arguments(<Expression>[
+ createVariableGet(receiverVariable),
+ readIndex,
+ ], types: readTarget.inferredExtensionTypeArguments)
+ ..fileOffset = node.readOffset)
+ ..fileOffset = node.readOffset;
+ }
+
+ VariableDeclaration leftVariable;
+ Expression left;
+ if (node.forEffect) {
+ left = read;
+ } else if (node.forPostIncDec) {
+ leftVariable = createVariable(read, readType);
+ left = createVariableGet(leftVariable);
+ } else {
+ left = read;
+ }
+
+ ObjectAccessTarget binaryTarget = inferrer.findInterfaceMember(
+ readType, node.binaryName, node.binaryOffset,
+ includeExtensionMethods: true);
+
+ MethodContravarianceCheckKind binaryCheckKind =
+ inferrer.preCheckInvocationContravariance(readType, binaryTarget,
+ isThisReceiver: false);
+
+ DartType binaryType = inferrer.getReturnType(binaryTarget, readType);
+ DartType rhsType =
+ inferrer.getPositionalParameterTypeForTarget(binaryTarget, readType, 0);
+
+ ExpressionInferenceResult rhsResult =
+ inferrer.inferExpression(node.rhs, rhsType, true, isVoidAllowed: true);
+ inferrer.ensureAssignable(
+ rhsType, rhsResult.inferredType, node.rhs, node.rhs.fileOffset);
+
+ if (inferrer.isOverloadedArithmeticOperatorAndType(
+ binaryTarget, readType)) {
+ binaryType = inferrer.typeSchemaEnvironment
+ .getTypeOfOverloadedArithmetic(readType, rhsResult.inferredType);
+ }
+
+ Expression binary;
+ if (binaryTarget.isMissing) {
+ binary = inferrer.helper.buildProblem(
+ templateUndefinedMethod.withArguments(node.binaryName.name, readType),
+ node.binaryOffset,
+ node.binaryName.name.length);
+ } else if (binaryTarget.isExtensionMember) {
+ binary = new StaticInvocation(
+ binaryTarget.member,
+ new Arguments(<Expression>[
+ left,
+ node.rhs,
+ ], types: binaryTarget.inferredExtensionTypeArguments)
+ ..fileOffset = node.binaryOffset)
+ ..fileOffset = node.binaryOffset;
+ } else {
+ binary = new MethodInvocation(
+ left,
+ node.binaryName,
+ new Arguments(<Expression>[
+ node.rhs,
+ ])
+ ..fileOffset = node.binaryOffset,
+ binaryTarget.member)
+ ..fileOffset = node.binaryOffset;
+
+ if (binaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
+ if (inferrer.instrumentation != null) {
+ inferrer.instrumentation.record(inferrer.uri, node.binaryOffset,
+ 'checkReturn', new InstrumentationValueForType(readType));
+ }
+ binary = new AsExpression(binary, binaryType)
+ ..isTypeError = true
+ ..fileOffset = node.binaryOffset;
+ }
+ }
+
+ ObjectAccessTarget writeTarget = node.setter != null
+ ? new ExtensionAccessTarget(
+ node.setter, null, ProcedureKind.Operator, extensionTypeArguments)
+ : const ObjectAccessTarget.missing();
+
+ DartType writeIndexType = inferrer.getPositionalParameterTypeForTarget(
+ writeTarget, receiverType, 0);
+ Expression writeIndex = createVariableGet(indexVariable);
+ Expression writeIndexReplacement = inferrer.ensureAssignable(writeIndexType,
+ indexResult.inferredType, writeIndex, writeIndex.fileOffset);
+ if (writeIndexReplacement != null) {
+ writeIndex = writeIndexReplacement;
+ }
+
+ DartType valueType =
+ inferrer.getIndexSetValueType(writeTarget, inferrer.thisType);
+ Expression binaryReplacement = inferrer.ensureAssignable(
+ valueType, binaryType, binary, node.fileOffset);
+ if (binaryReplacement != null) {
+ binary = binaryReplacement;
+ }
+
+ VariableDeclaration valueVariable;
+ Expression valueExpression;
+ if (node.forEffect || node.forPostIncDec) {
+ valueExpression = binary;
+ } else {
+ valueVariable = createVariable(binary, binaryType);
+ valueExpression = createVariableGet(valueVariable);
+ }
+
+ Expression write;
+
+ if (writeTarget.isMissing) {
+ write = inferrer.helper.buildProblem(
+ templateUndefinedMethod.withArguments(
+ indexSetName.name, receiverType),
+ node.writeOffset,
+ noLength);
+ } else {
+ assert(writeTarget.isExtensionMember);
+ write = new StaticInvocation(
+ writeTarget.member,
+ new Arguments(<Expression>[
+ createVariableGet(receiverVariable),
+ writeIndex,
+ valueExpression
+ ], types: writeTarget.inferredExtensionTypeArguments)
+ ..fileOffset = node.writeOffset)
+ ..fileOffset = node.writeOffset;
+ }
+
+ Expression inner;
+ if (node.forEffect) {
+ assert(leftVariable == null);
+ assert(valueVariable == null);
+ // Encode `Extension(o)[a] += b` as:
+ //
+ // let receiverVariable = o in
+ // let indexVariable = a in
+ // receiverVariable.[]=(receiverVariable, o.[](indexVariable) + b)
+ //
+ inner = createLet(indexVariable, write);
+ } else if (node.forPostIncDec) {
+ // Encode `Extension(o)[a]++` as:
+ //
+ // let receiverVariable = o in
+ // let indexVariable = a in
+ // let leftVariable = receiverVariable.[](indexVariable)
+ // let writeVariable =
+ // receiverVariable.[]=(indexVariable, leftVariable + 1) in
+ // leftVariable
+ //
+ assert(leftVariable != null);
+ assert(valueVariable == null);
+
+ VariableDeclaration writeVariable =
+ createVariable(write, const VoidType());
+ inner = createLet(
+ indexVariable,
+ createLet(leftVariable,
+ createLet(writeVariable, createVariableGet(leftVariable))));
+ } else {
+ // Encode `Extension(o)[a] += b` as:
+ //
+ // let receiverVariable = o in
+ // let indexVariable = a in
+ // let valueVariable = receiverVariable.[](indexVariable) + b
+ // let writeVariable =
+ // receiverVariable.[]=(indexVariable, valueVariable) in
+ // valueVariable
+ //
+ assert(leftVariable == null);
+ assert(valueVariable != null);
+
+ VariableDeclaration writeVariable =
+ createVariable(write, const VoidType());
+ inner = createLet(
+ indexVariable,
+ createLet(valueVariable,
+ createLet(writeVariable, createVariableGet(valueVariable))));
+ }
+
+ Expression replacement = new Let(receiverVariable, inner)
+ ..fileOffset = node.fileOffset;
+
+ node.replaceWith(replacement);
+ return new ExpressionInferenceResult(
+ node.forPostIncDec ? readType : binaryType, replacement);
+ }
+
@override
ExpressionInferenceResult visitNullLiteral(
NullLiteral node, DartType typeContext) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 294aa54..627fbc5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -184,12 +184,16 @@
enum InternalExpressionKind {
Cascade,
+ CompoundExtensionIndexSet,
CompoundIndexSet,
CompoundPropertySet,
CompoundSuperIndexSet,
DeferredCheck,
+ ExtensionIndexSet,
+ ExtensionTearOff,
ExtensionSet,
IfNull,
+ IfNullExtensionIndexSet,
IfNullIndexSet,
IfNullPropertySet,
IfNullSet,
@@ -1601,6 +1605,77 @@
}
}
+/// Internal expression representing an extension index set expression.
+///
+/// An extension index set expression of the form `Extension(o)[a] = b` used
+/// for value is encoded as the expression:
+///
+/// let receiverVariable = o
+/// let indexVariable = a in
+/// let valueVariable = b in '
+/// let writeVariable =
+/// receiverVariable.[]=(indexVariable, valueVariable) in
+/// valueVariable
+///
+/// An extension index set expression used for effect is encoded as
+///
+/// o.[]=(a, b)
+///
+/// using [StaticInvocation].
+///
+class ExtensionIndexSet extends InternalExpression {
+ final Extension extension;
+
+ final List<DartType> explicitTypeArguments;
+
+ /// The receiver of the extension access.
+ Expression receiver;
+
+ /// The []= member.
+ Member setter;
+
+ /// The index expression of the operation.
+ Expression index;
+
+ /// The value expression of the operation.
+ Expression value;
+
+ ExtensionIndexSet(this.extension, this.explicitTypeArguments, this.receiver,
+ this.setter, this.index, this.value)
+ : assert(explicitTypeArguments == null ||
+ explicitTypeArguments.length == extension.typeParameters.length) {
+ receiver?.parent = this;
+ index?.parent = this;
+ value?.parent = this;
+ }
+
+ @override
+ InternalExpressionKind get kind => InternalExpressionKind.ExtensionIndexSet;
+
+ @override
+ void visitChildren(Visitor<dynamic> v) {
+ receiver?.accept(v);
+ index?.accept(v);
+ value?.accept(v);
+ }
+
+ @override
+ void transformChildren(Transformer v) {
+ if (receiver != null) {
+ receiver = receiver.accept<TreeNode>(v);
+ receiver?.parent = this;
+ }
+ if (index != null) {
+ index = index.accept<TreeNode>(v);
+ index?.parent = this;
+ }
+ if (value != null) {
+ value = value.accept<TreeNode>(v);
+ value?.parent = this;
+ }
+ }
+}
+
/// Internal expression representing an if-null index assignment.
///
/// An if-null index assignment of the form `o[a] ??= b` is, if used for value,
@@ -1768,6 +1843,99 @@
}
}
+/// Internal expression representing an if-null super index set expression.
+///
+/// An if-null super index set expression of the form `super[a] ??= b` is, if
+/// used for value, encoded as the expression:
+///
+/// let v1 = a in
+/// let v2 = super.[](v1) in
+/// v2 == null
+/// ? (let v3 = b in
+/// let _ = super.[]=(v1, v3) in
+/// v3)
+/// : v2
+///
+/// and, if used for effect, encoded as the expression:
+///
+/// let v1 = a in
+/// let v2 = super.[](v1) in
+/// v2 == null ? super.[]=(v1, b) : null
+///
+class IfNullExtensionIndexSet extends InternalExpression {
+ final Extension extension;
+
+ final List<DartType> explicitTypeArguments;
+
+ /// The extension receiver;
+ Expression receiver;
+
+ /// The [] member;
+ Member getter;
+
+ /// The []= member;
+ Member setter;
+
+ /// The index expression of the operation.
+ Expression index;
+
+ /// The value expression of the operation.
+ Expression value;
+
+ /// The file offset for the [] operation.
+ final int readOffset;
+
+ /// The file offset for the == operation.
+ final int testOffset;
+
+ /// The file offset for the []= operation.
+ final int writeOffset;
+
+ /// If `true`, the expression is only need for effect and not for its value.
+ final bool forEffect;
+
+ IfNullExtensionIndexSet(this.extension, this.explicitTypeArguments,
+ this.receiver, this.getter, this.setter, this.index, this.value,
+ {this.readOffset, this.testOffset, this.writeOffset, this.forEffect})
+ : assert(explicitTypeArguments == null ||
+ explicitTypeArguments.length == extension.typeParameters.length),
+ assert(readOffset != null),
+ assert(testOffset != null),
+ assert(writeOffset != null),
+ assert(forEffect != null) {
+ receiver?.parent = this;
+ index?.parent = this;
+ value?.parent = this;
+ }
+
+ @override
+ InternalExpressionKind get kind =>
+ InternalExpressionKind.IfNullExtensionIndexSet;
+
+ @override
+ void visitChildren(Visitor<dynamic> v) {
+ receiver?.accept(v);
+ index?.accept(v);
+ value?.accept(v);
+ }
+
+ @override
+ void transformChildren(Transformer v) {
+ if (receiver != null) {
+ receiver = receiver.accept<TreeNode>(v);
+ receiver?.parent = this;
+ }
+ if (index != null) {
+ index = index.accept<TreeNode>(v);
+ index?.parent = this;
+ }
+ if (value != null) {
+ value = value.accept<TreeNode>(v);
+ value?.parent = this;
+ }
+ }
+}
+
/// Internal expression representing a compound index assignment.
///
/// An if-null index assignment of the form `o[a] += b` is, if used for value,
@@ -2112,6 +2280,117 @@
}
}
+/// Internal expression representing a compound extension index assignment.
+///
+/// An compound extension index assignment of the form `Extension(o)[a] += b`
+/// is, if used for value, encoded as the expression:
+///
+/// let receiverVariable = o;
+/// let indexVariable = a in
+/// let valueVariable = receiverVariable.[](indexVariable) + b
+/// let writeVariable =
+/// receiverVariable.[]=(indexVariable, valueVariable) in
+/// valueVariable
+///
+/// and, if used for effect, encoded as the expression:
+///
+/// let receiverVariable = o;
+/// let indexVariable = a in
+/// receiverVariable.[]=(indexVariable,
+/// receiverVariable.[](indexVariable) + b)
+///
+class CompoundExtensionIndexSet extends InternalExpression {
+ final Extension extension;
+
+ final List<DartType> explicitTypeArguments;
+
+ Expression receiver;
+
+ /// The [] member.
+ Member getter;
+
+ /// The []= member.
+ Member setter;
+
+ /// The index expression of the operation.
+ Expression index;
+
+ /// The name of the binary operation.
+ Name binaryName;
+
+ /// The right-hand side of the binary expression.
+ Expression rhs;
+
+ /// The file offset for the [] operation.
+ final int readOffset;
+
+ /// The file offset for the []= operation.
+ final int writeOffset;
+
+ /// The file offset for the binary operation.
+ final int binaryOffset;
+
+ /// If `true`, the expression is only need for effect and not for its value.
+ final bool forEffect;
+
+ /// If `true`, the expression is a post-fix inc/dec expression.
+ final bool forPostIncDec;
+
+ CompoundExtensionIndexSet(
+ this.extension,
+ this.explicitTypeArguments,
+ this.receiver,
+ this.getter,
+ this.setter,
+ this.index,
+ this.binaryName,
+ this.rhs,
+ {this.readOffset,
+ this.binaryOffset,
+ this.writeOffset,
+ this.forEffect,
+ this.forPostIncDec})
+ : assert(explicitTypeArguments == null ||
+ explicitTypeArguments.length == extension.typeParameters.length),
+ assert(readOffset != null),
+ assert(binaryOffset != null),
+ assert(writeOffset != null),
+ assert(forEffect != null),
+ assert(forPostIncDec != null) {
+ receiver?.parent = this;
+ index?.parent = this;
+ rhs?.parent = this;
+ fileOffset = binaryOffset;
+ }
+
+ @override
+ InternalExpressionKind get kind =>
+ InternalExpressionKind.CompoundExtensionIndexSet;
+
+ @override
+ void visitChildren(Visitor<dynamic> v) {
+ receiver?.accept(v);
+ index?.accept(v);
+ rhs?.accept(v);
+ }
+
+ @override
+ void transformChildren(Transformer v) {
+ if (receiver != null) {
+ receiver = receiver.accept<TreeNode>(v);
+ receiver?.parent = this;
+ }
+ if (index != null) {
+ index = index.accept<TreeNode>(v);
+ index?.parent = this;
+ }
+ if (rhs != null) {
+ rhs = rhs.accept<TreeNode>(v);
+ rhs?.parent = this;
+ }
+ }
+}
+
/// Internal expression representing an assignment to an extension setter.
///
/// An extension set of the form `receiver.target = value` is, if used for
@@ -2134,11 +2413,15 @@
///
// TODO(johnniwinther): Rename read-only to side-effect-free.
class ExtensionSet extends InternalExpression {
+ final Extension extension;
+
+ final List<DartType> explicitTypeArguments;
+
/// The receiver for the assignment.
Expression receiver;
/// The extension member called for the assignment.
- ObjectAccessTarget target;
+ Member target;
/// The right-hand side value of the assignment.
Expression value;
@@ -2151,9 +2434,12 @@
/// variable.
final bool readOnlyReceiver;
- ExtensionSet(this.receiver, this.target, this.value,
+ ExtensionSet(this.extension, this.explicitTypeArguments, this.receiver,
+ this.target, this.value,
{this.readOnlyReceiver, this.forEffect})
- : assert(readOnlyReceiver != null),
+ : assert(explicitTypeArguments == null ||
+ explicitTypeArguments.length == extension.typeParameters.length),
+ assert(readOnlyReceiver != null),
assert(forEffect != null) {
receiver?.parent = this;
value?.parent = this;
@@ -2221,6 +2507,7 @@
}
}
+/// Front end specific implementation of [PropertySet].
class PropertySetImpl extends PropertySet {
/// If `true` the assignment is need for its effect and not for its value.
final bool forEffect;
@@ -2235,6 +2522,46 @@
super(receiver, name, value, interfaceTarget);
}
+/// Internal representation of a read of an extension instance member.
+///
+/// A read of an extension instance member `o.foo` is encoded as the
+/// [StaticInvocation]
+///
+/// extension|foo(o)
+///
+/// where `extension|foo` is the top level method created for reading the
+/// `foo` member. If `foo` is an extension instance method, then `extension|foo`
+/// the special tear-off function created for extension instance methods.
+/// Otherwise `extension|foo` is the top level method corresponding to the
+/// extension instance getter being read.
+class ExtensionTearOff extends InternalExpression {
+ /// The top-level method that is that target for the read operation.
+ Member target;
+
+ /// The arguments provided to the top-level method.
+ Arguments arguments;
+
+ ExtensionTearOff(this.target, this.arguments) {
+ arguments?.parent = this;
+ }
+
+ @override
+ InternalExpressionKind get kind => InternalExpressionKind.ExtensionTearOff;
+
+ @override
+ void visitChildren(Visitor<dynamic> v) {
+ arguments?.accept(v);
+ }
+
+ @override
+ void transformChildren(Transformer v) {
+ if (arguments != null) {
+ arguments = arguments.accept<TreeNode>(v);
+ arguments?.parent = this;
+ }
+ }
+}
+
/// Creates a [Let] of [variable] with the given [body] using
/// `variable.fileOffset` as the file offset for the let.
///
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index af3ed3b..f5e9320 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -993,8 +993,9 @@
}
@override
- void endTypeVariable(Token token, int index, Token extendsOrSuper) {
- listener?.endTypeVariable(token, index, extendsOrSuper);
+ void endTypeVariable(
+ Token token, int index, Token extendsOrSuper, Token variance) {
+ listener?.endTypeVariable(token, index, extendsOrSuper, variance);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 9c67ac4..e5f5fad 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -1220,7 +1220,8 @@
/// - Type bound
///
/// See [beginTypeVariable] for additional substructures.
- void endTypeVariable(Token token, int index, Token extendsOrSuper) {
+ void endTypeVariable(
+ Token token, int index, Token extendsOrSuper, Token variance) {
logEvent("TypeVariable");
}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index e139297..f2753bd 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -5141,14 +5141,6 @@
Token parseSend(Token token, IdentifierContext context) {
Token beginToken = token = ensureIdentifier(token, context);
- if (optional('!', token.next)) {
- Token bang = token.next;
- Token next = bang.next;
- if (optional('(', next) || optional('[', next)) {
- listener.handleNonNullAssertExpression(bang);
- token = bang;
- }
- }
TypeParamOrArgInfo typeArg = computeMethodTypeArguments(token);
if (typeArg != noTypeParamOrArg) {
token = typeArg.parseArguments(token, this);
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index 2a16412..de9c32d 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -763,7 +763,7 @@
listener.beginTypeVariable(token);
listener.handleTypeVariablesDefined(token, 1);
listener.handleNoType(token);
- listener.endTypeVariable(endGroup, 0, null);
+ listener.endTypeVariable(endGroup, 0, null, null);
listener.endTypeVariables(beginGroup, endGroup);
return endGroup;
}
@@ -1075,7 +1075,7 @@
// Type variables are "completed" in reverse order, so capture the last
// consumed token from the first "completed" type variable.
token ??= token2;
- listener.endTypeVariable(next2, --count, extendsOrSuper);
+ listener.endTypeVariable(next2, --count, extendsOrSuper, variance);
typeStarts = typeStarts.tail;
superTypeInfos = superTypeInfos.tail;
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 400fba9..10bb91e 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -544,7 +544,8 @@
}
@override
- void endTypeVariable(Token token, int index, Token extendsOrSuper) {
+ void endTypeVariable(
+ Token token, int index, Token extendsOrSuper, Token variance) {
debugEvent("endTypeVariable");
}
@@ -586,6 +587,28 @@
}
@override
+ void endExtensionFactoryMethod(
+ Token beginToken, Token factoryKeyword, Token endToken) {
+ debugEvent("ExtensionFactoryMethod");
+ pop(); // bodyToken
+ pop(); // name
+ pop(); // metadata
+ checkEmpty(beginToken.charOffset);
+ // Skip the declaration. An error as already been produced by the parser.
+ }
+
+ @override
+ void endExtensionConstructor(Token getOrSet, Token beginToken,
+ Token beginParam, Token beginInitializers, Token endToken) {
+ debugEvent("ExtensionConstructor");
+ pop(); // bodyToken
+ pop(); // name
+ pop(); // metadata
+ checkEmpty(beginToken.charOffset);
+ // Skip the declaration. An error as already been produced by the parser.
+ }
+
+ @override
void endRedirectingFactoryBody(Token beginToken, Token endToken) {
debugEvent("RedirectingFactoryBody");
discard(1); // ConstructorReference.
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 77ca872..0377599 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -4,7 +4,7 @@
library fasta.outline_builder;
-import 'package:kernel/ast.dart' show ProcedureKind;
+import 'package:kernel/ast.dart' show ProcedureKind, Variance;
import '../builder/builder.dart';
@@ -1574,13 +1574,17 @@
}
@override
- void endTypeVariable(Token token, int index, Token extendsOrSuper) {
+ void endTypeVariable(
+ Token token, int index, Token extendsOrSuper, Token variance) {
debugEvent("endTypeVariable");
TypeBuilder bound = nullIfParserRecovery(pop());
// Peek to leave type parameters on top of stack.
List<TypeVariableBuilder> typeParameters = peek();
if (typeParameters != null) {
typeParameters[index].bound = bound;
+ if (variance != null) {
+ typeParameters[index].variance = Variance.fromString(variance.lexeme);
+ }
}
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 811db64..c1fcc30 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -2775,6 +2775,9 @@
void checkBoundsInStaticInvocation(
StaticInvocation node, TypeEnvironment typeEnvironment, Uri fileUri,
{bool inferred = false}) {
+ // TODO(johnniwinther): Handle partially inferred type arguments in
+ // extension method calls. Currently all are considered inferred in the
+ // error messages.
if (node.arguments.types.isEmpty) return;
Class klass = node.target.enclosingClass;
List<TypeParameter> parameters = node.target.function.typeParameters;
diff --git a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
index 8a1c08d..67cdaec 100644
--- a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
@@ -1316,7 +1316,8 @@
}
@override
- void endTypeVariable(Token token, int index, Token extendsOrSuper) {
+ void endTypeVariable(
+ Token token, int index, Token extendsOrSuper, Token variance) {
debugEvent("TypeVariable", token);
state.pop(); // Name.
}
@@ -1327,6 +1328,11 @@
}
@override
+ void handleVarianceModifier(Token variance) {
+ debugEvent("VarianceModifier", variance);
+ }
+
+ @override
void handleNoTypeVariables(Token token) {
debugEvent("NoTypeVariables", token);
}
diff --git a/pkg/front_end/lib/src/fasta/source/value_kinds.dart b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
index 08ecbf0..2047483 100644
--- a/pkg/front_end/lib/src/fasta/source/value_kinds.dart
+++ b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
@@ -47,6 +47,8 @@
const _SingleValueKind<List<type.FormalParameterBuilder>>(
NullValue.FormalParameters);
static const ValueKind Generator = const _SingleValueKind<type.Generator>();
+ static const ValueKind Initializer =
+ const _SingleValueKind<type.Initializer>();
static const ValueKind MethodBody = const _SingleValueKind<type.MethodBody>();
static const ValueKind Modifiers =
const _SingleValueKind<List<type.Modifier>>();
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 4717c77..faf4afd 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -66,7 +66,7 @@
import '../kernel/type_algorithms.dart' show hasAnyTypeVariables;
-import '../names.dart' show callName, unaryMinusName;
+import '../names.dart';
import '../problems.dart' show unexpected, unhandled;
@@ -656,10 +656,29 @@
return type is InterfaceType && type.classNode == coreTypes.nullClass;
}
- List<DartType> _inferExtensionTypeArguments(
- List<TypeParameter> typeParameters,
- DartType onType,
- DartType receiverType) {
+ /// Computes the type arguments for an access to an extension instance member
+ /// on [extension] with the static [receiverType]. If [explicitTypeArguments]
+ /// are provided, these are returned, otherwise type arguments are inferred
+ /// using [receiverType].
+ List<DartType> computeExtensionTypeArgument(Extension extension,
+ List<DartType> explicitTypeArguments, DartType receiverType) {
+ if (explicitTypeArguments != null) {
+ assert(explicitTypeArguments.length == extension.typeParameters.length);
+ return explicitTypeArguments;
+ } else if (extension.typeParameters.isEmpty) {
+ assert(explicitTypeArguments == null);
+ return const <DartType>[];
+ } else {
+ return inferExtensionTypeArguments(extension, receiverType);
+ }
+ }
+
+ /// Infers the type arguments for an access to an extension instance member
+ /// on [extension] with the static [receiverType].
+ List<DartType> inferExtensionTypeArguments(
+ Extension extension, DartType receiverType) {
+ List<TypeParameter> typeParameters = extension.typeParameters;
+ DartType onType = extension.onType;
List<DartType> inferredTypes =
new List<DartType>.filled(typeParameters.length, const UnknownType());
typeSchemaEnvironment.inferGenericFunctionOrType(
@@ -719,8 +738,23 @@
if (target.isUnresolved &&
receiverType is! DynamicType &&
includeExtensionMethods) {
+ Name otherName = name;
+ bool otherIsSetter;
+ if (name == indexGetName) {
+ // [] must be checked against []=.
+ otherName = indexSetName;
+ otherIsSetter = false;
+ } else if (name == indexSetName) {
+ // []= must be checked against [].
+ otherName = indexGetName;
+ otherIsSetter = false;
+ } else {
+ otherName = name;
+ otherIsSetter = !setter;
+ }
+
Member otherMember =
- _getInterfaceMember(classNode, name, !setter, fileOffset);
+ _getInterfaceMember(classNode, otherName, otherIsSetter, fileOffset);
if (otherMember != null) {
// If we're looking for `foo` and `foo=` can be found or vice-versa then
// extension methods should not be found.
@@ -730,12 +764,12 @@
ExtensionAccessCandidate bestSoFar;
List<ExtensionAccessCandidate> noneMoreSpecific = [];
library.scope.forEachExtension((ExtensionBuilder extensionBuilder) {
- MemberBuilder getterBuilder =
- extensionBuilder.lookupLocalMember(name.name, setter: false);
- MemberBuilder setterBuilder =
- extensionBuilder.lookupLocalMember(name.name, setter: true);
- if ((getterBuilder != null && !getterBuilder.isStatic) ||
- (setterBuilder != null && !setterBuilder.isStatic)) {
+ MemberBuilder thisBuilder =
+ extensionBuilder.lookupLocalMember(name.name, setter: setter);
+ MemberBuilder otherBuilder = extensionBuilder
+ .lookupLocalMember(otherName.name, setter: otherIsSetter);
+ if ((thisBuilder != null && !thisBuilder.isStatic) ||
+ (otherBuilder != null && !otherBuilder.isStatic)) {
DartType onType;
DartType onTypeInstantiateToBounds;
List<DartType> inferredTypeArguments;
@@ -746,10 +780,8 @@
} else {
List<TypeParameter> typeParameters =
extensionBuilder.extension.typeParameters;
- inferredTypeArguments = _inferExtensionTypeArguments(
- extensionBuilder.extension.typeParameters,
- extensionBuilder.extension.onType,
- receiverType);
+ inferredTypeArguments = inferExtensionTypeArguments(
+ extensionBuilder.extension, receiverType);
Substitution inferredSubstitution =
Substitution.fromPairs(typeParameters, inferredTypeArguments);
@@ -774,17 +806,14 @@
}
if (typeSchemaEnvironment.isSubtypeOf(receiverType, onType)) {
- MemberBuilder memberBuilder =
- setter ? setterBuilder : getterBuilder;
-
ExtensionAccessCandidate candidate = new ExtensionAccessCandidate(
onType,
onTypeInstantiateToBounds,
- memberBuilder != null
+ thisBuilder != null
? new ObjectAccessTarget.extensionMember(
- memberBuilder.procedure,
- memberBuilder.extensionTearOff,
- memberBuilder.kind,
+ thisBuilder.procedure,
+ thisBuilder.extensionTearOff,
+ thisBuilder.kind,
inferredTypeArguments)
: const ObjectAccessTarget.missing(),
isPlatform: extensionBuilder.library.uri.scheme == 'dart');
@@ -1154,6 +1183,19 @@
throw unhandled('$target', 'getFunctionType', null, null);
}
+ /// Returns the type of the receiver argument in an access to an extension
+ /// member on [extension] with the given extension [typeArguments].
+ DartType getExtensionReceiverType(
+ Extension extension, List<DartType> typeArguments) {
+ DartType receiverType = extension.onType;
+ if (extension.typeParameters.isNotEmpty) {
+ Substitution substitution =
+ Substitution.fromPairs(extension.typeParameters, typeArguments);
+ return substitution.substituteType(receiverType);
+ }
+ return receiverType;
+ }
+
/// Returns the return type of the invocation of [target] on [receiverType].
// TODO(johnniwinther): Cleanup [getFunctionType], [getReturnType],
// [getIndexKeyType] and [getIndexSetValueType]. We shouldn't need that many.
@@ -2121,8 +2163,13 @@
parent?.replaceChild(node, errorNode);
}
}
- _checkBoundsInMethodInvocation(target, receiverType, calleeType, methodName,
- arguments, node.fileOffset);
+ if (target.isExtensionMember) {
+ library.checkBoundsInStaticInvocation(
+ replacement, typeSchemaEnvironment, helper.uri);
+ } else {
+ _checkBoundsInMethodInvocation(target, receiverType, calleeType,
+ methodName, arguments, node.fileOffset);
+ }
return new ExpressionInferenceResult(inferredType, replacement);
}
@@ -2308,6 +2355,8 @@
receiver,
extensionTypeArguments:
readTarget.inferredExtensionTypeArguments)));
+ inferredType =
+ instantiateTearOff(inferredType, typeContext, expression);
break;
case ProcedureKind.Setter:
case ProcedureKind.Factory:
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 3742020..34bb332 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -98,7 +98,6 @@
ConstEvalKeyImplementsEqual/example: Fail
ConstEvalNegativeShift/analyzerCode: Fail # http://dartbug.com/33481
ConstEvalNegativeShift/example: Fail
-ConstEvalNonConstantLiteral/example: Fail
ConstEvalNonConstantVariableGet/example: Fail
ConstEvalNotListOrSetInSpread/example: Fail
ConstEvalNotMapInSpread/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 8568a27..2782772 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -104,10 +104,6 @@
template: "The key '#constant' does not have a primitive operator '=='."
analyzerCode: CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
-ConstEvalNonConstantLiteral:
- template: "Can't have a non-constant #string literal within a const context."
- analyzerCode: NON_CONSTANT_DEFAULT_VALUE
-
ConstEvalInvalidType:
template: "Expected constant '#constant' to be of type '#type', but was of type '#type2'."
@@ -125,19 +121,21 @@
template: "Binary operator '#string' on '#string2' requires non-negative operand, but was '#string3'."
ConstEvalInvalidMethodInvocation:
- template: "The method '#string' can't be invoked on '#constant' within a const context."
+ template: "The method '#string' can't be invoked on '#constant' in a constant expression."
analyzerCode: UNDEFINED_OPERATOR
ConstEvalInvalidPropertyGet:
- template: "The property '#string' can't be accessed on '#constant' within a const context."
+ template: "The property '#string' can't be accessed on '#constant' in a constant expression."
analyzerCode: CONST_EVAL_THROWS_EXCEPTION
ConstEvalInvalidStringInterpolationOperand:
- template: "The '#constant' can't be used as part of a string interpolation within a const context, only values of type 'null', 'bool', 'int', 'double', or 'String' can be used."
+ template: |
+ The constant value '#constant' can't be used as part of a string interpolation in a constant expression.
+ Only values of type 'null', 'bool', 'int', 'double', or 'String' can be used.
analyzerCode: CONST_EVAL_TYPE_BOOL_NUM_STRING
ConstEvalInvalidStaticInvocation:
- template: "The invocation of '#name' is not allowed within a const context."
+ template: "The invocation of '#name' is not allowed in a constant expression."
analyzerCode: CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
ConstEvalInvalidSymbolName:
@@ -1889,18 +1887,21 @@
template: "Extensions can't declare abstract members."
tip: "Try providing an implementation for the member."
analyzerCode: ParserErrorCode.EXTENSION_DECLARES_ABSTRACT_MEMBER
+ hasPublishedDocs: true
ExtensionDeclaresConstructor:
index: 92
template: "Extensions can't declare constructors."
tip: "Try removing the constructor declaration."
analyzerCode: ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR
+ hasPublishedDocs: true
ExtensionDeclaresInstanceField:
index: 93
template: "Extensions can't declare instance fields"
tip: "Try removing the field declaration or making it a static field"
analyzerCode: ParserErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD
+ hasPublishedDocs: true
ConflictsWithConstructor:
template: "Conflicts with constructor '#name'."
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart
new file mode 100644
index 0000000..63bb3d4
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart
@@ -0,0 +1 @@
+f() { foo.bar!.baz[arg]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart.expect
new file mode 100644
index 0000000..9ddb2a0
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart.expect
@@ -0,0 +1,37 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(foo, expression)
+ handleNoTypeArguments(.)
+ handleNoArguments(.)
+ handleSend(foo, .)
+ handleIdentifier(bar, expressionContinuation)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(bar, !)
+ endBinaryExpression(.)
+ handleNonNullAssertExpression(!)
+ handleIdentifier(baz, expressionContinuation)
+ handleNoTypeArguments([)
+ handleNoArguments([)
+ handleSend(baz, [)
+ endBinaryExpression(.)
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+endTopLevelMethod(f, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart
new file mode 100644
index 0000000..c4c6025
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart
@@ -0,0 +1 @@
+f() { (foo.bar)!.baz[arg]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart.expect
new file mode 100644
index 0000000..d10dfba
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart.expect
@@ -0,0 +1,38 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(foo, expression)
+ handleNoTypeArguments(.)
+ handleNoArguments(.)
+ handleSend(foo, .)
+ handleIdentifier(bar, expressionContinuation)
+ handleNoTypeArguments())
+ handleNoArguments())
+ handleSend(bar, ))
+ endBinaryExpression(.)
+ handleParenthesizedExpression(()
+ handleNonNullAssertExpression(!)
+ handleIdentifier(baz, expressionContinuation)
+ handleNoTypeArguments([)
+ handleNoArguments([)
+ handleSend(baz, [)
+ endBinaryExpression(.)
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+endTopLevelMethod(f, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart
new file mode 100644
index 0000000..25e3f32
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart
@@ -0,0 +1 @@
+f() { obj![arg]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart.expect
new file mode 100644
index 0000000..92b9ac2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart.expect
@@ -0,0 +1,27 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(obj, expression)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(obj, !)
+ handleNonNullAssertExpression(!)
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+ endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart
new file mode 100644
index 0000000..69f3bc6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart
@@ -0,0 +1 @@
+f() { obj![arg]![arg2]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart.expect
new file mode 100644
index 0000000..f6e7d35
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart.expect
@@ -0,0 +1,33 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(obj, expression)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(obj, !)
+ handleNonNullAssertExpression(!)
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleNonNullAssertExpression(!)
+ handleIdentifier(arg2, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg2, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+ endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart
new file mode 100644
index 0000000..16b0fe7
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart
@@ -0,0 +1 @@
+f() { (((obj!)[arg])!)[arg2]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart.expect
new file mode 100644
index 0000000..e1cdb65
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart.expect
@@ -0,0 +1,36 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(obj, expression)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(obj, !)
+ handleNonNullAssertExpression(!)
+ handleParenthesizedExpression(()
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleParenthesizedExpression(()
+ handleNonNullAssertExpression(!)
+ handleParenthesizedExpression(()
+ handleIdentifier(arg2, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg2, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+ endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart
new file mode 100644
index 0000000..b22f0d0
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart
@@ -0,0 +1 @@
+f() { foo.bar![arg]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart.expect
new file mode 100644
index 0000000..fbda0ef
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart.expect
@@ -0,0 +1,32 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(foo, expression)
+ handleNoTypeArguments(.)
+ handleNoArguments(.)
+ handleSend(foo, .)
+ handleIdentifier(bar, expressionContinuation)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(bar, !)
+ endBinaryExpression(.)
+ handleNonNullAssertExpression(!)
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart
new file mode 100644
index 0000000..97eb467
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart
@@ -0,0 +1 @@
+f() { (foo.bar)![arg]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart.expect
new file mode 100644
index 0000000..e014b78
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart.expect
@@ -0,0 +1,33 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(foo, expression)
+ handleNoTypeArguments(.)
+ handleNoArguments(.)
+ handleSend(foo, .)
+ handleIdentifier(bar, expressionContinuation)
+ handleNoTypeArguments())
+ handleNoArguments())
+ handleSend(bar, ))
+ endBinaryExpression(.)
+ handleParenthesizedExpression(()
+ handleNonNullAssertExpression(!)
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart
new file mode 100644
index 0000000..b927b26
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart
@@ -0,0 +1 @@
+f() { foo!.bar![arg]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart.expect
new file mode 100644
index 0000000..2fc33bb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart.expect
@@ -0,0 +1,33 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(foo, expression)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(foo, !)
+ handleNonNullAssertExpression(!)
+ handleIdentifier(bar, expressionContinuation)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(bar, !)
+ endBinaryExpression(.)
+ handleNonNullAssertExpression(!)
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart
new file mode 100644
index 0000000..f745152c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart
@@ -0,0 +1 @@
+f() { ((foo!).bar!)[arg]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart.expect
new file mode 100644
index 0000000..2aa6ce6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart.expect
@@ -0,0 +1,35 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(foo, expression)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(foo, !)
+ handleNonNullAssertExpression(!)
+ handleParenthesizedExpression(()
+ handleIdentifier(bar, expressionContinuation)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(bar, !)
+ endBinaryExpression(.)
+ handleNonNullAssertExpression(!)
+ handleParenthesizedExpression(()
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart
new file mode 100644
index 0000000..12a4bdc
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart
@@ -0,0 +1 @@
+f() { foo.bar![arg]![arg2]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart.expect
new file mode 100644
index 0000000..2d56362
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart.expect
@@ -0,0 +1,38 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(foo, expression)
+ handleNoTypeArguments(.)
+ handleNoArguments(.)
+ handleSend(foo, .)
+ handleIdentifier(bar, expressionContinuation)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(bar, !)
+ endBinaryExpression(.)
+ handleNonNullAssertExpression(!)
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleNonNullAssertExpression(!)
+ handleIdentifier(arg2, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg2, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart
new file mode 100644
index 0000000..f5c5a00
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart
@@ -0,0 +1 @@
+f() { (((foo.bar!)[arg])!)[arg2]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart.expect
new file mode 100644
index 0000000..f93cac9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart.expect
@@ -0,0 +1,41 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(foo, expression)
+ handleNoTypeArguments(.)
+ handleNoArguments(.)
+ handleSend(foo, .)
+ handleIdentifier(bar, expressionContinuation)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(bar, !)
+ endBinaryExpression(.)
+ handleNonNullAssertExpression(!)
+ handleParenthesizedExpression(()
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleParenthesizedExpression(()
+ handleNonNullAssertExpression(!)
+ handleParenthesizedExpression(()
+ handleIdentifier(arg2, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg2, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart
new file mode 100644
index 0000000..afd5a23
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart
@@ -0,0 +1 @@
+f() { foo!.bar![arg]![arg2]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart.expect
new file mode 100644
index 0000000..ee55e8f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart.expect
@@ -0,0 +1,39 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(foo, expression)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(foo, !)
+ handleNonNullAssertExpression(!)
+ handleIdentifier(bar, expressionContinuation)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(bar, !)
+ endBinaryExpression(.)
+ handleNonNullAssertExpression(!)
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleNonNullAssertExpression(!)
+ handleIdentifier(arg2, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg2, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart
new file mode 100644
index 0000000..a23cf8e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart
@@ -0,0 +1 @@
+f() { ((((foo!).bar!)[arg])!)[arg2]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart.expect
new file mode 100644
index 0000000..d1a1044
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart.expect
@@ -0,0 +1,43 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(foo, expression)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(foo, !)
+ handleNonNullAssertExpression(!)
+ handleParenthesizedExpression(()
+ handleIdentifier(bar, expressionContinuation)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(bar, !)
+ endBinaryExpression(.)
+ handleNonNullAssertExpression(!)
+ handleParenthesizedExpression(()
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleParenthesizedExpression(()
+ handleNonNullAssertExpression(!)
+ handleParenthesizedExpression(()
+ handleIdentifier(arg2, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg2, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart
new file mode 100644
index 0000000..380b3bc
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart
@@ -0,0 +1 @@
+f() { (obj!)[arg]; }
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart.expect
new file mode 100644
index 0000000..40baa37
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart.expect
@@ -0,0 +1,28 @@
+beginCompilationUnit(f)
+ beginMetadataStar(f)
+ endMetadataStar(0)
+ beginTopLevelMember(f)
+ beginTopLevelMethod(, null)
+ handleNoType()
+ handleIdentifier(f, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ handleIdentifier(obj, expression)
+ handleNoTypeArguments(!)
+ handleNoArguments(!)
+ handleSend(obj, !)
+ handleNonNullAssertExpression(!)
+ handleParenthesizedExpression(()
+ handleIdentifier(arg, expression)
+ handleNoTypeArguments(])
+ handleNoArguments(])
+ handleSend(arg, ])
+ handleIndexedExpression([, ])
+ handleExpressionStatement(;)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(f, null, })
+ endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/parser.status b/pkg/front_end/parser_testcases/parser.status
new file mode 100644
index 0000000..e22cfe5
--- /dev/null
+++ b/pkg/front_end/parser_testcases/parser.status
@@ -0,0 +1,3 @@
+# Copyright (c) 2019, 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.md file.
diff --git a/pkg/front_end/test/constants/data/function.dart b/pkg/front_end/test/constants/data/function.dart
index 656e0ab..987b64c5 100644
--- a/pkg/front_end/test/constants/data/function.dart
+++ b/pkg/front_end/test/constants/data/function.dart
@@ -14,15 +14,16 @@
/*cfe.Instantiation(method2<String,int>)*/ method2;
main() {
- print(/*Function(method1)*/ function0);
- // TODO(paulberry): analyzer should record instantiation information. See
- // dartbug.com/37608.
+ print(
+ /*cfe|dart2js.Function(method1)*/
+ /*analyzer.Function(method1,type=T Function<T>(T))*/
+ function0);
print(
/*cfe|dart2js.Instantiation(method1<int>)*/
- /*analyzer.Function(method1)*/
+ /*analyzer.Function(method1,type=int Function(int))*/
instantiation0);
print(
/*cfe|dart2js.Instantiation(method2<String,int>)*/
- /*analyzer.Function(method2)*/
+ /*analyzer.Function(method2,type=Map<String, int> Function(String, int))*/
instantiation1);
}
diff --git a/pkg/front_end/test/fasta/flow_analysis/flow_analysis_test.dart b/pkg/front_end/test/fasta/flow_analysis/flow_analysis_test.dart
index b93bf2e..a171dbf 100644
--- a/pkg/front_end/test/fasta/flow_analysis/flow_analysis_test.dart
+++ b/pkg/front_end/test/fasta/flow_analysis/flow_analysis_test.dart
@@ -190,14 +190,6 @@
expect(() => flow.finish(), _asserts);
});
- test('finish checks for un-added variables', () {
- var h = _Harness();
- var x = _Var('x', _Type('int'));
- var flow = h.createFlow();
- flow.isAssigned(x);
- expect(() => flow.finish(), _asserts);
- });
-
test('for_conditionBegin() un-promotes', () {
var h = _Harness();
var x = h.addVar('x', 'int?');
@@ -221,7 +213,7 @@
h.declare(y, initialized: true);
h.promote(y, 'int');
flow.for_conditionBegin({x});
- flow.add(x, assigned: true);
+ flow.write(x);
flow.for_bodyBegin(_Statement(), _Expression());
flow.for_updaterBegin();
flow.for_end();
@@ -705,8 +697,8 @@
h.promote(z, 'int');
flow.tryCatchStatement_catchEnd();
flow.tryCatchStatement_end();
- // Only x should be promoted, because it's the only variable promoted
- // in both the try body and the catch handler.
+ // Only x should be promoted, because it's the only variable
+ // promoted in both the try body and the catch handler.
expect(flow.promotedType(x).type, 'int');
expect(flow.promotedType(y), isNull);
expect(flow.promotedType(z), isNull);
@@ -850,7 +842,7 @@
h.declare(y, initialized: true);
h.promote(y, 'int');
flow.whileStatement_conditionBegin({x});
- flow.add(x, assigned: true);
+ flow.write(x);
flow.whileStatement_bodyBegin(_Statement(), _Expression());
flow.whileStatement_end();
});
@@ -951,54 +943,31 @@
});
});
- group('add', () {
- test('default', () {
- // By default, added variables are considered unassigned.
- var s1 = FlowModel<_Var, _Type>(true);
- var s2 = s1.add(intVar);
- expect(s2.reachable, true);
- expect(s2.variableInfo, {intVar: VariableModel<_Type>(null, false)});
- });
-
- test('unassigned', () {
- var s1 = FlowModel<_Var, _Type>(true);
- var s2 = s1.add(intVar, assigned: false);
- expect(s2.reachable, true);
- expect(s2.variableInfo, {intVar: VariableModel<_Type>(null, false)});
- });
-
- test('assigned', () {
- var s1 = FlowModel<_Var, _Type>(true);
- var s2 = s1.add(intVar, assigned: true);
- expect(s2.variableInfo, {intVar: VariableModel<_Type>(null, true)});
- });
- });
-
group('promote', () {
test('unpromoted -> unchanged (same)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true).add(intVar);
+ var s1 = FlowModel<_Var, _Type>(true);
var s2 = s1.promote(h, intVar, _Type('int'));
expect(s2, same(s1));
});
test('unpromoted -> unchanged (supertype)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true).add(intVar);
+ var s1 = FlowModel<_Var, _Type>(true);
var s2 = s1.promote(h, intVar, _Type('Object'));
expect(s2, same(s1));
});
test('unpromoted -> unchanged (unrelated)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true).add(intVar);
+ var s1 = FlowModel<_Var, _Type>(true);
var s2 = s1.promote(h, intVar, _Type('String'));
expect(s2, same(s1));
});
test('unpromoted -> subtype', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true).add(intQVar);
+ var s1 = FlowModel<_Var, _Type>(true);
var s2 = s1.promote(h, intQVar, _Type('int'));
expect(s2.reachable, true);
_Type.allowComparisons(() {
@@ -1009,36 +978,32 @@
test('promoted -> unchanged (same)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
- .add(objectQVar)
- .promote(h, objectQVar, _Type('int'));
+ var s1 =
+ FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int'));
var s2 = s1.promote(h, objectQVar, _Type('int'));
expect(s2, same(s1));
});
test('promoted -> unchanged (supertype)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
- .add(objectQVar)
- .promote(h, objectQVar, _Type('int'));
+ var s1 =
+ FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int'));
var s2 = s1.promote(h, objectQVar, _Type('Object'));
expect(s2, same(s1));
});
test('promoted -> unchanged (unrelated)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
- .add(objectQVar)
- .promote(h, objectQVar, _Type('int'));
+ var s1 =
+ FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int'));
var s2 = s1.promote(h, objectQVar, _Type('String'));
expect(s2, same(s1));
});
test('promoted -> subtype', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
- .add(objectQVar)
- .promote(h, objectQVar, _Type('int?'));
+ var s1 =
+ FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int?'));
var s2 = s1.promote(h, objectQVar, _Type('int'));
expect(s2.reachable, true);
_Type.allowComparisons(() {
@@ -1051,27 +1016,25 @@
group('write', () {
var objectQVar = _Var('x', _Type('Object?'));
test('unchanged', () {
- var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true).add(objectQVar, assigned: true);
- var s2 = s1.write(h, objectQVar);
+ var s1 = FlowModel<_Var, _Type>(true).write(objectQVar);
+ var s2 = s1.write(objectQVar);
expect(s2, same(s1));
});
test('marks as assigned', () {
- var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true).add(objectQVar, assigned: false);
- var s2 = s1.write(h, objectQVar);
+ var s1 = FlowModel<_Var, _Type>(true);
+ var s2 = s1.write(objectQVar);
expect(s2.reachable, true);
- expect(s2.variableInfo[objectQVar], VariableModel<_Type>(null, true));
+ expect(s2.infoFor(objectQVar), VariableModel<_Type>(null, true));
});
test('un-promotes', () {
var h = _Harness();
var s1 = FlowModel<_Var, _Type>(true)
- .add(objectQVar, assigned: true)
+ .write(objectQVar)
.promote(h, objectQVar, _Type('int'));
expect(s1.variableInfo, contains(objectQVar));
- var s2 = s1.write(h, objectQVar);
+ var s2 = s1.write(objectQVar);
expect(s2.reachable, true);
expect(s2.variableInfo, {objectQVar: VariableModel<_Type>(null, true)});
});
@@ -1080,35 +1043,33 @@
group('markNonNullable', () {
test('unpromoted -> unchanged', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true).add(intVar);
+ var s1 = FlowModel<_Var, _Type>(true);
var s2 = s1.markNonNullable(h, intVar);
expect(s2, same(s1));
});
test('unpromoted -> promoted', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true).add(intQVar);
+ var s1 = FlowModel<_Var, _Type>(true);
var s2 = s1.markNonNullable(h, intQVar);
expect(s2.reachable, true);
_Type.allowComparisons(() {
- expect(s2.variableInfo[intQVar], VariableModel(_Type('int'), false));
+ expect(s2.infoFor(intQVar), VariableModel(_Type('int'), false));
});
});
test('promoted -> unchanged', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
- .add(objectQVar)
- .promote(h, objectQVar, _Type('int'));
+ var s1 =
+ FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int'));
var s2 = s1.markNonNullable(h, objectQVar);
expect(s2, same(s1));
});
test('promoted -> re-promoted', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
- .add(objectQVar)
- .promote(h, objectQVar, _Type('int?'));
+ var s1 =
+ FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int?'));
var s2 = s1.markNonNullable(h, objectQVar);
expect(s2.reachable, true);
_Type.allowComparisons(() {
@@ -1121,22 +1082,18 @@
group('removePromotedAll', () {
test('unchanged', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
- .add(objectQVar)
- .add(intQVar)
- .promote(h, objectQVar, _Type('int'));
- var s2 = s1.removePromotedAll([intQVar], null);
+ var s1 =
+ FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int'));
+ var s2 = s1.removePromotedAll([intQVar]);
expect(s2, same(s1));
});
test('changed', () {
var h = _Harness();
var s1 = FlowModel<_Var, _Type>(true)
- .add(objectQVar)
- .add(intQVar)
.promote(h, objectQVar, _Type('int'))
.promote(h, intQVar, _Type('int'));
- var s2 = s1.removePromotedAll([intQVar], null);
+ var s2 = s1.removePromotedAll([intQVar]);
expect(s2.reachable, true);
_Type.allowComparisons(() {
expect(s2.variableInfo, {
@@ -1164,14 +1121,14 @@
var b = _Var('b', _Type('int'));
var c = _Var('c', _Type('int'));
var d = _Var('d', _Type('int'));
- var s0 = FlowModel<_Var, _Type>(true).add(a).add(b).add(c).add(d);
- var s1 = s0.write(h, a).write(h, b);
- var s2 = s0.write(h, a).write(h, c);
+ var s0 = FlowModel<_Var, _Type>(true);
+ var s1 = s0.write(a).write(b);
+ var s2 = s0.write(a).write(c);
var result = s1.restrict(h, s2, Set());
- expect(result.variableInfo[a].assigned, true);
- expect(result.variableInfo[b].assigned, true);
- expect(result.variableInfo[c].assigned, true);
- expect(result.variableInfo[d].assigned, false);
+ expect(result.infoFor(a).assigned, true);
+ expect(result.infoFor(b).assigned, true);
+ expect(result.infoFor(c).assigned, true);
+ expect(result.infoFor(d).assigned, false);
});
test('promotion', () {
@@ -1179,15 +1136,15 @@
String expectedType) {
var h = _Harness();
var x = _Var('x', _Type('Object?'));
- var s0 = FlowModel<_Var, _Type>(true).add(x, assigned: true);
+ var s0 = FlowModel<_Var, _Type>(true).write(x);
var s1 = thisType == null ? s0 : s0.promote(h, x, _Type(thisType));
var s2 = otherType == null ? s0 : s0.promote(h, x, _Type(otherType));
var result = s1.restrict(h, s2, unsafe ? [x].toSet() : Set());
if (expectedType == null) {
expect(result.variableInfo, contains(x));
- expect(result.variableInfo[x].promotedType, isNull);
+ expect(result.infoFor(x).promotedType, isNull);
} else {
- expect(result.variableInfo[x].promotedType.type, expectedType);
+ expect(result.infoFor(x).promotedType.type, expectedType);
}
}
@@ -1209,9 +1166,9 @@
var h = _Harness();
var x = _Var('x', _Type('Object?'));
var s0 = FlowModel<_Var, _Type>(true);
- var s1 = s0.add(x, assigned: true);
- expect(s0.restrict(h, s1, {}), same(s0));
- expect(s0.restrict(h, s1, {x}), same(s0));
+ var s1 = s0.write(x);
+ expect(s0.restrict(h, s1, {}), same(s1));
+ expect(s0.restrict(h, s1, {x}), same(s1));
expect(s1.restrict(h, s0, {}), same(s1));
expect(s1.restrict(h, s0, {x}), same(s1));
});
@@ -1374,7 +1331,9 @@
FlowAnalysis<_Statement, _Expression, _Var, _Type>(this, this, this);
void declare(_Var v, {@required bool initialized}) {
- _flow.add(v, assigned: initialized);
+ if (initialized) {
+ _flow.write(v);
+ }
}
/// Creates a [LazyExpression] representing an `== null` check performed on
@@ -1403,12 +1362,6 @@
_flow.ifStatement_end(false);
}
- @override
- bool isLocalVariable(_Var variable) {
- // TODO(paulberry): make tests where this returns false
- return true;
- }
-
/// Creates a [LazyExpression] representing an `is!` check, checking whether
/// [variable] has the given [type].
LazyExpression isNotType(_Var variable, String type) {
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index fe1bbc0..b7aeac8 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -127,7 +127,7 @@
" promotedType: void)",
new VariableUseGenerator(helper, token, variable, type));
check(
- "PropertyAccessGenerator(offset: 4, _receiverVariable: null,"
+ "PropertyAccessGenerator(offset: 4,"
" receiver: expression, name: bar, getter: $uri::myGetter,"
" setter: $uri::mySetter)",
new PropertyAccessGenerator(
diff --git a/pkg/front_end/test/fasta/messages_test.dart b/pkg/front_end/test/fasta/messages_test.dart
index 08e960e..f749478 100644
--- a/pkg/front_end/test/fasta/messages_test.dart
+++ b/pkg/front_end/test/fasta/messages_test.dart
@@ -104,6 +104,7 @@
Severity severity;
YamlNode badSeverity;
YamlNode unnecessarySeverity;
+ List<String> badHasPublishedDocsValue = <String>[];
List<String> spellingMessages;
const String spellingPostMessage = "\nIf the word(s) look okay, update "
"'spell_checking_list_messages.txt' or "
@@ -264,6 +265,12 @@
// index is validated during generation
break;
+ case "hasPublishedDocs":
+ if (value != true) {
+ badHasPublishedDocsValue.add(name);
+ }
+ break;
+
default:
unknownKeys.add(key);
}
@@ -306,6 +313,14 @@
: null);
yield createDescription(
+ 'hasPublishedDocs',
+ null,
+ badHasPublishedDocsValue.isNotEmpty
+ ? "Bad hasPublishedDocs value (only 'true' supported) in:"
+ " ${badHasPublishedDocsValue.join(', ')}"
+ : null);
+
+ yield createDescription(
"severity",
null,
badSeverity != null
@@ -320,6 +335,7 @@
? "The 'ERROR' severity is the default and not necessary."
: null,
location: unnecessarySeverity?.span?.start);
+
yield createDescription(
"spelling",
null,
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index 1dd6051..dc5203c 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -695,7 +695,7 @@
'beginTypeVariable T',
'handleTypeVariablesDefined T 1',
'handleNoType T',
- 'endTypeVariable > 0 null',
+ 'endTypeVariable > 0 null null',
'endTypeVariables < >',
'beginFunctionType Function',
'handleNoType ',
@@ -729,7 +729,7 @@
'beginTypeVariable T',
'handleTypeVariablesDefined T 1',
'handleNoType T',
- 'endTypeVariable > 0 null',
+ 'endTypeVariable > 0 null null',
'endTypeVariables < >',
'beginFunctionType Function',
'handleNoType ',
@@ -1377,7 +1377,7 @@
'beginTypeVariable T',
'handleTypeVariablesDefined T 1',
'handleNoType T',
- 'endTypeVariable > 0 null',
+ 'endTypeVariable > 0 null null',
'endTypeVariables < >',
'beginFunctionType C',
'beginTypeVariables <',
@@ -1387,7 +1387,7 @@
'beginTypeVariable T',
'handleTypeVariablesDefined T 1',
'handleNoType T',
- 'endTypeVariable > 0 null',
+ 'endTypeVariable > 0 null null',
'endTypeVariables < >',
'beginFunctionType C',
'handleIdentifier C prefixedTypeReference',
@@ -1638,7 +1638,7 @@
'beginTypeVariable T',
'handleTypeVariablesDefined T 1',
'handleNoType T',
- 'endTypeVariable > 0 null',
+ 'endTypeVariable > 0 null null',
'endTypeVariables < >',
]);
expect(listener.errors, isNull);
@@ -2023,9 +2023,9 @@
'beginTypeVariable T',
'handleTypeVariablesDefined T 2',
'handleNoType T',
- 'endTypeVariable > 1 null',
+ 'endTypeVariable > 1 null null',
'handleNoType S',
- 'endTypeVariable , 0 null',
+ 'endTypeVariable , 0 null null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<S extends T>',
@@ -2040,7 +2040,7 @@
'handleIdentifier T typeReference',
'handleNoTypeArguments >',
'handleType T null',
- 'endTypeVariable > 0 extends',
+ 'endTypeVariable > 0 extends null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<S extends List<T>>',
@@ -2059,7 +2059,7 @@
'handleType T null',
'endTypeArguments 1 < >',
'handleType List null',
- 'endTypeVariable > 0 extends',
+ 'endTypeVariable > 0 extends null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<R, S extends void Function()>',
@@ -2081,9 +2081,9 @@
'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
'endFunctionType Function null',
- 'endTypeVariable > 1 extends',
+ 'endTypeVariable > 1 extends null',
'handleNoType R',
- 'endTypeVariable , 0 null',
+ 'endTypeVariable , 0 null null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<@A S,T>', typeArgumentCount: 2, expectedCalls: [
@@ -2103,9 +2103,9 @@
'beginTypeVariable T',
'handleTypeVariablesDefined T 2',
'handleNoType T',
- 'endTypeVariable > 1 null',
+ 'endTypeVariable > 1 null null',
'handleNoType S',
- 'endTypeVariable , 0 null',
+ 'endTypeVariable , 0 null null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<@A() S,T>', typeArgumentCount: 2, expectedCalls: [
@@ -2126,9 +2126,9 @@
'beginTypeVariable T',
'handleTypeVariablesDefined T 2',
'handleNoType T',
- 'endTypeVariable > 1 null',
+ 'endTypeVariable > 1 null null',
'handleNoType S',
- 'endTypeVariable , 0 null',
+ 'endTypeVariable , 0 null null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<@A() @B S,T>',
@@ -2156,9 +2156,9 @@
'beginTypeVariable T',
'handleTypeVariablesDefined T 2',
'handleNoType T',
- 'endTypeVariable > 1 null',
+ 'endTypeVariable > 1 null null',
'handleNoType S',
- 'endTypeVariable , 0 null',
+ 'endTypeVariable , 0 null null',
'endTypeVariables < >',
]);
}
@@ -2179,7 +2179,7 @@
'handleIdentifier void typeReference',
'handleNoTypeArguments >',
'handleType void null',
- 'endTypeVariable > 0 extends',
+ 'endTypeVariable > 0 extends null',
'endTypeVariables < >'
]);
}
@@ -2198,7 +2198,7 @@
'beginTypeVariable S',
'handleTypeVariablesDefined S 1',
'handleNoType S',
- 'endTypeVariable Function 0 null',
+ 'endTypeVariable Function 0 null null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<void Function()>',
@@ -2214,7 +2214,7 @@
'beginTypeVariable ',
'handleTypeVariablesDefined 1',
'handleNoType ',
- 'endTypeVariable void 0 null',
+ 'endTypeVariable void 0 null null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<S<T>>', typeArgumentCount: 1, expectedErrors: [
@@ -2227,7 +2227,7 @@
'beginTypeVariable S',
'handleTypeVariablesDefined S 1',
'handleNoType S',
- 'endTypeVariable < 0 null',
+ 'endTypeVariable < 0 null null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<S T>',
@@ -2270,7 +2270,7 @@
'handleType T null',
'endTypeArguments 1 < >',
'handleType List null',
- 'endTypeVariable fieldName 0 extends',
+ 'endTypeVariable fieldName 0 extends null',
'endTypeVariables < >',
]);
}
@@ -2292,7 +2292,7 @@
'handleType T null',
'endTypeArguments 1 < >',
'handleType Comparable null',
- 'endTypeVariable > 0 extends',
+ 'endTypeVariable > 0 extends null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<T extends Comparable<S>, S>',
@@ -2309,7 +2309,7 @@
'beginTypeVariable S',
'handleTypeVariablesDefined S 2',
'handleNoType S',
- 'endTypeVariable > 1 null',
+ 'endTypeVariable > 1 null null',
'handleIdentifier Comparable typeReference',
'beginTypeArguments <',
'handleIdentifier S typeReference',
@@ -2317,7 +2317,7 @@
'handleType S null',
'endTypeArguments 1 < >',
'handleType Comparable null',
- 'endTypeVariable , 0 extends',
+ 'endTypeVariable , 0 extends null',
'endTypeVariables < >'
]);
expectComplexTypeParam('<T extends Function(T)>',
@@ -2345,7 +2345,7 @@
'MemberKind.GeneralizedFunctionType',
'endFormalParameters 1 ( ) MemberKind.GeneralizedFunctionType',
'endFunctionType Function null',
- 'endTypeVariable > 0 extends',
+ 'endTypeVariable > 0 extends null',
'endTypeVariables < >'
]);
expectComplexTypeParam('<T extends List<List<T>>>',
@@ -2368,7 +2368,7 @@
'handleType List null',
'endTypeArguments 1 < >',
'handleType List null',
- 'endTypeVariable > 0 extends',
+ 'endTypeVariable > 0 extends null',
'endTypeVariables < >'
]);
expectComplexTypeParam('<T extends List<Map<S, T>>>',
@@ -2394,7 +2394,7 @@
'handleType Map null',
'endTypeArguments 1 < >',
'handleType List null',
- 'endTypeVariable > 0 extends',
+ 'endTypeVariable > 0 extends null',
'endTypeVariables < >'
]);
expectComplexTypeParam('<T extends List<Map<S, T>>>=',
@@ -2421,7 +2421,7 @@
'handleType Map null',
'endTypeArguments 1 < >',
'handleType List null',
- 'endTypeVariable >= 0 extends',
+ 'endTypeVariable >= 0 extends null',
'endTypeVariables < >'
]);
}
@@ -2441,7 +2441,7 @@
'beginTypeVariable S',
'handleTypeVariablesDefined S 1',
'handleNoType S',
- 'endTypeVariable < 0 null',
+ 'endTypeVariable < 0 null null',
'endTypeVariables < >',
]);
expectComplexTypeParam('<S();> A',
@@ -2459,7 +2459,7 @@
'beginTypeVariable S',
'handleTypeVariablesDefined S 1',
'handleNoType S',
- 'endTypeVariable ( 0 null',
+ 'endTypeVariable ( 0 null null',
'endTypeVariables < >',
]);
}
@@ -2842,8 +2842,9 @@
}
@override
- void endTypeVariable(Token token, int index, Token extendsOrSuper) {
- calls.add('endTypeVariable $token $index $extendsOrSuper');
+ void endTypeVariable(
+ Token token, int index, Token extendsOrSuper, Token variance) {
+ calls.add('endTypeVariable $token $index $extendsOrSuper $variance');
assertTokenInStream(token);
assertTokenInStream(extendsOrSuper);
}
diff --git a/pkg/front_end/test/parser_test.dart b/pkg/front_end/test/parser_test.dart
new file mode 100644
index 0000000..3c6cffb
--- /dev/null
+++ b/pkg/front_end/test/parser_test.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2019, 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 'dart:async' show Future;
+
+import 'dart:convert' show jsonDecode;
+
+import 'dart:io' show File;
+
+import 'dart:typed_data' show Uint8List;
+
+import 'package:front_end/src/fasta/parser.dart' show Parser;
+
+import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart'
+ show Utf8BytesScanner;
+
+import 'package:front_end/src/scanner/token.dart' show Token;
+
+import 'package:testing/testing.dart'
+ show
+ Chain,
+ ChainContext,
+ ExpectationSet,
+ Result,
+ Step,
+ TestDescription,
+ runMe;
+
+import 'utils/kernel_chain.dart' show MatchContext;
+
+import 'parser_test_listener.dart' show ParserTestListener;
+
+const String EXPECTATIONS = '''
+[
+ {
+ "name": "ExpectationFileMismatch",
+ "group": "Fail"
+ },
+ {
+ "name": "ExpectationFileMissing",
+ "group": "Fail"
+ }
+]
+''';
+
+main([List<String> arguments = const []]) =>
+ runMe(arguments, createContext, configurationPath: "../testing.json");
+
+Future<Context> createContext(
+ Chain suite, Map<String, String> environment) async {
+ return new Context(environment["updateExpectations"] == "true");
+}
+
+class Context extends ChainContext with MatchContext {
+ final updateExpectations;
+
+ Context(this.updateExpectations);
+
+ final List<Step> steps = const <Step>[
+ const ParserStep(),
+ ];
+
+ final ExpectationSet expectationSet =
+ new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
+}
+
+class ParserStep extends Step<TestDescription, TestDescription, Context> {
+ const ParserStep();
+
+ String get name => "parser";
+
+ Future<Result<TestDescription>> run(
+ TestDescription description, Context context) async {
+ File f = new File.fromUri(description.uri);
+ List<int> rawBytes = f.readAsBytesSync();
+
+ Uint8List bytes = new Uint8List(rawBytes.length + 1);
+ bytes.setRange(0, rawBytes.length, rawBytes);
+
+ Utf8BytesScanner scanner =
+ new Utf8BytesScanner(bytes, includeComments: true);
+ Token firstToken = scanner.tokenize();
+
+ if (firstToken == null) {
+ return crash(description, StackTrace.current);
+ }
+
+ ParserTestListener parserTestListener = new ParserTestListener();
+ Parser parser = new Parser(parserTestListener);
+ parser.parseUnit(firstToken);
+
+ return context.match<TestDescription>(
+ ".expect", "${parserTestListener.sb}", description.uri, description);
+ }
+}
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart
new file mode 100644
index 0000000..8bd1ead
--- /dev/null
+++ b/pkg/front_end/test/parser_test_listener.dart
@@ -0,0 +1,1645 @@
+// Copyright (c) 2019, 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:front_end/src/fasta/messages.dart';
+import 'package:front_end/src/fasta/parser/assert.dart';
+import 'package:front_end/src/fasta/parser/declaration_kind.dart';
+import 'package:front_end/src/fasta/parser/formal_parameter_kind.dart';
+import 'package:front_end/src/fasta/parser/identifier_context.dart';
+import 'package:front_end/src/fasta/parser/listener.dart';
+import 'package:front_end/src/fasta/parser/member_kind.dart';
+import 'package:front_end/src/fasta/scanner/error_token.dart';
+import 'package:front_end/src/scanner/token.dart';
+
+// THIS FILE IS AUTO GENERATED BY 'test/parser_test_listener_creator.dart'
+
+class ParserTestListener implements Listener {
+ int indent = 0;
+ StringBuffer sb = new StringBuffer();
+
+ void doPrint(String s) {
+ sb.writeln((" " * indent) + s);
+ }
+
+ Uri get uri => null;
+
+ void logEvent(String name) {
+ doPrint('logEvent(' '$name)');
+ }
+
+ set suppressParseErrors(bool value) {
+ doPrint('suppressParseErrors(' '$value)');
+ }
+
+ void beginArguments(Token token) {
+ doPrint('beginArguments(' '$token)');
+ indent++;
+ }
+
+ void endArguments(int count, Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endArguments(' '$count, ' '$beginToken, ' '$endToken)');
+ }
+
+ void handleAsyncModifier(Token asyncToken, Token starToken) {
+ doPrint('handleAsyncModifier(' '$asyncToken, ' '$starToken)');
+ }
+
+ void beginAwaitExpression(Token token) {
+ doPrint('beginAwaitExpression(' '$token)');
+ indent++;
+ }
+
+ void endAwaitExpression(Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endAwaitExpression(' '$beginToken, ' '$endToken)');
+ }
+
+ void endInvalidAwaitExpression(
+ Token beginToken, Token endToken, MessageCode errorCode) {
+ indent--;
+ doPrint('endInvalidAwaitExpression('
+ '$beginToken, '
+ '$endToken, '
+ '$errorCode)');
+ }
+
+ void beginBlock(Token token) {
+ doPrint('beginBlock(' '$token)');
+ indent++;
+ }
+
+ void endBlock(int count, Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endBlock(' '$count, ' '$beginToken, ' '$endToken)');
+ }
+
+ void handleInvalidTopLevelBlock(Token token) {
+ doPrint('handleInvalidTopLevelBlock(' '$token)');
+ }
+
+ void beginCascade(Token token) {
+ doPrint('beginCascade(' '$token)');
+ indent++;
+ }
+
+ void endCascade() {
+ indent--;
+ doPrint('endCascade()');
+ }
+
+ void beginCaseExpression(Token caseKeyword) {
+ doPrint('beginCaseExpression(' '$caseKeyword)');
+ indent++;
+ }
+
+ void endCaseExpression(Token colon) {
+ indent--;
+ doPrint('endCaseExpression(' '$colon)');
+ }
+
+ void beginClassOrMixinBody(DeclarationKind kind, Token token) {
+ doPrint('beginClassOrMixinBody(' '$kind, ' '$token)');
+ indent++;
+ }
+
+ void endClassOrMixinBody(
+ DeclarationKind kind, int memberCount, Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endClassOrMixinBody('
+ '$kind, '
+ '$memberCount, '
+ '$beginToken, '
+ '$endToken)');
+ }
+
+ void beginClassOrNamedMixinApplicationPrelude(Token token) {
+ doPrint('beginClassOrNamedMixinApplicationPrelude(' '$token)');
+ indent++;
+ }
+
+ void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+ doPrint('beginClassDeclaration(' '$begin, ' '$abstractToken, ' '$name)');
+ indent++;
+ }
+
+ void handleClassExtends(Token extendsKeyword) {
+ doPrint('handleClassExtends(' '$extendsKeyword)');
+ }
+
+ void handleClassOrMixinImplements(
+ Token implementsKeyword, int interfacesCount) {
+ doPrint('handleClassOrMixinImplements('
+ '$implementsKeyword, '
+ '$interfacesCount)');
+ }
+
+ void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
+ doPrint('handleClassHeader(' '$begin, ' '$classKeyword, ' '$nativeToken)');
+ }
+
+ void handleRecoverClassHeader() {
+ doPrint('handleRecoverClassHeader()');
+ }
+
+ void endClassDeclaration(Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endClassDeclaration(' '$beginToken, ' '$endToken)');
+ }
+
+ void beginMixinDeclaration(Token mixinKeyword, Token name) {
+ doPrint('beginMixinDeclaration(' '$mixinKeyword, ' '$name)');
+ indent++;
+ }
+
+ void handleMixinOn(Token onKeyword, int typeCount) {
+ doPrint('handleMixinOn(' '$onKeyword, ' '$typeCount)');
+ }
+
+ void handleMixinHeader(Token mixinKeyword) {
+ doPrint('handleMixinHeader(' '$mixinKeyword)');
+ }
+
+ void handleRecoverMixinHeader() {
+ doPrint('handleRecoverMixinHeader()');
+ }
+
+ void endMixinDeclaration(Token mixinKeyword, Token endToken) {
+ indent--;
+ doPrint('endMixinDeclaration(' '$mixinKeyword, ' '$endToken)');
+ }
+
+ void beginExtensionDeclarationPrelude(Token extensionKeyword) {
+ doPrint('beginExtensionDeclarationPrelude(' '$extensionKeyword)');
+ indent++;
+ }
+
+ void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+ doPrint('beginExtensionDeclaration(' '$extensionKeyword, ' '$name)');
+ indent++;
+ }
+
+ void endExtensionDeclaration(
+ Token extensionKeyword, Token onKeyword, Token token) {
+ indent--;
+ doPrint('endExtensionDeclaration('
+ '$extensionKeyword, '
+ '$onKeyword, '
+ '$token)');
+ }
+
+ void beginCombinators(Token token) {
+ doPrint('beginCombinators(' '$token)');
+ indent++;
+ }
+
+ void endCombinators(int count) {
+ indent--;
+ doPrint('endCombinators(' '$count)');
+ }
+
+ void beginCompilationUnit(Token token) {
+ doPrint('beginCompilationUnit(' '$token)');
+ indent++;
+ }
+
+ void handleDirectivesOnly() {
+ doPrint('handleDirectivesOnly()');
+ }
+
+ void endCompilationUnit(int count, Token token) {
+ indent--;
+ doPrint('endCompilationUnit(' '$count, ' '$token)');
+ }
+
+ void beginConstLiteral(Token token) {
+ doPrint('beginConstLiteral(' '$token)');
+ indent++;
+ }
+
+ void endConstLiteral(Token token) {
+ indent--;
+ doPrint('endConstLiteral(' '$token)');
+ }
+
+ void beginConstructorReference(Token start) {
+ doPrint('beginConstructorReference(' '$start)');
+ indent++;
+ }
+
+ void endConstructorReference(
+ Token start, Token periodBeforeName, Token endToken) {
+ indent--;
+ doPrint('endConstructorReference('
+ '$start, '
+ '$periodBeforeName, '
+ '$endToken)');
+ }
+
+ void beginDoWhileStatement(Token token) {
+ doPrint('beginDoWhileStatement(' '$token)');
+ indent++;
+ }
+
+ void endDoWhileStatement(
+ Token doKeyword, Token whileKeyword, Token endToken) {
+ indent--;
+ doPrint(
+ 'endDoWhileStatement(' '$doKeyword, ' '$whileKeyword, ' '$endToken)');
+ }
+
+ void beginDoWhileStatementBody(Token token) {
+ doPrint('beginDoWhileStatementBody(' '$token)');
+ indent++;
+ }
+
+ void endDoWhileStatementBody(Token token) {
+ indent--;
+ doPrint('endDoWhileStatementBody(' '$token)');
+ }
+
+ void beginWhileStatementBody(Token token) {
+ doPrint('beginWhileStatementBody(' '$token)');
+ indent++;
+ }
+
+ void endWhileStatementBody(Token token) {
+ indent--;
+ doPrint('endWhileStatementBody(' '$token)');
+ }
+
+ void beginEnum(Token enumKeyword) {
+ doPrint('beginEnum(' '$enumKeyword)');
+ indent++;
+ }
+
+ void endEnum(Token enumKeyword, Token leftBrace, int count) {
+ indent--;
+ doPrint('endEnum(' '$enumKeyword, ' '$leftBrace, ' '$count)');
+ }
+
+ void beginExport(Token token) {
+ doPrint('beginExport(' '$token)');
+ indent++;
+ }
+
+ void endExport(Token exportKeyword, Token semicolon) {
+ indent--;
+ doPrint('endExport(' '$exportKeyword, ' '$semicolon)');
+ }
+
+ void handleExtraneousExpression(Token token, Message message) {
+ doPrint('handleExtraneousExpression(' '$token, ' '$message)');
+ }
+
+ void handleExpressionStatement(Token token) {
+ doPrint('handleExpressionStatement(' '$token)');
+ }
+
+ void beginFactoryMethod(
+ Token lastConsumed, Token externalToken, Token constToken) {
+ doPrint('beginFactoryMethod('
+ '$lastConsumed, '
+ '$externalToken, '
+ '$constToken)');
+ indent++;
+ }
+
+ void endClassFactoryMethod(
+ Token beginToken, Token factoryKeyword, Token endToken) {
+ indent--;
+ doPrint('endClassFactoryMethod('
+ '$beginToken, '
+ '$factoryKeyword, '
+ '$endToken)');
+ }
+
+ void endMixinFactoryMethod(
+ Token beginToken, Token factoryKeyword, Token endToken) {
+ indent--;
+ doPrint('endMixinFactoryMethod('
+ '$beginToken, '
+ '$factoryKeyword, '
+ '$endToken)');
+ }
+
+ void endExtensionFactoryMethod(
+ Token beginToken, Token factoryKeyword, Token endToken) {
+ indent--;
+ doPrint('endExtensionFactoryMethod('
+ '$beginToken, '
+ '$factoryKeyword, '
+ '$endToken)');
+ }
+
+ void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+ Token covariantToken, Token varFinalOrConst) {
+ doPrint('beginFormalParameter('
+ '$token, '
+ '$kind, '
+ '$requiredToken, '
+ '$covariantToken, '
+ '$varFinalOrConst)');
+ indent++;
+ }
+
+ void endFormalParameter(
+ Token thisKeyword,
+ Token periodAfterThis,
+ Token nameToken,
+ Token initializerStart,
+ Token initializerEnd,
+ FormalParameterKind kind,
+ MemberKind memberKind) {
+ indent--;
+ doPrint('endFormalParameter('
+ '$thisKeyword, '
+ '$periodAfterThis, '
+ '$nameToken, '
+ '$initializerStart, '
+ '$initializerEnd, '
+ '$kind, '
+ '$memberKind)');
+ }
+
+ void handleNoFormalParameters(Token token, MemberKind kind) {
+ doPrint('handleNoFormalParameters(' '$token, ' '$kind)');
+ }
+
+ void beginFormalParameters(Token token, MemberKind kind) {
+ doPrint('beginFormalParameters(' '$token, ' '$kind)');
+ indent++;
+ }
+
+ void endFormalParameters(
+ int count, Token beginToken, Token endToken, MemberKind kind) {
+ indent--;
+ doPrint('endFormalParameters('
+ '$count, '
+ '$beginToken, '
+ '$endToken, '
+ '$kind)');
+ }
+
+ void endClassFields(Token staticToken, Token covariantToken, Token lateToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endClassFields('
+ '$staticToken, '
+ '$covariantToken, '
+ '$lateToken, '
+ '$varFinalOrConst, '
+ '$count, '
+ '$beginToken, '
+ '$endToken)');
+ }
+
+ void endMixinFields(Token staticToken, Token covariantToken, Token lateToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endMixinFields('
+ '$staticToken, '
+ '$covariantToken, '
+ '$lateToken, '
+ '$varFinalOrConst, '
+ '$count, '
+ '$beginToken, '
+ '$endToken)');
+ }
+
+ void endExtensionFields(
+ Token staticToken,
+ Token covariantToken,
+ Token lateToken,
+ Token varFinalOrConst,
+ int count,
+ Token beginToken,
+ Token endToken) {
+ indent--;
+ doPrint('endExtensionFields('
+ '$staticToken, '
+ '$covariantToken, '
+ '$lateToken, '
+ '$varFinalOrConst, '
+ '$count, '
+ '$beginToken, '
+ '$endToken)');
+ }
+
+ void handleForInitializerEmptyStatement(Token token) {
+ doPrint('handleForInitializerEmptyStatement(' '$token)');
+ }
+
+ void handleForInitializerExpressionStatement(Token token) {
+ doPrint('handleForInitializerExpressionStatement(' '$token)');
+ }
+
+ void handleForInitializerLocalVariableDeclaration(Token token) {
+ doPrint('handleForInitializerLocalVariableDeclaration(' '$token)');
+ }
+
+ void beginForStatement(Token token) {
+ doPrint('beginForStatement(' '$token)');
+ indent++;
+ }
+
+ void handleForLoopParts(Token forKeyword, Token leftParen,
+ Token leftSeparator, int updateExpressionCount) {
+ doPrint('handleForLoopParts('
+ '$forKeyword, '
+ '$leftParen, '
+ '$leftSeparator, '
+ '$updateExpressionCount)');
+ }
+
+ void endForStatement(Token endToken) {
+ indent--;
+ doPrint('endForStatement(' '$endToken)');
+ }
+
+ void beginForStatementBody(Token token) {
+ doPrint('beginForStatementBody(' '$token)');
+ indent++;
+ }
+
+ void endForStatementBody(Token token) {
+ indent--;
+ doPrint('endForStatementBody(' '$token)');
+ }
+
+ void handleForInLoopParts(Token awaitToken, Token forToken,
+ Token leftParenthesis, Token inKeyword) {
+ doPrint('handleForInLoopParts('
+ '$awaitToken, '
+ '$forToken, '
+ '$leftParenthesis, '
+ '$inKeyword)');
+ }
+
+ void endForIn(Token endToken) {
+ indent--;
+ doPrint('endForIn(' '$endToken)');
+ }
+
+ void beginForInExpression(Token token) {
+ doPrint('beginForInExpression(' '$token)');
+ indent++;
+ }
+
+ void endForInExpression(Token token) {
+ indent--;
+ doPrint('endForInExpression(' '$token)');
+ }
+
+ void beginForInBody(Token token) {
+ doPrint('beginForInBody(' '$token)');
+ indent++;
+ }
+
+ void endForInBody(Token token) {
+ indent--;
+ doPrint('endForInBody(' '$token)');
+ }
+
+ void beginNamedFunctionExpression(Token token) {
+ doPrint('beginNamedFunctionExpression(' '$token)');
+ indent++;
+ }
+
+ void endNamedFunctionExpression(Token endToken) {
+ indent--;
+ doPrint('endNamedFunctionExpression(' '$endToken)');
+ }
+
+ void beginLocalFunctionDeclaration(Token token) {
+ doPrint('beginLocalFunctionDeclaration(' '$token)');
+ indent++;
+ }
+
+ void endLocalFunctionDeclaration(Token endToken) {
+ indent--;
+ doPrint('endLocalFunctionDeclaration(' '$endToken)');
+ }
+
+ void beginBlockFunctionBody(Token token) {
+ doPrint('beginBlockFunctionBody(' '$token)');
+ indent++;
+ }
+
+ void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endBlockFunctionBody(' '$count, ' '$beginToken, ' '$endToken)');
+ }
+
+ void handleNoFunctionBody(Token token) {
+ doPrint('handleNoFunctionBody(' '$token)');
+ }
+
+ void handleFunctionBodySkipped(Token token, bool isExpressionBody) {
+ doPrint('handleFunctionBodySkipped(' '$token, ' '$isExpressionBody)');
+ }
+
+ void beginFunctionName(Token token) {
+ doPrint('beginFunctionName(' '$token)');
+ indent++;
+ }
+
+ void endFunctionName(Token beginToken, Token token) {
+ indent--;
+ doPrint('endFunctionName(' '$beginToken, ' '$token)');
+ }
+
+ void beginFunctionTypeAlias(Token token) {
+ doPrint('beginFunctionTypeAlias(' '$token)');
+ indent++;
+ }
+
+ void endFunctionTypeAlias(
+ Token typedefKeyword, Token equals, Token endToken) {
+ indent--;
+ doPrint(
+ 'endFunctionTypeAlias(' '$typedefKeyword, ' '$equals, ' '$endToken)');
+ }
+
+ void handleClassWithClause(Token withKeyword) {
+ doPrint('handleClassWithClause(' '$withKeyword)');
+ }
+
+ void handleClassNoWithClause() {
+ doPrint('handleClassNoWithClause()');
+ }
+
+ void beginNamedMixinApplication(
+ Token begin, Token abstractToken, Token name) {
+ doPrint(
+ 'beginNamedMixinApplication(' '$begin, ' '$abstractToken, ' '$name)');
+ indent++;
+ }
+
+ void handleNamedMixinApplicationWithClause(Token withKeyword) {
+ doPrint('handleNamedMixinApplicationWithClause(' '$withKeyword)');
+ }
+
+ void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
+ Token implementsKeyword, Token endToken) {
+ indent--;
+ doPrint('endNamedMixinApplication('
+ '$begin, '
+ '$classKeyword, '
+ '$equals, '
+ '$implementsKeyword, '
+ '$endToken)');
+ }
+
+ void beginHide(Token hideKeyword) {
+ doPrint('beginHide(' '$hideKeyword)');
+ indent++;
+ }
+
+ void endHide(Token hideKeyword) {
+ indent--;
+ doPrint('endHide(' '$hideKeyword)');
+ }
+
+ void handleIdentifierList(int count) {
+ doPrint('handleIdentifierList(' '$count)');
+ }
+
+ void beginTypeList(Token token) {
+ doPrint('beginTypeList(' '$token)');
+ indent++;
+ }
+
+ void endTypeList(int count) {
+ indent--;
+ doPrint('endTypeList(' '$count)');
+ }
+
+ void beginIfStatement(Token token) {
+ doPrint('beginIfStatement(' '$token)');
+ indent++;
+ }
+
+ void endIfStatement(Token ifToken, Token elseToken) {
+ indent--;
+ doPrint('endIfStatement(' '$ifToken, ' '$elseToken)');
+ }
+
+ void beginThenStatement(Token token) {
+ doPrint('beginThenStatement(' '$token)');
+ indent++;
+ }
+
+ void endThenStatement(Token token) {
+ indent--;
+ doPrint('endThenStatement(' '$token)');
+ }
+
+ void beginElseStatement(Token token) {
+ doPrint('beginElseStatement(' '$token)');
+ indent++;
+ }
+
+ void endElseStatement(Token token) {
+ indent--;
+ doPrint('endElseStatement(' '$token)');
+ }
+
+ void beginImport(Token importKeyword) {
+ doPrint('beginImport(' '$importKeyword)');
+ indent++;
+ }
+
+ void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+ doPrint('handleImportPrefix(' '$deferredKeyword, ' '$asKeyword)');
+ }
+
+ void endImport(Token importKeyword, Token semicolon) {
+ indent--;
+ doPrint('endImport(' '$importKeyword, ' '$semicolon)');
+ }
+
+ void handleRecoverImport(Token semicolon) {
+ doPrint('handleRecoverImport(' '$semicolon)');
+ }
+
+ void beginConditionalUris(Token token) {
+ doPrint('beginConditionalUris(' '$token)');
+ indent++;
+ }
+
+ void endConditionalUris(int count) {
+ indent--;
+ doPrint('endConditionalUris(' '$count)');
+ }
+
+ void beginConditionalUri(Token ifKeyword) {
+ doPrint('beginConditionalUri(' '$ifKeyword)');
+ indent++;
+ }
+
+ void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
+ indent--;
+ doPrint('endConditionalUri(' '$ifKeyword, ' '$leftParen, ' '$equalSign)');
+ }
+
+ void handleDottedName(int count, Token firstIdentifier) {
+ doPrint('handleDottedName(' '$count, ' '$firstIdentifier)');
+ }
+
+ void beginImplicitCreationExpression(Token token) {
+ doPrint('beginImplicitCreationExpression(' '$token)');
+ indent++;
+ }
+
+ void endImplicitCreationExpression(Token token) {
+ indent--;
+ doPrint('endImplicitCreationExpression(' '$token)');
+ }
+
+ void beginInitializedIdentifier(Token token) {
+ doPrint('beginInitializedIdentifier(' '$token)');
+ indent++;
+ }
+
+ void endInitializedIdentifier(Token nameToken) {
+ indent--;
+ doPrint('endInitializedIdentifier(' '$nameToken)');
+ }
+
+ void beginFieldInitializer(Token token) {
+ doPrint('beginFieldInitializer(' '$token)');
+ indent++;
+ }
+
+ void endFieldInitializer(Token assignment, Token token) {
+ indent--;
+ doPrint('endFieldInitializer(' '$assignment, ' '$token)');
+ }
+
+ void handleNoFieldInitializer(Token token) {
+ doPrint('handleNoFieldInitializer(' '$token)');
+ }
+
+ void beginVariableInitializer(Token token) {
+ doPrint('beginVariableInitializer(' '$token)');
+ indent++;
+ }
+
+ void endVariableInitializer(Token assignmentOperator) {
+ indent--;
+ doPrint('endVariableInitializer(' '$assignmentOperator)');
+ }
+
+ void handleNoVariableInitializer(Token token) {
+ doPrint('handleNoVariableInitializer(' '$token)');
+ }
+
+ void beginInitializer(Token token) {
+ doPrint('beginInitializer(' '$token)');
+ indent++;
+ }
+
+ void endInitializer(Token token) {
+ indent--;
+ doPrint('endInitializer(' '$token)');
+ }
+
+ void beginInitializers(Token token) {
+ doPrint('beginInitializers(' '$token)');
+ indent++;
+ }
+
+ void endInitializers(int count, Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endInitializers(' '$count, ' '$beginToken, ' '$endToken)');
+ }
+
+ void handleNoInitializers() {
+ doPrint('handleNoInitializers()');
+ }
+
+ void handleInvalidExpression(Token token) {
+ doPrint('handleInvalidExpression(' '$token)');
+ }
+
+ void handleInvalidFunctionBody(Token token) {
+ doPrint('handleInvalidFunctionBody(' '$token)');
+ }
+
+ void handleInvalidTypeReference(Token token) {
+ doPrint('handleInvalidTypeReference(' '$token)');
+ }
+
+ void handleLabel(Token token) {
+ doPrint('handleLabel(' '$token)');
+ }
+
+ void beginLabeledStatement(Token token, int labelCount) {
+ doPrint('beginLabeledStatement(' '$token, ' '$labelCount)');
+ indent++;
+ }
+
+ void endLabeledStatement(int labelCount) {
+ indent--;
+ doPrint('endLabeledStatement(' '$labelCount)');
+ }
+
+ void beginLibraryName(Token token) {
+ doPrint('beginLibraryName(' '$token)');
+ indent++;
+ }
+
+ void endLibraryName(Token libraryKeyword, Token semicolon) {
+ indent--;
+ doPrint('endLibraryName(' '$libraryKeyword, ' '$semicolon)');
+ }
+
+ void handleLiteralMapEntry(Token colon, Token endToken) {
+ doPrint('handleLiteralMapEntry(' '$colon, ' '$endToken)');
+ }
+
+ void beginLiteralString(Token token) {
+ doPrint('beginLiteralString(' '$token)');
+ indent++;
+ }
+
+ void handleInterpolationExpression(Token leftBracket, Token rightBracket) {
+ doPrint('handleInterpolationExpression(' '$leftBracket, ' '$rightBracket)');
+ }
+
+ void endLiteralString(int interpolationCount, Token endToken) {
+ indent--;
+ doPrint('endLiteralString(' '$interpolationCount, ' '$endToken)');
+ }
+
+ void handleStringJuxtaposition(int literalCount) {
+ doPrint('handleStringJuxtaposition(' '$literalCount)');
+ }
+
+ void beginMember() {
+ doPrint('beginMember()');
+ indent++;
+ }
+
+ void handleInvalidMember(Token endToken) {
+ doPrint('handleInvalidMember(' '$endToken)');
+ }
+
+ void endMember() {
+ indent--;
+ doPrint('endMember()');
+ }
+
+ void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
+ Token varFinalOrConst, Token getOrSet, Token name) {
+ doPrint('beginMethod('
+ '$externalToken, '
+ '$staticToken, '
+ '$covariantToken, '
+ '$varFinalOrConst, '
+ '$getOrSet, '
+ '$name)');
+ indent++;
+ }
+
+ void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
+ Token beginInitializers, Token endToken) {
+ indent--;
+ doPrint('endClassMethod('
+ '$getOrSet, '
+ '$beginToken, '
+ '$beginParam, '
+ '$beginInitializers, '
+ '$endToken)');
+ }
+
+ void endMixinMethod(Token getOrSet, Token beginToken, Token beginParam,
+ Token beginInitializers, Token endToken) {
+ indent--;
+ doPrint('endMixinMethod('
+ '$getOrSet, '
+ '$beginToken, '
+ '$beginParam, '
+ '$beginInitializers, '
+ '$endToken)');
+ }
+
+ void endExtensionMethod(Token getOrSet, Token beginToken, Token beginParam,
+ Token beginInitializers, Token endToken) {
+ indent--;
+ doPrint('endExtensionMethod('
+ '$getOrSet, '
+ '$beginToken, '
+ '$beginParam, '
+ '$beginInitializers, '
+ '$endToken)');
+ }
+
+ void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam,
+ Token beginInitializers, Token endToken) {
+ indent--;
+ doPrint('endClassConstructor('
+ '$getOrSet, '
+ '$beginToken, '
+ '$beginParam, '
+ '$beginInitializers, '
+ '$endToken)');
+ }
+
+ void endMixinConstructor(Token getOrSet, Token beginToken, Token beginParam,
+ Token beginInitializers, Token endToken) {
+ indent--;
+ doPrint('endMixinConstructor('
+ '$getOrSet, '
+ '$beginToken, '
+ '$beginParam, '
+ '$beginInitializers, '
+ '$endToken)');
+ }
+
+ void endExtensionConstructor(Token getOrSet, Token beginToken,
+ Token beginParam, Token beginInitializers, Token endToken) {
+ indent--;
+ doPrint('endExtensionConstructor('
+ '$getOrSet, '
+ '$beginToken, '
+ '$beginParam, '
+ '$beginInitializers, '
+ '$endToken)');
+ }
+
+ void beginMetadataStar(Token token) {
+ doPrint('beginMetadataStar(' '$token)');
+ indent++;
+ }
+
+ void endMetadataStar(int count) {
+ indent--;
+ doPrint('endMetadataStar(' '$count)');
+ }
+
+ void beginMetadata(Token token) {
+ doPrint('beginMetadata(' '$token)');
+ indent++;
+ }
+
+ void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+ indent--;
+ doPrint('endMetadata(' '$beginToken, ' '$periodBeforeName, ' '$endToken)');
+ }
+
+ void beginOptionalFormalParameters(Token token) {
+ doPrint('beginOptionalFormalParameters(' '$token)');
+ indent++;
+ }
+
+ void endOptionalFormalParameters(
+ int count, Token beginToken, Token endToken) {
+ indent--;
+ doPrint(
+ 'endOptionalFormalParameters(' '$count, ' '$beginToken, ' '$endToken)');
+ }
+
+ void beginPart(Token token) {
+ doPrint('beginPart(' '$token)');
+ indent++;
+ }
+
+ void endPart(Token partKeyword, Token semicolon) {
+ indent--;
+ doPrint('endPart(' '$partKeyword, ' '$semicolon)');
+ }
+
+ void beginPartOf(Token token) {
+ doPrint('beginPartOf(' '$token)');
+ indent++;
+ }
+
+ void endPartOf(
+ Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
+ indent--;
+ doPrint('endPartOf('
+ '$partKeyword, '
+ '$ofKeyword, '
+ '$semicolon, '
+ '$hasName)');
+ }
+
+ void beginRedirectingFactoryBody(Token token) {
+ doPrint('beginRedirectingFactoryBody(' '$token)');
+ indent++;
+ }
+
+ void endRedirectingFactoryBody(Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endRedirectingFactoryBody(' '$beginToken, ' '$endToken)');
+ }
+
+ void beginReturnStatement(Token token) {
+ doPrint('beginReturnStatement(' '$token)');
+ indent++;
+ }
+
+ void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
+ doPrint('handleNativeFunctionBody(' '$nativeToken, ' '$semicolon)');
+ }
+
+ void handleNativeFunctionBodyIgnored(Token nativeToken, Token semicolon) {
+ doPrint('handleNativeFunctionBodyIgnored(' '$nativeToken, ' '$semicolon)');
+ }
+
+ void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
+ doPrint('handleNativeFunctionBodySkipped(' '$nativeToken, ' '$semicolon)');
+ }
+
+ void handleEmptyFunctionBody(Token semicolon) {
+ doPrint('handleEmptyFunctionBody(' '$semicolon)');
+ }
+
+ void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
+ doPrint('handleExpressionFunctionBody(' '$arrowToken, ' '$endToken)');
+ }
+
+ void endReturnStatement(
+ bool hasExpression, Token beginToken, Token endToken) {
+ indent--;
+ doPrint(
+ 'endReturnStatement(' '$hasExpression, ' '$beginToken, ' '$endToken)');
+ }
+
+ void handleSend(Token beginToken, Token endToken) {
+ doPrint('handleSend(' '$beginToken, ' '$endToken)');
+ }
+
+ void beginShow(Token showKeyword) {
+ doPrint('beginShow(' '$showKeyword)');
+ indent++;
+ }
+
+ void endShow(Token showKeyword) {
+ indent--;
+ doPrint('endShow(' '$showKeyword)');
+ }
+
+ void beginSwitchStatement(Token token) {
+ doPrint('beginSwitchStatement(' '$token)');
+ indent++;
+ }
+
+ void endSwitchStatement(Token switchKeyword, Token endToken) {
+ indent--;
+ doPrint('endSwitchStatement(' '$switchKeyword, ' '$endToken)');
+ }
+
+ void beginSwitchBlock(Token token) {
+ doPrint('beginSwitchBlock(' '$token)');
+ indent++;
+ }
+
+ void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endSwitchBlock(' '$caseCount, ' '$beginToken, ' '$endToken)');
+ }
+
+ void beginLiteralSymbol(Token token) {
+ doPrint('beginLiteralSymbol(' '$token)');
+ indent++;
+ }
+
+ void endLiteralSymbol(Token hashToken, int identifierCount) {
+ indent--;
+ doPrint('endLiteralSymbol(' '$hashToken, ' '$identifierCount)');
+ }
+
+ void handleThrowExpression(Token throwToken, Token endToken) {
+ doPrint('handleThrowExpression(' '$throwToken, ' '$endToken)');
+ }
+
+ void beginRethrowStatement(Token token) {
+ doPrint('beginRethrowStatement(' '$token)');
+ indent++;
+ }
+
+ void endRethrowStatement(Token rethrowToken, Token endToken) {
+ indent--;
+ doPrint('endRethrowStatement(' '$rethrowToken, ' '$endToken)');
+ }
+
+ void endTopLevelDeclaration(Token token) {
+ indent--;
+ doPrint('endTopLevelDeclaration(' '$token)');
+ }
+
+ void handleInvalidTopLevelDeclaration(Token endToken) {
+ doPrint('handleInvalidTopLevelDeclaration(' '$endToken)');
+ }
+
+ void beginTopLevelMember(Token token) {
+ doPrint('beginTopLevelMember(' '$token)');
+ indent++;
+ }
+
+ void endTopLevelFields(
+ Token staticToken,
+ Token covariantToken,
+ Token lateToken,
+ Token varFinalOrConst,
+ int count,
+ Token beginToken,
+ Token endToken) {
+ indent--;
+ doPrint('endTopLevelFields('
+ '$staticToken, '
+ '$covariantToken, '
+ '$lateToken, '
+ '$varFinalOrConst, '
+ '$count, '
+ '$beginToken, '
+ '$endToken)');
+ }
+
+ void beginTopLevelMethod(Token lastConsumed, Token externalToken) {
+ doPrint('beginTopLevelMethod(' '$lastConsumed, ' '$externalToken)');
+ indent++;
+ }
+
+ void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+ indent--;
+ doPrint('endTopLevelMethod(' '$beginToken, ' '$getOrSet, ' '$endToken)');
+ }
+
+ void beginTryStatement(Token token) {
+ doPrint('beginTryStatement(' '$token)');
+ indent++;
+ }
+
+ void handleCaseMatch(Token caseKeyword, Token colon) {
+ doPrint('handleCaseMatch(' '$caseKeyword, ' '$colon)');
+ }
+
+ void beginCatchClause(Token token) {
+ doPrint('beginCatchClause(' '$token)');
+ indent++;
+ }
+
+ void endCatchClause(Token token) {
+ indent--;
+ doPrint('endCatchClause(' '$token)');
+ }
+
+ void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
+ doPrint('handleCatchBlock(' '$onKeyword, ' '$catchKeyword, ' '$comma)');
+ }
+
+ void handleFinallyBlock(Token finallyKeyword) {
+ doPrint('handleFinallyBlock(' '$finallyKeyword)');
+ }
+
+ void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
+ indent--;
+ doPrint(
+ 'endTryStatement(' '$catchCount, ' '$tryKeyword, ' '$finallyKeyword)');
+ }
+
+ void handleType(Token beginToken, Token questionMark) {
+ doPrint('handleType(' '$beginToken, ' '$questionMark)');
+ }
+
+ void handleNonNullAssertExpression(Token bang) {
+ doPrint('handleNonNullAssertExpression(' '$bang)');
+ }
+
+ void reportErrorIfNullableType(Token questionMark) {
+ doPrint('reportErrorIfNullableType(' '$questionMark)');
+ }
+
+ void reportNonNullableModifierError(Token modifierToken) {
+ doPrint('reportNonNullableModifierError(' '$modifierToken)');
+ }
+
+ void reportNonNullAssertExpressionNotEnabled(Token bang) {
+ doPrint('reportNonNullAssertExpressionNotEnabled(' '$bang)');
+ }
+
+ void handleNoName(Token token) {
+ doPrint('handleNoName(' '$token)');
+ }
+
+ void beginFunctionType(Token beginToken) {
+ doPrint('beginFunctionType(' '$beginToken)');
+ indent++;
+ }
+
+ void endFunctionType(Token functionToken, Token questionMark) {
+ indent--;
+ doPrint('endFunctionType(' '$functionToken, ' '$questionMark)');
+ }
+
+ void beginTypeArguments(Token token) {
+ doPrint('beginTypeArguments(' '$token)');
+ indent++;
+ }
+
+ void endTypeArguments(int count, Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endTypeArguments(' '$count, ' '$beginToken, ' '$endToken)');
+ }
+
+ void handleInvalidTypeArguments(Token token) {
+ doPrint('handleInvalidTypeArguments(' '$token)');
+ }
+
+ void handleNoTypeArguments(Token token) {
+ doPrint('handleNoTypeArguments(' '$token)');
+ }
+
+ void beginTypeVariable(Token token) {
+ doPrint('beginTypeVariable(' '$token)');
+ indent++;
+ }
+
+ void handleTypeVariablesDefined(Token token, int count) {
+ doPrint('handleTypeVariablesDefined(' '$token, ' '$count)');
+ }
+
+ void endTypeVariable(
+ Token token, int index, Token extendsOrSuper, Token variance) {
+ indent--;
+ doPrint('endTypeVariable('
+ '$token, '
+ '$index, '
+ '$extendsOrSuper, '
+ '$variance)');
+ }
+
+ void beginTypeVariables(Token token) {
+ doPrint('beginTypeVariables(' '$token)');
+ indent++;
+ }
+
+ void endTypeVariables(Token beginToken, Token endToken) {
+ indent--;
+ doPrint('endTypeVariables(' '$beginToken, ' '$endToken)');
+ }
+
+ void handleVarianceModifier(Token variance) {
+ doPrint('handleVarianceModifier(' '$variance)');
+ }
+
+ void reportVarianceModifierNotEnabled(Token variance) {
+ doPrint('reportVarianceModifierNotEnabled(' '$variance)');
+ }
+
+ void beginFunctionExpression(Token token) {
+ doPrint('beginFunctionExpression(' '$token)');
+ indent++;
+ }
+
+ void endFunctionExpression(Token beginToken, Token token) {
+ indent--;
+ doPrint('endFunctionExpression(' '$beginToken, ' '$token)');
+ }
+
+ void beginVariablesDeclaration(
+ Token token, Token lateToken, Token varFinalOrConst) {
+ doPrint('beginVariablesDeclaration('
+ '$token, '
+ '$lateToken, '
+ '$varFinalOrConst)');
+ indent++;
+ }
+
+ void endVariablesDeclaration(int count, Token endToken) {
+ indent--;
+ doPrint('endVariablesDeclaration(' '$count, ' '$endToken)');
+ }
+
+ void beginWhileStatement(Token token) {
+ doPrint('beginWhileStatement(' '$token)');
+ indent++;
+ }
+
+ void endWhileStatement(Token whileKeyword, Token endToken) {
+ indent--;
+ doPrint('endWhileStatement(' '$whileKeyword, ' '$endToken)');
+ }
+
+ void handleAsOperator(Token operator) {
+ doPrint('handleAsOperator(' '$operator)');
+ }
+
+ void handleAssignmentExpression(Token token) {
+ doPrint('handleAssignmentExpression(' '$token)');
+ }
+
+ void beginBinaryExpression(Token token) {
+ doPrint('beginBinaryExpression(' '$token)');
+ indent++;
+ }
+
+ void endBinaryExpression(Token token) {
+ indent--;
+ doPrint('endBinaryExpression(' '$token)');
+ }
+
+ void beginConditionalExpression(Token question) {
+ doPrint('beginConditionalExpression(' '$question)');
+ indent++;
+ }
+
+ void handleConditionalExpressionColon() {
+ doPrint('handleConditionalExpressionColon()');
+ }
+
+ void endConditionalExpression(Token question, Token colon) {
+ indent--;
+ doPrint('endConditionalExpression(' '$question, ' '$colon)');
+ }
+
+ void beginConstExpression(Token constKeyword) {
+ doPrint('beginConstExpression(' '$constKeyword)');
+ indent++;
+ }
+
+ void endConstExpression(Token token) {
+ indent--;
+ doPrint('endConstExpression(' '$token)');
+ }
+
+ void beginForControlFlow(Token awaitToken, Token forToken) {
+ doPrint('beginForControlFlow(' '$awaitToken, ' '$forToken)');
+ indent++;
+ }
+
+ void endForControlFlow(Token token) {
+ indent--;
+ doPrint('endForControlFlow(' '$token)');
+ }
+
+ void endForInControlFlow(Token token) {
+ indent--;
+ doPrint('endForInControlFlow(' '$token)');
+ }
+
+ void beginIfControlFlow(Token ifToken) {
+ doPrint('beginIfControlFlow(' '$ifToken)');
+ indent++;
+ }
+
+ void beginThenControlFlow(Token token) {
+ doPrint('beginThenControlFlow(' '$token)');
+ indent++;
+ }
+
+ void handleElseControlFlow(Token elseToken) {
+ doPrint('handleElseControlFlow(' '$elseToken)');
+ }
+
+ void endIfControlFlow(Token token) {
+ indent--;
+ doPrint('endIfControlFlow(' '$token)');
+ }
+
+ void endIfElseControlFlow(Token token) {
+ indent--;
+ doPrint('endIfElseControlFlow(' '$token)');
+ }
+
+ void handleSpreadExpression(Token spreadToken) {
+ doPrint('handleSpreadExpression(' '$spreadToken)');
+ }
+
+ void beginFunctionTypedFormalParameter(Token token) {
+ doPrint('beginFunctionTypedFormalParameter(' '$token)');
+ indent++;
+ }
+
+ void endFunctionTypedFormalParameter(Token nameToken, Token question) {
+ indent--;
+ doPrint('endFunctionTypedFormalParameter(' '$nameToken, ' '$question)');
+ }
+
+ void handleIdentifier(Token token, IdentifierContext context) {
+ doPrint('handleIdentifier(' '$token, ' '$context)');
+ }
+
+ void handleIndexedExpression(
+ Token openSquareBracket, Token closeSquareBracket) {
+ doPrint('handleIndexedExpression('
+ '$openSquareBracket, '
+ '$closeSquareBracket)');
+ }
+
+ void handleIsOperator(Token isOperator, Token not) {
+ doPrint('handleIsOperator(' '$isOperator, ' '$not)');
+ }
+
+ void handleLiteralBool(Token token) {
+ doPrint('handleLiteralBool(' '$token)');
+ }
+
+ void handleBreakStatement(
+ bool hasTarget, Token breakKeyword, Token endToken) {
+ doPrint(
+ 'handleBreakStatement(' '$hasTarget, ' '$breakKeyword, ' '$endToken)');
+ }
+
+ void handleContinueStatement(
+ bool hasTarget, Token continueKeyword, Token endToken) {
+ doPrint('handleContinueStatement('
+ '$hasTarget, '
+ '$continueKeyword, '
+ '$endToken)');
+ }
+
+ void handleEmptyStatement(Token token) {
+ doPrint('handleEmptyStatement(' '$token)');
+ }
+
+ void beginAssert(Token assertKeyword, Assert kind) {
+ doPrint('beginAssert(' '$assertKeyword, ' '$kind)');
+ indent++;
+ }
+
+ void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
+ Token commaToken, Token semicolonToken) {
+ indent--;
+ doPrint('endAssert('
+ '$assertKeyword, '
+ '$kind, '
+ '$leftParenthesis, '
+ '$commaToken, '
+ '$semicolonToken)');
+ }
+
+ void handleLiteralDouble(Token token) {
+ doPrint('handleLiteralDouble(' '$token)');
+ }
+
+ void handleLiteralInt(Token token) {
+ doPrint('handleLiteralInt(' '$token)');
+ }
+
+ void handleLiteralList(
+ int count, Token leftBracket, Token constKeyword, Token rightBracket) {
+ doPrint('handleLiteralList('
+ '$count, '
+ '$leftBracket, '
+ '$constKeyword, '
+ '$rightBracket)');
+ }
+
+ void handleLiteralSetOrMap(
+ int count,
+ Token leftBrace,
+ Token constKeyword,
+ Token rightBrace,
+ bool hasSetEntry,
+ ) {
+ doPrint('handleLiteralSetOrMap('
+ '$count, '
+ '$leftBrace, '
+ '$constKeyword, '
+ '$rightBrace, '
+ '$hasSetEntry)');
+ }
+
+ void handleLiteralNull(Token token) {
+ doPrint('handleLiteralNull(' '$token)');
+ }
+
+ void handleNativeClause(Token nativeToken, bool hasName) {
+ doPrint('handleNativeClause(' '$nativeToken, ' '$hasName)');
+ }
+
+ void handleNamedArgument(Token colon) {
+ doPrint('handleNamedArgument(' '$colon)');
+ }
+
+ void beginNewExpression(Token token) {
+ doPrint('beginNewExpression(' '$token)');
+ indent++;
+ }
+
+ void endNewExpression(Token token) {
+ indent--;
+ doPrint('endNewExpression(' '$token)');
+ }
+
+ void handleNoArguments(Token token) {
+ doPrint('handleNoArguments(' '$token)');
+ }
+
+ void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
+ doPrint('handleNoConstructorReferenceContinuationAfterTypeArguments('
+ '$token)');
+ }
+
+ void handleNoType(Token lastConsumed) {
+ doPrint('handleNoType(' '$lastConsumed)');
+ }
+
+ void handleNoTypeVariables(Token token) {
+ doPrint('handleNoTypeVariables(' '$token)');
+ }
+
+ void handleOperator(Token token) {
+ doPrint('handleOperator(' '$token)');
+ }
+
+ void handleSymbolVoid(Token token) {
+ doPrint('handleSymbolVoid(' '$token)');
+ }
+
+ void handleOperatorName(Token operatorKeyword, Token token) {
+ doPrint('handleOperatorName(' '$operatorKeyword, ' '$token)');
+ }
+
+ void handleInvalidOperatorName(Token operatorKeyword, Token token) {
+ doPrint('handleInvalidOperatorName(' '$operatorKeyword, ' '$token)');
+ }
+
+ void handleParenthesizedCondition(Token token) {
+ doPrint('handleParenthesizedCondition(' '$token)');
+ }
+
+ void handleParenthesizedExpression(Token token) {
+ doPrint('handleParenthesizedExpression(' '$token)');
+ }
+
+ void handleQualified(Token period) {
+ doPrint('handleQualified(' '$period)');
+ }
+
+ void handleStringPart(Token token) {
+ doPrint('handleStringPart(' '$token)');
+ }
+
+ void handleSuperExpression(Token token, IdentifierContext context) {
+ doPrint('handleSuperExpression(' '$token, ' '$context)');
+ }
+
+ void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) {
+ doPrint(
+ 'beginSwitchCase(' '$labelCount, ' '$expressionCount, ' '$firstToken)');
+ indent++;
+ }
+
+ void endSwitchCase(
+ int labelCount,
+ int expressionCount,
+ Token defaultKeyword,
+ Token colonAfterDefault,
+ int statementCount,
+ Token firstToken,
+ Token endToken) {
+ indent--;
+ doPrint('endSwitchCase('
+ '$labelCount, '
+ '$expressionCount, '
+ '$defaultKeyword, '
+ '$colonAfterDefault, '
+ '$statementCount, '
+ '$firstToken, '
+ '$endToken)');
+ }
+
+ void handleThisExpression(Token token, IdentifierContext context) {
+ doPrint('handleThisExpression(' '$token, ' '$context)');
+ }
+
+ void handleUnaryPostfixAssignmentExpression(Token token) {
+ doPrint('handleUnaryPostfixAssignmentExpression(' '$token)');
+ }
+
+ void handleUnaryPrefixExpression(Token token) {
+ doPrint('handleUnaryPrefixExpression(' '$token)');
+ }
+
+ void handleUnaryPrefixAssignmentExpression(Token token) {
+ doPrint('handleUnaryPrefixAssignmentExpression(' '$token)');
+ }
+
+ void beginFormalParameterDefaultValueExpression() {
+ doPrint('beginFormalParameterDefaultValueExpression()');
+ indent++;
+ }
+
+ void endFormalParameterDefaultValueExpression() {
+ indent--;
+ doPrint('endFormalParameterDefaultValueExpression()');
+ }
+
+ void handleValuedFormalParameter(Token equals, Token token) {
+ doPrint('handleValuedFormalParameter(' '$equals, ' '$token)');
+ }
+
+ void handleFormalParameterWithoutValue(Token token) {
+ doPrint('handleFormalParameterWithoutValue(' '$token)');
+ }
+
+ void handleVoidKeyword(Token token) {
+ doPrint('handleVoidKeyword(' '$token)');
+ }
+
+ void beginYieldStatement(Token token) {
+ doPrint('beginYieldStatement(' '$token)');
+ indent++;
+ }
+
+ void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
+ indent--;
+ doPrint('endYieldStatement(' '$yieldToken, ' '$starToken, ' '$endToken)');
+ }
+
+ void handleRecoverableError(
+ Message message, Token startToken, Token endToken) {
+ doPrint(
+ 'handleRecoverableError(' '$message, ' '$startToken, ' '$endToken)');
+ }
+
+ void handleErrorToken(ErrorToken token) {
+ doPrint('handleErrorToken(' '$token)');
+ }
+
+ void handleUnescapeError(
+ Message message, Token location, int stringOffset, int length) {
+ doPrint('handleUnescapeError('
+ '$message, '
+ '$location, '
+ '$stringOffset, '
+ '$length)');
+ }
+
+ void handleInvalidStatement(Token token, Message message) {
+ doPrint('handleInvalidStatement(' '$token, ' '$message)');
+ }
+
+ void handleScript(Token token) {
+ doPrint('handleScript(' '$token)');
+ }
+
+ void discardTypeReplacedWithCommentTypeAssign() {
+ doPrint('discardTypeReplacedWithCommentTypeAssign()');
+ }
+
+ void handleCommentReferenceText(String referenceSource, int referenceOffset) {
+ doPrint(
+ 'handleCommentReferenceText(' '$referenceSource, ' '$referenceOffset)');
+ }
+
+ void handleCommentReference(
+ Token newKeyword, Token prefix, Token period, Token token) {
+ doPrint('handleCommentReference('
+ '$newKeyword, '
+ '$prefix, '
+ '$period, '
+ '$token)');
+ }
+
+ void handleNoCommentReference() {
+ doPrint('handleNoCommentReference()');
+ }
+}
diff --git a/pkg/front_end/test/parser_test_listener_creator.dart b/pkg/front_end/test/parser_test_listener_creator.dart
new file mode 100644
index 0000000..1d625bf
--- /dev/null
+++ b/pkg/front_end/test/parser_test_listener_creator.dart
@@ -0,0 +1,140 @@
+// Copyright (c) 2019, 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 'dart:io';
+import 'dart:typed_data';
+
+import 'package:front_end/src/fasta/parser.dart';
+import 'package:front_end/src/fasta/parser/formal_parameter_kind.dart';
+import 'package:front_end/src/fasta/parser/listener.dart';
+import 'package:front_end/src/fasta/parser/member_kind.dart';
+import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart';
+import 'package:front_end/src/scanner/token.dart';
+
+main() {
+ File f = new File.fromUri(
+ Platform.script.resolve("../lib/src/fasta/parser/listener.dart"));
+ List<int> rawBytes = f.readAsBytesSync();
+
+ Uint8List bytes = new Uint8List(rawBytes.length + 1);
+ bytes.setRange(0, rawBytes.length, rawBytes);
+
+ Utf8BytesScanner scanner = new Utf8BytesScanner(bytes, includeComments: true);
+ Token firstToken = scanner.tokenize();
+
+ print("""
+// Copyright (c) 2019, 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:front_end/src/fasta/messages.dart';
+import 'package:front_end/src/fasta/parser/assert.dart';
+import 'package:front_end/src/fasta/parser/declaration_kind.dart';
+import 'package:front_end/src/fasta/parser/formal_parameter_kind.dart';
+import 'package:front_end/src/fasta/parser/identifier_context.dart';
+import 'package:front_end/src/fasta/parser/listener.dart';
+import 'package:front_end/src/fasta/parser/member_kind.dart';
+import 'package:front_end/src/fasta/scanner/error_token.dart';
+import 'package:front_end/src/scanner/token.dart';
+
+// THIS FILE IS AUTO GENERATED BY 'test/parser_test_listener_creator.dart'
+
+class ParserTestListener implements Listener {
+ int indent = 0;
+ StringBuffer sb = new StringBuffer();
+
+ void doPrint(String s) {
+ sb.writeln((" " * indent) + s);
+ }
+ """);
+
+ ParserCreatorListener listener = new ParserCreatorListener();
+ ClassMemberParser parser = new ClassMemberParser(listener);
+ parser.parseUnit(firstToken);
+
+ print("""
+ }
+ """);
+}
+
+class ParserCreatorListener extends Listener {
+ bool insideListenerClass = false;
+ String currentMethodName;
+ List<String> parameters = <String>[];
+
+ void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+ if (name.lexeme == "Listener") insideListenerClass = true;
+ }
+
+ void endClassDeclaration(Token beginToken, Token endToken) {
+ insideListenerClass = false;
+ }
+
+ void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
+ Token varFinalOrConst, Token getOrSet, Token name) {
+ currentMethodName = name.lexeme;
+ }
+
+ void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
+ Token beginInitializers, Token endToken) {
+ if (insideListenerClass) {
+ Token token = beginToken;
+ Token latestToken;
+ while (true) {
+ if (latestToken != null && latestToken.charEnd < token.charOffset) {
+ stdout.write(" ");
+ }
+ stdout.write(token.lexeme);
+ if ((token is BeginToken &&
+ token.type == TokenType.OPEN_CURLY_BRACKET) ||
+ token is SimpleToken && token.type == TokenType.FUNCTION) {
+ break;
+ }
+ if (token == endToken) {
+ throw token.runtimeType;
+ }
+ latestToken = token;
+ token = token.next;
+ }
+
+ if (token is SimpleToken && token.type == TokenType.FUNCTION) {
+ stdout.write(" null;");
+ } else {
+ stdout.write("\n");
+ if (currentMethodName.startsWith("end")) {
+ stdout.write("indent--;\n");
+ }
+ stdout.write("doPrint('$currentMethodName(");
+ String separator = "";
+ for (int i = 0; i < parameters.length; i++) {
+ stdout.write(separator);
+ stdout.write(r"''$");
+ stdout.write(parameters[i]);
+ separator = ", ";
+ }
+ stdout.write(")');\n");
+
+ if (currentMethodName.startsWith("begin")) {
+ stdout.write("indent++;\n");
+ }
+
+ stdout.write("}");
+ }
+ stdout.write("\n\n");
+ }
+ parameters.clear();
+ currentMethodName = null;
+ }
+
+ void endFormalParameter(
+ Token thisKeyword,
+ Token periodAfterThis,
+ Token nameToken,
+ Token initializerStart,
+ Token initializerEnd,
+ FormalParameterKind kind,
+ MemberKind memberKind) {
+ parameters.add(nameToken.lexeme);
+ }
+}
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 22cb2ac..e017d56 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -22,6 +22,7 @@
approximation
asserter
auth
+auto
autobianchi
b0x
b1x
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart b/pkg/front_end/testcases/extensions/check_bounds.dart
new file mode 100644
index 0000000..60a157d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2019, 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.
+
+class A {}
+class B extends A {}
+
+class Class<T extends A> {}
+
+extension Extension<T extends B> on Class<T> {
+ method() {}
+ genericMethod<S extends B>(S s) {}
+}
+
+main() {
+
+}
+
+test() {
+ A a;
+
+ Class<A> classA = new Class<A>();
+ classA.method();
+ Extension(classA).method();
+ Extension<A>(classA).method();
+ Extension<B>(classA).method();
+
+ Class<B> classB = new Class<B>();
+ classB.method();
+ Extension(classB).method();
+ Extension<A>(classB).method();
+ Extension<B>(classB).method();
+
+ classB.genericMethod(a);
+ classB.genericMethod<A>(a);
+ classB.genericMethod<B>(a);
+ Extension(classB).genericMethod(a);
+ Extension(classB).genericMethod<A>(a);
+ Extension(classB).genericMethod<B>(a);
+ Extension<A>(classB).genericMethod(a);
+ Extension<A>(classB).genericMethod<A>(a);
+ Extension<A>(classB).genericMethod<B>(a);
+ Extension<B>(classB).genericMethod(a);
+ Extension<B>(classB).genericMethod<A>(a);
+ Extension<B>(classB).genericMethod<B>(a);
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart.outline.expect b/pkg/front_end/testcases/extensions/check_bounds.dart.outline.expect
new file mode 100644
index 0000000..f5164e8
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart.outline.expect
@@ -0,0 +1,34 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ ;
+}
+class B extends self::A {
+ synthetic constructor •() → self::B*
+ ;
+}
+class Class<T extends self::A* = self::A*> extends core::Object {
+ synthetic constructor •() → self::Class<self::Class::T*>*
+ ;
+}
+extension Extension<T extends self::B* = dynamic> on self::Class<T*>* {
+ method method = self::Extension|method;
+ tearoff method = self::Extension|get#method;
+ method genericMethod = self::Extension|genericMethod;
+ tearoff genericMethod = self::Extension|get#genericMethod;
+}
+static method Extension|method<T extends self::B* = dynamic>(final self::Class<self::Extension|method::T*>* #this) → dynamic
+ ;
+static method Extension|get#method<T extends self::B* = dynamic>(final self::Class<self::Extension|get#method::T*>* #this) → () →* dynamic
+ return () → dynamic => self::Extension|method<self::Extension|get#method::T*>(#this);
+static method Extension|genericMethod<T extends self::B* = dynamic, S extends self::B* = dynamic>(final self::Class<self::Extension|genericMethod::T*>* #this, self::Extension|genericMethod::S* s) → dynamic
+ ;
+static method Extension|get#genericMethod<T extends self::B* = dynamic>(final self::Class<self::Extension|get#genericMethod::T*>* #this) → <S extends self::B* = dynamic>(S*) →* dynamic
+ return <S extends self::B* = dynamic>(S* s) → dynamic => self::Extension|genericMethod<self::Extension|get#genericMethod::T*, S*>(#this, s);
+static method main() → dynamic
+ ;
+static method test() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart.strong.expect b/pkg/front_end/testcases/extensions/check_bounds.dart.strong.expect
new file mode 100644
index 0000000..b551a0a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart.strong.expect
@@ -0,0 +1,162 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:23:10: Error: The method 'method' isn't defined for the class 'Class<A>'.
+// - 'Class' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'method'.
+// classA.method();
+// ^^^^^^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:24:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'T' on 'Extension|method'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension(classA).method();
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:10:21: Context: This is the type variable whose bound isn't conformed to.
+// extension Extension<T extends B> on Class<T> {
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:25:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'T' on 'Extension|method'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension<A>(classA).method();
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:10:21: Context: This is the type variable whose bound isn't conformed to.
+// extension Extension<T extends B> on Class<T> {
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:31:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'T' on 'Extension|method'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension<A>(classB).method();
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:10:21: Context: This is the type variable whose bound isn't conformed to.
+// extension Extension<T extends B> on Class<T> {
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:34:10: Error: Type argument 'A' doesn't conform to the bound 'B' of the type variable 'S' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// classB.genericMethod(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:12:17: Context: This is the type variable whose bound isn't conformed to.
+// genericMethod<S extends B>(S s) {}
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:35:10: Error: Type argument 'A' doesn't conform to the bound 'B' of the type variable 'S' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// classB.genericMethod<A>(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:12:17: Context: This is the type variable whose bound isn't conformed to.
+// genericMethod<S extends B>(S s) {}
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:37:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'S' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension(classB).genericMethod(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:12:17: Context: This is the type variable whose bound isn't conformed to.
+// genericMethod<S extends B>(S s) {}
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:40:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'T' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension<A>(classB).genericMethod(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:10:21: Context: This is the type variable whose bound isn't conformed to.
+// extension Extension<T extends B> on Class<T> {
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:40:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'S' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension<A>(classB).genericMethod(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:12:17: Context: This is the type variable whose bound isn't conformed to.
+// genericMethod<S extends B>(S s) {}
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:43:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'S' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension<B>(classB).genericMethod(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:12:17: Context: This is the type variable whose bound isn't conformed to.
+// genericMethod<S extends B>(S s) {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+}
+class B extends self::A {
+ synthetic constructor •() → self::B*
+ : super self::A::•()
+ ;
+}
+class Class<T extends self::A* = self::A*> extends core::Object {
+ synthetic constructor •() → self::Class<self::Class::T*>*
+ : super core::Object::•()
+ ;
+}
+extension Extension<T extends self::B* = dynamic> on self::Class<T*>* {
+ method method = self::Extension|method;
+ tearoff method = self::Extension|get#method;
+ method genericMethod = self::Extension|genericMethod;
+ tearoff genericMethod = self::Extension|get#genericMethod;
+}
+static method Extension|method<T extends self::B* = dynamic>(final self::Class<self::Extension|method::T*>* #this) → dynamic {}
+static method Extension|get#method<T extends self::B* = dynamic>(final self::Class<self::Extension|get#method::T*>* #this) → () →* dynamic
+ return () → dynamic => self::Extension|method<self::Extension|get#method::T*>(#this);
+static method Extension|genericMethod<T extends self::B* = dynamic, S extends self::B* = dynamic>(final self::Class<self::Extension|genericMethod::T*>* #this, self::Extension|genericMethod::S* s) → dynamic {}
+static method Extension|get#genericMethod<T extends self::B* = dynamic>(final self::Class<self::Extension|get#genericMethod::T*>* #this) → <S extends self::B* = dynamic>(S*) →* dynamic
+ return <S extends self::B* = dynamic>(S* s) → dynamic => self::Extension|genericMethod<self::Extension|get#genericMethod::T*, S*>(#this, s);
+static method main() → dynamic {}
+static method test() → dynamic {
+ self::A* a;
+ self::Class<self::A*>* classA = new self::Class::•<self::A*>();
+ invalid-expression "pkg/front_end/testcases/extensions/check_bounds.dart:23:10: Error: The method 'method' isn't defined for the class 'Class<A>'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+ - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'method'.
+ classA.method();
+ ^^^^^^";
+ self::Extension|method<self::A*>(classA);
+ self::Extension|method<self::A*>(classA);
+ self::Extension|method<self::B*>(classA as{TypeError} self::Class<self::B*>*);
+ self::Class<self::B*>* classB = new self::Class::•<self::B*>();
+ self::Extension|method<self::B*>(classB);
+ self::Extension|method<self::B*>(classB);
+ self::Extension|method<self::A*>(classB);
+ self::Extension|method<self::B*>(classB);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::B*>(classB, a as{TypeError} self::B*);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::B*>(classB, a as{TypeError} self::B*);
+ self::Extension|genericMethod<self::A*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::A*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::A*, self::B*>(classB, a as{TypeError} self::B*);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::B*>(classB, a as{TypeError} self::B*);
+}
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/check_bounds.dart.strong.transformed.expect
new file mode 100644
index 0000000..b551a0a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart.strong.transformed.expect
@@ -0,0 +1,162 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:23:10: Error: The method 'method' isn't defined for the class 'Class<A>'.
+// - 'Class' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'method'.
+// classA.method();
+// ^^^^^^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:24:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'T' on 'Extension|method'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension(classA).method();
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:10:21: Context: This is the type variable whose bound isn't conformed to.
+// extension Extension<T extends B> on Class<T> {
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:25:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'T' on 'Extension|method'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension<A>(classA).method();
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:10:21: Context: This is the type variable whose bound isn't conformed to.
+// extension Extension<T extends B> on Class<T> {
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:31:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'T' on 'Extension|method'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension<A>(classB).method();
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:10:21: Context: This is the type variable whose bound isn't conformed to.
+// extension Extension<T extends B> on Class<T> {
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:34:10: Error: Type argument 'A' doesn't conform to the bound 'B' of the type variable 'S' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// classB.genericMethod(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:12:17: Context: This is the type variable whose bound isn't conformed to.
+// genericMethod<S extends B>(S s) {}
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:35:10: Error: Type argument 'A' doesn't conform to the bound 'B' of the type variable 'S' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// classB.genericMethod<A>(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:12:17: Context: This is the type variable whose bound isn't conformed to.
+// genericMethod<S extends B>(S s) {}
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:37:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'S' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension(classB).genericMethod(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:12:17: Context: This is the type variable whose bound isn't conformed to.
+// genericMethod<S extends B>(S s) {}
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:40:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'T' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension<A>(classB).genericMethod(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:10:21: Context: This is the type variable whose bound isn't conformed to.
+// extension Extension<T extends B> on Class<T> {
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:40:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'S' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension<A>(classB).genericMethod(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:12:17: Context: This is the type variable whose bound isn't conformed to.
+// genericMethod<S extends B>(S s) {}
+// ^
+//
+// pkg/front_end/testcases/extensions/check_bounds.dart:43:3: Error: Inferred type argument 'A' doesn't conform to the bound 'B' of the type variable 'S' on 'Extension|genericMethod'.
+// - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// - 'B' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// Extension<B>(classB).genericMethod(a);
+// ^
+// pkg/front_end/testcases/extensions/check_bounds.dart:12:17: Context: This is the type variable whose bound isn't conformed to.
+// genericMethod<S extends B>(S s) {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+}
+class B extends self::A {
+ synthetic constructor •() → self::B*
+ : super self::A::•()
+ ;
+}
+class Class<T extends self::A* = self::A*> extends core::Object {
+ synthetic constructor •() → self::Class<self::Class::T*>*
+ : super core::Object::•()
+ ;
+}
+extension Extension<T extends self::B* = dynamic> on self::Class<T*>* {
+ method method = self::Extension|method;
+ tearoff method = self::Extension|get#method;
+ method genericMethod = self::Extension|genericMethod;
+ tearoff genericMethod = self::Extension|get#genericMethod;
+}
+static method Extension|method<T extends self::B* = dynamic>(final self::Class<self::Extension|method::T*>* #this) → dynamic {}
+static method Extension|get#method<T extends self::B* = dynamic>(final self::Class<self::Extension|get#method::T*>* #this) → () →* dynamic
+ return () → dynamic => self::Extension|method<self::Extension|get#method::T*>(#this);
+static method Extension|genericMethod<T extends self::B* = dynamic, S extends self::B* = dynamic>(final self::Class<self::Extension|genericMethod::T*>* #this, self::Extension|genericMethod::S* s) → dynamic {}
+static method Extension|get#genericMethod<T extends self::B* = dynamic>(final self::Class<self::Extension|get#genericMethod::T*>* #this) → <S extends self::B* = dynamic>(S*) →* dynamic
+ return <S extends self::B* = dynamic>(S* s) → dynamic => self::Extension|genericMethod<self::Extension|get#genericMethod::T*, S*>(#this, s);
+static method main() → dynamic {}
+static method test() → dynamic {
+ self::A* a;
+ self::Class<self::A*>* classA = new self::Class::•<self::A*>();
+ invalid-expression "pkg/front_end/testcases/extensions/check_bounds.dart:23:10: Error: The method 'method' isn't defined for the class 'Class<A>'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+ - 'A' is from 'pkg/front_end/testcases/extensions/check_bounds.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'method'.
+ classA.method();
+ ^^^^^^";
+ self::Extension|method<self::A*>(classA);
+ self::Extension|method<self::A*>(classA);
+ self::Extension|method<self::B*>(classA as{TypeError} self::Class<self::B*>*);
+ self::Class<self::B*>* classB = new self::Class::•<self::B*>();
+ self::Extension|method<self::B*>(classB);
+ self::Extension|method<self::B*>(classB);
+ self::Extension|method<self::A*>(classB);
+ self::Extension|method<self::B*>(classB);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::B*>(classB, a as{TypeError} self::B*);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::B*>(classB, a as{TypeError} self::B*);
+ self::Extension|genericMethod<self::A*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::A*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::A*, self::B*>(classB, a as{TypeError} self::B*);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::A*>(classB, a);
+ self::Extension|genericMethod<self::B*, self::B*>(classB, a as{TypeError} self::B*);
+}
diff --git a/pkg/front_end/testcases/extensions/extension_call.dart b/pkg/front_end/testcases/extensions/extension_call.dart
new file mode 100644
index 0000000..026883a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_call.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+class Class<T> {
+ T method(T a) => a;
+}
+
+extension Extension<T> on Class<T> {
+ T call(T a) => method(a);
+}
+
+main() {
+ Class<int> c = new Class<int>();
+ expect(42, c(42));
+ expect(87, Extension(c)(87));
+ expect(123, Extension<int>(c)(123));
+ expect(42, c.call(42));
+ expect(87, Extension(c).call(87));
+ expect(123, Extension<int>(c).call(123));
+}
+
+expect(expected, actual) {
+ if (expected != actual) {
+ throw 'Mismatch: expected=$expected, actual=$actual';
+ }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extensions/extension_call.dart.outline.expect b/pkg/front_end/testcases/extensions/extension_call.dart.outline.expect
new file mode 100644
index 0000000..21fa0dd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_call.dart.outline.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::Class<self::Class::T*>*
+ ;
+ method method(generic-covariant-impl self::Class::T* a) → self::Class::T*
+ ;
+}
+extension Extension<T extends core::Object* = dynamic> on self::Class<T*>* {
+ method call = self::Extension|call;
+ tearoff call = self::Extension|get#call;
+}
+static method Extension|call<T extends core::Object* = dynamic>(final self::Class<self::Extension|call::T*>* #this, self::Extension|call::T* a) → self::Extension|call::T*
+ ;
+static method Extension|get#call<T extends core::Object* = dynamic>(final self::Class<self::Extension|get#call::T*>* #this) → (self::Extension|get#call::T*) →* self::Extension|get#call::T*
+ return (self::Extension|get#call::T* a) → self::Extension|get#call::T* => self::Extension|call<self::Extension|get#call::T*>(#this, a);
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/extensions/extension_call.dart.strong.expect b/pkg/front_end/testcases/extensions/extension_call.dart.strong.expect
new file mode 100644
index 0000000..599862a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_call.dart.strong.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::Class<self::Class::T*>*
+ : super core::Object::•()
+ ;
+ method method(generic-covariant-impl self::Class::T* a) → self::Class::T*
+ return a;
+}
+extension Extension<T extends core::Object* = dynamic> on self::Class<T*>* {
+ method call = self::Extension|call;
+ tearoff call = self::Extension|get#call;
+}
+static method Extension|call<T extends core::Object* = dynamic>(final self::Class<self::Extension|call::T*>* #this, self::Extension|call::T* a) → self::Extension|call::T*
+ return #this.{self::Class::method}(a);
+static method Extension|get#call<T extends core::Object* = dynamic>(final self::Class<self::Extension|get#call::T*>* #this) → (self::Extension|get#call::T*) →* self::Extension|get#call::T*
+ return (self::Extension|get#call::T* a) → self::Extension|get#call::T* => self::Extension|call<self::Extension|get#call::T*>(#this, a);
+static method main() → dynamic {
+ self::Class<core::int*>* c = new self::Class::•<core::int*>();
+ self::expect(42, self::Extension|call<core::int*>(c, 42));
+ self::expect(87, self::Extension|call<core::int*>(c, 87));
+ self::expect(123, self::Extension|call<core::int*>(c, 123));
+ self::expect(42, self::Extension|call<core::int*>(c, 42));
+ self::expect(87, self::Extension|call<core::int*>(c, 87));
+ self::expect(123, self::Extension|call<core::int*>(c, 123));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual)) {
+ throw "Mismatch: expected=${expected}, actual=${actual}";
+ }
+}
diff --git a/pkg/front_end/testcases/extensions/extension_call.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/extension_call.dart.strong.transformed.expect
new file mode 100644
index 0000000..599862a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_call.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::Class<self::Class::T*>*
+ : super core::Object::•()
+ ;
+ method method(generic-covariant-impl self::Class::T* a) → self::Class::T*
+ return a;
+}
+extension Extension<T extends core::Object* = dynamic> on self::Class<T*>* {
+ method call = self::Extension|call;
+ tearoff call = self::Extension|get#call;
+}
+static method Extension|call<T extends core::Object* = dynamic>(final self::Class<self::Extension|call::T*>* #this, self::Extension|call::T* a) → self::Extension|call::T*
+ return #this.{self::Class::method}(a);
+static method Extension|get#call<T extends core::Object* = dynamic>(final self::Class<self::Extension|get#call::T*>* #this) → (self::Extension|get#call::T*) →* self::Extension|get#call::T*
+ return (self::Extension|get#call::T* a) → self::Extension|get#call::T* => self::Extension|call<self::Extension|get#call::T*>(#this, a);
+static method main() → dynamic {
+ self::Class<core::int*>* c = new self::Class::•<core::int*>();
+ self::expect(42, self::Extension|call<core::int*>(c, 42));
+ self::expect(87, self::Extension|call<core::int*>(c, 87));
+ self::expect(123, self::Extension|call<core::int*>(c, 123));
+ self::expect(42, self::Extension|call<core::int*>(c, 42));
+ self::expect(87, self::Extension|call<core::int*>(c, 87));
+ self::expect(123, self::Extension|call<core::int*>(c, 123));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual)) {
+ throw "Mismatch: expected=${expected}, actual=${actual}";
+ }
+}
diff --git a/pkg/front_end/testcases/extensions/extension_constructor.dart b/pkg/front_end/testcases/extensions/extension_constructor.dart
new file mode 100644
index 0000000..5cd257d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_constructor.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, 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.
+
+class Class {}
+
+extension Extension on Class {
+ Extension() {}
+ Extension.named() {}
+ factory Extension.fact() => null;
+ factory Extension.redirect() = Extension;
+
+ method() {}
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extensions/extension_constructor.dart.outline.expect b/pkg/front_end/testcases/extensions/extension_constructor.dart.outline.expect
new file mode 100644
index 0000000..76431a3
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_constructor.dart.outline.expect
@@ -0,0 +1,55 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:8:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// Extension() {}
+// ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:9:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// Extension.named() {}
+// ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:10:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// factory Extension.fact() => null;
+// ^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:11:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// factory Extension.redirect() = Extension;
+// ^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:10:11: Error: 'Extension' isn't a type.
+// factory Extension.fact() => null;
+// ^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_constructor.dart:7:11: Context: This isn't a type.
+// extension Extension on Class {
+// ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:11:11: Error: 'Extension' isn't a type.
+// factory Extension.redirect() = Extension;
+// ^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_constructor.dart:7:11: Context: This isn't a type.
+// extension Extension on Class {
+// ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class*
+ ;
+}
+extension Extension on self::Class* {
+ method method = self::Extension|method;
+ tearoff method = self::Extension|get#method;
+}
+static method Extension|method(final self::Class* #this) → dynamic
+ ;
+static method Extension|get#method(final self::Class* #this) → () →* dynamic
+ return () → dynamic => self::Extension|method(#this);
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/extensions/extension_constructor.dart.strong.expect b/pkg/front_end/testcases/extensions/extension_constructor.dart.strong.expect
new file mode 100644
index 0000000..b043e9d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_constructor.dart.strong.expect
@@ -0,0 +1,54 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:8:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// Extension() {}
+// ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:9:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// Extension.named() {}
+// ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:10:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// factory Extension.fact() => null;
+// ^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:11:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// factory Extension.redirect() = Extension;
+// ^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:10:11: Error: 'Extension' isn't a type.
+// factory Extension.fact() => null;
+// ^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_constructor.dart:7:11: Context: This isn't a type.
+// extension Extension on Class {
+// ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:11:11: Error: 'Extension' isn't a type.
+// factory Extension.redirect() = Extension;
+// ^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_constructor.dart:7:11: Context: This isn't a type.
+// extension Extension on Class {
+// ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+}
+extension Extension on self::Class* {
+ method method = self::Extension|method;
+ tearoff method = self::Extension|get#method;
+}
+static method Extension|method(final self::Class* #this) → dynamic {}
+static method Extension|get#method(final self::Class* #this) → () →* dynamic
+ return () → dynamic => self::Extension|method(#this);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/extension_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/extension_constructor.dart.strong.transformed.expect
new file mode 100644
index 0000000..b043e9d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_constructor.dart.strong.transformed.expect
@@ -0,0 +1,54 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:8:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// Extension() {}
+// ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:9:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// Extension.named() {}
+// ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:10:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// factory Extension.fact() => null;
+// ^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:11:3: Error: Extensions can't declare constructors.
+// Try removing the constructor declaration.
+// factory Extension.redirect() = Extension;
+// ^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:10:11: Error: 'Extension' isn't a type.
+// factory Extension.fact() => null;
+// ^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_constructor.dart:7:11: Context: This isn't a type.
+// extension Extension on Class {
+// ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_constructor.dart:11:11: Error: 'Extension' isn't a type.
+// factory Extension.redirect() = Extension;
+// ^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_constructor.dart:7:11: Context: This isn't a type.
+// extension Extension on Class {
+// ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+}
+extension Extension on self::Class* {
+ method method = self::Extension|method;
+ tearoff method = self::Extension|get#method;
+}
+static method Extension|method(final self::Class* #this) → dynamic {}
+static method Extension|get#method(final self::Class* #this) → () →* dynamic
+ return () → dynamic => self::Extension|method(#this);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart b/pkg/front_end/testcases/extensions/extension_setter.dart
index de0ed9e..79ab6ce 100644
--- a/pkg/front_end/testcases/extensions/extension_setter.dart
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart
@@ -71,6 +71,12 @@
}
}
+class GenericClass<T> {}
+
+extension GenericExtension<T> on GenericClass<T> {
+ set setter(T value) {}
+}
+
main() {
var c = new Class();
expect(null, c.field);
@@ -191,9 +197,10 @@
new Class().testInternal();
+ GenericClass<int> genericClass = new GenericClass<int>();
+ expect(1, GenericExtension(genericClass).setter = 1);
}
-
expect(expected, actual) {
if (expected != actual) {
throw 'Mismatch: expected=$expected, actual=$actual';
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.outline.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.outline.expect
index 15b272e..0c3a704 100644
--- a/pkg/front_end/testcases/extensions/extension_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.outline.expect
@@ -7,6 +7,10 @@
synthetic constructor •() → self::Class*
;
}
+class GenericClass<T extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::GenericClass<self::GenericClass::T*>*
+ ;
+}
extension Extension on self::Class* {
get simpleSetter = self::Extension|get#simpleSetter;
get mutatingSetter = self::Extension|get#mutatingSetter;
@@ -19,6 +23,9 @@
set setterWithReturn = self::Extension|set#setterWithReturn;
set setterWithClosure = self::Extension|set#setterWithClosure;
}
+extension GenericExtension<T extends core::Object* = dynamic> on self::GenericClass<T*>* {
+ set setter = self::GenericExtension|set#setter;
+}
static method Extension|get#simpleSetter(final self::Class* #this) → core::int*
;
static method Extension|set#simpleSetter(final self::Class* #this, core::int* value) → void
@@ -39,6 +46,8 @@
;
static method Extension|get#testInternal(final self::Class* #this) → () →* dynamic
return () → dynamic => self::Extension|testInternal(#this);
+static method GenericExtension|set#setter<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#setter::T*>* #this, self::GenericExtension|set#setter::T* value) → void
+ ;
static method main() → dynamic
;
static method expect(dynamic expected, dynamic actual) → dynamic
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect
index f487199..0eb2783 100644
--- a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect
@@ -8,6 +8,11 @@
: super core::Object::•()
;
}
+class GenericClass<T extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::GenericClass<self::GenericClass::T*>*
+ : super core::Object::•()
+ ;
+}
extension Extension on self::Class* {
get simpleSetter = self::Extension|get#simpleSetter;
get mutatingSetter = self::Extension|get#mutatingSetter;
@@ -20,6 +25,9 @@
set setterWithReturn = self::Extension|set#setterWithReturn;
set setterWithClosure = self::Extension|set#setterWithClosure;
}
+extension GenericExtension<T extends core::Object* = dynamic> on self::GenericClass<T*>* {
+ set setter = self::GenericExtension|set#setter;
+}
static method Extension|get#simpleSetter(final self::Class* #this) → core::int*
return #this.{self::Class::field};
static method Extension|set#simpleSetter(final self::Class* #this, core::int* value) → void {
@@ -76,6 +84,7 @@
}
static method Extension|get#testInternal(final self::Class* #this) → () →* dynamic
return () → dynamic => self::Extension|testInternal(#this);
+static method GenericExtension|set#setter<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#setter::T*>* #this, self::GenericExtension|set#setter::T* value) → void {}
static method main() → dynamic {
self::Class* c = new self::Class::•();
self::expect(null, c.{self::Class::field});
@@ -184,6 +193,8 @@
let final self::Class* #t129 = c in #t129.{core::Object::==}(null) ?{core::Null?} null : #t129.{self::Class::field} = null;
self::expect(2, let final self::Class* #t130 = c in #t130.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t131 = self::Extension|get#simpleSetter(#t130) in #t131.{core::num::==}(null) ?{core::int*} let final core::int* #t132 = 2 in let final void #t133 = self::Extension|set#simpleSetter(#t130, #t132) in #t132 : #t131);
self::Extension|testInternal(new self::Class::•());
+ self::GenericClass<core::int*>* genericClass = new self::GenericClass::•<core::int*>();
+ self::expect(1, let final self::GenericClass<core::int*>* #t134 = genericClass in let final core::int* #t135 = 1 in let final void #t136 = self::GenericExtension|set#setter<core::int*>(#t134, #t135) in #t135);
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
index f487199..0eb2783 100644
--- a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
@@ -8,6 +8,11 @@
: super core::Object::•()
;
}
+class GenericClass<T extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::GenericClass<self::GenericClass::T*>*
+ : super core::Object::•()
+ ;
+}
extension Extension on self::Class* {
get simpleSetter = self::Extension|get#simpleSetter;
get mutatingSetter = self::Extension|get#mutatingSetter;
@@ -20,6 +25,9 @@
set setterWithReturn = self::Extension|set#setterWithReturn;
set setterWithClosure = self::Extension|set#setterWithClosure;
}
+extension GenericExtension<T extends core::Object* = dynamic> on self::GenericClass<T*>* {
+ set setter = self::GenericExtension|set#setter;
+}
static method Extension|get#simpleSetter(final self::Class* #this) → core::int*
return #this.{self::Class::field};
static method Extension|set#simpleSetter(final self::Class* #this, core::int* value) → void {
@@ -76,6 +84,7 @@
}
static method Extension|get#testInternal(final self::Class* #this) → () →* dynamic
return () → dynamic => self::Extension|testInternal(#this);
+static method GenericExtension|set#setter<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#setter::T*>* #this, self::GenericExtension|set#setter::T* value) → void {}
static method main() → dynamic {
self::Class* c = new self::Class::•();
self::expect(null, c.{self::Class::field});
@@ -184,6 +193,8 @@
let final self::Class* #t129 = c in #t129.{core::Object::==}(null) ?{core::Null?} null : #t129.{self::Class::field} = null;
self::expect(2, let final self::Class* #t130 = c in #t130.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t131 = self::Extension|get#simpleSetter(#t130) in #t131.{core::num::==}(null) ?{core::int*} let final core::int* #t132 = 2 in let final void #t133 = self::Extension|set#simpleSetter(#t130, #t132) in #t132 : #t131);
self::Extension|testInternal(new self::Class::•());
+ self::GenericClass<core::int*>* genericClass = new self::GenericClass::•<core::int*>();
+ self::expect(1, let final self::GenericClass<core::int*>* #t134 = genericClass in let final core::int* #t135 = 1 in let final void #t136 = self::GenericExtension|set#setter<core::int*>(#t134, #t135) in #t135);
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/extension_setter_error.dart b/pkg/front_end/testcases/extensions/extension_setter_error.dart
new file mode 100644
index 0000000..db67de0
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter_error.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, 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.
+
+class GenericClass<T> {}
+
+extension GenericExtension<T> on GenericClass<T> {
+ set setter(T value) {}
+}
+
+error() {
+ GenericClass<int> genericClass = new GenericClass<int>();
+ expect(null, GenericExtension<double>(genericClass).setter = null);
+}
+
+
+expect(expected, actual) {
+ if (expected != actual) {
+ throw 'Mismatch: expected=$expected, actual=$actual';
+ }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extensions/extension_setter_error.dart.outline.expect b/pkg/front_end/testcases/extensions/extension_setter_error.dart.outline.expect
new file mode 100644
index 0000000..bdf566f
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter_error.dart.outline.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class GenericClass<T extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::GenericClass<self::GenericClass::T*>*
+ ;
+}
+extension GenericExtension<T extends core::Object* = dynamic> on self::GenericClass<T*>* {
+ set setter = self::GenericExtension|set#setter;
+}
+static method GenericExtension|set#setter<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#setter::T*>* #this, self::GenericExtension|set#setter::T* value) → void
+ ;
+static method error() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/extensions/extension_setter_error.dart.strong.expect b/pkg/front_end/testcases/extensions/extension_setter_error.dart.strong.expect
new file mode 100644
index 0000000..569b235
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter_error.dart.strong.expect
@@ -0,0 +1,35 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/extension_setter_error.dart:13:41: Error: A value of type 'GenericClass<int>' can't be assigned to a variable of type 'GenericClass<double>'.
+// - 'GenericClass' is from 'pkg/front_end/testcases/extensions/extension_setter_error.dart'.
+// Try changing the type of the left hand side, or casting the right hand side to 'GenericClass<double>'.
+// expect(null, GenericExtension<double>(genericClass).setter = null);
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class GenericClass<T extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::GenericClass<self::GenericClass::T*>*
+ : super core::Object::•()
+ ;
+}
+extension GenericExtension<T extends core::Object* = dynamic> on self::GenericClass<T*>* {
+ set setter = self::GenericExtension|set#setter;
+}
+static method GenericExtension|set#setter<T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#setter::T*>* #this, self::GenericExtension|set#setter::T* value) → void {}
+static method error() → dynamic {
+ self::GenericClass<core::int*>* genericClass = new self::GenericClass::•<core::int*>();
+ self::expect(null, let final self::GenericClass<core::int*>* #t1 = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/extensions/extension_setter_error.dart:13:41: Error: A value of type 'GenericClass<int>' can't be assigned to a variable of type 'GenericClass<double>'.
+ - 'GenericClass' is from 'pkg/front_end/testcases/extensions/extension_setter_error.dart'.
+Try changing the type of the left hand side, or casting the right hand side to 'GenericClass<double>'.
+ expect(null, GenericExtension<double>(genericClass).setter = null);
+ ^" in genericClass as{TypeError} self::GenericClass<core::double*>* in let final core::Null? #t3 = null in let final void #t4 = self::GenericExtension|set#setter<core::double*>(#t1, #t3) in #t3);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual)) {
+ throw "Mismatch: expected=${expected}, actual=${actual}";
+ }
+}
diff --git a/pkg/front_end/testcases/extensions/index.dart b/pkg/front_end/testcases/extensions/index.dart
index 582d067..0e19617 100644
--- a/pkg/front_end/testcases/extensions/index.dart
+++ b/pkg/front_end/testcases/extensions/index.dart
@@ -15,6 +15,12 @@
}
main() {
+ implicit();
+ explicitWithTypeArguments();
+ explicitInferredTypeArguments();
+}
+
+implicit() {
MapLike<int, String> map1 = new MapLike();
expect(null, map1[0]);
map1.put(0, '0');
@@ -41,7 +47,64 @@
expect(6, map2[0]);
expect(5, --map2[0]);
expect(5, map2[0]);
+}
+explicitWithTypeArguments() {
+ MapLike<int, String> map1 = new MapLike();
+ expect(null, Extension<int, String>(map1)[0]);
+ map1.put(0, '0');
+ expect('0', Extension<int, String>(map1)[0]);
+ expect(null, Extension<int, String>(map1)[1]);
+ Extension<int, String>(map1)[1] = '1';
+ expect('1', Extension<int, String>(map1)[1]);
+ expect('2', Extension<int, String>(map1)[1] = '2');
+ expect('2', Extension<int, String>(map1)[1]);
+ Extension<int, String>(map1)[1] ??= '3';
+ expect('2', Extension<int, String>(map1)[1]);
+ expect('2', Extension<int, String>(map1)[1] ??= '4');
+ expect('2', Extension<int, String>(map1)[1]);
+ Extension<int, String>(map1)[2] ??= '2';
+ expect('2', Extension<int, String>(map1)[2]);
+ expect('3', Extension<int, String>(map1)[3] ??= '3');
+ expect('3', Extension<int, String>(map1)[3]);
+
+ MapLike<int, int> map2 = new MapLike();
+ expect(1, Extension<int, int>(map2)[0] = 1);
+ expect(3, Extension<int, int>(map2)[0] += 2);
+ expect(5, Extension<int, int>(map2)[0] += 2);
+ expect(5, Extension<int, int>(map2)[0]++);
+ expect(6, Extension<int, int>(map2)[0]);
+ expect(5, --Extension<int, int>(map2)[0]);
+ expect(5, Extension<int, int>(map2)[0]);
+}
+
+explicitInferredTypeArguments() {
+ MapLike<int, String> map1 = new MapLike();
+ expect(null, Extension(map1)[0]);
+ map1.put(0, '0');
+ expect('0', Extension(map1)[0]);
+ expect(null, Extension(map1)[1]);
+ Extension(map1)[1] = '1';
+ expect('1', Extension(map1)[1]);
+ expect('2', Extension(map1)[1] = '2');
+ expect('2', Extension(map1)[1]);
+ Extension(map1)[1] ??= '3';
+ expect('2', Extension(map1)[1]);
+ expect('2', Extension(map1)[1] ??= '4');
+ expect('2', Extension(map1)[1]);
+ Extension(map1)[2] ??= '2';
+ expect('2', Extension(map1)[2]);
+ expect('3', Extension(map1)[3] ??= '3');
+ expect('3', Extension(map1)[3]);
+
+ MapLike<int, int> map2 = new MapLike();
+ expect(1, Extension(map2)[0] = 1);
+ expect(3, Extension(map2)[0] += 2);
+ expect(5, Extension(map2)[0] += 2);
+ expect(5, Extension(map2)[0]++);
+ expect(6, Extension(map2)[0]);
+ expect(5, --Extension(map2)[0]);
+ expect(5, Extension(map2)[0]);
}
expect(expected, actual) {
diff --git a/pkg/front_end/testcases/extensions/index.dart.outline.expect b/pkg/front_end/testcases/extensions/index.dart.outline.expect
index c9b2e9d..f94d2d2 100644
--- a/pkg/front_end/testcases/extensions/index.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.outline.expect
@@ -21,5 +21,11 @@
;
static method main() → dynamic
;
+static method implicit() → dynamic
+ ;
+static method explicitWithTypeArguments() → dynamic
+ ;
+static method explicitInferredTypeArguments() → dynamic
+ ;
static method expect(dynamic expected, dynamic actual) → dynamic
;
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.expect b/pkg/front_end/testcases/extensions/index.dart.strong.expect
index 4f14d3dc..cc8481e 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.expect
@@ -21,6 +21,11 @@
static method Extension|[]=<K extends core::Object* = dynamic, V extends core::Object* = dynamic>(final self::MapLike<self::Extension|[]=::K*, self::Extension|[]=::V*>* #this, self::Extension|[]=::K* key, self::Extension|[]=::V* value) → void
return #this.{self::MapLike::put}(key, value);
static method main() → dynamic {
+ self::implicit();
+ self::explicitWithTypeArguments();
+ self::explicitInferredTypeArguments();
+}
+static method implicit() → dynamic {
self::MapLike<core::int*, core::String*>* map1 = new self::MapLike::•<core::int*, core::String*>();
self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 0));
map1.{self::MapLike::put}(0, "0");
@@ -47,6 +52,60 @@
self::expect(5, let final self::MapLike<core::int*, core::int*>* #t39 = map2 in let final core::int* #t40 = 0 in let final core::int* #t41 = self::Extension|[]<core::int*, core::int*>(#t39, #t40).{core::num::-}(1) in let final void #t42 = self::Extension|[]=<core::int*, core::int*>(#t39, #t40, #t41) in #t41);
self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
}
+static method explicitWithTypeArguments() → dynamic {
+ self::MapLike<core::int*, core::String*>* map1 = new self::MapLike::•<core::int*, core::String*>();
+ self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 0));
+ map1.{self::MapLike::put}(0, "0");
+ self::expect("0", self::Extension|[]<core::int*, core::String*>(map1, 0));
+ self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
+ self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::expect("2", let final self::MapLike<core::int*, core::String*>* #t43 = map1 in let final core::int* #t44 = 1 in let final core::String* #t45 = "2" in let final void #t46 = self::Extension|[]=<core::int*, core::String*>(#t43, #t44, #t45) in #t45);
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ let final self::MapLike<core::int*, core::String*>* #t47 = map1 in let final core::int* #t48 = 1 in self::Extension|[]<core::int*, core::String*>(#t47, #t48).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t47, #t48, "3") : null;
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::expect("2", let final self::MapLike<core::int*, core::String*>* #t49 = map1 in let final core::int* #t50 = 1 in let final core::String* #t51 = self::Extension|[]<core::int*, core::String*>(#t49, #t50) in #t51.{core::String::==}(null) ?{core::String*} let final core::String* #t52 = "4" in let final void #t53 = self::Extension|[]=<core::int*, core::String*>(#t49, #t50, #t52) in #t52 : #t51);
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ let final self::MapLike<core::int*, core::String*>* #t54 = map1 in let final core::int* #t55 = 2 in self::Extension|[]<core::int*, core::String*>(#t54, #t55).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t54, #t55, "2") : null;
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
+ self::expect("3", let final self::MapLike<core::int*, core::String*>* #t56 = map1 in let final core::int* #t57 = 3 in let final core::String* #t58 = self::Extension|[]<core::int*, core::String*>(#t56, #t57) in #t58.{core::String::==}(null) ?{core::String*} let final core::String* #t59 = "3" in let final void #t60 = self::Extension|[]=<core::int*, core::String*>(#t56, #t57, #t59) in #t59 : #t58);
+ self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
+ self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
+ self::expect(1, let final self::MapLike<core::int*, core::int*>* #t61 = map2 in let final core::int* #t62 = 0 in let final core::int* #t63 = 1 in let final void #t64 = self::Extension|[]=<core::int*, core::int*>(#t61, #t62, #t63) in #t63);
+ self::expect(3, let final core::Object* #t65 = map2 in let final core::int* #t66 = 0 in let final core::int* #t67 = self::Extension|[]<core::int*, core::int*>(#t65, #t66).{core::num::+}(2) in let final void #t68 = self::Extension|[]=<core::int*, core::int*>(#t65, #t66, #t67) in #t67);
+ self::expect(5, let final core::Object* #t69 = map2 in let final core::int* #t70 = 0 in let final core::int* #t71 = self::Extension|[]<core::int*, core::int*>(#t69, #t70).{core::num::+}(2) in let final void #t72 = self::Extension|[]=<core::int*, core::int*>(#t69, #t70, #t71) in #t71);
+ self::expect(5, let final core::Object* #t73 = map2 in let final core::int* #t74 = 0 in let final core::int* #t75 = self::Extension|[]<core::int*, core::int*>(#t73, #t74) in let final void #t76 = self::Extension|[]=<core::int*, core::int*>(#t73, #t74, #t75.{core::num::+}(1)) in #t75);
+ self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
+ self::expect(5, let final core::Object* #t77 = map2 in let final core::int* #t78 = 0 in let final core::int* #t79 = self::Extension|[]<core::int*, core::int*>(#t77, #t78).{core::num::-}(1) in let final void #t80 = self::Extension|[]=<core::int*, core::int*>(#t77, #t78, #t79) in #t79);
+ self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
+}
+static method explicitInferredTypeArguments() → dynamic {
+ self::MapLike<core::int*, core::String*>* map1 = new self::MapLike::•<core::int*, core::String*>();
+ self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 0));
+ map1.{self::MapLike::put}(0, "0");
+ self::expect("0", self::Extension|[]<core::int*, core::String*>(map1, 0));
+ self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
+ self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::expect("2", let final self::MapLike<core::int*, core::String*>* #t81 = map1 in let final core::int* #t82 = 1 in let final core::String* #t83 = "2" in let final void #t84 = self::Extension|[]=<core::int*, core::String*>(#t81, #t82, #t83) in #t83);
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ let final self::MapLike<core::int*, core::String*>* #t85 = map1 in let final core::int* #t86 = 1 in self::Extension|[]<core::int*, core::String*>(#t85, #t86).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t85, #t86, "3") : null;
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::expect("2", let final self::MapLike<core::int*, core::String*>* #t87 = map1 in let final core::int* #t88 = 1 in let final core::String* #t89 = self::Extension|[]<core::int*, core::String*>(#t87, #t88) in #t89.{core::String::==}(null) ?{core::String*} let final core::String* #t90 = "4" in let final void #t91 = self::Extension|[]=<core::int*, core::String*>(#t87, #t88, #t90) in #t90 : #t89);
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ let final self::MapLike<core::int*, core::String*>* #t92 = map1 in let final core::int* #t93 = 2 in self::Extension|[]<core::int*, core::String*>(#t92, #t93).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t92, #t93, "2") : null;
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
+ self::expect("3", let final self::MapLike<core::int*, core::String*>* #t94 = map1 in let final core::int* #t95 = 3 in let final core::String* #t96 = self::Extension|[]<core::int*, core::String*>(#t94, #t95) in #t96.{core::String::==}(null) ?{core::String*} let final core::String* #t97 = "3" in let final void #t98 = self::Extension|[]=<core::int*, core::String*>(#t94, #t95, #t97) in #t97 : #t96);
+ self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
+ self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
+ self::expect(1, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = 1 in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
+ self::expect(3, let final core::Object* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
+ self::expect(5, let final core::Object* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108).{core::num::+}(2) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109) in #t109);
+ self::expect(5, let final core::Object* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113.{core::num::+}(1)) in #t113);
+ self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
+ self::expect(5, let final core::Object* #t115 = map2 in let final core::int* #t116 = 0 in let final core::int* #t117 = self::Extension|[]<core::int*, core::int*>(#t115, #t116).{core::num::-}(1) in let final void #t118 = self::Extension|[]=<core::int*, core::int*>(#t115, #t116, #t117) in #t117);
+ self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
+}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
throw "Mismatch: expected=${expected}, actual=${actual}";
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
index 4f14d3dc..cc8481e 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
@@ -21,6 +21,11 @@
static method Extension|[]=<K extends core::Object* = dynamic, V extends core::Object* = dynamic>(final self::MapLike<self::Extension|[]=::K*, self::Extension|[]=::V*>* #this, self::Extension|[]=::K* key, self::Extension|[]=::V* value) → void
return #this.{self::MapLike::put}(key, value);
static method main() → dynamic {
+ self::implicit();
+ self::explicitWithTypeArguments();
+ self::explicitInferredTypeArguments();
+}
+static method implicit() → dynamic {
self::MapLike<core::int*, core::String*>* map1 = new self::MapLike::•<core::int*, core::String*>();
self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 0));
map1.{self::MapLike::put}(0, "0");
@@ -47,6 +52,60 @@
self::expect(5, let final self::MapLike<core::int*, core::int*>* #t39 = map2 in let final core::int* #t40 = 0 in let final core::int* #t41 = self::Extension|[]<core::int*, core::int*>(#t39, #t40).{core::num::-}(1) in let final void #t42 = self::Extension|[]=<core::int*, core::int*>(#t39, #t40, #t41) in #t41);
self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
}
+static method explicitWithTypeArguments() → dynamic {
+ self::MapLike<core::int*, core::String*>* map1 = new self::MapLike::•<core::int*, core::String*>();
+ self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 0));
+ map1.{self::MapLike::put}(0, "0");
+ self::expect("0", self::Extension|[]<core::int*, core::String*>(map1, 0));
+ self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
+ self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::expect("2", let final self::MapLike<core::int*, core::String*>* #t43 = map1 in let final core::int* #t44 = 1 in let final core::String* #t45 = "2" in let final void #t46 = self::Extension|[]=<core::int*, core::String*>(#t43, #t44, #t45) in #t45);
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ let final self::MapLike<core::int*, core::String*>* #t47 = map1 in let final core::int* #t48 = 1 in self::Extension|[]<core::int*, core::String*>(#t47, #t48).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t47, #t48, "3") : null;
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::expect("2", let final self::MapLike<core::int*, core::String*>* #t49 = map1 in let final core::int* #t50 = 1 in let final core::String* #t51 = self::Extension|[]<core::int*, core::String*>(#t49, #t50) in #t51.{core::String::==}(null) ?{core::String*} let final core::String* #t52 = "4" in let final void #t53 = self::Extension|[]=<core::int*, core::String*>(#t49, #t50, #t52) in #t52 : #t51);
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ let final self::MapLike<core::int*, core::String*>* #t54 = map1 in let final core::int* #t55 = 2 in self::Extension|[]<core::int*, core::String*>(#t54, #t55).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t54, #t55, "2") : null;
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
+ self::expect("3", let final self::MapLike<core::int*, core::String*>* #t56 = map1 in let final core::int* #t57 = 3 in let final core::String* #t58 = self::Extension|[]<core::int*, core::String*>(#t56, #t57) in #t58.{core::String::==}(null) ?{core::String*} let final core::String* #t59 = "3" in let final void #t60 = self::Extension|[]=<core::int*, core::String*>(#t56, #t57, #t59) in #t59 : #t58);
+ self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
+ self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
+ self::expect(1, let final self::MapLike<core::int*, core::int*>* #t61 = map2 in let final core::int* #t62 = 0 in let final core::int* #t63 = 1 in let final void #t64 = self::Extension|[]=<core::int*, core::int*>(#t61, #t62, #t63) in #t63);
+ self::expect(3, let final core::Object* #t65 = map2 in let final core::int* #t66 = 0 in let final core::int* #t67 = self::Extension|[]<core::int*, core::int*>(#t65, #t66).{core::num::+}(2) in let final void #t68 = self::Extension|[]=<core::int*, core::int*>(#t65, #t66, #t67) in #t67);
+ self::expect(5, let final core::Object* #t69 = map2 in let final core::int* #t70 = 0 in let final core::int* #t71 = self::Extension|[]<core::int*, core::int*>(#t69, #t70).{core::num::+}(2) in let final void #t72 = self::Extension|[]=<core::int*, core::int*>(#t69, #t70, #t71) in #t71);
+ self::expect(5, let final core::Object* #t73 = map2 in let final core::int* #t74 = 0 in let final core::int* #t75 = self::Extension|[]<core::int*, core::int*>(#t73, #t74) in let final void #t76 = self::Extension|[]=<core::int*, core::int*>(#t73, #t74, #t75.{core::num::+}(1)) in #t75);
+ self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
+ self::expect(5, let final core::Object* #t77 = map2 in let final core::int* #t78 = 0 in let final core::int* #t79 = self::Extension|[]<core::int*, core::int*>(#t77, #t78).{core::num::-}(1) in let final void #t80 = self::Extension|[]=<core::int*, core::int*>(#t77, #t78, #t79) in #t79);
+ self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
+}
+static method explicitInferredTypeArguments() → dynamic {
+ self::MapLike<core::int*, core::String*>* map1 = new self::MapLike::•<core::int*, core::String*>();
+ self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 0));
+ map1.{self::MapLike::put}(0, "0");
+ self::expect("0", self::Extension|[]<core::int*, core::String*>(map1, 0));
+ self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
+ self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::expect("2", let final self::MapLike<core::int*, core::String*>* #t81 = map1 in let final core::int* #t82 = 1 in let final core::String* #t83 = "2" in let final void #t84 = self::Extension|[]=<core::int*, core::String*>(#t81, #t82, #t83) in #t83);
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ let final self::MapLike<core::int*, core::String*>* #t85 = map1 in let final core::int* #t86 = 1 in self::Extension|[]<core::int*, core::String*>(#t85, #t86).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t85, #t86, "3") : null;
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ self::expect("2", let final self::MapLike<core::int*, core::String*>* #t87 = map1 in let final core::int* #t88 = 1 in let final core::String* #t89 = self::Extension|[]<core::int*, core::String*>(#t87, #t88) in #t89.{core::String::==}(null) ?{core::String*} let final core::String* #t90 = "4" in let final void #t91 = self::Extension|[]=<core::int*, core::String*>(#t87, #t88, #t90) in #t90 : #t89);
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+ let final self::MapLike<core::int*, core::String*>* #t92 = map1 in let final core::int* #t93 = 2 in self::Extension|[]<core::int*, core::String*>(#t92, #t93).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t92, #t93, "2") : null;
+ self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
+ self::expect("3", let final self::MapLike<core::int*, core::String*>* #t94 = map1 in let final core::int* #t95 = 3 in let final core::String* #t96 = self::Extension|[]<core::int*, core::String*>(#t94, #t95) in #t96.{core::String::==}(null) ?{core::String*} let final core::String* #t97 = "3" in let final void #t98 = self::Extension|[]=<core::int*, core::String*>(#t94, #t95, #t97) in #t97 : #t96);
+ self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
+ self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
+ self::expect(1, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = 1 in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
+ self::expect(3, let final core::Object* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
+ self::expect(5, let final core::Object* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108).{core::num::+}(2) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109) in #t109);
+ self::expect(5, let final core::Object* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113.{core::num::+}(1)) in #t113);
+ self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
+ self::expect(5, let final core::Object* #t115 = map2 in let final core::int* #t116 = 0 in let final core::int* #t117 = self::Extension|[]<core::int*, core::int*>(#t115, #t116).{core::num::-}(1) in let final void #t118 = self::Extension|[]=<core::int*, core::int*>(#t115, #t116, #t117) in #t117);
+ self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
+}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
throw "Mismatch: expected=${expected}, actual=${actual}";
diff --git a/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.strong.expect b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.strong.expect
index b24b206..86beef5 100644
--- a/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.strong.expect
@@ -30,9 +30,9 @@
// Extension(c1).foo = null;
// ^^^
//
-// pkg/front_end/testcases/extensions/invalid_explicit_access.dart:31:3: Error: Getter not found: 'foo'.
+// pkg/front_end/testcases/extensions/invalid_explicit_access.dart:31:17: Error: Method not found: 'foo'.
// Extension(c1).foo();
-// ^^^
+// ^^^
//
// pkg/front_end/testcases/extensions/invalid_explicit_access.dart:32:3: Error: Too few positional arguments: 2 required, 1 given.
// Extension(c1).method();
@@ -180,9 +180,9 @@
invalid-expression "pkg/front_end/testcases/extensions/invalid_explicit_access.dart:30:3: Error: Setter not found: 'foo'.
Extension(c1).foo = null;
^^^";
- invalid-expression "pkg/front_end/testcases/extensions/invalid_explicit_access.dart:31:3: Error: Getter not found: 'foo'.
+ invalid-expression "pkg/front_end/testcases/extensions/invalid_explicit_access.dart:31:17: Error: Method not found: 'foo'.
Extension(c1).foo();
- ^^^";
+ ^^^";
invalid-expression "pkg/front_end/testcases/extensions/invalid_explicit_access.dart:32:3: Error: Too few positional arguments: 2 required, 1 given.
Extension(c1).method();
^";
diff --git a/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.strong.transformed.expect
index b24b206..86beef5 100644
--- a/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.strong.transformed.expect
@@ -30,9 +30,9 @@
// Extension(c1).foo = null;
// ^^^
//
-// pkg/front_end/testcases/extensions/invalid_explicit_access.dart:31:3: Error: Getter not found: 'foo'.
+// pkg/front_end/testcases/extensions/invalid_explicit_access.dart:31:17: Error: Method not found: 'foo'.
// Extension(c1).foo();
-// ^^^
+// ^^^
//
// pkg/front_end/testcases/extensions/invalid_explicit_access.dart:32:3: Error: Too few positional arguments: 2 required, 1 given.
// Extension(c1).method();
@@ -180,9 +180,9 @@
invalid-expression "pkg/front_end/testcases/extensions/invalid_explicit_access.dart:30:3: Error: Setter not found: 'foo'.
Extension(c1).foo = null;
^^^";
- invalid-expression "pkg/front_end/testcases/extensions/invalid_explicit_access.dart:31:3: Error: Getter not found: 'foo'.
+ invalid-expression "pkg/front_end/testcases/extensions/invalid_explicit_access.dart:31:17: Error: Method not found: 'foo'.
Extension(c1).foo();
- ^^^";
+ ^^^";
invalid-expression "pkg/front_end/testcases/extensions/invalid_explicit_access.dart:32:3: Error: Too few positional arguments: 2 required, 1 given.
Extension(c1).method();
^";
diff --git a/pkg/front_end/testcases/extensions/tear_offs.dart b/pkg/front_end/testcases/extensions/tear_offs.dart
new file mode 100644
index 0000000..3d7e5a6
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/tear_offs.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2019, 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.
+
+class Class {}
+
+extension Extension on Class {
+ T id<T>(T t) => t;
+
+ T Function<T>(T) get getter => id;
+
+ method() {
+ String Function(String) stringId = id;
+ }
+
+ errors() {
+ int Function(int) intId = getter;
+ }
+}
+
+
+main() {
+ Class c = new Class();
+ int Function(int) intId = c.id;
+ double Function(double) doubleId = Extension(c).id;
+}
+
+errors() {
+ Class c = new Class();
+ num Function(num) numId = c.getter;
+ bool Function(bool) boolId = Extension(c).getter;
+}
+
diff --git a/pkg/front_end/testcases/extensions/tear_offs.dart.outline.expect b/pkg/front_end/testcases/extensions/tear_offs.dart.outline.expect
new file mode 100644
index 0000000..7ad8711
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/tear_offs.dart.outline.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class*
+ ;
+}
+extension Extension on self::Class* {
+ method id = self::Extension|id;
+ tearoff id = self::Extension|get#id;
+ get getter = self::Extension|get#getter;
+ method method = self::Extension|method;
+ tearoff method = self::Extension|get#method;
+ method errors = self::Extension|errors;
+ tearoff errors = self::Extension|get#errors;
+}
+static method Extension|id<T extends core::Object* = dynamic>(final self::Class* #this, self::Extension|id::T* t) → self::Extension|id::T*
+ ;
+static method Extension|get#id(final self::Class* #this) → <T extends core::Object* = dynamic>(T*) →* T*
+ return <T extends core::Object* = dynamic>(T* t) → T* => self::Extension|id<T*>(#this, t);
+static method Extension|get#getter(final self::Class* #this) → <T extends core::Object* = dynamic>(T*) →* T*
+ ;
+static method Extension|method(final self::Class* #this) → dynamic
+ ;
+static method Extension|get#method(final self::Class* #this) → () →* dynamic
+ return () → dynamic => self::Extension|method(#this);
+static method Extension|errors(final self::Class* #this) → dynamic
+ ;
+static method Extension|get#errors(final self::Class* #this) → () →* dynamic
+ return () → dynamic => self::Extension|errors(#this);
+static method main() → dynamic
+ ;
+static method errors() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/extensions/tear_offs.dart.strong.expect b/pkg/front_end/testcases/extensions/tear_offs.dart.strong.expect
new file mode 100644
index 0000000..86c38ea
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/tear_offs.dart.strong.expect
@@ -0,0 +1,71 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/tear_offs.dart:17:31: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int Function(int)'.
+// int Function(int) intId = getter;
+// ^
+//
+// pkg/front_end/testcases/extensions/tear_offs.dart:30:31: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'num Function(num)'.
+// Try changing the type of the left hand side, or casting the right hand side to 'num Function(num)'.
+// num Function(num) numId = c.getter;
+// ^
+//
+// pkg/front_end/testcases/extensions/tear_offs.dart:31:32: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'bool Function(bool)'.
+// Try changing the type of the left hand side, or casting the right hand side to 'bool Function(bool)'.
+// bool Function(bool) boolId = Extension(c).getter;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+}
+extension Extension on self::Class* {
+ method id = self::Extension|id;
+ tearoff id = self::Extension|get#id;
+ get getter = self::Extension|get#getter;
+ method method = self::Extension|method;
+ tearoff method = self::Extension|get#method;
+ method errors = self::Extension|errors;
+ tearoff errors = self::Extension|get#errors;
+}
+static method Extension|id<T extends core::Object* = dynamic>(final self::Class* #this, self::Extension|id::T* t) → self::Extension|id::T*
+ return t;
+static method Extension|get#id(final self::Class* #this) → <T extends core::Object* = dynamic>(T*) →* T*
+ return <T extends core::Object* = dynamic>(T* t) → T* => self::Extension|id<T*>(#this, t);
+static method Extension|get#getter(final self::Class* #this) → <T extends core::Object* = dynamic>(T*) →* T*
+ return self::Extension|get#id(#this);
+static method Extension|method(final self::Class* #this) → dynamic {
+ (core::String*) →* core::String* stringId = self::Extension|get#id(#this)<core::String*>;
+}
+static method Extension|get#method(final self::Class* #this) → () →* dynamic
+ return () → dynamic => self::Extension|method(#this);
+static method Extension|errors(final self::Class* #this) → dynamic {
+ (core::int*) →* core::int* intId = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/extensions/tear_offs.dart:17:31: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+Try changing the type of the left hand side, or casting the right hand side to 'int Function(int)'.
+ int Function(int) intId = getter;
+ ^" in self::Extension|get#getter(#this) as{TypeError} (core::int*) →* core::int*;
+}
+static method Extension|get#errors(final self::Class* #this) → () →* dynamic
+ return () → dynamic => self::Extension|errors(#this);
+static method main() → dynamic {
+ self::Class* c = new self::Class::•();
+ (core::int*) →* core::int* intId = self::Extension|get#id(c)<core::int*>;
+ (core::double*) →* core::double* doubleId = self::Extension|get#id(c)<core::double*>;
+}
+static method errors() → dynamic {
+ self::Class* c = new self::Class::•();
+ (core::num*) →* core::num* numId = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/extensions/tear_offs.dart:30:31: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'num Function(num)'.
+Try changing the type of the left hand side, or casting the right hand side to 'num Function(num)'.
+ num Function(num) numId = c.getter;
+ ^" in self::Extension|get#getter(c) as{TypeError} (core::num*) →* core::num*;
+ (core::bool*) →* core::bool* boolId = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/extensions/tear_offs.dart:31:32: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'bool Function(bool)'.
+Try changing the type of the left hand side, or casting the right hand side to 'bool Function(bool)'.
+ bool Function(bool) boolId = Extension(c).getter;
+ ^" in self::Extension|get#getter(c) as{TypeError} (core::bool*) →* core::bool*;
+}
diff --git a/pkg/front_end/testcases/extensions/tear_offs.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/tear_offs.dart.strong.transformed.expect
new file mode 100644
index 0000000..86c38ea
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/tear_offs.dart.strong.transformed.expect
@@ -0,0 +1,71 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/tear_offs.dart:17:31: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int Function(int)'.
+// int Function(int) intId = getter;
+// ^
+//
+// pkg/front_end/testcases/extensions/tear_offs.dart:30:31: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'num Function(num)'.
+// Try changing the type of the left hand side, or casting the right hand side to 'num Function(num)'.
+// num Function(num) numId = c.getter;
+// ^
+//
+// pkg/front_end/testcases/extensions/tear_offs.dart:31:32: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'bool Function(bool)'.
+// Try changing the type of the left hand side, or casting the right hand side to 'bool Function(bool)'.
+// bool Function(bool) boolId = Extension(c).getter;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+}
+extension Extension on self::Class* {
+ method id = self::Extension|id;
+ tearoff id = self::Extension|get#id;
+ get getter = self::Extension|get#getter;
+ method method = self::Extension|method;
+ tearoff method = self::Extension|get#method;
+ method errors = self::Extension|errors;
+ tearoff errors = self::Extension|get#errors;
+}
+static method Extension|id<T extends core::Object* = dynamic>(final self::Class* #this, self::Extension|id::T* t) → self::Extension|id::T*
+ return t;
+static method Extension|get#id(final self::Class* #this) → <T extends core::Object* = dynamic>(T*) →* T*
+ return <T extends core::Object* = dynamic>(T* t) → T* => self::Extension|id<T*>(#this, t);
+static method Extension|get#getter(final self::Class* #this) → <T extends core::Object* = dynamic>(T*) →* T*
+ return self::Extension|get#id(#this);
+static method Extension|method(final self::Class* #this) → dynamic {
+ (core::String*) →* core::String* stringId = self::Extension|get#id(#this)<core::String*>;
+}
+static method Extension|get#method(final self::Class* #this) → () →* dynamic
+ return () → dynamic => self::Extension|method(#this);
+static method Extension|errors(final self::Class* #this) → dynamic {
+ (core::int*) →* core::int* intId = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/extensions/tear_offs.dart:17:31: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
+Try changing the type of the left hand side, or casting the right hand side to 'int Function(int)'.
+ int Function(int) intId = getter;
+ ^" in self::Extension|get#getter(#this) as{TypeError} (core::int*) →* core::int*;
+}
+static method Extension|get#errors(final self::Class* #this) → () →* dynamic
+ return () → dynamic => self::Extension|errors(#this);
+static method main() → dynamic {
+ self::Class* c = new self::Class::•();
+ (core::int*) →* core::int* intId = self::Extension|get#id(c)<core::int*>;
+ (core::double*) →* core::double* doubleId = self::Extension|get#id(c)<core::double*>;
+}
+static method errors() → dynamic {
+ self::Class* c = new self::Class::•();
+ (core::num*) →* core::num* numId = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/extensions/tear_offs.dart:30:31: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'num Function(num)'.
+Try changing the type of the left hand side, or casting the right hand side to 'num Function(num)'.
+ num Function(num) numId = c.getter;
+ ^" in self::Extension|get#getter(c) as{TypeError} (core::num*) →* core::num*;
+ (core::bool*) →* core::bool* boolId = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/extensions/tear_offs.dart:31:32: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'bool Function(bool)'.
+Try changing the type of the left hand side, or casting the right hand side to 'bool Function(bool)'.
+ bool Function(bool) boolId = Extension(c).getter;
+ ^" in self::Extension|get#getter(c) as{TypeError} (core::bool*) →* core::bool*;
+}
diff --git a/pkg/front_end/testcases/general/magic_const.dart.strong.expect b/pkg/front_end/testcases/general/magic_const.dart.strong.expect
index de74647..7f979c6 100644
--- a/pkg/front_end/testcases/general/magic_const.dart.strong.expect
+++ b/pkg/front_end/testcases/general/magic_const.dart.strong.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general/magic_const.dart:15:39: Error: Constant evaluation error:
-// foo({a: Constant(), b: Constant(), c: []}) {}
-// ^
-// pkg/front_end/testcases/general/magic_const.dart:15:39: Context: Can't have a non-constant List literal within a const context.
-// foo({a: Constant(), b: Constant(), c: []}) {}
-// ^
-// pkg/front_end/testcases/general/magic_const.dart:15:36: Context: While analyzing:
-// foo({a: Constant(), b: Constant(), c: []}) {}
-// ^
-//
library;
//
// Problems in library:
@@ -48,7 +35,7 @@
: super core::Object::•()
;
}
-static method foo({dynamic a = #C1, dynamic b = #C1, dynamic c = invalid-expression "Can't have a non-constant List literal within a const context."}) → dynamic {}
+static method foo({dynamic a = #C1, dynamic b = #C1, dynamic c = invalid-expression "Non-constant list literal"}) → dynamic {}
static method test() → dynamic {
invalid-expression "pkg/front_end/testcases/general/magic_const.dart:18:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.
diff --git a/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect b/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
index de74647..7f979c6 100644
--- a/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general/magic_const.dart:15:39: Error: Constant evaluation error:
-// foo({a: Constant(), b: Constant(), c: []}) {}
-// ^
-// pkg/front_end/testcases/general/magic_const.dart:15:39: Context: Can't have a non-constant List literal within a const context.
-// foo({a: Constant(), b: Constant(), c: []}) {}
-// ^
-// pkg/front_end/testcases/general/magic_const.dart:15:36: Context: While analyzing:
-// foo({a: Constant(), b: Constant(), c: []}) {}
-// ^
-//
library;
//
// Problems in library:
@@ -48,7 +35,7 @@
: super core::Object::•()
;
}
-static method foo({dynamic a = #C1, dynamic b = #C1, dynamic c = invalid-expression "Can't have a non-constant List literal within a const context."}) → dynamic {}
+static method foo({dynamic a = #C1, dynamic b = #C1, dynamic c = invalid-expression "Non-constant list literal"}) → dynamic {}
static method test() → dynamic {
invalid-expression "pkg/front_end/testcases/general/magic_const.dart:18:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
Try using a constructor or factory that is 'const'.
diff --git a/pkg/front_end/testcases/inference/unresolved_super.dart.strong.expect b/pkg/front_end/testcases/inference/unresolved_super.dart.strong.expect
index d7d9a11..1f4d51b 100644
--- a/pkg/front_end/testcases/inference/unresolved_super.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/unresolved_super.dart.strong.expect
@@ -4,7 +4,7 @@
//
// pkg/front_end/testcases/inference/unresolved_super.dart:16:37: Error: Superclass has no method named '[]='.
// var /*@type=dynamic*/ v5 = super[0] = /*@typeArgs=dynamic*/ f();
-// ^^^
+// ^
//
import self as self;
import "dart:core" as core;
@@ -16,7 +16,7 @@
method test() → void {
dynamic v5 = let final core::int* #t1 = 0 in let final dynamic #t2 = self::f<dynamic>() in let final void #t3 = invalid-expression "pkg/front_end/testcases/inference/unresolved_super.dart:16:37: Error: Superclass has no method named '[]='.
var /*@type=dynamic*/ v5 = super[0] = /*@typeArgs=dynamic*/ f();
- ^^^" in #t2;
+ ^" in #t2;
}
}
static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/unresolved_super.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unresolved_super.dart.strong.transformed.expect
index d7d9a11..1f4d51b 100644
--- a/pkg/front_end/testcases/inference/unresolved_super.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unresolved_super.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
//
// pkg/front_end/testcases/inference/unresolved_super.dart:16:37: Error: Superclass has no method named '[]='.
// var /*@type=dynamic*/ v5 = super[0] = /*@typeArgs=dynamic*/ f();
-// ^^^
+// ^
//
import self as self;
import "dart:core" as core;
@@ -16,7 +16,7 @@
method test() → void {
dynamic v5 = let final core::int* #t1 = 0 in let final dynamic #t2 = self::f<dynamic>() in let final void #t3 = invalid-expression "pkg/front_end/testcases/inference/unresolved_super.dart:16:37: Error: Superclass has no method named '[]='.
var /*@type=dynamic*/ v5 = super[0] = /*@typeArgs=dynamic*/ f();
- ^^^" in #t2;
+ ^" in #t2;
}
}
static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.34.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.34.compile.1.dill
new file mode 100644
index 0000000..6af2b34
--- /dev/null
+++ b/pkg/front_end/testcases/old_dills/dart2js.version.34.compile.1.dill
Binary files differ
diff --git a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect
index 9096c74..9989711 100644
--- a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:18: Error: Constant evaluation error:
-// main(arguments = [x]) {
-// ^
-// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:18: Context: Can't have a non-constant List literal within a const context.
-// main(arguments = [x]) {
-// ^
-// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:6: Context: While analyzing:
-// main(arguments = [x]) {
-// ^
-//
library;
//
// Problems in library:
@@ -31,4 +18,4 @@
//
import self as self;
-static method main(dynamic arguments = invalid-expression "Can't have a non-constant List literal within a const context.") → dynamic {}
+static method main(dynamic arguments = invalid-expression "Non-constant list literal") → dynamic {}
diff --git a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect
index 9096c74..9989711 100644
--- a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:18: Error: Constant evaluation error:
-// main(arguments = [x]) {
-// ^
-// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:18: Context: Can't have a non-constant List literal within a const context.
-// main(arguments = [x]) {
-// ^
-// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:6: Context: While analyzing:
-// main(arguments = [x]) {
-// ^
-//
library;
//
// Problems in library:
@@ -31,4 +18,4 @@
//
import self as self;
-static method main(dynamic arguments = invalid-expression "Can't have a non-constant List literal within a const context.") → dynamic {}
+static method main(dynamic arguments = invalid-expression "Non-constant list literal") → dynamic {}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 91148be..e02ba42 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -6,6 +6,7 @@
# Kernel ASTs directly, that is, code in pkg/fasta/lib/src/kernel/ with
# strong-mode enabled.
+extensions/extension_setter_error: TypeCheckError
extensions/instance_access_of_static: RuntimeError
extensions/invalid_explicit_access: RuntimeError
extensions/static_access_of_instance: RuntimeError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 95610cc..6bafcf8 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -10,6 +10,7 @@
expression/eval: TextSerializationFailure # Was: Pass
expression/main: TextSerializationFailure # Was: Pass
extensions/annotations: TextSerializationFailure
+extensions/check_bounds: TextSerializationFailure
extensions/compounds: TextSerializationFailure
extensions/conflicts: TextSerializationFailure
extensions/default_values: TextSerializationFailure
@@ -21,8 +22,11 @@
extensions/explicit_generic_extension_access: TextSerializationFailure
extensions/explicit_invalid_access: TextSerializationFailure
extensions/explicit_this: TextSerializationFailure
+extensions/extension_call: TextSerializationFailure
+extensions/extension_constructor: TextSerializationFailure
extensions/extension_methods: TextSerializationFailure
extensions/extension_setter: TextSerializationFailure
+extensions/extension_setter_error: TypeCheckError
extensions/getter_setter_conflict: TextSerializationFailure
extensions/if_null: TextSerializationFailure
extensions/implicit_extension_inference: TextSerializationFailure
@@ -43,6 +47,7 @@
extensions/other_kinds: TextSerializationFailure
extensions/static_access: TextSerializationFailure
extensions/static_access_of_instance: TextSerializationFailure
+extensions/tear_offs: TextSerializationFailure
extensions/type_variables: TextSerializationFailure
extensions/unnamed_extensions: TextSerializationFailure
extensions/use_this: TextSerializationFailure
@@ -1113,4 +1118,6 @@
runtime_checks_new/stub_from_interface_covariant_from_interface: TextSerializationFailure # Was: Pass
runtime_checks_new/stub_from_interface_covariant_from_super: TextSerializationFailure # Was: Pass
set_literals/disambiguation_rule: TextSerializationFailure # Was: RuntimeError
+variance/class_type_parameter_modifier: TextSerializationFailure
+variance/mixin_type_parameter_modifier: TextSerializationFailure
top_level_variance_test: TextSerializationFailure
diff --git a/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart b/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart
new file mode 100644
index 0000000..71aa5cf
--- /dev/null
+++ b/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, 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.
+
+class A<out X, in Y, inout Z> {}
+
+main() {
+ A a = new A();
+}
diff --git a/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart.outline.expect b/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart.outline.expect
new file mode 100644
index 0000000..05b61d8
--- /dev/null
+++ b/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart.outline.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object* = dynamic, contravariant Y extends core::Object* = dynamic, invariant Z extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X*, self::A::Y*, self::A::Z*>*
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart.strong.expect b/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart.strong.expect
new file mode 100644
index 0000000..cb21b6a
--- /dev/null
+++ b/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart.strong.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object* = dynamic, contravariant Y extends core::Object* = dynamic, invariant Z extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X*, self::A::Y*, self::A::Z*>*
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {
+ self::A<dynamic, dynamic, dynamic>* a = new self::A::•<dynamic, dynamic, dynamic>();
+}
diff --git a/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart.strong.transformed.expect b/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart.strong.transformed.expect
new file mode 100644
index 0000000..cb21b6a
--- /dev/null
+++ b/pkg/front_end/testcases/variance/class_type_parameter_modifier.dart.strong.transformed.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object* = dynamic, contravariant Y extends core::Object* = dynamic, invariant Z extends core::Object* = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X*, self::A::Y*, self::A::Z*>*
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {
+ self::A<dynamic, dynamic, dynamic>* a = new self::A::•<dynamic, dynamic, dynamic>();
+}
diff --git a/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart
new file mode 100644
index 0000000..2aefefb
--- /dev/null
+++ b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, 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.
+
+class A {}
+
+mixin B<inout X, out Y, in Z> on A {}
+
+main() {}
diff --git a/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.outline.expect b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.outline.expect
new file mode 100644
index 0000000..44fe61a
--- /dev/null
+++ b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.outline.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ ;
+}
+abstract class B<invariant X extends core::Object* = dynamic, Y extends core::Object* = dynamic, contravariant Z extends core::Object* = dynamic> extends self::A {
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.expect b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.expect
new file mode 100644
index 0000000..0c6c3cdf
--- /dev/null
+++ b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+}
+abstract class B<invariant X extends core::Object* = dynamic, Y extends core::Object* = dynamic, contravariant Z extends core::Object* = dynamic> extends self::A {
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.transformed.expect b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.transformed.expect
new file mode 100644
index 0000000..0c6c3cdf
--- /dev/null
+++ b/pkg/front_end/testcases/variance/mixin_type_parameter_modifier.dart.strong.transformed.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+}
+abstract class B<invariant X extends core::Object* = dynamic, Y extends core::Object* = dynamic, contravariant Z extends core::Object* = dynamic> extends self::A {
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/variance/test.options b/pkg/front_end/testcases/variance/test.options
new file mode 100644
index 0000000..3ce5008
--- /dev/null
+++ b/pkg/front_end/testcases/variance/test.options
@@ -0,0 +1 @@
+--enable-experiment=variance
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 2c8c9b8..5262250 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -177,6 +177,17 @@
"exclude": []
},
{
+ "name": "parser_test",
+ "kind": "Chain",
+ "source": "test/parser_test.dart",
+ "path": "parser_testcases/",
+ "status": "parser_testcases/parser.status",
+ "pattern": [
+ "\\.dart$"
+ ],
+ "exclude": []
+ },
+ {
"name": "lint_test",
"kind": "Chain",
"source": "test/lint_test.dart",
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 5152615..d8a353e 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -143,7 +143,7 @@
type ComponentFile {
UInt32 magic = 0x90ABCDEF;
- UInt32 formatVersion = 33;
+ UInt32 formatVersion = 34;
List<String> problemsAsJson; // Described in problems.md.
Library[] libraries;
UriSource sourceMap;
@@ -1236,6 +1236,8 @@
enum Nullability { nullable = 0, nonNullable = 1, neither = 2, legacy = 3, }
+enum Variance { unrelated = 0, covariant = 1, contravariant = 2, invariant = 3, }
+
abstract type DartType extends Node {}
type BottomType extends DartType {
@@ -1332,6 +1334,7 @@
// Note: there is no tag on TypeParameter
Byte flags (isGenericCovariantImpl);
List<Expression> annotations;
+ Byte variance; // Index into the Variance enum above
StringReference name; // Cosmetic, may be empty, not unique.
DartType bound; // 'dynamic' if no explicit bound was given.
Option<DartType> defaultType; // type used when the parameter is not passed
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 1f1835c..cd777e3 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -6003,6 +6003,18 @@
if (a == invariant || b == invariant) return invariant;
return a == b ? covariant : contravariant;
}
+
+ static int fromString(String variance) {
+ if (variance == "in") {
+ return contravariant;
+ } else if (variance == "inout") {
+ return invariant;
+ } else if (variance == "out") {
+ return covariant;
+ } else {
+ return unrelated;
+ }
+ }
}
/// Declaration of a type variable.
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index f8585a5..f717ce2 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -2184,10 +2184,10 @@
void readTypeParameter(TypeParameter node) {
node.flags = readByte();
node.annotations = readAnnotationList(node);
+ node.variance = readByte();
node.name = readStringOrNullIfEmpty();
node.bound = readDartType();
node.defaultType = readDartTypeOption();
- node.variance = Variance.covariant;
}
Arguments readArguments() {
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 9e34e8c..8abfe1b 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -2121,6 +2121,7 @@
void visitTypeParameter(TypeParameter node) {
writeByte(node.flags);
writeAnnotationList(node.annotations);
+ writeByte(node.variance);
writeStringReference(node.name ?? '');
writeNode(node.bound);
writeOptionalNode(node.defaultType);
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 33091c0..1768aae 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -148,7 +148,7 @@
/// Internal version of kernel binary format.
/// Bump it when making incompatible changes in kernel binaries.
/// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
- static const int BinaryFormatVersion = 33;
+ static const int BinaryFormatVersion = 34;
}
abstract class ConstantTag {
diff --git a/pkg/nnbd_migration/lib/instrumentation.dart b/pkg/nnbd_migration/lib/instrumentation.dart
index a108610..7689928 100644
--- a/pkg/nnbd_migration/lib/instrumentation.dart
+++ b/pkg/nnbd_migration/lib/instrumentation.dart
@@ -179,6 +179,9 @@
/// After migration is complete, this getter can be used to query whether
/// the type associated with this node was determined to be nullable.
bool get isNullable;
+
+ /// The edges that caused this node to have the nullability that it has.
+ Iterable<EdgeInfo> get upstreamEdges;
}
/// Information exposed to the migration client about a single step in the
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index 546590f..f200e92 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -36,14 +36,17 @@
factory NullabilityFixDescription.addRequired(
String className, String functionName, String paramName) =>
NullabilityFixDescription._(
- appliedMessage: "Add 'required' keyword to parameter $paramName in " +
- (className == null ? functionName : '$className.$functionName'));
+ appliedMessage:
+ "Add 'required' keyword to parameter '$paramName' in " +
+ (className == null
+ ? functionName
+ : "'$className.$functionName'"));
/// An explicit type mentioned in the source program needs to be made
/// nullable.
factory NullabilityFixDescription.makeTypeNullable(String type) =>
NullabilityFixDescription._(
- appliedMessage: 'Changed type $type to be nullable',
+ appliedMessage: "Changed type '$type' to be nullable",
);
const NullabilityFixDescription._({@required this.appliedMessage});
diff --git a/pkg/nnbd_migration/lib/src/conditional_discard.dart b/pkg/nnbd_migration/lib/src/conditional_discard.dart
index 0295834..8495d47 100644
--- a/pkg/nnbd_migration/lib/src/conditional_discard.dart
+++ b/pkg/nnbd_migration/lib/src/conditional_discard.dart
@@ -50,7 +50,6 @@
/// to `true` is reachable after migration.
bool get keepTrue => trueGuard == null || trueGuard.isNullable;
- @override
Iterable<FixReasonInfo> get reasons sync* {
if (!keepTrue) yield falseGuard;
if (!keepFalse) yield trueGuard;
diff --git a/pkg/nnbd_migration/lib/src/decorated_type.dart b/pkg/nnbd_migration/lib/src/decorated_type.dart
index 8cb67ac..d599c48 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type.dart
@@ -3,11 +3,14 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart' as type_algebra;
import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
@@ -346,6 +349,84 @@
return _substitute(substitution, undecoratedResult);
}
+ /// Convert this decorated type into the [DartType] that it will represent
+ /// after the code has been migrated.
+ ///
+ /// This method should be used after nullability propagation; it makes use of
+ /// the nullabilities associated with nullability nodes to determine which
+ /// types should be nullable and which types should not.
+ DartType toFinalType(TypeProvider typeProvider) {
+ var type = this.type;
+ if (type.isVoid || type.isDynamic) return type;
+ if (type.isBottom || type.isDartCoreNull) {
+ if (node.isNullable) {
+ return (typeProvider.nullType as TypeImpl)
+ .withNullability(NullabilitySuffix.none);
+ } else {
+ return BottomTypeImpl.instance;
+ }
+ }
+ var nullabilitySuffix =
+ node.isNullable ? NullabilitySuffix.question : NullabilitySuffix.none;
+ if (type is FunctionType) {
+ var newTypeFormals = <TypeParameterElementImpl>[];
+ var typeFormalSubstitution = <TypeParameterElement, DartType>{};
+ for (var typeFormal in typeFormals) {
+ var newTypeFormal = TypeParameterElementImpl.synthetic(typeFormal.name);
+ newTypeFormals.add(newTypeFormal);
+ typeFormalSubstitution[typeFormal] = TypeParameterTypeImpl(
+ newTypeFormal,
+ nullabilitySuffix: NullabilitySuffix.none);
+ }
+ for (int i = 0; i < newTypeFormals.length; i++) {
+ newTypeFormals[i].bound = type_algebra.substitute(
+ typeFormalBounds[i].toFinalType(typeProvider),
+ typeFormalSubstitution);
+ }
+ var parameters = <ParameterElement>[];
+ for (int i = 0; i < type.parameters.length; i++) {
+ var origParameter = type.parameters[i];
+ ParameterKind parameterKind;
+ DecoratedType parameterType;
+ var name = origParameter.name;
+ if (origParameter.isNamed) {
+ // TODO(paulberry): infer ParameterKind.NAMED_REQUIRED when
+ // appropriate. See https://github.com/dart-lang/sdk/issues/38596.
+ parameterKind = ParameterKind.NAMED;
+ parameterType = namedParameters[name];
+ } else {
+ parameterKind = origParameter.isOptional
+ ? ParameterKind.POSITIONAL
+ : ParameterKind.REQUIRED;
+ parameterType = positionalParameters[i];
+ }
+ parameters.add(ParameterElementImpl.synthetic(
+ name,
+ type_algebra.substitute(parameterType.toFinalType(typeProvider),
+ typeFormalSubstitution),
+ parameterKind));
+ }
+ return FunctionTypeImpl.synthetic(
+ type_algebra.substitute(
+ returnType.toFinalType(typeProvider), typeFormalSubstitution),
+ newTypeFormals,
+ parameters,
+ nullabilitySuffix: nullabilitySuffix);
+ } else if (type is InterfaceType) {
+ return InterfaceTypeImpl.explicit(type.element,
+ [for (var arg in typeArguments) arg.toFinalType(typeProvider)],
+ nullabilitySuffix: nullabilitySuffix);
+ } else if (type is TypeParameterType) {
+ return TypeParameterTypeImpl(type.element,
+ nullabilitySuffix: nullabilitySuffix);
+ } else {
+ // The above cases should cover all possible types. On the off chance
+ // they don't, fall back on returning DecoratedType.type.
+ assert(false, 'Unexpected type (${type.runtimeType})');
+ return type;
+ }
+ }
+
@override
String toString() {
var trailing = node == null ? '' : node.debugSuffix;
diff --git a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
index 088cc91..3e9f14e 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
@@ -11,7 +11,7 @@
/// [TypeOperations] that works with [DecoratedType]s.
class DecoratedTypeOperations
- implements TypeOperations<VariableElement, DecoratedType> {
+ implements TypeOperations<PromotableElement, DecoratedType> {
final TypeSystem _typeSystem;
final VariableRepository _variableRepository;
final NullabilityGraph _graph;
@@ -20,11 +20,6 @@
this._typeSystem, this._variableRepository, this._graph);
@override
- bool isLocalVariable(VariableElement element) {
- return element is LocalVariableElement;
- }
-
- @override
bool isSameType(DecoratedType type1, DecoratedType type2) {
return type1 == type2;
}
@@ -40,7 +35,7 @@
}
@override
- DecoratedType variableType(VariableElement variable) {
+ DecoratedType variableType(PromotableElement variable) {
return _variableRepository.decoratedElementType(variable);
}
}
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 1663b16..7fa652c 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -111,12 +111,12 @@
/// If we are visiting a function body or initializer, instance of flow
/// analysis. Otherwise `null`.
- FlowAnalysis<Statement, Expression, VariableElement, DecoratedType>
+ FlowAnalysis<Statement, Expression, PromotableElement, DecoratedType>
_flowAnalysis;
/// If we are visiting a function body or initializer, assigned variable
/// information used in flow analysis. Otherwise `null`.
- AssignedVariables<AstNode, VariableElement> _assignedVariables;
+ AssignedVariables<AstNode, PromotableElement> _assignedVariables;
/// For convenience, a [DecoratedType] representing non-nullable `Object`.
final DecoratedType _notNullType;
@@ -192,10 +192,9 @@
List<String> _objectGetNames;
EdgeBuilder(this._typeProvider, this._typeSystem, this._variables,
- this._graph, this.source, this.listener,
+ this._graph, this.source, this.listener, this._decoratedClassHierarchy,
{this.instrumentation})
- : _decoratedClassHierarchy = DecoratedClassHierarchy(_variables, _graph),
- _inheritanceManager = InheritanceManager3(_typeSystem),
+ : _inheritanceManager = InheritanceManager3(_typeSystem),
_notNullType = DecoratedType(_typeProvider.objectType, _graph.never),
_nonNullableBoolType =
DecoratedType(_typeProvider.boolType, _graph.never),
@@ -261,7 +260,7 @@
}
@override
- DecoratedType visitAssertStatement(AssertStatement node) {
+ DecoratedType visitAssertInitializer(AssertInitializer node) {
_checkExpressionNotNull(node.condition);
if (identical(_conditionInfo?.condition, node.condition)) {
var intentNode = _conditionInfo.trueDemonstratesNonNullIntent;
@@ -276,7 +275,7 @@
}
@override
- DecoratedType visitAssertInitializer(AssertInitializer node) {
+ DecoratedType visitAssertStatement(AssertStatement node) {
_checkExpressionNotNull(node.condition);
if (identical(_conditionInfo?.condition, node.condition)) {
var intentNode = _conditionInfo.trueDemonstratesNonNullIntent;
@@ -340,7 +339,7 @@
// TODO(paulberry): figure out what the rules for isPure should be.
isPure = true;
var element = leftOperand.staticElement;
- if (element is VariableElement) {
+ if (element is PromotableElement) {
_flowAnalysis.conditionEqNull(node, element, notEqual: notEqual);
}
}
@@ -383,18 +382,14 @@
_variables.recordDecoratedExpressionType(node, expressionType);
return expressionType;
} else if (operatorType.isUserDefinableOperator) {
- _checkExpressionNotNull(node.leftOperand);
+ var targetType = _checkExpressionNotNull(node.leftOperand);
var callee = node.staticElement;
- assert(!(callee is ClassMemberElement &&
- (callee.enclosingElement as ClassElement)
- .typeParameters
- .isNotEmpty)); // TODO(paulberry)
if (callee == null) {
node.rightOperand.accept(this);
return _dynamicType;
} else {
- var calleeType = getOrComputeElementType(callee);
- // TODO(paulberry): substitute if necessary
+ var calleeType =
+ getOrComputeElementType(callee, targetType: targetType);
assert(calleeType.positionalParameters.length > 0); // TODO(paulberry)
_handleAssignment(node.rightOperand,
destinationType: calleeType.positionalParameters[0]);
@@ -443,8 +438,7 @@
node.stackTraceParameter
]) {
if (identifier != null) {
- _flowAnalysis.add(identifier.staticElement as VariableElement,
- assigned: true);
+ _flowAnalysis.write(identifier.staticElement as PromotableElement);
}
}
// The catch clause may not execute, so create a new scope for
@@ -866,7 +860,7 @@
expression.accept(this);
if (expression is SimpleIdentifier) {
var element = expression.staticElement;
- if (element is VariableElement) {
+ if (element is PromotableElement) {
_flowAnalysis.isExpression_end(
node, element, node.notOperator != null, decoratedType);
}
@@ -1176,7 +1170,7 @@
@override
DecoratedType visitSimpleIdentifier(SimpleIdentifier node) {
var staticElement = node.staticElement;
- if (staticElement is VariableElement) {
+ if (staticElement is PromotableElement) {
if (!node.inDeclarationContext()) {
var promotedType = _flowAnalysis.promotedType(staticElement);
if (promotedType != null) return promotedType;
@@ -1372,10 +1366,12 @@
for (var variable in node.variables) {
variable.metadata.accept(this);
var initializer = variable.initializer;
- _flowAnalysis.add(variable.declaredElement,
- assigned: initializer != null);
+ var declaredElement = variable.declaredElement;
+ if (declaredElement is PromotableElement && initializer != null) {
+ _flowAnalysis.write(declaredElement);
+ }
if (initializer != null) {
- var destinationType = getOrComputeElementType(variable.declaredElement);
+ var destinationType = getOrComputeElementType(declaredElement);
if (typeAnnotation == null) {
var initializerType = initializer.accept(this);
if (initializerType == null) {
@@ -1420,7 +1416,7 @@
void _addParametersToFlowAnalysis(FormalParameterList parameters) {
if (parameters != null) {
for (var parameter in parameters.parameters) {
- _flowAnalysis.add(parameter.declaredElement, assigned: true);
+ _flowAnalysis.write(parameter.declaredElement);
}
}
}
@@ -1470,7 +1466,7 @@
assert(_flowAnalysis == null);
assert(_assignedVariables == null);
_flowAnalysis =
- FlowAnalysis<Statement, Expression, VariableElement, DecoratedType>(
+ FlowAnalysis<Statement, Expression, PromotableElement, DecoratedType>(
const AnalyzerNodeOperations(),
DecoratedTypeOperations(_typeSystem, _variables, _graph),
AnalyzerFunctionBodyAccess(node is FunctionBody ? node : null));
@@ -1600,11 +1596,11 @@
(destinationExpression == null) != (destinationType == null),
'Either destinationExpression or destinationType should be supplied, '
'but not both');
- VariableElement destinationLocalVariable;
+ PromotableElement destinationLocalVariable;
if (destinationType == null) {
if (destinationExpression is SimpleIdentifier) {
var element = destinationExpression.staticElement;
- if (element is VariableElement) {
+ if (element is PromotableElement) {
destinationLocalVariable = element;
}
}
@@ -1841,7 +1837,6 @@
if (parts is ForEachPartsWithDeclaration) {
var variableElement = parts.loopVariable.declaredElement;
lhsElement = variableElement;
- _flowAnalysis.add(variableElement, assigned: false);
} else if (parts is ForEachPartsWithIdentifier) {
lhsElement = parts.identifier.staticElement;
} else {
@@ -1863,7 +1858,7 @@
}
}
_flowAnalysis.forEach_bodyBegin(_assignedVariables.writtenInNode(node),
- lhsElement is VariableElement ? lhsElement : null);
+ lhsElement is PromotableElement ? lhsElement : null);
}
// The condition may fail/iterable may be empty, so the body gets a new
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 1f5d917..66a9fc2 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -437,7 +437,7 @@
hard: true);
break;
case _NullabilityComment.question:
- _graph.connect(_graph.always, decoratedType.node,
+ _graph.union(_graph.always, decoratedType.node,
NullabilityCommentOrigin(source, node));
break;
case _NullabilityComment.none:
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index 247fee8..0f778dd 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -8,6 +8,7 @@
import 'package:meta/meta.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
+import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
import 'package:nnbd_migration/src/edge_builder.dart';
import 'package:nnbd_migration/src/node_builder.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
@@ -26,6 +27,8 @@
final NullabilityMigrationInstrumentation _instrumentation;
+ DecoratedClassHierarchy _decoratedClassHierarchy;
+
/// Prepares to perform nullability migration.
///
/// If [permissive] is `true`, exception handling logic will try to proceed
@@ -60,8 +63,11 @@
}
void prepareInput(ResolvedUnitResult result) {
- _variables ??= Variables(_graph, result.typeProvider,
- instrumentation: _instrumentation);
+ if (_variables == null) {
+ _variables = Variables(_graph, result.typeProvider,
+ instrumentation: _instrumentation);
+ _decoratedClassHierarchy = DecoratedClassHierarchy(_variables, _graph);
+ }
var unit = result.unit;
unit.accept(NodeBuilder(_variables, unit.declaredElement.source,
_permissive ? listener : null, _graph, result.typeProvider,
@@ -70,8 +76,14 @@
void processInput(ResolvedUnitResult result) {
var unit = result.unit;
- unit.accept(EdgeBuilder(result.typeProvider, result.typeSystem, _variables,
- _graph, unit.declaredElement.source, _permissive ? listener : null,
+ unit.accept(EdgeBuilder(
+ result.typeProvider,
+ result.typeSystem,
+ _variables,
+ _graph,
+ unit.declaredElement.source,
+ _permissive ? listener : null,
+ _decoratedClassHierarchy,
instrumentation: _instrumentation));
}
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index f0122b0..3c057df 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -500,6 +500,9 @@
/// nullability migration needs to decide whether it is optional or required.
bool get isPossiblyOptional => _isPossiblyOptional;
+ @override
+ Iterable<EdgeInfo> get upstreamEdges => _upstreamEdges;
+
String get _debugPrefix;
NullabilityState get _state;
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index c0d90a0..0a81426 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -1047,6 +1047,16 @@
await _checkSingleFileChanges(content, expected);
}
+ test_explicit_nullable_overrides_hard_edge() async {
+ var content = '''
+int f(int/*?*/ i) => i + 1;
+''';
+ var expected = '''
+int f(int?/*?*/ i) => i! + 1;
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
test_field_formal_param_typed() async {
var content = '''
class C {
diff --git a/pkg/nnbd_migration/test/decorated_type_test.dart b/pkg/nnbd_migration/test/decorated_type_test.dart
index 61e8b6d..22a2dc0 100644
--- a/pkg/nnbd_migration/test/decorated_type_test.dart
+++ b/pkg/nnbd_migration/test/decorated_type_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
@@ -38,6 +39,13 @@
ClassElement get listElement => typeProvider.listElement;
+ void assertDartType(DartType type, String expected) {
+ // Note: by default DartType.toString doesn't print nullability suffixes,
+ // so we have to override that behavior in order to make sure the
+ // nullability suffixes are correct.
+ expect((type as TypeImpl).toString(withNullability: true), expected);
+ }
+
void setUp() {
NullabilityNode.clearDebugNames();
}
@@ -291,6 +299,227 @@
expect(list(argType, node: node) == list(argType, node: node), isTrue);
}
+ test_toFinalType_bottom_non_nullable() {
+ var type =
+ DecoratedType(BottomTypeImpl.instance, never).toFinalType(typeProvider);
+ assertDartType(type, 'Never');
+ }
+
+ test_toFinalType_bottom_nullable() {
+ var type = DecoratedType(BottomTypeImpl.instance, always)
+ .toFinalType(typeProvider);
+ assertDartType(type, 'Null');
+ }
+
+ test_toFinalType_dynamic() {
+ var type = dynamic_.toFinalType(typeProvider);
+ assertDartType(type, 'dynamic');
+ }
+
+ test_toFinalType_function_generic_substitute_bounds() {
+ var u = typeParameter('U', object(node: never));
+ var t = typeParameter(
+ 'T', list(typeParameterType(u, node: never), node: never));
+ var v = typeParameter(
+ 'V', list(typeParameterType(u, node: never), node: never));
+ var type = function(dynamic_, typeFormals: [t, u, v], node: never)
+ .toFinalType(typeProvider) as FunctionType;
+ assertDartType(
+ type,
+ 'dynamic Function<T extends List<U>,U extends Object,'
+ 'V extends List<U>>()');
+ expect(type.typeFormals[0], isNot(same(t)));
+ expect(type.typeFormals[1], isNot(same(u)));
+ expect(type.typeFormals[2], isNot(same(v)));
+ expect(
+ ((type.typeFormals[0].bound as InterfaceType).typeArguments[0]
+ as TypeParameterType)
+ .element,
+ same(type.typeFormals[1]));
+ expect(
+ ((type.typeFormals[2].bound as InterfaceType).typeArguments[0]
+ as TypeParameterType)
+ .element,
+ same(type.typeFormals[1]));
+ }
+
+ test_toFinalType_function_generic_substitute_named() {
+ var t = typeParameter('T', object(node: never));
+ var type = function(dynamic_,
+ typeFormals: [t],
+ named: {'x': list(typeParameterType(t, node: never), node: never)},
+ node: never)
+ .toFinalType(typeProvider) as FunctionType;
+ assertDartType(type, 'dynamic Function<T extends Object>({x: List<T>})');
+ expect(type.typeFormals[0], isNot(same(t)));
+ expect(
+ ((type.parameters[0].type as InterfaceType).typeArguments[0]
+ as TypeParameterType)
+ .element,
+ same(type.typeFormals[0]));
+ }
+
+ test_toFinalType_function_generic_substitute_optional() {
+ var t = typeParameter('T', object(node: never));
+ var type = function(dynamic_,
+ typeFormals: [t],
+ positional: [list(typeParameterType(t, node: never), node: never)],
+ node: never)
+ .toFinalType(typeProvider) as FunctionType;
+ assertDartType(type, 'dynamic Function<T extends Object>([List<T>])');
+ expect(type.typeFormals[0], isNot(same(t)));
+ expect(
+ ((type.parameters[0].type as InterfaceType).typeArguments[0]
+ as TypeParameterType)
+ .element,
+ same(type.typeFormals[0]));
+ }
+
+ test_toFinalType_function_generic_substitute_required() {
+ var t = typeParameter('T', object());
+ var type = function(dynamic_,
+ typeFormals: [t],
+ required: [list(typeParameterType(t, node: never), node: never)],
+ node: never)
+ .toFinalType(typeProvider) as FunctionType;
+ assertDartType(type, 'dynamic Function<T extends Object>(List<T>)');
+ expect(type.typeFormals[0], isNot(same(t)));
+ expect(
+ ((type.parameters[0].type as InterfaceType).typeArguments[0]
+ as TypeParameterType)
+ .element,
+ same(type.typeFormals[0]));
+ }
+
+ test_toFinalType_function_generic_substitute_return_type() {
+ var t = typeParameter('T', object(node: never));
+ var type = function(list(typeParameterType(t, node: never), node: never),
+ typeFormals: [t], node: never)
+ .toFinalType(typeProvider) as FunctionType;
+ assertDartType(type, 'List<T> Function<T extends Object>()');
+ expect(type.typeFormals[0], isNot(same(t)));
+ expect(
+ ((type.returnType as InterfaceType).typeArguments[0]
+ as TypeParameterType)
+ .element,
+ same(type.typeFormals[0]));
+ }
+
+ test_toFinalType_function_named_parameter_non_nullable() {
+ var xType = int_(node: never);
+ var type = function(dynamic_, named: {'x': xType}, node: never)
+ .toFinalType(typeProvider);
+ assertDartType(type, 'dynamic Function({x: int})');
+ }
+
+ test_toFinalType_function_named_parameter_nullable() {
+ var xType = int_(node: always);
+ var type = function(dynamic_, named: {'x': xType}, node: never)
+ .toFinalType(typeProvider);
+ assertDartType(type, 'dynamic Function({x: int?})');
+ }
+
+ test_toFinalType_function_non_nullable() {
+ var type = function(dynamic_, node: never).toFinalType(typeProvider);
+ assertDartType(type, 'dynamic Function()');
+ }
+
+ test_toFinalType_function_nullable() {
+ var type = function(dynamic_, node: always).toFinalType(typeProvider);
+ assertDartType(type, 'dynamic Function()?');
+ }
+
+ test_toFinalType_function_optional_parameter_non_nullable() {
+ var argType = int_(node: never);
+ var type = function(dynamic_, positional: [argType], node: never)
+ .toFinalType(typeProvider);
+ assertDartType(type, 'dynamic Function([int])');
+ }
+
+ test_toFinalType_function_optional_parameter_nullable() {
+ var argType = int_(node: always);
+ var type = function(dynamic_, positional: [argType], node: never)
+ .toFinalType(typeProvider);
+ assertDartType(type, 'dynamic Function([int?])');
+ }
+
+ test_toFinalType_function_required_parameter_non_nullable() {
+ var argType = int_(node: never);
+ var type = function(dynamic_, required: [argType], node: never)
+ .toFinalType(typeProvider);
+ assertDartType(type, 'dynamic Function(int)');
+ }
+
+ test_toFinalType_function_required_parameter_nullable() {
+ var argType = int_(node: always);
+ var type = function(dynamic_, required: [argType], node: never)
+ .toFinalType(typeProvider);
+ assertDartType(type, 'dynamic Function(int?)');
+ }
+
+ test_toFinalType_function_return_type_non_nullable() {
+ var returnType = int_(node: never);
+ var type = function(returnType, node: never).toFinalType(typeProvider);
+ assertDartType(type, 'int Function()');
+ }
+
+ test_toFinalType_function_return_type_nullable() {
+ var returnType = int_(node: always);
+ var type = function(returnType, node: never).toFinalType(typeProvider);
+ assertDartType(type, 'int? Function()');
+ }
+
+ test_toFinalType_interface_non_nullable() {
+ var type = int_(node: never).toFinalType(typeProvider);
+ assertDartType(type, 'int');
+ }
+
+ test_toFinalType_interface_nullable() {
+ var type = int_(node: always).toFinalType(typeProvider);
+ assertDartType(type, 'int?');
+ }
+
+ test_toFinalType_interface_type_argument_non_nullable() {
+ var argType = int_(node: never);
+ var type = list(argType, node: never).toFinalType(typeProvider);
+ assertDartType(type, 'List<int>');
+ }
+
+ test_toFinalType_interface_type_argument_nullable() {
+ var argType = int_(node: always);
+ var type = list(argType, node: never).toFinalType(typeProvider);
+ assertDartType(type, 'List<int?>');
+ }
+
+ test_toFinalType_null_non_nullable() {
+ var type = DecoratedType(null_.type, never).toFinalType(typeProvider);
+ assertDartType(type, 'Never');
+ }
+
+ test_toFinalType_null_nullable() {
+ var type = DecoratedType(null_.type, always).toFinalType(typeProvider);
+ assertDartType(type, 'Null');
+ }
+
+ test_toFinalType_typeParameter_non_nullable() {
+ var t = typeParameter('T', object(node: never));
+ var type = typeParameterType(t, node: never).toFinalType(typeProvider);
+ expect(type, TypeMatcher<TypeParameterType>());
+ assertDartType(type, 'T');
+ }
+
+ test_toFinalType_typeParameter_nullable() {
+ var t = typeParameter('T', object(node: never));
+ var type = typeParameterType(t, node: always).toFinalType(typeProvider);
+ expect(type, TypeMatcher<TypeParameterType>());
+ assertDartType(type, 'T?');
+ }
+
+ test_toFinalType_void() {
+ var type = void_.toFinalType(typeProvider);
+ assertDartType(type, 'void');
+ }
+
test_toString_bottom() {
var node = newNode();
var decoratedType = DecoratedType(BottomTypeImpl.instance, node);
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index e70c987..45fbad0 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -1167,6 +1167,25 @@
hard: true));
}
+ test_binaryExpression_plus_substituted() async {
+ await analyze('''
+class _C<T, U> {
+ T operator+(U u) => throw 'foo';
+}
+Object _f(_C<int, String> c, String s) => c + s;
+''');
+ assertEdge(
+ decoratedTypeAnnotation('String s').node,
+ substitutionNode(decoratedTypeAnnotation('String>').node,
+ decoratedTypeAnnotation('U u').node),
+ hard: true);
+ assertEdge(
+ substitutionNode(decoratedTypeAnnotation('int,').node,
+ decoratedTypeAnnotation('T operator').node),
+ decoratedTypeAnnotation('Object _f').node,
+ hard: false);
+ }
+
test_binaryExpression_questionQuestion() async {
await analyze('''
int f(int i, int j) => i ?? j;
diff --git a/pkg/nnbd_migration/test/migration_visitor_test_base.dart b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
index 4c16e02..91219ff 100644
--- a/pkg/nnbd_migration/test/migration_visitor_test_base.dart
+++ b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
@@ -12,6 +12,7 @@
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/src/conditional_discard.dart';
+import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/edge_builder.dart';
import 'package:nnbd_migration/src/expression_checks.dart';
@@ -135,13 +136,16 @@
}
class EdgeBuilderTestBase extends MigrationVisitorTestBase {
+ DecoratedClassHierarchy decoratedClassHierarchy;
+
/// Analyzes the given source code, producing constraint variables and
/// constraints for it.
@override
Future<CompilationUnit> analyze(String code) async {
var unit = await super.analyze(code);
- unit.accept(EdgeBuilder(
- typeProvider, typeSystem, variables, graph, testSource, null));
+ decoratedClassHierarchy = DecoratedClassHierarchy(variables, graph);
+ unit.accept(EdgeBuilder(typeProvider, typeSystem, variables, graph,
+ testSource, null, decoratedClassHierarchy));
return unit;
}
}
diff --git a/pkg/nnbd_migration/test/node_builder_test.dart b/pkg/nnbd_migration/test/node_builder_test.dart
index a85aed0..16bef49 100644
--- a/pkg/nnbd_migration/test/node_builder_test.dart
+++ b/pkg/nnbd_migration/test/node_builder_test.dart
@@ -1507,7 +1507,7 @@
await analyze('''
void f(int/*?*/ i) {}
''');
- assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
+ assertUnion(always, decoratedTypeAnnotation('int').node);
}
test_type_parameter_explicit_bound() async {
diff --git a/pkg/nnbd_migration/tool/trial_migration.dart b/pkg/nnbd_migration/tool/trial_migration.dart
index f207d07..e2f9af1 100644
--- a/pkg/nnbd_migration/tool/trial_migration.dart
+++ b/pkg/nnbd_migration/tool/trial_migration.dart
@@ -107,7 +107,7 @@
} else if (edit.replacement == "import 'package:meta/meta.dart';\n" &&
edit.length == 0) {
++numMetaImportsAdded;
- } else if (edit.replacement == '@required ' && edit.length == 0) {
+ } else if (edit.replacement == 'required ' && edit.length == 0) {
++numRequiredAnnotationsAdded;
} else if ((edit.replacement == '/* ' ||
edit.replacement == ' /*' ||
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 61c2e71..687c3b0 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -76,6 +76,8 @@
front_end/test/*: SkipByDesign # Only meant to run on vm, most use dart:mirrors and dart:io
front_end/tool/*: SkipByDesign # Only meant to run on vm
modular_test/test/memory_pipeline_test: Slow
+modular_test/test/validate_pipeline_test: Slow
+modular_test/test/validate_suite_test: Slow
nnbd_migration/test/*: SkipByDesign # Uses mirrors
smith/test/*: SkipByDesign # Only meant to run on vm
status_file/test/normalize_test: SkipByDesign # Uses dart:io
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index 5ac46ed..9feb36a 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -590,8 +590,6 @@
bool get _isArm64 => _configuration.architecture == Architecture.arm64;
- bool get _isSimArm64 => _configuration.architecture == Architecture.simarm64;
-
bool get _isX64 => _configuration.architecture == Architecture.x64;
bool get _isIA32 => _configuration.architecture == Architecture.ia32;
@@ -632,6 +630,15 @@
}
}
+ if (_configuration.useElf && _isAndroid) {
+ // On Android, run the NDK's "strip" tool with "--strip-unneeded" to copy
+ // Flutter's workflow. Skip this step on tests for DWARF (which may get
+ // stripped).
+ if (!arguments.last.contains("dwarf")) {
+ commands.add(computeStripCommand(tempDir, environmentOverrides));
+ }
+ }
+
return CommandArtifact(
commands, '$tempDir', 'application/dart-precompiled');
}
@@ -702,27 +709,26 @@
alwaysCompile: !_useSdk);
}
+ static const String ndkPath = "third_party/android_tools/ndk";
+ String get abiTriple => _isArm
+ ? "arm-linux-androideabi"
+ : _isArm64 ? "aarch64-linux-android" : null;
+ String get host =>
+ Platform.isLinux ? "linux" : Platform.isMacOS ? "darwin" : null;
+
Command computeAssembleCommand(String tempDir, List arguments,
Map<String, String> environmentOverrides) {
String cc, shared, ldFlags;
- if (_isAndroid || _isSimArm || _isSimArm64) {
- var ndk = "third_party/android_tools/ndk";
- String triple;
- if (_isArm || _isSimArm) {
- triple = "arm-linux-androideabi";
- } else if (_isArm64 || _isSimArm64) {
- triple = "aarch64-linux-android";
- }
- String host;
- if (Platform.isLinux) {
- host = "linux";
- } else if (Platform.isMacOS) {
- host = "darwin";
- }
- cc = "$ndk/toolchains/$triple-4.9/prebuilt/$host-x86_64/bin/$triple-gcc";
+ if (_isAndroid) {
+ cc = "$ndkPath/toolchains/$abiTriple-4.9/prebuilt/"
+ "$host-x86_64/bin/$abiTriple-gcc";
shared = '-shared';
} else if (Platform.isLinux) {
- cc = 'gcc';
+ if (_isSimArm) {
+ cc = 'arm-linux-gnueabihf-gcc';
+ } else {
+ cc = 'gcc';
+ }
shared = '-shared';
} else if (Platform.isMacOS) {
cc = 'clang';
@@ -764,6 +770,19 @@
alwaysCompile: !_useSdk);
}
+ Command computeStripCommand(
+ String tempDir, Map<String, String> environmentOverrides) {
+ final String stripTool = "$ndkPath/toolchains/$abiTriple-4.9/prebuilt/"
+ "$host-x86_64/bin/$abiTriple-strip";
+ final List<String> args = [
+ '--strip-unneeded',
+ "$tempDir/out.aotsnapshot",
+ ];
+ return CompilationCommand('strip', tempDir, bootstrapDependencies(),
+ stripTool, args, environmentOverrides,
+ alwaysCompile: !_useSdk);
+ }
+
/// Creates a command to clean up large temporary assembly files.
///
/// This step reduces the amount of space needed to run the precompilation
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index 65164f6..f215187 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -33,10 +33,12 @@
show
asFileUri,
compileToKernel,
- parseCommandLineDefines,
convertFileOrUriArgumentToUri,
- createFrontEndTarget,
createFrontEndFileSystem,
+ createFrontEndTarget,
+ forEachPackage,
+ packageFor,
+ parseCommandLineDefines,
runWithFrontEndCompilerContext,
setVMEnvironmentDefines,
writeDepfile;
@@ -341,6 +343,7 @@
compilerOptions.bytecode = options['gen-bytecode'];
final BytecodeOptions bytecodeOptions = new BytecodeOptions(
enableAsserts: options['enable-asserts'],
+ emitSourceFiles: options['embed-source-text'],
environmentDefines: environmentDefines)
..parseCommandLineFlags(options['bytecode-options']);
@@ -549,6 +552,59 @@
}
}
+ bool _elementsIdentical(List a, List b) {
+ if (a.length != b.length) return false;
+ for (int i = 0; i < a.length; i++) {
+ if (!identical(a[i], b[i])) return false;
+ }
+ return true;
+ }
+
+ final _packageLibraries = new Expando();
+ final _packageBytes = new Expando();
+
+ void _writePackage(Component component, String package,
+ List<Library> libraries, IOSink sink) {
+ final canCache = libraries.isNotEmpty &&
+ _compilerOptions.bytecode &&
+ errors.isEmpty &&
+ package != "main";
+
+ if (canCache) {
+ var cachedLibraries = _packageLibraries[libraries.first];
+ if ((cachedLibraries != null) &&
+ _elementsIdentical(cachedLibraries, libraries)) {
+ sink.add(_packageBytes[libraries.first]);
+ return;
+ }
+ }
+
+ Component partComponent = component;
+ if (_compilerOptions.bytecode && errors.isEmpty) {
+ generateBytecode(partComponent,
+ options: _bytecodeOptions,
+ libraries: libraries,
+ coreTypes: _generator.getCoreTypes(),
+ hierarchy: _generator.getClassHierarchy());
+
+ if (_options['drop-ast']) {
+ partComponent = createFreshComponentWithBytecode(partComponent);
+ }
+ }
+
+ final byteSink = new ByteSink();
+ final BinaryPrinter printer = new LimitedBinaryPrinter(byteSink,
+ (lib) => packageFor(lib) == package, false /* excludeUriToSource */);
+ printer.writeComponentFile(partComponent);
+
+ final bytes = byteSink.builder.takeBytes();
+ sink.add(bytes);
+ if (canCache) {
+ _packageLibraries[libraries.first] = libraries;
+ _packageBytes[libraries.first] = bytes;
+ }
+ }
+
@override
Future<Null> recompileDelta({String entryPoint}) async {
final String boundaryKey = new Uuid().generateV4();
@@ -564,8 +620,21 @@
transformer.transform(deltaProgram);
}
final compiledSources = deltaProgram.uriToSource.keys;
- deltaProgram = await _generateBytecodeIfNeeded(deltaProgram);
- await writeDillFile(deltaProgram, _kernelBinaryFilename);
+
+ if (_compilerOptions.bytecode) {
+ final IOSink sink = new File(_kernelBinaryFilename).openWrite();
+ await runWithFrontEndCompilerContext(
+ _mainSource, _compilerOptions, deltaProgram, () async {
+ await forEachPackage(deltaProgram,
+ (String package, List<Library> libraries) async {
+ _writePackage(deltaProgram, package, libraries, sink);
+ });
+ });
+ await sink.close();
+ } else {
+ await writeDillFile(deltaProgram, _kernelBinaryFilename);
+ }
+
_outputStream.writeln(boundaryKey);
await _outputDependenciesDelta(compiledSources);
_outputStream
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 3c71ea3..1a633c6 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -595,28 +595,6 @@
BytecodeOptions bytecodeOptions,
bool dropAST: false,
}) async {
- // Package sharing: make the encoding not depend on the order in which parts
- // of a package are loaded.
- component.libraries.sort((Library a, Library b) {
- return a.importUri.toString().compareTo(b.importUri.toString());
- });
- component.computeCanonicalNames();
- for (Library lib in component.libraries) {
- lib.additionalExports.sort((Reference a, Reference b) {
- return a.canonicalName.toString().compareTo(b.canonicalName.toString());
- });
- }
-
- final packagesSet = new Set<String>();
- for (Library lib in component.libraries) {
- packagesSet.add(packageFor(lib));
- }
- packagesSet.remove('main');
- packagesSet.remove(null);
-
- final List<String> packages = packagesSet.toList();
- packages.add('main'); // Make sure main package is last.
-
if (bytecodeOptions.showBytecodeSizeStatistics) {
BytecodeSizeStatistics.reset();
}
@@ -629,31 +607,24 @@
new ClassHierarchy(component, onAmbiguousSupertypes: (cls, a, b) {});
}
+ final packages = new List<String>();
await runWithFrontEndCompilerContext(source, compilerOptions, component,
() async {
- for (String package in packages) {
+ await forEachPackage(component,
+ (String package, List<Library> libraries) async {
+ packages.add(package);
final String filename = '$outputFileName-$package.dilp';
final IOSink sink = new File(filename).openWrite();
- final main = component.mainMethod;
- final problems = component.problemsAsJson;
- if (package != 'main') {
- component.mainMethod = null;
- component.problemsAsJson = null;
- }
-
Component partComponent = component;
if (genBytecode) {
- final List<Library> libraries = component.libraries
- .where((lib) => packageFor(lib) == package)
- .toList();
- generateBytecode(component,
+ generateBytecode(partComponent,
options: bytecodeOptions,
libraries: libraries,
hierarchy: hierarchy);
if (dropAST) {
- partComponent = createFreshComponentWithBytecode(component);
+ partComponent = createFreshComponentWithBytecode(partComponent);
}
}
@@ -661,11 +632,8 @@
(lib) => packageFor(lib) == package, false /* excludeUriToSource */);
printer.writeComponentFile(partComponent);
- component.mainMethod = main;
- component.problemsAsJson = problems;
-
await sink.close();
- }
+ });
});
if (bytecodeOptions.showBytecodeSizeStatistics) {
@@ -692,6 +660,47 @@
return 'main';
}
+Future<Null> forEachPackage<T>(Component component,
+ T action(String package, List<Library> libraries)) async {
+ // Package sharing: make the encoding not depend on the order in which parts
+ // of a package are loaded.
+ component.libraries.sort((Library a, Library b) {
+ return a.importUri.toString().compareTo(b.importUri.toString());
+ });
+ component.computeCanonicalNames();
+ for (Library lib in component.libraries) {
+ lib.additionalExports.sort((Reference a, Reference b) {
+ return a.canonicalName.toString().compareTo(b.canonicalName.toString());
+ });
+ }
+
+ final packages = new Map<String, List<Library>>();
+ for (Library lib in component.libraries) {
+ packages.putIfAbsent(packageFor(lib), () => new List<Library>()).add(lib);
+ }
+ if (packages.containsKey(null)) {
+ packages.remove(null);
+ }
+ if (packages.containsKey('main')) {
+ // Make sure main package is last.
+ packages['main'] = packages.remove('main');
+ }
+
+ for (String package in packages.keys) {
+ final main = component.mainMethod;
+ final problems = component.problemsAsJson;
+ if (package != 'main') {
+ component.mainMethod = null;
+ component.problemsAsJson = null;
+ }
+
+ await action(package, packages[package]);
+
+ component.mainMethod = main;
+ component.problemsAsJson = problems;
+ }
+}
+
String _escapePath(String path) {
return path.replaceAll('\\', '\\\\').replaceAll(' ', '\\ ');
}
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 68ded73..a5de560 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## 2.1.0
+- Added `HeapSnapshotGraph` class which parses the binary events posted to the
+ `HeapSnapshot` stream after a `requestHeapSnapshot` invocation.
+- Fixed issue where listening to `EventStream.kHeapSnapshot` and calling
+ `requestHeapSnapshot` would throw an exception.
+
## 2.0.0
- **breaking**: VM service objects which have fields now have constructors with
named parameters for each field. Required fields are annotated with `@required`.
diff --git a/pkg/vm_service/lib/src/snapshot_graph.dart b/pkg/vm_service/lib/src/snapshot_graph.dart
new file mode 100644
index 0000000..7265cd4
--- /dev/null
+++ b/pkg/vm_service/lib/src/snapshot_graph.dart
@@ -0,0 +1,373 @@
+// Copyright (c) 2019, 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 'dart:async';
+import 'dart:convert';
+import 'dart:typed_data';
+
+import '../vm_service.dart';
+
+class _ReadStream {
+ final List<ByteData> _chunks;
+ int _chunkIndex = 0;
+ int _byteIndex = 0;
+
+ _ReadStream(this._chunks);
+
+ int readByte() {
+ while (_byteIndex >= _chunks[_chunkIndex].lengthInBytes) {
+ _chunkIndex++;
+ _byteIndex = 0;
+ }
+ return _chunks[_chunkIndex].getUint8(_byteIndex++);
+ }
+
+ /// Read one ULEB128 number.
+ int readUnsigned() {
+ int result = 0;
+ int shift = 0;
+ for (;;) {
+ int part = readByte();
+ result |= (part & 0x7F) << shift;
+ if ((part & 0x80) == 0) {
+ break;
+ }
+ shift += 7;
+ }
+ return result;
+ }
+
+ /// Read one SLEB128 number.
+ int readSigned() {
+ int result = 0;
+ int shift = 0;
+ for (;;) {
+ int part = readByte();
+ result |= (part & 0x7F) << shift;
+ shift += 7;
+ if ((part & 0x80) == 0) {
+ if ((part & 0x40) != 0) {
+ result |= (-1 << shift);
+ }
+ break;
+ }
+ }
+ return result;
+ }
+
+ double readFloat64() {
+ final bytes = Uint8List(8);
+ for (int i = 0; i < 8; i++) {
+ bytes[i] = readByte();
+ }
+ return Float64List.view(bytes.buffer)[0];
+ }
+
+ String readUtf8() {
+ int len = readUnsigned();
+ final bytes = Uint8List(len);
+ for (int i = 0; i < len; i++) {
+ bytes[i] = readByte();
+ }
+ return Utf8Codec(allowMalformed: true).decode(bytes);
+ }
+
+ String readLatin1() {
+ int len = readUnsigned();
+ final codeUnits = Uint8List(len);
+ for (int i = 0; i < len; i++) {
+ codeUnits[i] = readByte();
+ }
+ return String.fromCharCodes(codeUnits);
+ }
+
+ String readUtf16() {
+ int len = readUnsigned();
+ final codeUnits = Uint16List(len);
+ for (int i = 0; i < len; i++) {
+ codeUnits[i] = readByte() | (readByte() << 8);
+ }
+ return String.fromCharCodes(codeUnits);
+ }
+}
+
+/// A representation of a field captured in a memory snapshot.
+class HeapSnapshotField {
+ /// A 0-origin index into [HeapSnapshotObject.references].
+ int get index => _index;
+
+ /// The name of the field.
+ String get name => _name;
+
+ int _index;
+ String _name;
+
+ HeapSnapshotField._read(_ReadStream reader) {
+ // flags (reserved)
+ reader.readUnsigned();
+
+ _index = reader.readUnsigned();
+ _name = reader.readUtf8();
+
+ // reserved
+ reader.readUtf8();
+ }
+}
+
+/// A representation of a class type captured in a memory snapshot.
+class HeapSnapshotClass {
+ /// The simple (not qualified) name of the class.
+ String get name => _name;
+
+ /// The name of the class's library.
+ String get libraryName => _libraryName;
+
+ /// The [Uri] of the class's library.
+ Uri get libraryUri => _libraryUri;
+
+ /// The list of fields in the class.
+ List<HeapSnapshotField> get fields => _fields;
+
+ String _name;
+ String _libraryName;
+ Uri _libraryUri;
+ List<HeapSnapshotField> _fields = <HeapSnapshotField>[];
+
+ HeapSnapshotClass._read(_ReadStream reader) {
+ // flags (reserved).
+ reader.readUnsigned();
+
+ _name = reader.readUtf8();
+ _libraryName = reader.readUtf8();
+ _libraryUri = Uri.parse(reader.readUtf8());
+
+ // reserved
+ reader.readUtf8();
+
+ _populateFields(reader);
+ }
+
+ void _populateFields(_ReadStream reader) {
+ final fieldCount = reader.readUnsigned();
+ for (int i = 0; i < fieldCount; ++i) {
+ _fields.add(HeapSnapshotField._read(reader));
+ }
+ }
+}
+
+/// A representation of an object instance captured in a memory snapshot.
+class HeapSnapshotObject {
+ /// The class ID representing the type of this object.
+ int get classId => _classId;
+
+ /// The space used by this object in bytes.
+ int get shallowSize => _shallowSize;
+
+ /// Data associated with this object.
+ dynamic get data => _data;
+
+ /// A list of 1-origin indicies into [HeapSnapshotGraph.objects].
+ List<int> get references => _references;
+
+ int _classId;
+ int _shallowSize;
+ dynamic _data;
+ List<int> _references = <int>[];
+
+ HeapSnapshotObject._read(_ReadStream reader) {
+ _classId = reader.readUnsigned();
+ _shallowSize = reader.readUnsigned();
+ _data = _getNonReferenceData(reader);
+ _populateReferences(reader);
+ }
+
+ void _populateReferences(_ReadStream reader) {
+ final referencesCount = reader.readUnsigned();
+ for (int i = 0; i < referencesCount; ++i) {
+ _references.add(reader.readUnsigned());
+ }
+ }
+}
+
+/// A representation of an external property captured in a memory snapshot.
+class HeapSnapshotExternalProperty {
+ /// A 1-origin index into [HeapSnapshotGraph.objects].
+ final int object;
+
+ /// The amount of external memory used.
+ final int externalSize;
+
+ /// The name of the external property.
+ final String name;
+
+ HeapSnapshotExternalProperty._read(_ReadStream reader)
+ : object = reader.readUnsigned(),
+ externalSize = reader.readUnsigned(),
+ name = reader.readUtf8();
+}
+
+/// A graph representation of a heap snapshot.
+class HeapSnapshotGraph {
+ /// The name of the isolate represented by this heap snapshot.
+ String get name => _name;
+
+ int get flags => _flags;
+
+ /// The sum of shallow sizes of all objects in this graph in bytes.
+ int get shallowSize => _shallowSize;
+
+ /// The amount of memory reserved for this heap in bytes.
+ ///
+ /// At least as large as [shallowSize].
+ int get capacity => _capacity;
+
+ /// The sum of sizes of all external properties in this graph in bytes.
+ int get externalSize => _externalSize;
+
+ /// The list of classes found in this snapshot.
+ List<HeapSnapshotClass> get classes => _classes;
+
+ /// At least as big as the sum of all [HeapSnapshotObject.referenceCount].
+ int get referenceCount => _referenceCount;
+
+ /// The list of objects found in this snapshot.
+ List<HeapSnapshotObject> get objects => _objects;
+
+ /// The list of external properties found in this snapshot.
+ List<HeapSnapshotExternalProperty> get externalProperties =>
+ _externalProperties;
+
+ String _name;
+ int _flags;
+ int _shallowSize;
+ int _capacity;
+ int _externalSize;
+ List<HeapSnapshotClass> _classes = <HeapSnapshotClass>[];
+ int _referenceCount;
+ List<HeapSnapshotObject> _objects = <HeapSnapshotObject>[];
+ List<HeapSnapshotExternalProperty> _externalProperties =
+ <HeapSnapshotExternalProperty>[];
+
+ /// Requests a heap snapshot for a given isolate and builds a
+ /// [HeapSnapshotGraph].
+ ///
+ /// Note: this method calls [VmService.streamListen] and
+ /// [VmService.streamCancel] on [EventStreams.kHeapSnapshot].
+ static Future<HeapSnapshotGraph> getSnapshot(
+ VmService service, IsolateRef isolate) async {
+ await service.streamListen(EventStreams.kHeapSnapshot);
+
+ final completer = Completer<HeapSnapshotGraph>();
+ final chunks = <ByteData>[];
+ service.onHeapSnapshotEvent.listen((e) async {
+ chunks.add(e.data);
+ if (e.last) {
+ await service.streamCancel(EventStreams.kHeapSnapshot);
+ completer.complete(HeapSnapshotGraph.fromChunks(chunks));
+ }
+ });
+
+ await service.requestHeapSnapshot(isolate.id);
+ return completer.future;
+ }
+
+ /// Populates the [HeapSnapshotGraph] by parsing the events from the
+ /// `HeapSnapshot` stream.
+ HeapSnapshotGraph.fromChunks(List<ByteData> chunks) {
+ final reader = _ReadStream(chunks);
+
+ // Skip magic header
+ for (int i = 0; i < 8; ++i) {
+ reader.readByte();
+ }
+
+ _flags = reader.readUnsigned();
+ _name = reader.readUtf8();
+ _shallowSize = reader.readUnsigned();
+ _capacity = reader.readUnsigned();
+ _externalSize = reader.readUnsigned();
+ _populateClasses(reader);
+ _referenceCount = reader.readUnsigned();
+ _populateObjects(reader);
+ _populateExternalProperties(reader);
+ }
+
+ void _populateClasses(_ReadStream reader) {
+ final classCount = reader.readUnsigned();
+ for (int i = 0; i < classCount; ++i) {
+ _classes.add(HeapSnapshotClass._read(reader));
+ }
+ }
+
+ void _populateObjects(_ReadStream reader) {
+ final objectCount = reader.readUnsigned();
+ for (int i = 0; i < objectCount; ++i) {
+ _objects.add(HeapSnapshotObject._read(reader));
+ }
+ }
+
+ void _populateExternalProperties(_ReadStream reader) {
+ final propertiesCount = reader.readUnsigned();
+ for (int i = 0; i < propertiesCount; ++i) {
+ _externalProperties.add(HeapSnapshotExternalProperty._read(reader));
+ }
+ }
+}
+
+const _kNoData = 0;
+const _kNullData = 1;
+const _kBoolData = 2;
+const _kIntData = 3;
+const _kDoubleData = 4;
+const _kLatin1Data = 5;
+const _kUtf16Data = 6;
+const _kLengthData = 7;
+const _kNameData = 8;
+
+dynamic _getNonReferenceData(_ReadStream reader) {
+ final tag = reader.readUnsigned();
+ switch (tag) {
+ case _kNoData:
+ return const HeapSnapshotObjectNoData();
+ case _kNullData:
+ return const HeapSnapshotObjectNullData();
+ case _kBoolData:
+ return (reader.readByte() == 1);
+ case _kIntData:
+ return reader.readUnsigned();
+ case _kDoubleData:
+ return reader.readFloat64();
+ case _kLatin1Data:
+ final len = reader.readUnsigned();
+ final str = reader.readLatin1();
+ return (str.length < len) ? '$str...' : str;
+ case _kUtf16Data:
+ final len = reader.readUnsigned();
+ final str = reader.readUtf16();
+ return (str.length < len) ? '$str...' : str;
+ return reader.readUtf16();
+ case _kLengthData:
+ return HeapSnapshotObjectLengthData(reader.readUnsigned());
+ case _kNameData:
+ return reader.readUtf8();
+ default:
+ throw 'Invalid tag: $tag';
+ }
+}
+
+/// Represents that no data is associated with an object.
+class HeapSnapshotObjectNoData {
+ const HeapSnapshotObjectNoData();
+}
+
+/// Represents that the data associated with an object is null.
+class HeapSnapshotObjectNullData {
+ const HeapSnapshotObjectNullData();
+}
+
+/// Represents the length of an object.
+class HeapSnapshotObjectLengthData {
+ final int length;
+ HeapSnapshotObjectLengthData(this.length);
+}
diff --git a/pkg/vm_service/lib/vm_service.dart b/pkg/vm_service/lib/vm_service.dart
index 63ab8a8..5133141 100644
--- a/pkg/vm_service/lib/vm_service.dart
+++ b/pkg/vm_service/lib/vm_service.dart
@@ -18,6 +18,16 @@
import 'src/service_extension_registry.dart';
export 'src/service_extension_registry.dart' show ServiceExtensionRegistry;
+export 'src/snapshot_graph.dart'
+ show
+ HeapSnapshotClass,
+ HeapSnapshotExternalProperty,
+ HeapSnapshotField,
+ HeapSnapshotGraph,
+ HeapSnapshotObject,
+ HeapSnapshotObjectLengthData,
+ HeapSnapshotObjectNoData,
+ HeapSnapshotObjectNullData;
const String vmServiceVersion = '3.27.0';
@@ -1736,19 +1746,19 @@
}
void _processMessageByteData(ByteData bytes) {
- int offset = 0;
- int metaSize = bytes.getUint32(offset + 4, Endian.big);
- offset += 8;
- String meta = utf8.decode(
- Uint8List.view(bytes.buffer, bytes.offsetInBytes + offset, metaSize));
- offset += metaSize;
- ByteData data = ByteData.view(bytes.buffer, bytes.offsetInBytes + offset,
- bytes.lengthInBytes - offset);
+ final int metaOffset = 4;
+ final int dataOffset = bytes.getUint32(0, Endian.little);
+ final metaLength = dataOffset - metaOffset;
+ final dataLength = bytes.lengthInBytes - dataOffset;
+ final meta = utf8.decode(Uint8List.view(
+ bytes.buffer, bytes.offsetInBytes + metaOffset, metaLength));
+ final data = ByteData.view(
+ bytes.buffer, bytes.offsetInBytes + dataOffset, dataLength);
dynamic map = jsonDecode(meta);
if (map != null && map['method'] == 'streamNotify') {
String streamId = map['params']['streamId'];
Map event = map['params']['event'];
- event['_data'] = data;
+ event['data'] = data;
_getEventController(streamId)
.add(createServiceObject(event, const ['Event']));
}
@@ -3245,6 +3255,20 @@
@optional
String newValue;
+ /// Specifies whether this event is the last of a group of events.
+ ///
+ /// This is provided for the event kinds:
+ /// - HeapSnapshot
+ @optional
+ bool last;
+
+ /// Binary data associated with the event.
+ ///
+ /// This is provided for the event kinds:
+ /// - HeapSnapshot
+ @optional
+ ByteData data;
+
Event({
@required this.kind,
@required this.timestamp,
@@ -3268,6 +3292,8 @@
this.alias,
this.flag,
this.newValue,
+ this.last,
+ this.data,
});
Event._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
kind = json['kind'];
@@ -3298,6 +3324,8 @@
alias = json['alias'];
flag = json['flag'];
newValue = json['newValue'];
+ last = json['last'];
+ data = json['data'];
}
@override
@@ -3330,6 +3358,8 @@
_setIfNotNull(json, 'alias', alias);
_setIfNotNull(json, 'flag', flag);
_setIfNotNull(json, 'newValue', newValue);
+ _setIfNotNull(json, 'last', last);
+ _setIfNotNull(json, 'data', data);
return json;
}
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index af6597f..c26a959 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -2,7 +2,7 @@
description: >-
A library to communicate with a service implementing the Dart VM
service protocol.
-version: 2.0.0
+version: 2.1.0
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
diff --git a/pkg/vm_service/test/heap_snapshot_graph_test.dart b/pkg/vm_service/test/heap_snapshot_graph_test.dart
new file mode 100644
index 0000000..6fb85dd
--- /dev/null
+++ b/pkg/vm_service/test/heap_snapshot_graph_test.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2019, 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 'dart:async';
+import 'dart:typed_data';
+
+import 'package:vm_service/vm_service.dart';
+import 'package:test/test.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+class Foo {
+ dynamic left;
+ dynamic right;
+}
+
+Foo r;
+
+List lst;
+
+void script() {
+ // Create 3 instances of Foo, with out-degrees
+ // 0 (for b), 1 (for a), and 2 (for staticFoo).
+ r = Foo();
+ var a = Foo();
+ var b = Foo();
+ r.left = a;
+ r.right = b;
+ a.left = b;
+
+ lst = List(2);
+ lst[0] = lst; // Self-loop.
+ // Larger than any other fixed-size list in a fresh heap.
+ lst[1] = List(1234569);
+}
+
+var tests = <IsolateTest>[
+ (VmService service, IsolateRef isolate) async {
+ final snapshotGraph = await HeapSnapshotGraph.getSnapshot(service, isolate);
+ expect(snapshotGraph.name, "main");
+ expect(snapshotGraph.flags, isNotNull);
+ expect(snapshotGraph.objects, isNotNull);
+ expect(snapshotGraph.objects.length > 0, isTrue);
+
+ int actualShallowSize = 0;
+ int actualRefCount = 0;
+ snapshotGraph.objects.forEach((HeapSnapshotObject o) {
+ expect(o.classId >= 0, isTrue);
+ expect(o.data, isNotNull);
+ expect(o.references, isNotNull);
+ actualShallowSize += o.shallowSize;
+ actualRefCount += o.references.length;
+ });
+
+ // Some accounting differences in the VM result in the global shallow size
+ // often being greater than the sum of the object shallow sizes.
+ expect(snapshotGraph.shallowSize >= actualShallowSize, isTrue);
+ expect(snapshotGraph.shallowSize <= snapshotGraph.capacity, isTrue);
+ expect(snapshotGraph.referenceCount >= actualRefCount, isTrue);
+
+ int actualExternalSize = 0;
+ expect(snapshotGraph.externalProperties.length > 0, isTrue);
+ snapshotGraph.externalProperties.forEach((HeapSnapshotExternalProperty e) {
+ actualExternalSize += e.externalSize;
+ expect(e.object >= 0, isTrue);
+ expect(e.name, isNotNull);
+ });
+ expect(snapshotGraph.externalSize, actualExternalSize);
+
+ expect(snapshotGraph.classes.length > 0, isTrue);
+ snapshotGraph.classes.forEach((HeapSnapshotClass c) {
+ expect(c.name, isNotNull);
+ expect(c.libraryName, isNotNull);
+ expect(c.libraryUri, isNotNull);
+ expect(c.fields, isNotNull);
+ });
+ },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 58607c9..6c01c9c 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -55,6 +55,14 @@
import 'src/service_extension_registry.dart';
export 'src/service_extension_registry.dart' show ServiceExtensionRegistry;
+export 'src/snapshot_graph.dart' show HeapSnapshotClass,
+ HeapSnapshotExternalProperty,
+ HeapSnapshotField,
+ HeapSnapshotGraph,
+ HeapSnapshotObject,
+ HeapSnapshotObjectLengthData,
+ HeapSnapshotObjectNoData,
+ HeapSnapshotObjectNullData;
''';
final String _implCode = r'''
@@ -143,20 +151,21 @@
}
void _processMessageByteData(ByteData bytes) {
- int offset = 0;
- int metaSize = bytes.getUint32(offset + 4, Endian.big);
- offset += 8;
- String meta = utf8.decode(Uint8List.view(
- bytes.buffer, bytes.offsetInBytes + offset, metaSize));
- offset += metaSize;
- ByteData data = ByteData.view(bytes.buffer, bytes.offsetInBytes + offset,
- bytes.lengthInBytes - offset);
+ final int metaOffset = 4;
+ final int dataOffset = bytes.getUint32(0, Endian.little);
+ final metaLength = dataOffset - metaOffset;
+ final dataLength = bytes.lengthInBytes - dataOffset;
+ final meta = utf8.decode(Uint8List.view(
+ bytes.buffer, bytes.offsetInBytes + metaOffset, metaLength));
+ final data = ByteData.view(
+ bytes.buffer, bytes.offsetInBytes + dataOffset, dataLength);
dynamic map = jsonDecode(meta);
if (map != null && map['method'] == 'streamNotify') {
String streamId = map['params']['streamId'];
Map event = map['params']['event'];
- event['_data'] = data;
- _getEventController(streamId).add(createServiceObject(event, const ['Event']));
+ event['data'] = data;
+ _getEventController(streamId)
+ .add(createServiceObject(event, const ['Event']));
}
}
@@ -1215,7 +1224,8 @@
name == 'num' ||
name == 'String' ||
name == 'bool' ||
- name == 'double');
+ name == 'double' ||
+ name == 'ByteData');
bool get isListTypeSimple =>
arrayDepth == 1 &&
@@ -1223,7 +1233,8 @@
name == 'num' ||
name == 'String' ||
name == 'bool' ||
- name == 'double');
+ name == 'double' ||
+ name == 'ByteData');
String toString() => ref;
}
@@ -1929,6 +1940,18 @@
expect(';');
}
+ // Special case for Event in order to expose binary response for
+ // HeapSnapshot events.
+ if (type.rawName == 'Event') {
+ final comment = 'Binary data associated with the event.\n\n'
+ 'This is provided for the event kinds:\n - HeapSnapshot';
+ TypeField dataField = TypeField(type, comment);
+ dataField.type.types.add(TypeRef('ByteData'));
+ dataField.name = 'data';
+ dataField.optional = true;
+ type.fields.add(dataField);
+ }
+
expect('}');
}
}
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index a3cc367..41776f5 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -2,7 +2,6 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-import("../build/dart/dart_host_sdk_toolchain.gni")
import("configs.gni")
import("runtime_args.gni")
@@ -67,28 +66,22 @@
config("dart_os_config") {
defines = []
- # If dart_host_toolchain is the current toolchain, and it is different from
- # host_toolchain, then we are building the SDK for the host, and should not
- # hardcode these defines.
- if (current_toolchain != dart_host_toolchain ||
- host_toolchain == dart_host_toolchain) {
- if (target_os == "android") {
- defines += [ "TARGET_OS_ANDROID" ]
- } else if (target_os == "fuchsia") {
- defines += [ "TARGET_OS_FUCHSIA" ]
- } else if (target_os == "ios") {
- defines += [ "TARGET_OS_MACOS" ]
- defines += [ "TARGET_OS_MACOS_IOS" ]
- } else if (target_os == "linux") {
- defines += [ "TARGET_OS_LINUX" ]
- } else if (target_os == "mac") {
- defines += [ "TARGET_OS_MACOS" ]
- } else if (target_os == "win") {
- defines += [ "TARGET_OS_WINDOWS" ]
- } else {
- print("Unknown target_os: $target_os")
- assert(false)
- }
+ if (target_os == "android") {
+ defines += [ "TARGET_OS_ANDROID" ]
+ } else if (target_os == "fuchsia") {
+ defines += [ "TARGET_OS_FUCHSIA" ]
+ } else if (target_os == "ios") {
+ defines += [ "TARGET_OS_MACOS" ]
+ defines += [ "TARGET_OS_MACOS_IOS" ]
+ } else if (target_os == "linux") {
+ defines += [ "TARGET_OS_LINUX" ]
+ } else if (target_os == "mac") {
+ defines += [ "TARGET_OS_MACOS" ]
+ } else if (target_os == "win") {
+ defines += [ "TARGET_OS_WINDOWS" ]
+ } else {
+ print("Unknown target_os: $target_os")
+ assert(false)
}
}
@@ -102,32 +95,26 @@
config("dart_arch_config") {
defines = []
- # If dart_host_toolchain is the current toolchain, and it is different from
- # host_toolchain, then we are building the SDK for the host, and should not
- # hardcode these defines.
- if (current_toolchain != dart_host_toolchain ||
- host_toolchain == dart_host_toolchain) {
- if (dart_target_arch == "arm") {
- defines += [ "TARGET_ARCH_ARM" ]
- } else if (dart_target_arch == "armv6") {
- defines += [ "TARGET_ARCH_ARM" ]
- defines += [ "TARGET_ARCH_ARM_6" ]
- } else if (dart_target_arch == "armv5te") {
- defines += [ "TARGET_ARCH_ARM" ]
- defines += [ "TARGET_ARCH_ARM_5TE" ]
- } else if (dart_target_arch == "arm64") {
- defines += [ "TARGET_ARCH_ARM64" ]
- } else if (dart_target_arch == "x64") {
- defines += [ "TARGET_ARCH_X64" ]
- } else if (dart_target_arch == "ia32" || dart_target_arch == "x86") {
- defines += [ "TARGET_ARCH_IA32" ]
- } else if (dart_target_arch == "dbc") {
- defines += [ "TARGET_ARCH_DBC" ]
- defines += [ "USING_SIMULATOR" ]
- } else {
- print("Invalid dart_target_arch: $dart_target_arch")
- assert(false)
- }
+ if (dart_target_arch == "arm") {
+ defines += [ "TARGET_ARCH_ARM" ]
+ } else if (dart_target_arch == "armv6") {
+ defines += [ "TARGET_ARCH_ARM" ]
+ defines += [ "TARGET_ARCH_ARM_6" ]
+ } else if (dart_target_arch == "armv5te") {
+ defines += [ "TARGET_ARCH_ARM" ]
+ defines += [ "TARGET_ARCH_ARM_5TE" ]
+ } else if (dart_target_arch == "arm64") {
+ defines += [ "TARGET_ARCH_ARM64" ]
+ } else if (dart_target_arch == "x64") {
+ defines += [ "TARGET_ARCH_X64" ]
+ } else if (dart_target_arch == "ia32" || dart_target_arch == "x86") {
+ defines += [ "TARGET_ARCH_IA32" ]
+ } else if (dart_target_arch == "dbc") {
+ defines += [ "TARGET_ARCH_DBC" ]
+ defines += [ "USING_SIMULATOR" ]
+ } else {
+ print("Invalid dart_target_arch: $dart_target_arch")
+ assert(false)
}
}
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 6570f8b..87e6415 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -291,7 +291,10 @@
"$fuchsia_sdk_root/pkg:fdio",
]
} else {
- deps += [ "//sdk/fidl/fuchsia.netstack" ]
+ deps += [
+ "//sdk/fidl/fuchsia.netstack",
+ "//sdk/lib/sys/cpp",
+ ]
public_deps = [
"//zircon/public/lib/fdio",
]
@@ -416,7 +419,10 @@
"$fuchsia_sdk_root/pkg:fdio",
]
} else {
- deps += [ "//sdk/fidl/fuchsia.netstack" ]
+ deps += [
+ "//sdk/fidl/fuchsia.netstack",
+ "//sdk/lib/sys/cpp",
+ ]
public_deps = [
"//zircon/public/lib/fdio",
]
@@ -902,13 +908,12 @@
depfile = "$target_gen_dir/gen_kernel_bytecode.dill.d"
outputs = [
output,
- depfile,
]
script = "../../pkg/vm/bin/gen_kernel.dart"
abs_depfile = rebase_path(depfile)
- rebased_output = rebase_path(output, root_out_dir)
+ rebased_output = rebase_path(output, root_build_dir)
vm_args = [
"--depfile=$abs_depfile",
"--depfile_output_filename=$rebased_output",
diff --git a/runtime/bin/elf_loader.cc b/runtime/bin/elf_loader.cc
index 9672dbe..b74fe3a 100644
--- a/runtime/bin/elf_loader.cc
+++ b/runtime/bin/elf_loader.cc
@@ -224,6 +224,7 @@
bool LoadedElf::LoadSegments() {
// Calculate the total amount of virtual memory needed.
uword total_memory = 0;
+ uword maximum_alignment = PageSize();
for (uword i = 0; i < header_.num_program_headers; ++i) {
const dart::elf::ProgramHeader header = program_table_[i];
@@ -235,13 +236,13 @@
total_memory);
CHECK_ERROR(Utils::IsPowerOfTwo(header.alignment),
"Alignment must be a power of two.");
- CHECK_ERROR(header.alignment <= PageSize(),
- "Cannot align greater than page size.")
+ maximum_alignment =
+ Utils::Maximum(maximum_alignment, static_cast<uword>(header.alignment));
}
total_memory = Utils::RoundUp(total_memory, PageSize());
base_.reset(VirtualMemory::AllocateAligned(
- total_memory, /*alignment=*/PageSize(),
+ total_memory, /*alignment=*/maximum_alignment,
/*is_executable=*/false, /*mapping name=*/filename_.get()));
CHECK_ERROR(base_ != nullptr, "Could not reserve virtual memory.");
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index d7a2a4e..b497db8 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -745,8 +745,8 @@
isolate_flags.entry_points = no_entry_points;
}
- auto isolate_group_data =
- new IsolateGroupData(nullptr, nullptr, nullptr, nullptr, false);
+ auto isolate_group_data = std::unique_ptr<IsolateGroupData>(
+ new IsolateGroupData(nullptr, nullptr, nullptr, nullptr, false));
Dart_Isolate isolate;
char* error = NULL;
if (isolate_snapshot_data == NULL) {
@@ -755,17 +755,17 @@
isolate_flags.load_vmservice_library = true;
isolate = Dart_CreateIsolateGroupFromKernel(
NULL, NULL, kernel_buffer, kernel_buffer_size, &isolate_flags,
- isolate_group_data, /*isolate_data=*/nullptr, &error);
+ isolate_group_data.get(), /*isolate_data=*/nullptr, &error);
} else {
isolate = Dart_CreateIsolateGroup(NULL, NULL, isolate_snapshot_data,
isolate_snapshot_instructions, NULL, NULL,
- &isolate_flags, isolate_group_data,
+ &isolate_flags, isolate_group_data.get(),
/*isolate_data=*/nullptr, &error);
}
if (isolate == NULL) {
- delete isolate_group_data;
Syslog::PrintErr("%s\n", error);
free(error);
+ free(kernel_buffer);
return kErrorExitCode;
}
@@ -827,6 +827,8 @@
Dart_ExitScope();
Dart_ShutdownIsolate();
+
+ free(kernel_buffer);
return 0;
}
diff --git a/runtime/lib/wasm.cc b/runtime/lib/wasm.cc
index a94aac9..0094e6b 100644
--- a/runtime/lib/wasm.cc
+++ b/runtime/lib/wasm.cc
@@ -85,6 +85,54 @@
}
}
+static Dart_Handle ToWasmValue(Dart_Handle value,
+ wasmer_value_tag type,
+ wasmer_value* out) {
+ switch (type) {
+ case wasmer_value_tag::WASM_I32: {
+ int64_t i64;
+ Dart_Handle result = Dart_IntegerToInt64(value, &i64);
+ out->I32 = i64;
+ if (out->I32 != i64) {
+ return Dart_NewApiError("Int doesn't fit into 32-bits");
+ }
+ return result;
+ }
+ case wasmer_value_tag::WASM_I64:
+ return Dart_IntegerToInt64(value, &out->I64);
+ case wasmer_value_tag::WASM_F32: {
+ double f64;
+ Dart_Handle result = Dart_DoubleValue(value, &f64);
+ out->F32 = f64;
+ return result;
+ }
+ case wasmer_value_tag::WASM_F64:
+ return Dart_DoubleValue(value, &out->F64);
+ default:
+ FATAL("Unknown WASM type");
+ return nullptr;
+ }
+}
+
+static bool ToWasmValueTag(classid_t type, wasmer_value_tag* out) {
+ switch (type) {
+ case kWasmInt32Cid:
+ *out = wasmer_value_tag::WASM_I32;
+ return true;
+ case kWasmInt64Cid:
+ *out = wasmer_value_tag::WASM_I64;
+ return true;
+ case kWasmFloatCid:
+ *out = wasmer_value_tag::WASM_F32;
+ return true;
+ case kWasmDoubleCid:
+ *out = wasmer_value_tag::WASM_F64;
+ return true;
+ default:
+ return false;
+ }
+}
+
static RawObject* ToDartObject(wasmer_value_t ret) {
switch (ret.tag) {
case wasmer_value_tag::WASM_I32:
@@ -101,6 +149,22 @@
}
}
+static Dart_Handle ToDartApiObject(wasmer_value value, wasmer_value_tag type) {
+ switch (type) {
+ case wasmer_value_tag::WASM_I32:
+ return Dart_NewInteger(value.I32);
+ case wasmer_value_tag::WASM_I64:
+ return Dart_NewInteger(value.I64);
+ case wasmer_value_tag::WASM_F32:
+ return Dart_NewDouble(value.F32);
+ case wasmer_value_tag::WASM_F64:
+ return Dart_NewDouble(value.F64);
+ default:
+ FATAL("Unknown WASM type");
+ return nullptr;
+ }
+}
+
RawExternalTypedData* WasmMemoryToExternalTypedData(wasmer_memory_t* memory) {
uint8_t* data = wasmer_memory_data(memory);
uint32_t size = wasmer_memory_data_length(memory);
@@ -158,52 +222,174 @@
return String::New(desc.str().c_str());
}
+class WasmImports;
+
+struct WasmFunctionImport {
+ WasmImports* imports;
+ std::unique_ptr<wasmer_value_tag[]> args;
+ intptr_t num_args;
+ wasmer_value_tag ret;
+ intptr_t num_rets;
+ int64_t fn_id;
+ wasmer_import_func_t* wasm_fn;
+ wasmer_trampoline_buffer_t* buffer;
+ WasmFunctionImport(WasmImports* imports_,
+ std::unique_ptr<wasmer_value_tag[]> args_,
+ intptr_t num_args_,
+ wasmer_value_tag ret_,
+ intptr_t num_rets_,
+ int64_t fn_id_)
+ : imports(imports_),
+ args(std::move(args_)),
+ num_args(num_args_),
+ ret(ret_),
+ num_rets(num_rets_),
+ fn_id(fn_id_),
+ wasm_fn(nullptr),
+ buffer(nullptr) {}
+ ~WasmFunctionImport() {
+ wasmer_trampoline_buffer_destroy(buffer);
+ wasmer_import_func_destroy(wasm_fn);
+ }
+};
+
+extern "C" {
+int64_t Trampoline(void* context, int64_t* args);
+}
+
class WasmImports {
public:
- explicit WasmImports(std::unique_ptr<char[]> module_name)
- : _module_name(std::move(module_name)) {}
+ WasmImports() {}
~WasmImports() {
for (wasmer_global_t* global : _globals) {
wasmer_global_destroy(global);
}
+ for (WasmFunctionImport* fn_imp : _functions) {
+ delete fn_imp;
+ }
for (const char* name : _import_names) {
delete[] name;
}
}
+ void SetHandle(FinalizablePersistentHandle* handle) { _handle = handle; }
size_t NumImports() const { return _imports.length(); }
wasmer_import_t* RawImports() { return _imports.data(); }
- void AddMemory(std::unique_ptr<char[]> name, wasmer_memory_t* memory) {
- AddImport(std::move(name), wasmer_import_export_kind::WASM_MEMORY)->memory =
- memory;
+ void AddMemory(std::unique_ptr<char[]> module_name,
+ std::unique_ptr<char[]> name,
+ wasmer_memory_t* memory) {
+ AddImport(std::move(module_name), std::move(name),
+ wasmer_import_export_kind::WASM_MEMORY)
+ ->memory = memory;
}
- void AddGlobal(std::unique_ptr<char[]> name,
+ void AddGlobal(std::unique_ptr<char[]> module_name,
+ std::unique_ptr<char[]> name,
wasmer_value_t value,
bool mutable_) {
wasmer_global_t* global = wasmer_global_new(value, mutable_);
_globals.Add(global);
- AddImport(std::move(name), wasmer_import_export_kind::WASM_GLOBAL)->global =
- global;
+ AddImport(std::move(module_name), std::move(name),
+ wasmer_import_export_kind::WASM_GLOBAL)
+ ->global = global;
+ }
+
+ void AddFunction(std::unique_ptr<char[]> module_name,
+ std::unique_ptr<char[]> name,
+ int64_t fn_id,
+ std::unique_ptr<wasmer_value_tag[]> args,
+ intptr_t num_args,
+ wasmer_value_tag ret,
+ intptr_t num_rets) {
+ // Trampoline args include the context pointer.
+ const intptr_t num_trampoline_args = num_args + 1;
+
+ WasmFunctionImport* fn_imp = new WasmFunctionImport(
+ this, std::move(args), num_args, ret, num_rets, fn_id);
+ _functions.Add(fn_imp);
+
+ wasmer_trampoline_buffer_builder_t* builder =
+ wasmer_trampoline_buffer_builder_new();
+ uintptr_t trampoline_id =
+ wasmer_trampoline_buffer_builder_add_callinfo_trampoline(
+ builder,
+ reinterpret_cast<wasmer_trampoline_callable_t*>(Trampoline),
+ reinterpret_cast<void*>(fn_imp), num_trampoline_args);
+ fn_imp->buffer = wasmer_trampoline_buffer_builder_build(builder);
+
+ const wasmer_trampoline_callable_t* trampoline =
+ wasmer_trampoline_buffer_get_trampoline(fn_imp->buffer, trampoline_id);
+ fn_imp->wasm_fn = wasmer_import_func_new(
+ reinterpret_cast<void (*)(void*)>(
+ const_cast<wasmer_trampoline_callable_t*>(trampoline)),
+ fn_imp->args.get(), num_args, &ret, num_rets);
+
+ AddImport(std::move(module_name), std::move(name),
+ wasmer_import_export_kind::WASM_FUNCTION)
+ ->func = fn_imp->wasm_fn;
+ }
+
+ int64_t CallImportedFunction(WasmFunctionImport* fn_imp, int64_t* raw_args) {
+ wasmer_value* wasm_args = reinterpret_cast<wasmer_value*>(raw_args);
+ Dart_Handle inst = Dart_HandleFromWeakPersistent(_handle->apiHandle());
+ Dart_Handle dart_args[2] = {
+ inst,
+ Dart_NewInteger(fn_imp->fn_id),
+ };
+ Dart_Handle closure = Dart_Invoke(Dart_InstanceGetType(inst),
+ Dart_NewStringFromCString("getFunction"),
+ ARRAY_SIZE(dart_args), dart_args);
+ if (Dart_IsError(closure)) {
+ Dart_ThrowException(closure);
+ UNREACHABLE();
+ }
+ Dart_Handle result;
+ {
+ auto args =
+ std::unique_ptr<Dart_Handle[]>(new Dart_Handle[fn_imp->num_args]);
+ for (intptr_t i = 0; i < fn_imp->num_args; ++i) {
+ args[i] = ToDartApiObject(wasm_args[i], fn_imp->args[i]);
+ }
+ result = Dart_InvokeClosure(closure, fn_imp->num_args, args.get());
+ }
+ if (Dart_IsError(result)) {
+ Dart_ThrowException(result);
+ UNREACHABLE();
+ }
+ if (fn_imp->num_rets == 0) {
+ // Wasmer ignores the result of this function if it expects no results,
+ // so skip the converters below (we get errors if we run them).
+ return 0;
+ }
+ wasmer_value wasm_result;
+ result = ToWasmValue(result, fn_imp->ret, &wasm_result);
+ if (Dart_IsError(result)) {
+ Dart_ThrowException(result);
+ UNREACHABLE();
+ }
+ return wasm_result.I64;
}
private:
- std::unique_ptr<char[]> _module_name;
+ FinalizablePersistentHandle* _handle;
MallocGrowableArray<const char*> _import_names;
MallocGrowableArray<wasmer_global_t*> _globals;
+ MallocGrowableArray<WasmFunctionImport*> _functions;
MallocGrowableArray<wasmer_import_t> _imports;
- wasmer_import_export_value* AddImport(std::unique_ptr<char[]> name,
+ wasmer_import_export_value* AddImport(std::unique_ptr<char[]> module_name,
+ std::unique_ptr<char[]> name,
wasmer_import_export_kind tag) {
wasmer_import_t import;
import.module_name.bytes =
- reinterpret_cast<const uint8_t*>(_module_name.get());
- import.module_name.bytes_len = (uint32_t)strlen(_module_name.get());
+ reinterpret_cast<const uint8_t*>(module_name.get());
+ import.module_name.bytes_len = (uint32_t)strlen(module_name.get());
import.import_name.bytes = reinterpret_cast<const uint8_t*>(name.get());
import.import_name.bytes_len = (uint32_t)strlen(name.get());
import.tag = tag;
+ _import_names.Add(module_name.release());
_import_names.Add(name.release());
_imports.Add(import);
return &_imports.Last().value;
@@ -212,6 +398,14 @@
DISALLOW_COPY_AND_ASSIGN(WasmImports);
};
+extern "C" {
+int64_t Trampoline(void* context, int64_t* args) {
+ WasmFunctionImport* fn_imp = reinterpret_cast<WasmFunctionImport*>(context);
+ // Skip the first arg (it's another context pointer).
+ return fn_imp->imports->CallImportedFunction(fn_imp, args + 1);
+}
+}
+
class WasmFunction {
public:
WasmFunction(MallocGrowableArray<classid_t> args,
@@ -459,25 +653,26 @@
return DescribeModule(module);
}
-DEFINE_NATIVE_ENTRY(Wasm_initImports, 0, 2) {
+DEFINE_NATIVE_ENTRY(Wasm_initImports, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, imp_wrap, arguments->NativeArgAt(0));
- GET_NON_NULL_NATIVE_ARGUMENT(String, module_name, arguments->NativeArgAt(1));
ASSERT(imp_wrap.NumNativeFields() == 1);
- WasmImports* imports = new WasmImports(ToUTF8(module_name));
+ WasmImports* imports = new WasmImports();
imp_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(imports));
- FinalizablePersistentHandle::New(thread->isolate(), imp_wrap, imports,
- Finalize<WasmImports>, sizeof(WasmImports));
+ imports->SetHandle(FinalizablePersistentHandle::New(
+ thread->isolate(), imp_wrap, imports, Finalize<WasmImports>,
+ sizeof(WasmImports)));
return Object::null();
}
-DEFINE_NATIVE_ENTRY(Wasm_addMemoryImport, 0, 3) {
+DEFINE_NATIVE_ENTRY(Wasm_addMemoryImport, 0, 4) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, imp_wrap, arguments->NativeArgAt(0));
- GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, mem_wrap, arguments->NativeArgAt(2));
+ GET_NON_NULL_NATIVE_ARGUMENT(String, module_name, arguments->NativeArgAt(1));
+ GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(2));
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, mem_wrap, arguments->NativeArgAt(3));
ASSERT(imp_wrap.NumNativeFields() == 1);
ASSERT(mem_wrap.NumNativeFields() == 1);
@@ -487,17 +682,18 @@
wasmer_memory_t* memory =
reinterpret_cast<wasmer_memory_t*>(mem_wrap.GetNativeField(0));
- imports->AddMemory(ToUTF8(name), memory);
+ imports->AddMemory(ToUTF8(module_name), ToUTF8(name), memory);
return Object::null();
}
-DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 5) {
+DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 6) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, imp_wrap, arguments->NativeArgAt(0));
- GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
- GET_NON_NULL_NATIVE_ARGUMENT(Number, value, arguments->NativeArgAt(2));
- GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(3));
- GET_NON_NULL_NATIVE_ARGUMENT(Bool, mutable_, arguments->NativeArgAt(4));
+ GET_NON_NULL_NATIVE_ARGUMENT(String, module_name, arguments->NativeArgAt(1));
+ GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(2));
+ GET_NON_NULL_NATIVE_ARGUMENT(Number, value, arguments->NativeArgAt(3));
+ GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(4));
+ GET_NON_NULL_NATIVE_ARGUMENT(Bool, mutable_, arguments->NativeArgAt(5));
ASSERT(imp_wrap.NumNativeFields() == 1);
@@ -505,12 +701,62 @@
reinterpret_cast<WasmImports*>(imp_wrap.GetNativeField(0));
wasmer_value_t wasm_value;
if (!ToWasmValue(value, type.type_class_id(), &wasm_value)) {
- Exceptions::ThrowArgumentError(String::Handle(String::NewFormatted(
- "Can't convert dart value to WASM global variable")));
+ Exceptions::ThrowArgumentError(String::Handle(
+ zone, String::NewFormatted(
+ "Can't convert dart value to WASM global variable")));
UNREACHABLE();
}
- imports->AddGlobal(ToUTF8(name), wasm_value, mutable_.value());
+ imports->AddGlobal(ToUTF8(module_name), ToUTF8(name), wasm_value,
+ mutable_.value());
+
+ return Object::null();
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_addFunctionImport, 0, 5) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, imp_wrap, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(String, module_name, arguments->NativeArgAt(1));
+ GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(2));
+ GET_NON_NULL_NATIVE_ARGUMENT(Integer, fn_id, arguments->NativeArgAt(3));
+ GET_NON_NULL_NATIVE_ARGUMENT(Type, fn_type, arguments->NativeArgAt(4));
+
+ ASSERT(imp_wrap.NumNativeFields() == 1);
+
+ Function& sig = Function::Handle(zone, fn_type.signature());
+
+ classid_t ret = AbstractType::Handle(zone, sig.result_type()).type_class_id();
+ intptr_t num_rets = ret == kWasmVoidCid ? 0 : 1;
+ wasmer_value_tag wasm_ret = wasmer_value_tag::WASM_I64;
+ if (num_rets != 0) {
+ if (!ToWasmValueTag(ret, &wasm_ret)) {
+ Exceptions::ThrowArgumentError(String::Handle(
+ zone, String::NewFormatted("Return type is not a valid WASM type")));
+ UNREACHABLE();
+ }
+ }
+
+ Array& args = Array::Handle(zone, sig.parameter_types());
+ AbstractType& arg_type = AbstractType::Handle(zone);
+ intptr_t first_arg_index = sig.NumImplicitParameters();
+ intptr_t num_args = args.Length() - first_arg_index;
+ auto wasm_args =
+ std::unique_ptr<wasmer_value_tag[]>(new wasmer_value_tag[num_args]);
+ for (intptr_t i = 0; i < num_args; ++i) {
+ arg_type ^= args.At(i + first_arg_index);
+ classid_t dart_arg = arg_type.type_class_id();
+ if (!ToWasmValueTag(dart_arg, &wasm_args[i])) {
+ wasm_args.reset();
+ Exceptions::ThrowArgumentError(String::Handle(
+ zone, String::NewFormatted(
+ "Type of arg %" Pd " is not a valid WASM type", i)));
+ UNREACHABLE();
+ }
+ }
+
+ WasmImports* imports =
+ reinterpret_cast<WasmImports*>(imp_wrap.GetNativeField(0));
+ imports->AddFunction(ToUTF8(module_name), ToUTF8(name), fn_id.AsInt64Value(),
+ std::move(wasm_args), num_args, wasm_ret, num_rets);
return Object::null();
}
@@ -610,15 +856,16 @@
String& error = String::Handle(zone);
{
- Function& sig = Function::Handle(fn_type.signature());
- Array& args = Array::Handle(sig.parameter_types());
+ Function& sig = Function::Handle(zone, fn_type.signature());
+ Array& args = Array::Handle(zone, sig.parameter_types());
+ AbstractType& arg_type = AbstractType::Handle(zone);
MallocGrowableArray<classid_t> dart_args;
for (intptr_t i = sig.NumImplicitParameters(); i < args.Length(); ++i) {
- dart_args.Add(
- AbstractType::Cast(Object::Handle(args.At(i))).type_class_id());
+ arg_type ^= args.At(i);
+ dart_args.Add(arg_type.type_class_id());
}
classid_t dart_ret =
- AbstractType::Handle(sig.result_type()).type_class_id();
+ AbstractType::Handle(zone, sig.result_type()).type_class_id();
std::unique_ptr<char[]> name_raw = ToUTF8(name);
fn = inst->GetFunction(name_raw.get(), dart_args, dart_ret, &error);
@@ -643,19 +890,21 @@
WasmFunction* fn = reinterpret_cast<WasmFunction*>(fn_wrap.GetNativeField(0));
if (args.Length() != fn->args().length()) {
- Exceptions::ThrowArgumentError(String::Handle(String::NewFormatted(
- "Wrong number of args. Expected %" Pu " but found %" Pd ".",
- fn->args().length(), args.Length())));
+ Exceptions::ThrowArgumentError(String::Handle(
+ zone, String::NewFormatted("Wrong number of args. Expected %" Pu
+ " but found %" Pd ".",
+ fn->args().length(), args.Length())));
UNREACHABLE();
}
auto params = std::unique_ptr<wasmer_value_t[]>(
new wasmer_value_t[fn->args().length()]);
+ Number& arg_num = Number::Handle(zone);
for (intptr_t i = 0; i < args.Length(); ++i) {
- if (!ToWasmValue(Number::Cast(Object::Handle(args.At(i))), fn->args()[i],
- ¶ms[i])) {
+ arg_num ^= args.At(i);
+ if (!ToWasmValue(arg_num, fn->args()[i], ¶ms[i])) {
params.reset();
Exceptions::ThrowArgumentError(String::Handle(
- String::NewFormatted("Arg %" Pd " is the wrong type.", i)));
+ zone, String::NewFormatted("Arg %" Pd " is the wrong type.", i)));
UNREACHABLE();
}
}
@@ -694,17 +943,22 @@
return nullptr;
}
-DEFINE_NATIVE_ENTRY(Wasm_initImports, 0, 2) {
+DEFINE_NATIVE_ENTRY(Wasm_initImports, 0, 1) {
Exceptions::ThrowUnsupportedError("WASM is disabled");
return nullptr;
}
-DEFINE_NATIVE_ENTRY(Wasm_addMemoryImport, 0, 3) {
+DEFINE_NATIVE_ENTRY(Wasm_addMemoryImport, 0, 4) {
Exceptions::ThrowUnsupportedError("WASM is disabled");
return nullptr;
}
-DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 5) {
+DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 6) {
+ Exceptions::ThrowUnsupportedError("WASM is disabled");
+ return nullptr;
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_addFunctionImport, 0, 5) {
Exceptions::ThrowUnsupportedError("WASM is disabled");
return nullptr;
}
diff --git a/runtime/tools/dartfuzz/dartfuzz.dart b/runtime/tools/dartfuzz/dartfuzz.dart
index 56730f1..21f0a79 100644
--- a/runtime/tools/dartfuzz/dartfuzz.dart
+++ b/runtime/tools/dartfuzz/dartfuzz.dart
@@ -9,12 +9,12 @@
import 'dartfuzz_values.dart';
import 'dartfuzz_api_table.dart';
-import 'dartfuzz_ffiapi.dart';
+import 'dartfuzz_ffi_api.dart';
// Version of DartFuzz. Increase this each time changes are made
// to preserve the property that a given version of DartFuzz yields
// the same fuzzed program for a deterministic random seed.
-const String version = '1.52';
+const String version = '1.53';
// Restriction on statements and expressions.
const int stmtDepth = 1;
@@ -542,13 +542,18 @@
emit('X${classFields.length - 1}().run()');
}, () {
emitLn("print('X${classFields.length - 1}().run() throws');");
- }, finallyBody: () {
- emitLn("print('", newline: false);
+ });
+
+ emitTryCatchFinally(() {
+ emit("print('", newline: false);
for (int i = 0; i < globalVars.length; i++) {
emit('\$$varName$i\\n');
}
- emit("');", newline: true);
+ emit("')");
+ }, () {
+ emitLn("print('print throws');");
});
+
indent -= 2;
emitLn('}');
}
diff --git a/runtime/tools/dartfuzz/dartfuzz_ffiapi.dart b/runtime/tools/dartfuzz/dartfuzz_ffi_api.dart
similarity index 100%
rename from runtime/tools/dartfuzz/dartfuzz_ffiapi.dart
rename to runtime/tools/dartfuzz/dartfuzz_ffi_api.dart
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 336163a..f3ae235 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -393,9 +393,10 @@
V(TransferableTypedData_materialize, 1) \
V(Wasm_initModule, 2) \
V(Wasm_describeModule, 1) \
- V(Wasm_initImports, 2) \
- V(Wasm_addMemoryImport, 3) \
- V(Wasm_addGlobalImport, 5) \
+ V(Wasm_initImports, 1) \
+ V(Wasm_addMemoryImport, 4) \
+ V(Wasm_addGlobalImport, 6) \
+ V(Wasm_addFunctionImport, 5) \
V(Wasm_initMemory, 3) \
V(Wasm_growMemory, 2) \
V(Wasm_initInstance, 3) \
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index c142b3f..80df237 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1323,6 +1323,13 @@
return kLegacy;
}
+Variance KernelReaderHelper::ReadVariance() {
+ if (translation_helper_.info().kernel_binary_version() >= 34) {
+ return reader_.ReadVariance();
+ }
+ return kCovariant;
+}
+
void StreamingFlowGraphBuilder::loop_depth_inc() {
++flow_graph_builder_->loop_depth_;
}
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index a6b9762..d089309 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -163,6 +163,11 @@
CalculateListOfExpressionsFingerprint();
helper.SetJustRead(TypeParameterHelper::kAnnotations);
+ helper.ReadUntilExcluding(TypeParameterHelper::kVariance);
+ Variance variance = ReadVariance();
+ BuildHash(variance);
+ helper.SetJustRead(TypeParameterHelper::kVariance);
+
helper.ReadUntilExcluding(TypeParameterHelper::kBound);
// The helper isn't needed after this point.
CalculateDartTypeFingerprint();
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index eb23c65..e5b6bf2 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -911,6 +911,9 @@
case kAnnotations:
helper_->SkipListOfExpressions(); // read annotations.
break;
+ case kVariance:
+ helper_->ReadVariance();
+ break;
case kName:
name_index_ = helper_->ReadStringReference(); // read name index.
break;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 6187caa..b8152f4 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -317,6 +317,7 @@
kStart, // tag.
kFlags,
kAnnotations,
+ kVariance,
kName,
kBound,
kDefaultType,
@@ -1087,6 +1088,7 @@
Tag ReadTag(uint8_t* payload = NULL);
uint8_t ReadFlags() { return reader_.ReadFlags(); }
Nullability ReadNullability();
+ Variance ReadVariance();
intptr_t SourceTableSize();
intptr_t GetOffsetForSourceInfo(intptr_t index);
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 3af03f5..848564d 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -15,8 +15,8 @@
V(::, identical, ObjectIdentical, 0xc6e9467a) \
V(ClassID, getID, ClassIDgetID, 0xf0376ced) \
V(Object, Object., ObjectConstructor, 0x8f3ae7ea) \
- V(List, ., ListFactory, 0xd834242d) \
- V(_List, ., ObjectArrayAllocate, 0xe9c6d2be) \
+ V(List, ., ListFactory, 0xda0d774c) \
+ V(_List, ., ObjectArrayAllocate, 0x704c8d5d) \
V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 0xa24c2704) \
V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 0xa491df3e) \
V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 0xb65ae1fc) \
@@ -69,8 +69,8 @@
V(_Double, _sub, DoubleSub, 0x6d3cec71) \
V(_Double, _mul, DoubleMul, 0x648e67af) \
V(_Double, _div, DoubleDiv, 0x6d72d7d4) \
- V(::, min, MathMin, 0x07168bf9) \
- V(::, max, MathMax, 0xc7dbc9a0) \
+ V(::, min, MathMin, 0x3ccbc098) \
+ V(::, max, MathMax, 0x4e398e7f) \
V(::, _doublePow, MathDoublePow, 0x5ae04e61) \
V(::, _intPow, MathIntPow, 0x569ffd3f) \
V(Float32x4, Float32x4., Float32x4Constructor, 0xdf9f0693) \
@@ -143,8 +143,8 @@
V(::, _classRangeCheck, ClassRangeCheck, 0xca52e30a) \
V(::, _asyncStackTraceHelper, AsyncStackTraceHelper, 0xaeaed5cb) \
V(::, _abi, FfiAbi, 0xf2e89620) \
- V(::, _asFunctionInternal, FfiAsFunctionInternal, 0x82525e9e) \
- V(::, _nativeCallbackFunction, FfiNativeCallbackFunction, 0x591fb33c) \
+ V(::, _asFunctionInternal, FfiAsFunctionInternal, 0x92a67518) \
+ V(::, _nativeCallbackFunction, FfiNativeCallbackFunction, 0x59cc5edb) \
// List of intrinsics:
// (class-name, function-name, intrinsification method, fingerprint).
@@ -177,7 +177,7 @@
V(_Double, get:isNegative, Double_getIsNegative, 0xb15ff274) \
V(_Double, _mulFromInteger, Double_mulFromInteger, 0xe2853768) \
V(_Double, .fromInteger, DoubleFromInteger, 0x89504536) \
- V(_GrowableList, ._withData, GrowableArray_Allocate, 0x55981e03) \
+ V(_GrowableList, ._withData, GrowableArray_Allocate, 0x57717122) \
V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, 0xb961fc8d) \
V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, 0xb22daf53) \
V(Object, ==, ObjectEquals, 0x91ead0d6) \
@@ -404,9 +404,9 @@
// (factory-name-symbol, class-name-string, constructor-name-string,
// result-cid, fingerprint).
#define RECOGNIZED_LIST_FACTORY_LIST(V) \
- V(_ListFactory, _List, ., kArrayCid, 0xe9c6d2be) \
+ V(_ListFactory, _List, ., kArrayCid, 0x704c8d5d) \
V(_GrowableListWithData, _GrowableList, ._withData, kGrowableObjectArrayCid, \
- 0x55981e03) \
+ 0x57717122) \
V(_GrowableListFactory, _GrowableList, ., kGrowableObjectArrayCid, \
0x3eed680b) \
V(_Int8ArrayFactory, Int8List, ., kTypedDataInt8ArrayCid, 0x6ce2f102) \
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index fc85292..e78124c 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -65,6 +65,14 @@
DECLARE_FLAG(bool, trace_service);
DECLARE_FLAG(bool, warn_on_pause_with_no_debugger);
+// TODO(bkonyi): remove this flag around Nov 2019 after UX studies are
+// complete. See issue 38535.
+DEFINE_FLAG(int,
+ object_id_ring_size,
+ ObjectIdRing::kDefaultCapacity,
+ "(EXPERIMENTAL) Manually set the size of the service protocol's "
+ "object ID ring buffer. Set to be removed by Nov 2019.");
+
// Reload flags.
DECLARE_FLAG(int, reload_every);
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
@@ -1296,7 +1304,12 @@
#ifndef PRODUCT
if (FLAG_support_service) {
- ObjectIdRing::Init(result);
+ if (FLAG_object_id_ring_size != ObjectIdRing::kDefaultCapacity) {
+ OS::Print(
+ "WARNING: this flag is temporary, is not supported, and should"
+ " only be used for UX studies. Use at your own risk!\n");
+ }
+ ObjectIdRing::Init(result, FLAG_object_id_ring_size);
}
#endif // !PRODUCT
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 03415ac..2ed72dd 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,7 +20,7 @@
// Both version numbers are inclusive.
static const uint32_t kMinSupportedKernelFormatVersion = 18;
-static const uint32_t kMaxSupportedKernelFormatVersion = 33;
+static const uint32_t kMaxSupportedKernelFormatVersion = 34;
// Keep in sync with package:kernel/lib/binary/tag.dart
#define KERNEL_TAG_LIST(V) \
@@ -170,6 +170,14 @@
kLegacy = 3,
};
+// Keep in sync with package:kernel/lib/ast.dart
+enum Variance {
+ kUnrelated = 0,
+ kCovariant = 1,
+ kContravariant = 2,
+ kInvariant = 3,
+};
+
static const int SpecializedIntLiteralBias = 3;
static const int LibraryCountFieldCountFromEnd = 1;
static const int SourceTableFieldCountFromFirstLibraryOffset = 6;
@@ -332,6 +340,11 @@
return static_cast<Nullability>(byte);
}
+ Variance ReadVariance() {
+ uint8_t byte = ReadByte();
+ return static_cast<Variance>(byte);
+ }
+
void EnsureEnd() {
if (offset_ != size_) {
FATAL2(
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index c37a63f..25b08e9 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1854,6 +1854,12 @@
// This is provided for the event kinds:
// VMFlagUpdate
String newValue [optional];
+
+ // Specifies whether this event is the last of a group of events.
+ //
+ // This is provided for the event kinds:
+ // HeapSnapshot
+ bool last [optional];
}
```
diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart
index 7601485..0a5e478 100644
--- a/sdk/lib/_http/http_headers.dart
+++ b/sdk/lib/_http/http_headers.dart
@@ -255,7 +255,7 @@
}
ContentType get contentType {
- var values = _headers["content-type"];
+ var values = _headers[HttpHeaders.contentTypeHeader];
if (values != null) {
return ContentType.parse(values[0]);
} else {
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index cdf2412..46611c0 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -261,7 +261,7 @@
if (hostList != null) {
host = hostList.first;
} else {
- hostList = headers['host'];
+ hostList = headers[HttpHeaders.hostHeader];
if (hostList != null) {
host = hostList.first;
} else {
@@ -840,7 +840,9 @@
_HttpResponse(Uri uri, String protocolVersion, _HttpOutgoing outgoing,
HttpHeaders defaultHeaders, String serverHeader)
: super(uri, protocolVersion, outgoing, initialHeaders: defaultHeaders) {
- if (serverHeader != null) headers.set('server', serverHeader);
+ if (serverHeader != null) {
+ headers.set(HttpHeaders.serverHeader, serverHeader);
+ }
}
bool get _isConnectionClosed => _httpRequest._httpConnection._isClosing;
@@ -865,7 +867,7 @@
Future redirect(Uri location, {int status: HttpStatus.movedTemporarily}) {
if (_outgoing.headersWritten) throw new StateError("Header already sent");
statusCode = status;
- headers.set("location", location.toString());
+ headers.set(HttpHeaders.locationHeader, location.toString());
return close();
}
@@ -1704,7 +1706,7 @@
..port = port
.._add(HttpHeaders.acceptEncodingHeader, "gzip");
if (_httpClient.userAgent != null) {
- request.headers._add('user-agent', _httpClient.userAgent);
+ request.headers._add(HttpHeaders.userAgentHeader, _httpClient.userAgent);
}
if (proxy.isAuthenticated) {
// If the proxy configuration contains user information use that
diff --git a/sdk/lib/_http/http_parser.dart b/sdk/lib/_http/http_parser.dart
index bd85b2b..f0444c2 100644
--- a/sdk/lib/_http/http_parser.dart
+++ b/sdk/lib/_http/http_parser.dart
@@ -658,11 +658,11 @@
} else {
String headerField = new String.fromCharCodes(_headerField);
String headerValue = new String.fromCharCodes(_headerValue);
- if (headerField == "transfer-encoding" &&
+ if (headerField == HttpHeaders.transferEncodingHeader &&
_caseInsensitiveCompare("chunked".codeUnits, _headerValue)) {
_chunked = true;
}
- if (headerField == "connection") {
+ if (headerField == HttpHeaders.connectionHeader) {
List<String> tokens = _tokenizeFieldValue(headerValue);
final bool isResponse = _messageType == _MessageType.RESPONSE;
final bool isUpgradeCode =
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index fd82931..f581bd8 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
@@ -94,7 +94,11 @@
// more compact that the inlined expansion.
@pragma('dart2js:noInline')
Object setRuntimeTypeInfo(Object target, var rti) {
- assert(rti == null || isJsArray(rti));
+ if (JS_GET_FLAG('USE_NEW_RTI')) {
+ assert(rti != null);
+ } else {
+ assert(rti == null || isJsArray(rti));
+ }
String rtiName = JS_GET_NAME(JsGetName.RTI_NAME);
JS('var', r'#[#] = #', target, rtiName, rti);
return target;
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index 15d13e2..dba3d2a 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -1207,9 +1207,17 @@
static Object typeRules(universe) =>
JS('', '#.#', universe, RtiUniverseFieldNames.typeRules);
- static Object findRule(universe, String targetType) =>
+ static Object _findRule(universe, String targetType) =>
JS('', '#.#', typeRules(universe), targetType);
+ static Object findRule(universe, String targetType) {
+ Object rule = _findRule(universe, targetType);
+ while (_Utils.isString(rule)) {
+ rule = _findRule(universe, _Utils.asString(rule));
+ }
+ return rule;
+ }
+
static void addRules(universe, rules) {
// TODO(fishythefish): Use `Object.assign()` when IE11 is deprecated.
var keys = JS('JSArray', 'Object.keys(#)', rules);
diff --git a/sdk/lib/_internal/vm/lib/wasm_patch.dart b/sdk/lib/_internal/vm/lib/wasm_patch.dart
index 1637384..5ae21c4 100644
--- a/sdk/lib/_internal/vm/lib/wasm_patch.dart
+++ b/sdk/lib/_internal/vm/lib/wasm_patch.dart
@@ -45,8 +45,8 @@
@patch
class WasmImports {
@patch
- factory WasmImports(String moduleName) {
- return _NativeWasmImports(moduleName);
+ factory WasmImports() {
+ return _NativeWasmImports();
}
}
@@ -66,24 +66,42 @@
class _NativeWasmImports extends NativeFieldWrapperClass1
implements WasmImports {
List<WasmMemory> _memories;
+ List<Function> _fns;
- _NativeWasmImports(String moduleName) : _memories = [] {
- _init(moduleName);
+ _NativeWasmImports()
+ : _memories = [],
+ _fns = [] {
+ _init();
}
- void addMemory(String name, WasmMemory memory) {
+ void addMemory(String moduleName, String name, WasmMemory memory) {
_memories.add(memory);
- _addMemory(name, memory);
+ _addMemory(moduleName, name, memory);
}
- void addGlobal<T>(String name, num value, bool mutable) {
- _addGlobal(name, value, T, mutable);
+ void addGlobal<T>(String moduleName, String name, num value, bool mutable) {
+ _addGlobal(moduleName, name, value, T, mutable);
}
- void _init(String moduleName) native 'Wasm_initImports';
- void _addMemory(String name, WasmMemory memory) native 'Wasm_addMemoryImport';
- void _addGlobal(String name, num value, Type type, bool mutable)
- native 'Wasm_addGlobalImport';
+ void addFunction<T extends Function>(
+ String moduleName, String name, Function fn) {
+ int id = _fns.length;
+ _fns.add(fn);
+ _addFunction(moduleName, name, id, T);
+ }
+
+ @pragma("vm:entry-point")
+ static Function getFunction(_NativeWasmImports imp, int id) {
+ return imp._fns[id];
+ }
+
+ void _init() native 'Wasm_initImports';
+ void _addMemory(String moduleName, String name, WasmMemory memory)
+ native 'Wasm_addMemoryImport';
+ void _addGlobal(String moduleName, String name, num value, Type type,
+ bool mutable) native 'Wasm_addGlobalImport';
+ void _addFunction(String moduleName, String name, int id, Type type)
+ native 'Wasm_addFunctionImport';
}
class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {
diff --git a/sdk/lib/wasm/wasm.dart b/sdk/lib/wasm/wasm.dart
index 9fe5ba1..f5814ca 100644
--- a/sdk/lib/wasm/wasm.dart
+++ b/sdk/lib/wasm/wasm.dart
@@ -38,13 +38,17 @@
// WasmImports holds all the imports for a WasmInstance.
abstract class WasmImports {
// Create an imports object.
- external factory WasmImports(String moduleName);
+ external factory WasmImports();
// Add a global variable to the imports.
- void addGlobal<T>(String name, num value, bool mutable);
+ void addGlobal<T>(String moduleName, String name, num value, bool mutable);
// Add a memory to the imports.
- void addMemory(String name, WasmMemory memory);
+ void addMemory(String moduleName, String name, WasmMemory memory);
+
+ // Add a function to the imports.
+ void addFunction<T extends Function>(
+ String moduleName, String name, Function fn);
}
// WasmMemory is a sandbox for a WasmInstance to run in.
diff --git a/sdk_nnbd/lib/_http/http_headers.dart b/sdk_nnbd/lib/_http/http_headers.dart
index 58fe2af..f383790 100644
--- a/sdk_nnbd/lib/_http/http_headers.dart
+++ b/sdk_nnbd/lib/_http/http_headers.dart
@@ -257,7 +257,7 @@
}
ContentType get contentType {
- var values = _headers["content-type"];
+ var values = _headers[HttpHeaders.contentTypeHeader];
if (values != null) {
return ContentType.parse(values[0]);
} else {
diff --git a/sdk_nnbd/lib/_http/http_impl.dart b/sdk_nnbd/lib/_http/http_impl.dart
index 9741981..dbbddb6 100644
--- a/sdk_nnbd/lib/_http/http_impl.dart
+++ b/sdk_nnbd/lib/_http/http_impl.dart
@@ -263,7 +263,7 @@
if (hostList != null) {
host = hostList.first;
} else {
- hostList = headers['host'];
+ hostList = headers[HttpHeaders.hostHeader];
if (hostList != null) {
host = hostList.first;
} else {
@@ -842,7 +842,9 @@
_HttpResponse(Uri uri, String protocolVersion, _HttpOutgoing outgoing,
HttpHeaders defaultHeaders, String serverHeader)
: super(uri, protocolVersion, outgoing, initialHeaders: defaultHeaders) {
- if (serverHeader != null) headers.set('server', serverHeader);
+ if (serverHeader != null) {
+ headers.set(HttpHeaders.serverHeader, serverHeader);
+ }
}
bool get _isConnectionClosed => _httpRequest._httpConnection._isClosing;
@@ -867,7 +869,7 @@
Future redirect(Uri location, {int status: HttpStatus.movedTemporarily}) {
if (_outgoing.headersWritten) throw new StateError("Header already sent");
statusCode = status;
- headers.set("location", location.toString());
+ headers.set(HttpHeaders.locationHeader, location.toString());
return close();
}
@@ -1706,7 +1708,7 @@
..port = port
.._add(HttpHeaders.acceptEncodingHeader, "gzip");
if (_httpClient.userAgent != null) {
- request.headers._add('user-agent', _httpClient.userAgent);
+ request.headers._add(HttpHeaders.userAgentHeader, _httpClient.userAgent);
}
if (proxy.isAuthenticated) {
// If the proxy configuration contains user information use that
diff --git a/sdk_nnbd/lib/_http/http_parser.dart b/sdk_nnbd/lib/_http/http_parser.dart
index f3c619d..bc5623b 100644
--- a/sdk_nnbd/lib/_http/http_parser.dart
+++ b/sdk_nnbd/lib/_http/http_parser.dart
@@ -660,11 +660,11 @@
} else {
String headerField = new String.fromCharCodes(_headerField);
String headerValue = new String.fromCharCodes(_headerValue);
- if (headerField == "transfer-encoding" &&
+ if (headerField == HttpHeaders.transferEncodingHeader &&
_caseInsensitiveCompare("chunked".codeUnits, _headerValue)) {
_chunked = true;
}
- if (headerField == "connection") {
+ if (headerField == HttpHeaders.connectionHeader) {
List<String> tokens = _tokenizeFieldValue(headerValue);
final bool isResponse = _messageType == _MessageType.RESPONSE;
final bool isUpgradeCode =
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_rti.dart
index 9487c0d..2f06cbc 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_rti.dart
@@ -96,7 +96,11 @@
// more compact that the inlined expansion.
@pragma('dart2js:noInline')
Object setRuntimeTypeInfo(Object target, var rti) {
- assert(rti == null || isJsArray(rti));
+ if (JS_GET_FLAG('USE_NEW_RTI')) {
+ assert(rti != null);
+ } else {
+ assert(rti == null || isJsArray(rti));
+ }
String rtiName = JS_GET_NAME(JsGetName.RTI_NAME);
JS('var', r'#[#] = #', target, rtiName, rti);
return target;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
index 67f1d0b..f74d8dd 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
@@ -1209,9 +1209,17 @@
static Object typeRules(universe) =>
JS('', '#.#', universe, RtiUniverseFieldNames.typeRules);
- static Object findRule(universe, String targetType) =>
+ static Object _findRule(universe, String targetType) =>
JS('', '#.#', typeRules(universe), targetType);
+ static Object findRule(universe, String targetType) {
+ Object rule = _findRule(universe, targetType);
+ while (_Utils.isString(rule)) {
+ rule = _findRule(universe, _Utils.asString(rule));
+ }
+ return rule;
+ }
+
static void addRules(universe, rules) {
// TODO(fishythefish): Use `Object.assign()` when IE11 is deprecated.
var keys = JS('JSArray', 'Object.keys(#)', rules);
diff --git a/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
index 8339229..df3e33e 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
@@ -47,8 +47,8 @@
@patch
class WasmImports {
@patch
- factory WasmImports(String moduleName) {
- return _NativeWasmImports(moduleName);
+ factory WasmImports() {
+ return _NativeWasmImports();
}
}
@@ -68,24 +68,42 @@
class _NativeWasmImports extends NativeFieldWrapperClass1
implements WasmImports {
List<WasmMemory> _memories;
+ List<Function> _fns;
- _NativeWasmImports(String moduleName) : _memories = [] {
- _init(moduleName);
+ _NativeWasmImports()
+ : _memories = [],
+ _fns = [] {
+ _init();
}
- void addMemory(String name, WasmMemory memory) {
+ void addMemory(String moduleName, String name, WasmMemory memory) {
_memories.add(memory);
- _addMemory(name, memory);
+ _addMemory(moduleName, name, memory);
}
- void addGlobal<T>(String name, num value, bool mutable) {
- _addGlobal(name, value, T, mutable);
+ void addGlobal<T>(String moduleName, String name, num value, bool mutable) {
+ _addGlobal(moduleName, name, value, T, mutable);
}
- void _init(String moduleName) native 'Wasm_initImports';
- void _addMemory(String name, WasmMemory memory) native 'Wasm_addMemoryImport';
- void _addGlobal(String name, num value, Type type, bool mutable)
- native 'Wasm_addGlobalImport';
+ void addFunction<T extends Function>(
+ String moduleName, String name, Function fn) {
+ int id = _fns.length;
+ _fns.add(fn);
+ _addFunction(moduleName, name, id, T);
+ }
+
+ @pragma("vm:entry-point")
+ static Function getFunction(_NativeWasmImports imp, int id) {
+ return imp._fns[id];
+ }
+
+ void _init() native 'Wasm_initImports';
+ void _addMemory(String moduleName, String name, WasmMemory memory)
+ native 'Wasm_addMemoryImport';
+ void _addGlobal(String moduleName, String name, num value, Type type,
+ bool mutable) native 'Wasm_addGlobalImport';
+ void _addFunction(String moduleName, String name, int id, Type type)
+ native 'Wasm_addFunctionImport';
}
class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {
diff --git a/sdk_nnbd/lib/core/function.dart b/sdk_nnbd/lib/core/function.dart
index 6c0462b..7c34bf5 100644
--- a/sdk_nnbd/lib/core/function.dart
+++ b/sdk_nnbd/lib/core/function.dart
@@ -47,23 +47,26 @@
/**
* Test whether another object is equal to this function.
*
- * System-created function objects are only equal to other functions.
+ * Function objects are only equal to other function objects
+ * (an object satisfying `object is Function`),
+ * and never to non-function objects.
*
- * Two function objects are known to represent the same function if
+ * Some function objects are considered equal by `==`
+ * because they are recognized as representing the "same function":
*
* - It is the same object. Static and top-level functions are compile time
* constants when used as values, so referring to the same function twice
- * always give the same object,
- * - or if they refer to the same member method extracted from the same object.
- * Extracting a member method as a function value twice gives equal, but
- * not necessarily identical, function values.
+ * always give the same object, as does referring to a local function
+ * declaration twice in the same scope where it was declared.
+ * - if they refer to the same member method extracted from the same object.
+ * Repeatedly extracting an instance method of an object as a function value
+ * gives equal, but not necessarily identical, function values.
*
- * Function expressions never give rise to equal function objects. Each time
- * a function expression is evaluated, it creates a new closure value that
- * is not known to be equal to other closures created by the same expression.
- *
- * Classes implementing `Function` by having a `call` method should have their
- * own `operator==` and `hashCode` depending on the object.
+ * Different evaluations of function literals
+ * never give rise to equal function objects.
+ * Each time a function literal is evaluated,
+ * it creates a new function value that is not equal to any other function
+ * value, not even ones created by the same expression.
*/
bool operator ==(Object other);
}
diff --git a/sdk_nnbd/lib/wasm/wasm.dart b/sdk_nnbd/lib/wasm/wasm.dart
index 3830d56..4394189 100644
--- a/sdk_nnbd/lib/wasm/wasm.dart
+++ b/sdk_nnbd/lib/wasm/wasm.dart
@@ -40,13 +40,17 @@
// WasmImports holds all the imports for a WasmInstance.
abstract class WasmImports {
// Create an imports object.
- external factory WasmImports(String moduleName);
+ external factory WasmImports();
// Add a global variable to the imports.
- void addGlobal<T>(String name, num value, bool mutable);
+ void addGlobal<T>(String moduleName, String name, num value, bool mutable);
// Add a memory to the imports.
- void addMemory(String name, WasmMemory memory);
+ void addMemory(String moduleName, String name, WasmMemory memory);
+
+ // Add a function to the imports.
+ void addFunction<T extends Function>(
+ String moduleName, String name, Function fn);
}
// WasmMemory is a sandbox for a WasmInstance to run in.
diff --git a/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart b/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
index 664916f..ad98f03 100644
--- a/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
+++ b/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
@@ -153,11 +153,17 @@
c1b.m1 += 0;
// ^^
// [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
+ // ^^
+ // [cfe] unspecified
+ // ^^
// [cfe] unspecified
c1b.m1++;
// ^^
// [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
+ // ^^
+ // [cfe] unspecified
+ // ^^
// [cfe] unspecified
c1b.m2;
@@ -165,7 +171,6 @@
// [analyzer] COMPILE_TIME_ERROR.AMBIGUOUS_EXTENSION_MEMBER_ACCESS
// [cfe] unspecified
-
c1b[0];
// ^^
// [analyzer] unspecified
@@ -179,11 +184,17 @@
c1b[0] += 0;
// ^^
// [analyzer] unspecified
+ // ^
+ // [cfe] unspecified
+ // ^
// [cfe] unspecified
c1b[0]++;
// ^^
// [analyzer] unspecified
+ // ^
+ // [cfe] unspecified
+ // ^
// [cfe] unspecified
}
diff --git a/tests/language_2/extension_methods/static_extension_internal_name_conflict_error_test.dart b/tests/language_2/extension_methods/static_extension_internal_name_conflict_error_test.dart
index 0e55982..6e4ebdfb 100644
--- a/tests/language_2/extension_methods/static_extension_internal_name_conflict_error_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_name_conflict_error_test.dart
@@ -112,23 +112,18 @@
static int method() => 0;
// ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
- // [cfe] unspecified
static int get property => 1;
// ^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
- // [cfe] unspecified
static void set property(int value) {}
// ^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
- // [cfe] unspecified
static int get property2 => 1;
// ^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
- // [cfe] unspecified
static void set property3(int x) {}
// ^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
- // [cfe] unspecified
static int field = 3;
// ^^^^^
// [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
@@ -136,15 +131,28 @@
static int field2 = 3;
// ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
- // [cfe] unspecified
int method() => 0;
+ // ^^^^^^
+ // [cfe] unspecified
int get property => 1;
+ // ^^^^^^^^
+ // [cfe] unspecified
void set property(int value) {}
+ // ^^^^^^^^
+ // [cfe] unspecified
void set property2(int value) {}
+ // ^^^^^^^^^
+ // [cfe] unspecified
int get property3 => 1;
+ // ^^^^^^^^^
+ // [cfe] unspecified
void set field(int value) {}
+ // ^^^^^
+ // [cfe] unspecified
int get field2 => 1;
+ // ^^^^^^
+ // [cfe] unspecified
}
// Check a static method colliding with a static getter.
@@ -159,6 +167,8 @@
// Check a static method colliding with a static setter.
extension E7 on int {
static int method() => 0;
+ // ^^^^^^
+ // [cfe] unspecified
static void set method(int value) {}
// ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
@@ -197,8 +207,9 @@
static int method() => 0;
// ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
- // [cfe] unspecified
int get method => 1;
+ // ^^^^^^
+ // [cfe] unspecified
}
// Check a static method colliding with an instance setter.
@@ -206,8 +217,9 @@
static int method() => 0;
// ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
- // [cfe] unspecified
void set method(int value) {}
+ // ^^^^^^
+ // [cfe] unspecified
}
// Check an instance method colliding with a static getter.
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 097b176..8aadd79 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -2,6 +2,7 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
html/cross_frame_test: Skip # Issue 32039, test reloads itself (not by design - investigate)
+wasm/*: Skip # dart:wasm is currently behind a Dart SDK build flag.
[ $arch == simarm64 ]
convert/utf85_test: Skip # Pass, Slow Issue 20111.
diff --git a/tests/lib_2/wasm/basic_test.dart b/tests/lib_2/wasm/basic_test.dart
index 34ae182..4ab1e7c 100644
--- a/tests/lib_2/wasm/basic_test.dart
+++ b/tests/lib_2/wasm/basic_test.dart
@@ -20,9 +20,9 @@
0x7e, 0x0b,
]);
- var inst = WasmModule(data).instantiate(WasmImports("env")
- ..addMemory("memory", WasmMemory(256, 1024))
- ..addGlobal<Int32>("__memory_base", 1024, false));
+ var inst = WasmModule(data).instantiate(WasmImports()
+ ..addMemory("env", "memory", WasmMemory(256, 1024))
+ ..addGlobal<Int32>("env", "__memory_base", 1024, false));
var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
int n = fn.call([1234]);
diff --git a/tests/lib_2/wasm/fn_call_error_test.dart b/tests/lib_2/wasm/fn_call_error_test.dart
index e1d2441..db696d7 100644
--- a/tests/lib_2/wasm/fn_call_error_test.dart
+++ b/tests/lib_2/wasm/fn_call_error_test.dart
@@ -20,9 +20,9 @@
0x7e, 0x0b,
]);
- var inst = WasmModule(data).instantiate(WasmImports("env")
- ..addMemory("memory", WasmMemory(256, 1024))
- ..addGlobal<Int32>("__memory_base", 1024, false));
+ var inst = WasmModule(data).instantiate(WasmImports()
+ ..addMemory("env", "memory", WasmMemory(256, 1024))
+ ..addGlobal<Int32>("env", "__memory_base", 1024, false));
var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
Expect.throwsArgumentError(() => fn.call([]));
diff --git a/tests/lib_2/wasm/fn_import_error_test.dart b/tests/lib_2/wasm/fn_import_error_test.dart
new file mode 100644
index 0000000..40466fb
--- /dev/null
+++ b/tests/lib_2/wasm/fn_import_error_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test errors thrown by function imports.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+ // This module expects a function import like:
+ // int64_t someFn(int32_t a, int64_t b, float c, double d);
+ var data = Uint8List.fromList([
+ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x02, 0x60,
+ 0x04, 0x7f, 0x7e, 0x7d, 0x7c, 0x01, 0x7e, 0x60, 0x00, 0x00, 0x02, 0x0e,
+ 0x01, 0x03, 0x65, 0x6e, 0x76, 0x06, 0x73, 0x6f, 0x6d, 0x65, 0x46, 0x6e,
+ 0x00, 0x00, 0x03, 0x02, 0x01, 0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01,
+ 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41,
+ 0x80, 0x88, 0x04, 0x0b, 0x07, 0x11, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f,
+ 0x72, 0x79, 0x02, 0x00, 0x04, 0x62, 0x6c, 0x61, 0x68, 0x00, 0x01, 0x0a,
+ 0x1d, 0x01, 0x1b, 0x00, 0x41, 0x01, 0x42, 0x02, 0x43, 0x00, 0x00, 0x40,
+ 0x40, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x10, 0x80,
+ 0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b,
+ ]);
+
+ var mod = WasmModule(data);
+ var imp = WasmImports()
+ ..addFunction<Int64 Function(Int32, Int64, Float, Double)>(
+ "env", "someFn", (num a, num b, num c, num d) => 123);
+ mod.instantiate(imp);
+
+ imp = WasmImports();
+ Expect.throwsArgumentError(() => mod.instantiate(imp));
+
+ imp = WasmImports()
+ ..addFunction<Int64 Function(Int32)>("env", "someFn", (num a) => 123);
+ Expect.throwsArgumentError(() => mod.instantiate(imp));
+
+ imp = WasmImports()
+ ..addFunction<Double Function(Int32, Int64, Float, Double)>(
+ "env", "someFn", (num a, num b, num c, num d) => 123);
+ Expect.throwsArgumentError(() => mod.instantiate(imp));
+
+ imp = WasmImports()
+ ..addFunction<Int64 Function(Int32, Int64, Float, Float)>(
+ "env", "someFn", (num a, num b, num c, num d) => 123);
+ Expect.throwsArgumentError(() => mod.instantiate(imp));
+
+ Expect.throwsArgumentError(() => WasmImports()
+ ..addFunction<dynamic Function(Int32, Int64, Float, Double)>(
+ "env", "someFn", (num a, num b, num c, num d) => 123));
+
+ Expect.throwsArgumentError(() => WasmImports()
+ ..addFunction<Int64 Function(Int32, Int64, dynamic, Double)>(
+ "env", "someFn", (num a, num b, num c, num d) => 123));
+
+ imp = WasmImports()..addGlobal<Int64>("env", "someFn", 123, false);
+ Expect.throwsArgumentError(() => mod.instantiate(imp));
+}
diff --git a/tests/lib_2/wasm/fn_import_exception_test.dart b/tests/lib_2/wasm/fn_import_exception_test.dart
new file mode 100644
index 0000000..73298d9
--- /dev/null
+++ b/tests/lib_2/wasm/fn_import_exception_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test throwing exceptions from an imported function.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+ // int64_t fn(int64_t x) { return throwIfNegative(x); }
+ var data = Uint8List.fromList([
+ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
+ 0x01, 0x7e, 0x01, 0x7e, 0x02, 0x17, 0x01, 0x03, 0x65, 0x6e, 0x76, 0x0f,
+ 0x74, 0x68, 0x72, 0x6f, 0x77, 0x49, 0x66, 0x4e, 0x65, 0x67, 0x61, 0x74,
+ 0x69, 0x76, 0x65, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01,
+ 0x70, 0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01,
+ 0x7f, 0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x0f, 0x02, 0x06, 0x6d,
+ 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x02, 0x66, 0x6e, 0x00, 0x01,
+ 0x0a, 0x0c, 0x01, 0x0a, 0x00, 0x20, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80,
+ 0x00, 0x0b,
+ ]);
+
+ dynamic override = null;
+ var inst = WasmModule(data).instantiate(WasmImports()
+ ..addMemory("env", "memory", WasmMemory(256, 1024))
+ ..addGlobal<Int32>("env", "__memory_base", 1024, false)
+ ..addFunction<Int64 Function(Int64)>("env", "throwIfNegative", (int x) {
+ if (x < 0) {
+ throw Exception(x);
+ }
+ if (override != null) {
+ return override;
+ }
+ return x;
+ }));
+ var fn = inst.lookupFunction<Int64 Function(Int64)>("fn");
+
+ Expect.equals(123, fn.call([123]));
+ Expect.throws(() => fn.call([-456]), (Exception e) => "$e".contains("-456"));
+
+ override = "Not an integer";
+ Expect.throwsArgumentError(() => fn.call([789]));
+ override = 0.123;
+ Expect.throwsArgumentError(() => fn.call([789]));
+}
diff --git a/tests/lib_2/wasm/fn_import_test.dart b/tests/lib_2/wasm/fn_import_test.dart
new file mode 100644
index 0000000..8172c20
--- /dev/null
+++ b/tests/lib_2/wasm/fn_import_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that we can load a wasm module, find a function, and call it.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+ // void reportStuff() { report(123, 456); }
+ var data = Uint8List.fromList([
+ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x60,
+ 0x02, 0x7e, 0x7e, 0x00, 0x60, 0x00, 0x00, 0x02, 0x0e, 0x01, 0x03, 0x65,
+ 0x6e, 0x76, 0x06, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x03,
+ 0x02, 0x01, 0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01, 0x01, 0x05, 0x03,
+ 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41, 0x80, 0x88, 0x04,
+ 0x0b, 0x07, 0x18, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02,
+ 0x00, 0x0b, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x75, 0x66,
+ 0x66, 0x00, 0x01, 0x0a, 0x10, 0x01, 0x0e, 0x00, 0x42, 0xfb, 0x00, 0x42,
+ 0xc8, 0x03, 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, 0x0b,
+ ]);
+
+ int report_x = -1;
+ int report_y = -1;
+
+ var inst = WasmModule(data).instantiate(WasmImports()
+ ..addMemory("env", "memory", WasmMemory(256, 1024))
+ ..addGlobal<Int32>("env", "__memory_base", 1024, false)
+ ..addFunction<Void Function(Int64, Int64)>("env", "report", (int x, int y) {
+ report_x = x;
+ report_y = y;
+ }));
+ var fn = inst.lookupFunction<Void Function()>("reportStuff");
+ fn.call([]);
+ Expect.equals(report_x, 123);
+ Expect.equals(report_y, 456);
+}
diff --git a/tests/lib_2/wasm/fn_mismatch_error_test.dart b/tests/lib_2/wasm/fn_mismatch_error_test.dart
index b12d515..01e825b 100644
--- a/tests/lib_2/wasm/fn_mismatch_error_test.dart
+++ b/tests/lib_2/wasm/fn_mismatch_error_test.dart
@@ -20,9 +20,9 @@
0x7e, 0x0b,
]);
- var inst = WasmModule(data).instantiate(WasmImports("env")
- ..addMemory("memory", WasmMemory(256, 1024))
- ..addGlobal<Int32>("__memory_base", 1024, false));
+ var inst = WasmModule(data).instantiate(WasmImports()
+ ..addMemory("env", "memory", WasmMemory(256, 1024))
+ ..addGlobal<Int32>("env", "__memory_base", 1024, false));
Expect.isNotNull(inst.lookupFunction<Int64 Function(Int64)>("square"));
Expect.throwsArgumentError(
() => inst.lookupFunction<Int64 Function(Int64)>("blah"));
diff --git a/tests/lib_2/wasm/import_error_test.dart b/tests/lib_2/wasm/import_error_test.dart
new file mode 100644
index 0000000..071dc4b
--- /dev/null
+++ b/tests/lib_2/wasm/import_error_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test errors thrown by WasmImports.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+ var imp = WasmImports();
+ Expect.throwsArgumentError(() => imp.addGlobal<int>("env", "a", 1, true));
+ Expect.throwsArgumentError(() => imp.addGlobal<double>("env", "b", 2, true));
+ Expect.throwsArgumentError(() => imp.addGlobal<dynamic>("env", "c", 3, true));
+}
diff --git a/tests/lib_2/wasm/memory_error_test.dart b/tests/lib_2/wasm/memory_error_test.dart
new file mode 100644
index 0000000..e866bf0
--- /dev/null
+++ b/tests/lib_2/wasm/memory_error_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test errors thrown by WasmMemory.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+ Expect.throwsArgumentError(() => WasmMemory(1000000000));
+ var mem = WasmMemory(1000);
+ Expect.throwsArgumentError(() => mem.grow(1000000000));
+}
diff --git a/tests/lib_2/wasm/memory_test.dart b/tests/lib_2/wasm/memory_test.dart
index 1160aca..52d12c3 100644
--- a/tests/lib_2/wasm/memory_test.dart
+++ b/tests/lib_2/wasm/memory_test.dart
@@ -20,4 +20,7 @@
Expect.equals(1100, mem.lengthInPages);
Expect.equals(1100 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
Expect.equals(45, mem[123]);
+
+ Expect.throwsArgumentError(() => WasmMemory(1000000000));
+ Expect.throwsArgumentError(() => mem.grow(1000000000));
}
diff --git a/tests/lib_2/wasm/numerics_test.dart b/tests/lib_2/wasm/numerics_test.dart
index 1d7a199..6255d20 100644
--- a/tests/lib_2/wasm/numerics_test.dart
+++ b/tests/lib_2/wasm/numerics_test.dart
@@ -29,9 +29,9 @@
0x01, 0x92, 0x0b,
]);
- var inst = WasmModule(data).instantiate(WasmImports("env")
- ..addMemory("memory", WasmMemory(256, 1024))
- ..addGlobal<Int32>("__memory_base", 1024, false));
+ var inst = WasmModule(data).instantiate(WasmImports()
+ ..addMemory("env", "memory", WasmMemory(256, 1024))
+ ..addGlobal<Int32>("env", "__memory_base", 1024, false));
var addI64 = inst.lookupFunction<Int64 Function(Int64, Int64)>("addI64");
var addI32 = inst.lookupFunction<Int32 Function(Int32, Int32)>("addI32");
var addF64 = inst.lookupFunction<Double Function(Double, Double)>("addF64");
diff --git a/tests/lib_2/wasm/void_test.dart b/tests/lib_2/wasm/void_test.dart
index c2f0707..210c9b0 100644
--- a/tests/lib_2/wasm/void_test.dart
+++ b/tests/lib_2/wasm/void_test.dart
@@ -25,9 +25,9 @@
0x80, 0x08, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]);
- var inst = WasmModule(data).instantiate(WasmImports("env")
- ..addMemory("memory", WasmMemory(256, 1024))
- ..addGlobal<Int32>("__memory_base", 1024, false));
+ var inst = WasmModule(data).instantiate(WasmImports()
+ ..addMemory("env", "memory", WasmMemory(256, 1024))
+ ..addGlobal<Int32>("env", "__memory_base", 1024, false));
var setFn = inst.lookupFunction<Void Function(Int64, Int64)>("set");
var getFn = inst.lookupFunction<Int64 Function()>("get");
Expect.isNull(setFn.call([123, 456]));
diff --git a/tools/VERSION b/tools/VERSION
index e6b0140..f4e2a13 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
MAJOR 2
MINOR 6
PATCH 0
-PRERELEASE 3
+PRERELEASE 4
PRERELEASE_PATCH 0
ABI_VERSION 16
OLDEST_SUPPORTED_ABI_VERSION 16
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index aca2268..201302b 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -202,6 +202,8 @@
"samples-dev/",
"tools/",
"third_party/android_tools/sdk/platform-tools/adb",
+ "third_party/android_tools/ndk/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip",
+ "third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip",
"third_party/pkg/",
"third_party/pkg_tested/",
"third_party/observatory_pub_packages/packages/",
@@ -780,14 +782,18 @@
"name": "build dart",
"script": "tools/build.py",
"arguments": ["runtime"],
- "environment": {"DART_USE_ASAN": 1}
+ "environment": {
+ "DART_USE_ASAN": 1,
+ "ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0",
+ "ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
+ }
},
{
"name": "vm tests",
"arguments": [
"-ndartk-asan-linux-release-${arch}"],
"environment": {
- "ASAN_OPTIONS": "handle_segv=0:detect_stack_use_after_return=0:disable_coredump=0",
+ "ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0",
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
}
}
diff --git a/tools/generate_idefiles.py b/tools/generate_idefiles.py
index 6e8ead5..a7b89d8 100755
--- a/tools/generate_idefiles.py
+++ b/tools/generate_idefiles.py
@@ -84,7 +84,7 @@
To prevent dartanalyzer from tripping on the non-Dart files when it is
started from the root dart-sdk directory.
- https://github.com/Dart-Code/Dart-Code/issues/1295
+ https://github.com/dart-lang/sdk/issues/35562
Args:
options: supported options include: force, dir
@@ -96,6 +96,7 @@
- runtime/**
- samples-dev/swarm/**
- sdk/lib/**
+ - sdk_nnbd/lib/**
- tests/**
- third_party/observatory_pub_packages/**
- third_party/pkg/**
@@ -106,7 +107,7 @@
- tools/dom/**
- tools/sdks/dart-sdk/lib/**
- tools/status_clean.dart
- - xcodebuild / **"""
+ - xcodebuild/**"""
fname = os.path.join(options.dir, "analysis_options.yaml")
diff --git a/utils/application_snapshot.gni b/utils/application_snapshot.gni
index 4356f1c..c012046 100644
--- a/utils/application_snapshot.gni
+++ b/utils/application_snapshot.gni
@@ -78,11 +78,10 @@
# Build the kernel file using the prebuilt VM to speed up the debug and
# simulator builds.
prebuilt_dart_action(target_name + "_dill") {
- deps =
- extra_deps + [
- "$_dart_root/runtime/vm:kernel_platform_files($dart_host_toolchain)",
- "$_dart_root/runtime/vm:vm_platform",
- ]
+ deps = extra_deps + [
+ "$_dart_root/runtime/vm:kernel_platform_files($host_toolchain)",
+ "$_dart_root/runtime/vm:vm_platform",
+ ]
gen_kernel_script = "$_dart_root/pkg/vm/bin/gen_kernel.dart"
platform_dill = "$root_out_dir/vm_platform_strong.dill"
diff --git a/utils/kernel-service/BUILD.gn b/utils/kernel-service/BUILD.gn
index 9ed386a..c65d570 100644
--- a/utils/kernel-service/BUILD.gn
+++ b/utils/kernel-service/BUILD.gn
@@ -3,7 +3,6 @@
# BSD-style license that can be found in the LICENSE file.
import("../../build/dart/dart_action.gni")
-import("../../build/dart/dart_host_sdk_toolchain.gni")
import("../../runtime/runtime_args.gni")
import("../application_snapshot.gni")
@@ -50,7 +49,7 @@
application_snapshot("frontend_server") {
main_dart = "../../pkg/vm/bin/frontend_server_starter.dart"
deps = [
- "../../runtime/vm:kernel_platform_files($dart_host_toolchain)",
+ "../../runtime/vm:kernel_platform_files($host_toolchain)",
]
sdk_root = rebase_path("$root_out_dir")
training_args = [
@@ -65,7 +64,7 @@
template("kernel_service_dill") {
prebuilt_dart_action("kernel_service" + target_name + "_dill") {
deps = [
- "../../runtime/vm:kernel_platform_files($dart_host_toolchain)",
+ "../../runtime/vm:kernel_platform_files($host_toolchain)",
"../../runtime/vm:vm_platform",
]
kernel_service_script = "../../pkg/vm/bin/kernel_service.dart"