Version 2.10.0-51.0.dev
Merge commit 'db9b25dc7c52407328d680ac672c2607e04ed5a1' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 515b734..052e071 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
"constraint, update this by running tools/generate_package_config.dart."
],
"configVersion": 2,
- "generated": "2020-08-17T14:05:33.104579",
+ "generated": "2020-08-18T11:26:08.472483",
"generator": "tools/generate_package_config.dart",
"packages": [
{
@@ -515,7 +515,7 @@
"name": "shelf",
"rootUri": "../third_party/pkg/shelf",
"packageUri": "lib/",
- "languageVersion": "2.0"
+ "languageVersion": "2.1"
},
{
"name": "shelf_packages_handler",
@@ -716,6 +716,12 @@
"languageVersion": "2.8"
},
{
+ "name": "wasm",
+ "rootUri": "../pkg/wasm",
+ "packageUri": "lib/",
+ "languageVersion": "2.6"
+ },
+ {
"name": "watcher",
"rootUri": "../third_party/pkg/watcher",
"packageUri": "lib/",
diff --git a/.packages b/.packages
index ee073a7..ebac358 100644
--- a/.packages
+++ b/.packages
@@ -116,6 +116,7 @@
vm:pkg/vm/lib
vm_service:pkg/vm_service/lib
vm_snapshot_analysis:pkg/vm_snapshot_analysis/lib
+wasm:pkg/wasm/lib
watcher:third_party/pkg/watcher/lib
webdriver:third_party/pkg/webdriver/lib
web_components:third_party/pkg/web_components/lib
diff --git a/DEPS b/DEPS
index 8ddee13..0353d74 100644
--- a/DEPS
+++ b/DEPS
@@ -133,7 +133,7 @@
"quiver-dart_tag": "246e754fe45cecb6aa5f3f13b4ed61037ff0d784",
"resource_rev": "f8e37558a1c4f54550aa463b88a6a831e3e33cd6",
"root_certificates_rev": "7e5ec82c99677a2e5b95ce296c4d68b0d3378ed8",
- "rust_revision": "60960a260f7b5c695fd0717311d72ce62dd4eb43",
+ "rust_revision": "cbe7c5ce705896d4e22bf6096590bc1f17993b78",
"shelf_static_rev": "v0.2.8",
"shelf_packages_handler_tag": "2.0.0",
"shelf_proxy_tag": "0.1.0+7",
diff --git a/build/rust/rust.gni b/build/rust/rust.gni
index caabcc8..c3fb4dc 100644
--- a/build/rust/rust.gni
+++ b/build/rust/rust.gni
@@ -2,40 +2,103 @@
# 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_root = get_path_info("../..", "abspath")
+
template("rust_library") {
manifest = rebase_path("Cargo.toml")
if (defined(invoker.manifest)) {
manifest = invoker.manifest
}
+ debug = defined(invoker.debug) && invoker.debug
+ shared = defined(invoker.shared) && invoker.shared
+
cmd = [
- rebase_path("//buildtools/${current_os}-${current_cpu}/rust/bin/cargo"),
+ rebase_path("//buildtools/${host_os}-${host_cpu}/rust/bin/cargo"),
"build",
"--target-dir",
rebase_path(target_out_dir),
"--manifest-path",
manifest,
]
- output = "$target_out_dir/lib${invoker.lib_name}.a"
- debug = defined(invoker.debug) && invoker.debug
- if (!debug) {
+ # For cross compilation, figure out the target triple. You can get a full list
+ # of the targets that rust supports like this: rustc --print target-list
+ cargo_out_dir = target_out_dir
+ if (is_linux) {
+ rust_os = "unknown-linux-gnu"
+ } else if (is_mac) {
+ rust_os = "apple-darwin"
+ } else if (is_win) {
+ rust_os = "pc-windows-gnu"
+ } else if (is_android) {
+ rust_os = "linux-android"
+ } else if (is_fuchsia) {
+ rust_os = "fuchsia"
+ }
+ if (defined(rust_os)) {
+ if (current_cpu == "x86") {
+ rust_target = "i686-${rust_os}"
+ } else if (current_cpu == "x64") {
+ rust_target = "x86_64-${rust_os}"
+ } else if (current_cpu == "arm") {
+ rust_target = "arm-${rust_os}eabi"
+ } else if (current_cpu == "arm64") {
+ rust_target = "aarch64-${rust_os}"
+ }
+ }
+ if (defined(rust_target)) {
+ cmd += [
+ "--target",
+ rust_target,
+ ]
+ cargo_out_dir += "/${rust_target}"
+ }
+
+ if (debug) {
+ cargo_out_dir += "/debug"
+ } else {
+ cargo_out_dir += "/release"
cmd += [ "--release" ]
}
- action(target_name) {
- script = "//build/rust/run.py"
+ output_file = ""
+ if (shared) {
+ if (is_win) {
+ output_file = "${invoker.lib_name}.dll"
+ } else if (is_mac) {
+ output_file = "lib${invoker.lib_name}.dylib"
+ } else {
+ output_file = "lib${invoker.lib_name}.so"
+ }
+ } else {
+ if (is_win) {
+ output_file = "${invoker.lib_name}.lib"
+ }else {
+ output_file = "lib${invoker.lib_name}.a"
+ }
+ }
+
+ action("${target_name}_cargo") {
+ script = "${_dart_root}/build/rust/run.py"
args = cmd
- outputs = [ output ]
+ outputs = [ "${cargo_out_dir}/${output_file}" ]
public_configs = [ ":${target_name}_config" ]
}
- config("${target_name}_config") {
- libs = [ "wasmer" ]
- if (debug) {
- lib_dirs = [ "$target_out_dir/debug" ]
- } else {
- lib_dirs = [ "$target_out_dir/release" ]
+ config("${target_name}_cargo_config") {
+ if (!shared) {
+ libs = [ invoker.lib_name ]
+ lib_dirs = [ out_dir ]
}
}
+
+ # Cargo leaves the library in cargo_out_dir, which varies based on the target.
+ # So we need to copy it to target_out_dir to make it easier for dependees to
+ # locate the library.
+ copy(target_name) {
+ deps = [ ":${target_name}_cargo" ]
+ sources = [ "${cargo_out_dir}/${output_file}" ]
+ outputs = [ "${target_out_dir}/${output_file}" ]
+ }
}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
new file mode 100644
index 0000000..3a8456c
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ignore_for_file: prefer_single_quotes, slash_for_doc_comments
+import 'package:analyzer/error/error.dart';
+
+/// An error code representing a problem in a file containing an encoding of a
+/// transform set.
+class TransformSetErrorCode extends ErrorCode {
+ /**
+ * Parameters:
+ * 0: the unsupported key
+ */
+ static const TransformSetErrorCode unsupportedKey = TransformSetErrorCode(
+ 'unsupported_key', "The key '{0}' isn't supported.");
+
+ /**
+ * Parameters:
+ * 0: the message produced by the YAML parser
+ */
+ static const TransformSetErrorCode yamlSyntaxError =
+ TransformSetErrorCode('yaml_syntax_error', "{0}");
+
+ /// Initialize a newly created error code.
+ const TransformSetErrorCode(String name, String message,
+ {String correction, bool hasPublishedDocs = false})
+ : super.temporary(name, message,
+ correction: correction, hasPublishedDocs: hasPublishedDocs);
+
+ @override
+ ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
+
+ @override
+ ErrorType get type => ErrorType.COMPILE_TIME_ERROR;
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
new file mode 100644
index 0000000..3a3af62
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
@@ -0,0 +1,240 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/change.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/rename.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
+import 'package:analysis_server/src/utilities/extensions/yaml.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:yaml/yaml.dart';
+
+/// A parser used to read a transform set from a file.
+class TransformSetParser {
+ static const String _changesKey = 'changes';
+
+ static const String _componentsKey = 'components';
+
+ static const String _elementKey = 'element';
+
+ static const String _kindKey = 'kind';
+
+ static const String _newNameKey = 'newName';
+
+ static const String _titleKey = 'title';
+
+ static const String _transformsKey = 'transforms';
+
+ static const String _urisKey = 'uris';
+
+ static const String _versionKey = 'version';
+
+ static const String _renameKind = 'rename';
+
+ static const int currentVersion = 1;
+
+ /// The error reporter to which diagnostics will be reported.
+ final ErrorReporter errorReporter;
+
+ /// Initialize a newly created parser to report diagnostics to the
+ /// [errorReporter].
+ TransformSetParser(this.errorReporter);
+
+ /// Return the result of parsing the file [content] into a transform set.
+ TransformSet parse(String content) {
+ assert(content != null);
+ var map = _parseYaml(content);
+ if (map == null) {
+ return TransformSet();
+ }
+ return _translateTransformSet(map);
+ }
+
+ /// Return the result of parsing the file [content] into a YAML node.
+ YamlNode _parseYaml(String content) {
+ try {
+ return loadYamlNode(content);
+ } on YamlException catch (e) {
+ var span = e.span;
+ errorReporter.reportErrorForOffset(TransformSetErrorCode.yamlSyntaxError,
+ span.start.offset, span.length, [e.message]);
+ }
+ return null;
+ }
+
+ /// Report a diagnostic with the given [code] associated with the given
+ /// [node]. A list of [arguments] should be provided if the diagnostic message
+ /// has parameters.
+ void _reportError(TransformSetErrorCode code, YamlNode node,
+ [List<String> arguments]) {
+ var span = node.span;
+ errorReporter.reportErrorForOffset(
+ code, span.start.offset, span.length, arguments);
+ }
+
+ /// Report any keys in the [map] whose values are not in [validKeys].
+ void _reportUnsupportedKeys(YamlMap map, Set<String> validKeys) {
+ for (var keyNode in map.nodes.keys) {
+ if (keyNode is YamlScalar) {
+ var key = _translateString(keyNode);
+ if (key != null && !validKeys.contains(key)) {
+ _reportError(TransformSetErrorCode.unsupportedKey, keyNode, [key]);
+ }
+ } else {
+ // TODO(brianwilkerson) Report the unsupported key.
+ }
+ }
+ }
+
+ /// Translate the [node] into a change.
+ Change _translateChange(YamlNode node) {
+ if (node is YamlMap) {
+ var kind = _translateString(node.valueAt(_kindKey));
+ // TODO(brianwilkerson) Implement additional change kinds.
+ if (kind == _renameKind) {
+ return _translateRenameChange(node);
+ }
+ // TODO(brianwilkerson) Report the invalid change kind.
+ return null;
+ } else if (node == null) {
+ // TODO(brianwilkerson) Report the missing YAML.
+ return null;
+ } else {
+ // TODO(brianwilkerson) Report the invalid YAML.
+ return null;
+ }
+ }
+
+ /// Translate the [node] into an element descriptor.
+ ElementDescriptor _translateElement(YamlNode node) {
+ if (node is YamlMap) {
+ var uris = _translateList(node.valueAt(_urisKey), _translateString);
+ var components =
+ _translateList(node.valueAt(_componentsKey), _translateString);
+ return ElementDescriptor(libraryUris: uris, components: components);
+ } else if (node == null) {
+ // TODO(brianwilkerson) Report the missing YAML.
+ return null;
+ } else {
+ // TODO(brianwilkerson) Report the invalid YAML.
+ return null;
+ }
+ }
+
+ /// Translate the [node] into an integer.
+ int _translateInteger(YamlNode node) {
+ if (node is YamlScalar) {
+ var value = node.value;
+ if (value is int) {
+ return value;
+ }
+ // TODO(brianwilkerson) Report the invalid YAML. For the best UX we
+ // probably need to pass in the code to report.
+ return null;
+ } else if (node == null) {
+ // TODO(brianwilkerson) Report the missing YAML. For the best UX we
+ // probably need to pass in the code to report.
+ return null;
+ } else {
+ // TODO(brianwilkerson) Report the invalid YAML. For the best UX we
+ // probably need to pass in the code to report.
+ return null;
+ }
+ }
+
+ /// Translate the [node] into a list of objects using the [elementTranslator].
+ List<R> _translateList<R>(
+ YamlNode node, R Function(YamlNode) elementTranslator) {
+ if (node is YamlList) {
+ var translatedList = <R>[];
+ for (var element in node.nodes) {
+ var result = elementTranslator(element);
+ if (result != null) {
+ translatedList.add(result);
+ }
+ }
+ return translatedList;
+ } else if (node == null) {
+ // TODO(brianwilkerson) Report the missing YAML.
+ return null;
+ } else {
+ // TODO(brianwilkerson) Report the invalid YAML.
+ return null;
+ }
+ }
+
+ /// Translate the [node] into a rename change.
+ Change _translateRenameChange(YamlMap node) {
+ _reportUnsupportedKeys(node, const {_kindKey, _newNameKey});
+ var newName = _translateString(node.valueAt(_newNameKey));
+ return Rename(newName: newName);
+ }
+
+ /// Translate the [node] into a string.
+ String _translateString(YamlNode node) {
+ if (node is YamlScalar) {
+ var value = node.value;
+ if (value is String) {
+ return value;
+ }
+ // TODO(brianwilkerson) Report the invalid YAML. For the best UX we
+ // probably need to pass in the code to report.
+ return null;
+ } else if (node == null) {
+ // TODO(brianwilkerson) Report the missing YAML. For the best UX we
+ // probably need to pass in the code to report.
+ return null;
+ } else {
+ // TODO(brianwilkerson) Report the invalid YAML. For the best UX we
+ // probably need to pass in the code to report.
+ return null;
+ }
+ }
+
+ /// Translate the [node] into a transform.
+ Transform _translateTransform(YamlNode node) {
+ if (node is YamlMap) {
+ _reportUnsupportedKeys(node, const {_changesKey, _elementKey, _titleKey});
+ var title = _translateString(node.valueAt(_titleKey));
+ var element = _translateElement(node.valueAt(_elementKey));
+ var changes =
+ _translateList<Change>(node.valueAt(_changesKey), _translateChange);
+ return Transform(title: title, element: element, changes: changes);
+ } else if (node == null) {
+ // TODO(brianwilkerson) Report the missing YAML.
+ return null;
+ } else {
+ // TODO(brianwilkerson) Report the invalid YAML.
+ return null;
+ }
+ }
+
+ /// Translate the [node] into a transform set.
+ TransformSet _translateTransformSet(YamlNode node) {
+ if (node is YamlMap) {
+ _reportUnsupportedKeys(node, const {_transformsKey, _versionKey});
+ var set = TransformSet();
+ // TODO(brianwilkerson) Version information is currently being ignored,
+ // but needs to be used to select a translator.
+ var version = _translateInteger(node.valueAt(_versionKey));
+ if (version != currentVersion) {
+ // TODO(brianwilkerson) Report the unsupported version.
+ }
+ var transformations =
+ _translateList(node.valueAt(_transformsKey), _translateTransform);
+ for (var transform in transformations) {
+ set.addTransform(transform);
+ }
+ return set;
+ } else if (node == null) {
+ // TODO(brianwilkerson) Report the missing YAML.
+ return null;
+ } else {
+ // TODO(brianwilkerson) Report the invalid YAML.
+ return null;
+ }
+ }
+}
diff --git a/pkg/analysis_server/lib/src/utilities/extensions/yaml.dart b/pkg/analysis_server/lib/src/utilities/extensions/yaml.dart
new file mode 100644
index 0000000..0107f62
--- /dev/null
+++ b/pkg/analysis_server/lib/src/utilities/extensions/yaml.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:yaml/yaml.dart';
+
+extension YamlMapExtensions on YamlMap {
+ /// Return the value associated with the key whose value matches the given
+ /// [key], or `null` if there is no matching key.
+ YamlNode valueAt(String key) {
+ for (var keyNode in nodes.keys) {
+ if (keyNode is YamlScalar && keyNode.value == key) {
+ return nodes[key];
+ }
+ }
+ return null;
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart
new file mode 100644
index 0000000..6f035e1
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'unsupported_key_test.dart' as unsupported_key;
+import 'yaml_syntax_error_test.dart' as yaml_syntax_error;
+
+void main() {
+ defineReflectiveSuite(() {
+ unsupported_key.main();
+ yaml_syntax_error.main();
+ });
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/unsupported_key_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/unsupported_key_test.dart
new file mode 100644
index 0000000..9358bee
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/unsupported_key_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../transform_set_parser_test_support.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UnsupportedKeyTest);
+ });
+}
+
+@reflectiveTest
+class UnsupportedKeyTest extends AbstractTransformSetParserTest {
+ void test_rename() {
+ assertErrors('''
+version: 1
+transforms:
+- title: 'Rename A'
+ element:
+ uris:
+ - 'test.dart'
+ components:
+ - 'A'
+ changes:
+ - kind: 'rename'
+ oldName: 'A'
+ newName: 'B'
+''', [
+ error(TransformSetErrorCode.unsupportedKey, 150, 7),
+ ]);
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/yaml_syntax_error_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/yaml_syntax_error_test.dart
new file mode 100644
index 0000000..dfa3444
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/yaml_syntax_error_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../transform_set_parser_test_support.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(YamlSyntaxErrorTest);
+ });
+}
+
+@reflectiveTest
+class YamlSyntaxErrorTest extends AbstractTransformSetParserTest {
+ void test_syntaxError() {
+ assertErrors('''
+{
+''', [
+ error(TransformSetErrorCode.yamlSyntaxError, 2, 0),
+ ]);
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
index 1a39ea9..b6be18f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
@@ -5,13 +5,17 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'add_type_parameter_test.dart' as add_type_parameter_change;
+import 'diagnostics/test_all.dart' as diagnostics;
import 'modify_parameters_test.dart' as modify_parameters;
import 'rename_test.dart' as rename_change;
+import 'transform_set_parser_test.dart' as transform_set_parser;
void main() {
defineReflectiveSuite(() {
add_type_parameter_change.main();
+ diagnostics.main();
modify_parameters.main();
rename_change.main();
+ transform_set_parser.main();
});
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
new file mode 100644
index 0000000..543f5ac
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/rename.dart';
+import 'package:matcher/matcher.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'transform_set_parser_test_support.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(TransformSetParserTest);
+ });
+}
+
+@reflectiveTest
+class TransformSetParserTest extends AbstractTransformSetParserTest {
+ void test_rename() {
+ parse('''
+version: 1
+transforms:
+- title: 'Rename A'
+ element:
+ uris:
+ - 'test.dart'
+ components:
+ - 'A'
+ changes:
+ - kind: 'rename'
+ newName: 'B'
+''');
+ var transforms = result.transformsFor('A', ['test.dart']);
+ expect(transforms, hasLength(1));
+ var transform = transforms[0];
+ expect(transform.title, 'Rename A');
+ expect(transform.changes, hasLength(1));
+ var rename = transform.changes[0] as Rename;
+ expect(rename.newName, 'B');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart
new file mode 100644
index 0000000..1fa4200
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_parser.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/error/listener.dart';
+
+import '../../../../../mocks.dart';
+import '../../../../../utils/test_support.dart';
+
+/// Utilities shared between tests of the [TransformSetParser].
+abstract class AbstractTransformSetParserTest {
+ /// The listener to which errors will be reported.
+ GatheringErrorListener errorListener;
+
+ /// The result of parsing the test file's content.
+ TransformSet result;
+
+ Future<void> assertErrors(
+ String code, List<ExpectedError> expectedErrors) async {
+ parse(code);
+ errorListener.assertErrors(expectedErrors);
+ }
+
+ ExpectedError error(ErrorCode code, int offset, int length,
+ {String text,
+ Pattern messageContains,
+ List<ExpectedContextMessage> contextMessages =
+ const <ExpectedContextMessage>[]}) =>
+ ExpectedError(code, offset, length,
+ message: text,
+ messageContains: messageContains,
+ expectedContextMessages: contextMessages);
+
+ void parse(String content) {
+ errorListener = GatheringErrorListener();
+ var errorReporter = ErrorReporter(errorListener, MockSource('data.yaml'));
+ var parser = TransformSetParser(errorReporter);
+ result = parser.parse(content);
+ }
+}
diff --git a/pkg/analysis_server/test/utils/test_support.dart b/pkg/analysis_server/test/utils/test_support.dart
new file mode 100644
index 0000000..959be9b
--- /dev/null
+++ b/pkg/analysis_server/test/utils/test_support.dart
@@ -0,0 +1,384 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// These classes were copied from `analyzer`. They should be moved into the
+/// `analyzer/lib/src/test_utilities` directory so that they can be shared.
+/// (This version has been converted to a more modern style.)
+import 'package:analyzer/diagnostic/diagnostic.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:test/test.dart';
+
+/// A description of a message that is expected to be reported with an error.
+class ExpectedContextMessage {
+ /// The path of the file with which the message is associated.
+ final String filePath;
+
+ /// The offset of the beginning of the error's region.
+ final int offset;
+
+ /// The offset of the beginning of the error's region.
+ final int length;
+
+ /// The message text for the error.
+ final String text;
+
+ ExpectedContextMessage(this.filePath, this.offset, this.length, {this.text});
+
+ /// Return `true` if the [message] matches this description of what the state
+ /// of the [message] is expected to be.
+ bool matches(DiagnosticMessage message) {
+ return message.filePath == filePath &&
+ message.offset == offset &&
+ message.length == length &&
+ (text == null || message.message == text);
+ }
+}
+
+/// A description of an error that is expected to be reported.
+class ExpectedError {
+ /// An empty array of error descriptors used when no errors are expected.
+ static List<ExpectedError> NO_ERRORS = <ExpectedError>[];
+
+ /// The error code associated with the error.
+ final ErrorCode code;
+
+ /// The offset of the beginning of the error's region.
+ final int offset;
+
+ /// The offset of the beginning of the error's region.
+ final int length;
+
+ /// The message text of the error or `null` if the message should not be checked.
+ final String message;
+
+ /// A pattern that should be contained in the error message or `null` if the message
+ /// contents should not be checked.
+ final Pattern messageContains;
+
+ /// The list of context messages that are expected to be associated with the
+ /// error.
+ final List<ExpectedContextMessage> expectedContextMessages;
+
+ /// Initialize a newly created error description.
+ ExpectedError(this.code, this.offset, this.length,
+ {this.message,
+ this.messageContains,
+ this.expectedContextMessages = const <ExpectedContextMessage>[]});
+
+ /// Return `true` if the [error] matches this description of what the state
+ /// of the [error] is expected to be.
+ bool matches(AnalysisError error) {
+ if (error.offset != offset ||
+ error.length != length ||
+ error.errorCode != code) {
+ return false;
+ }
+ if (message != null && error.message != message) {
+ return false;
+ }
+ if (messageContains != null &&
+ error.message?.contains(messageContains) != true) {
+ return false;
+ }
+ var contextMessages = error.contextMessages.toList();
+ contextMessages.sort((first, second) {
+ var result = first.filePath.compareTo(second.filePath);
+ if (result != 0) {
+ return result;
+ }
+ return second.offset - first.offset;
+ });
+ if (contextMessages.length != expectedContextMessages.length) {
+ return false;
+ }
+ for (var i = 0; i < expectedContextMessages.length; i++) {
+ if (!expectedContextMessages[i].matches(contextMessages[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+/// An error listener that collects all of the errors passed to it for later
+/// examination.
+class GatheringErrorListener implements AnalysisErrorListener {
+ /// A flag indicating whether error ranges are to be compared when comparing
+ /// expected and actual errors.
+ final bool checkRanges;
+
+ /// A list containing the errors that were collected.
+ final List<AnalysisError> _errors = <AnalysisError>[];
+
+ /// A table mapping sources to the line information for the source.
+ final Map<Source, LineInfo> _lineInfoMap = <Source, LineInfo>{};
+
+ /// Initialize a newly created error listener to collect errors.
+ GatheringErrorListener({this.checkRanges = Parser.useFasta});
+
+ /// Return the errors that were collected.
+ List<AnalysisError> get errors => _errors;
+
+ /// Return `true` if at least one error has been gathered.
+ bool get hasErrors => _errors.isNotEmpty;
+
+ /// Add the given [errors] to this listener.
+ void addAll(List<AnalysisError> errors) {
+ for (var error in errors) {
+ onError(error);
+ }
+ }
+
+ /// Add all of the errors recorded by the given [listener] to this listener.
+ void addAll2(RecordingErrorListener listener) {
+ addAll(listener.errors);
+ }
+
+ /// Assert that the number of errors that have been gathered matches the
+ /// number of [expectedErrors] and that they have the expected error codes and
+ /// locations. The order in which the errors were gathered is ignored.
+ void assertErrors(List<ExpectedError> expectedErrors) {
+ //
+ // Match actual errors to expected errors.
+ //
+ var unmatchedActual = errors.toList();
+ var unmatchedExpected = expectedErrors.toList();
+ var actualIndex = 0;
+ while (actualIndex < unmatchedActual.length) {
+ var matchFound = false;
+ var expectedIndex = 0;
+ while (expectedIndex < unmatchedExpected.length) {
+ if (unmatchedExpected[expectedIndex]
+ .matches(unmatchedActual[actualIndex])) {
+ matchFound = true;
+ unmatchedActual.removeAt(actualIndex);
+ unmatchedExpected.removeAt(expectedIndex);
+ break;
+ }
+ expectedIndex++;
+ }
+ if (!matchFound) {
+ actualIndex++;
+ }
+ }
+ //
+ // Write the results.
+ //
+ var buffer = StringBuffer();
+ if (unmatchedExpected.isNotEmpty) {
+ buffer.writeln('Expected but did not find:');
+ for (var expected in unmatchedExpected) {
+ buffer.write(' ');
+ buffer.write(expected.code);
+ buffer.write(' [');
+ buffer.write(expected.offset);
+ buffer.write(', ');
+ buffer.write(expected.length);
+ if (expected.message != null) {
+ buffer.write(', ');
+ buffer.write(expected.message);
+ }
+ buffer.writeln(']');
+ }
+ }
+ if (unmatchedActual.isNotEmpty) {
+ if (buffer.isNotEmpty) {
+ buffer.writeln();
+ }
+ buffer.writeln('Found but did not expect:');
+ for (var actual in unmatchedActual) {
+ buffer.write(' ');
+ buffer.write(actual.errorCode);
+ buffer.write(' [');
+ buffer.write(actual.offset);
+ buffer.write(', ');
+ buffer.write(actual.length);
+ buffer.write(', ');
+ buffer.write(actual.message);
+ buffer.writeln(']');
+ }
+ }
+ if (buffer.isNotEmpty) {
+ errors.sort((first, second) => first.offset.compareTo(second.offset));
+ buffer.writeln();
+ buffer.writeln('To accept the current state, expect:');
+ for (var actual in errors) {
+ var contextMessages = actual.contextMessages;
+ buffer.write(' error(');
+ buffer.write(actual.errorCode);
+ buffer.write(', ');
+ buffer.write(actual.offset);
+ buffer.write(', ');
+ buffer.write(actual.length);
+ if (contextMessages.isNotEmpty) {
+ buffer.write(', contextMessages: [');
+ for (var i = 0; i < contextMessages.length; i++) {
+ var message = contextMessages[i];
+ if (i > 0) {
+ buffer.write(', ');
+ }
+ buffer.write('message(\'');
+ buffer.write(message.filePath);
+ buffer.write('\', ');
+ buffer.write(message.offset);
+ buffer.write(', ');
+ buffer.write(message.length);
+ buffer.write(')');
+ }
+ buffer.write(']');
+ }
+ buffer.writeln('),');
+ }
+ fail(buffer.toString());
+ }
+ }
+
+ /// Assert that the number of errors that have been gathered matches the
+ /// number of [expectedErrorCodes] and that they have the expected error
+ /// codes. The order in which the errors were gathered is ignored.
+ void assertErrorsWithCodes(
+ [List<ErrorCode> expectedErrorCodes = const <ErrorCode>[]]) {
+ var buffer = StringBuffer();
+ //
+ // Compute the expected number of each type of error.
+ //
+ var expectedCounts = <ErrorCode, int>{};
+ for (var code in expectedErrorCodes) {
+ var count = expectedCounts[code];
+ if (count == null) {
+ count = 1;
+ } else {
+ count = count + 1;
+ }
+ expectedCounts[code] = count;
+ }
+ //
+ // Compute the actual number of each type of error.
+ //
+ var errorsByCode = <ErrorCode, List<AnalysisError>>{};
+ for (var error in _errors) {
+ errorsByCode
+ .putIfAbsent(error.errorCode, () => <AnalysisError>[])
+ .add(error);
+ }
+ //
+ // Compare the expected and actual number of each type of error.
+ //
+ expectedCounts.forEach((ErrorCode code, int expectedCount) {
+ int actualCount;
+ var list = errorsByCode.remove(code);
+ if (list == null) {
+ actualCount = 0;
+ } else {
+ actualCount = list.length;
+ }
+ if (actualCount != expectedCount) {
+ if (buffer.length == 0) {
+ buffer.write('Expected ');
+ } else {
+ buffer.write('; ');
+ }
+ buffer.write(expectedCount);
+ buffer.write(' errors of type ');
+ buffer.write(code.uniqueName);
+ buffer.write(', found ');
+ buffer.write(actualCount);
+ }
+ });
+ //
+ // Check that there are no more errors in the actual-errors map,
+ // otherwise record message.
+ //
+ errorsByCode.forEach((ErrorCode code, List<AnalysisError> actualErrors) {
+ var actualCount = actualErrors.length;
+ if (buffer.length == 0) {
+ buffer.write('Expected ');
+ } else {
+ buffer.write('; ');
+ }
+ buffer.write('0 errors of type ');
+ buffer.write(code.uniqueName);
+ buffer.write(', found ');
+ buffer.write(actualCount);
+ buffer.write(' (');
+ for (var i = 0; i < actualErrors.length; i++) {
+ var error = actualErrors[i];
+ if (i > 0) {
+ buffer.write(', ');
+ }
+ buffer.write(error.offset);
+ }
+ buffer.write(')');
+ });
+ if (buffer.length > 0) {
+ fail(buffer.toString());
+ }
+ }
+
+ /// Assert that the number of errors that have been gathered matches the
+ /// number of [expectedSeverities] and that there are the same number of
+ /// errors and warnings as specified by the argument. The order in which the
+ /// errors were gathered is ignored.
+ void assertErrorsWithSeverities(List<ErrorSeverity> expectedSeverities) {
+ var expectedErrorCount = 0;
+ var expectedWarningCount = 0;
+ for (var severity in expectedSeverities) {
+ if (severity == ErrorSeverity.ERROR) {
+ expectedErrorCount++;
+ } else {
+ expectedWarningCount++;
+ }
+ }
+ var actualErrorCount = 0;
+ var actualWarningCount = 0;
+ for (var error in _errors) {
+ if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) {
+ actualErrorCount++;
+ } else {
+ actualWarningCount++;
+ }
+ }
+ if (expectedErrorCount != actualErrorCount ||
+ expectedWarningCount != actualWarningCount) {
+ fail('Expected $expectedErrorCount errors '
+ 'and $expectedWarningCount warnings, '
+ 'found $actualErrorCount errors '
+ 'and $actualWarningCount warnings');
+ }
+ }
+
+ /// Assert that no errors have been gathered.
+ void assertNoErrors() {
+ assertErrors(ExpectedError.NO_ERRORS);
+ }
+
+ /// Return the line information associated with the given [source], or `null`
+ /// if no line information has been associated with the source.
+ LineInfo getLineInfo(Source source) => _lineInfoMap[source];
+
+ /// Return `true` if an error with the given [errorCode] has been gathered.
+ bool hasError(ErrorCode errorCode) {
+ for (var error in _errors) {
+ if (identical(error.errorCode, errorCode)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ void onError(AnalysisError error) {
+ _errors.add(error);
+ }
+
+ /// Set the line information associated with the given [source] to the given
+ /// list of [lineStarts].
+ void setLineInfo(Source source, List<int> lineStarts) {
+ _lineInfoMap[source] = LineInfo(lineStarts);
+ }
+}
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index b6f824d..7ff78e1 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.40.1-dev
+* Added `LocalVariableElement.hasInitializer`,
+ `PropertyInducingElement.hasInitializer`, `ParameterElement.hasDefaultValue`.
+
## 0.40.0
* Added `LibraryElement.featureSet`.
* Removed deprecated `EmbedderSdk` and related classes.
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index d605b1c..31dadf0 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1388,7 +1388,10 @@
/// A local variable.
///
/// Clients may not extend, implement or mix-in this class.
-abstract class LocalVariableElement implements PromotableElement {}
+abstract class LocalVariableElement implements PromotableElement {
+ /// Return `true` if this variable has an initializer at declaration.
+ bool get hasInitializer;
+}
/// An element that represents a method defined within a class.
///
@@ -1440,6 +1443,9 @@
/// Return the Dart code of the default value, or `null` if no default value.
String get defaultValueCode;
+ /// Return `true` if this parameter has a default value.
+ bool get hasDefaultValue;
+
/// Return `true` if this parameter is covariant, meaning it is allowed to
/// have a narrower type in an override.
bool get isCovariant;
@@ -1598,6 +1604,9 @@
/// will be synthetic.
PropertyAccessorElement get getter;
+ /// Return `true` if this variable has an initializer at declaration.
+ bool get hasInitializer;
+
/// Return the setter associated with this variable, or `null` if the variable
/// is effectively `final` and therefore does not have a setter associated
/// with it. (This can happen either because the variable is explicitly
@@ -1728,6 +1737,7 @@
/// `null` if this variable does not have an initializer. The function will
/// have no parameters. The return type of the function will be the
/// compile-time type of the initialization expression.
+ @deprecated
FunctionElement get initializer;
/// Return `true` if this variable was declared with the 'const' modifier.
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 9a4651c..191f7af 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -369,7 +369,7 @@
// that we won't be confused by incorrect code.
if ((field.isFinal || field.isConst) &&
!field.isStatic &&
- field.initializer != null) {
+ field.hasInitializer) {
callback(field);
}
}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 3ad2cf9..46b2b3e 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1784,6 +1784,9 @@
}
@override
+ bool get hasInitializer => false;
+
+ @override
String get name {
if (linkedNode != null) {
return reference.name;
@@ -5615,6 +5618,9 @@
/// A concrete implementation of a [LocalVariableElement].
class LocalVariableElementImpl extends NonParameterVariableElementImpl
implements LocalVariableElement {
+ @override
+ bool hasInitializer;
+
/// Initialize a newly created method element to have the given [name] and
/// [offset].
LocalVariableElementImpl(String name, int offset) : super(name, offset);
@@ -6218,24 +6224,26 @@
super.hasImplicitType = hasImplicitType;
}
+ bool get hasInitializer {
+ return linkedNode != null && linkedContext.hasInitializer(linkedNode);
+ }
+
+ @deprecated
@override
FunctionElement get initializer {
- if (_initializer == null) {
- if (linkedNode != null) {
- if (linkedContext.hasInitializer(linkedNode)) {
- _initializer = FunctionElementImpl('', -1)
- ..isSynthetic = true
- .._type = FunctionTypeImpl(
- typeFormals: const [],
- parameters: const [],
- returnType: type,
- nullabilitySuffix: NullabilitySuffix.star,
- )
- ..enclosingElement = this;
- }
- }
+ if (hasInitializer) {
+ return FunctionElementImpl('', -1)
+ ..enclosingElement = this
+ ..isSynthetic = true
+ ..returnType = type
+ .._type = FunctionTypeImpl(
+ typeFormals: const [],
+ parameters: const [],
+ returnType: type,
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
}
- return super.initializer;
+ return null;
}
@override
@@ -6278,19 +6286,16 @@
return null;
}
- bool get _hasInitializer {
- return linkedNode != null && linkedContext.hasInitializer(linkedNode);
- }
-
/// Return `true` if this variable needs the setter.
bool get _hasSetter {
if (isConst) {
return false;
}
+ // TODO(scheglov) is this right?
if (isLate) {
if (isFinal) {
- return !_hasInitializer;
+ return !hasInitializer;
}
return true;
}
@@ -6389,6 +6394,11 @@
}
@override
+ bool get hasDefaultValue {
+ return defaultValueCode != null;
+ }
+
+ @override
bool get hasImplicitType {
if (linkedNode != null) {
return linkedContext.hasImplicitType(linkedNode);
@@ -6421,28 +6431,6 @@
}
@override
- FunctionElement get initializer {
- if (_initializer != null) return _initializer;
-
- if (linkedNode != null) {
- if (linkedContext.hasDefaultValue(linkedNode)) {
- _initializer = FunctionElementImpl('', -1)
- ..enclosingElement = this
- ..isSynthetic = true;
- }
- }
-
- return super.initializer;
- }
-
- /// Set the function representing this variable's initializer to the given
- /// [function].
- @override
- set initializer(FunctionElement function) {
- super.initializer = function;
- }
-
- @override
bool get isCovariant {
if (isExplicitlyCovariant || inheritsCovariant) {
return true;
@@ -7112,6 +7100,10 @@
@override
PropertyAccessorElement setter;
+ /// This field is set during linking, and performs type inference for
+ /// this property. After linking this field is always `null`.
+ PropertyInducingElementTypeInference typeInference;
+
/// Initialize a newly created synthetic element to have the given [name] and
/// [offset].
PropertyInducingElementImpl(String name, int offset) : super(name, offset);
@@ -7156,6 +7148,12 @@
}
}
+/// Instances of this class are set for fields and top-level variables
+/// to perform top-level type inference during linking.
+abstract class PropertyInducingElementTypeInference {
+ void perform();
+}
+
/// A concrete implementation of a [ShowElementCombinator].
class ShowElementCombinatorImpl implements ShowElementCombinator {
final LinkedUnitContext linkedContext;
@@ -7557,10 +7555,6 @@
/// The type of this variable.
DartType _type;
- /// A synthetic function representing this variable's initializer, or `null
- ///` if this variable does not have an initializer.
- FunctionElement _initializer;
-
/// Initialize a newly created variable element to have the given [name] and
/// [offset].
VariableElementImpl(String name, int offset) : super(name, offset);
@@ -7613,17 +7607,9 @@
setModifier(Modifier.IMPLICIT_TYPE, hasImplicitType);
}
+ @deprecated
@override
- FunctionElement get initializer => _initializer;
-
- /// Set the function representing this variable's initializer to the given
- /// [function].
- set initializer(FunctionElement function) {
- if (function != null) {
- (function as FunctionElementImpl).enclosingElement = this;
- }
- _initializer = function;
- }
+ FunctionElement get initializer => null;
@override
bool get isConst {
@@ -7684,6 +7670,7 @@
@override
void visitChildren(ElementVisitor visitor) {
super.visitChildren(visitor);
- _initializer?.accept(visitor);
+ // ignore: deprecated_member_use_from_same_package
+ initializer?.accept(visitor);
}
}
diff --git a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
index 52fab94..641f80f 100644
--- a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
+++ b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
@@ -166,14 +166,19 @@
for (int i = 0; i < typeFormals.length; i++) {
TypeParameterElement typeParam = typeFormals[i];
var constraints = _constraints[typeParam];
- var typeParamBound = typeParam.bound != null
- ? Substitution.fromPairs(typeFormals, inferredTypes)
- .substituteType(typeParam.bound)
- : typeProvider.dynamicType;
+
+ var typeParamBound = typeParam.bound;
+ if (typeParamBound != null) {
+ typeParamBound = Substitution.fromPairs(typeFormals, inferredTypes)
+ .substituteType(typeParamBound);
+ typeParamBound = _toLegacyElementIfOptOut(typeParamBound);
+ } else {
+ typeParamBound = typeProvider.dynamicType;
+ }
var inferred = inferredTypes[i];
bool success =
- constraints.every((c) => c.isSatisifedBy(_typeSystem, inferred));
+ constraints.every((c) => c.isSatisfiedBy(_typeSystem, inferred));
if (success && !typeParamBound.isDynamic) {
// If everything else succeeded, check the `extends` constraint.
var extendsConstraint = _TypeConstraint.fromExtends(
@@ -182,7 +187,7 @@
isNonNullableByDefault: isNonNullableByDefault,
);
constraints.add(extendsConstraint);
- success = extendsConstraint.isSatisifedBy(_typeSystem, inferred);
+ success = extendsConstraint.isSatisfiedBy(_typeSystem, inferred);
}
if (!success) {
@@ -344,8 +349,8 @@
// will fail.
upper = _typeSystem.getGreatestLowerBound(upper, constraint.upperBound);
lower = _typeSystem.getLeastUpperBound(lower, constraint.lowerBound);
- upper = _toLegacyType(upper);
- lower = _toLegacyType(lower);
+ upper = _toLegacyElementIfOptOut(upper);
+ lower = _toLegacyElementIfOptOut(lower);
}
// Prefer the known bound, if any.
@@ -405,7 +410,7 @@
Iterable<_TypeConstraint> isSatisified(bool expected) => constraintsByOrigin
.values
.where((l) =>
- l.every((c) => c.isSatisifedBy(_typeSystem, inferred)) == expected)
+ l.every((c) => c.isSatisfiedBy(_typeSystem, inferred)) == expected)
.expand((i) => i);
String unsatisified = _formatConstraints(isSatisified(false));
@@ -479,7 +484,7 @@
/// If in a legacy library, return the legacy version of the [type].
/// Otherwise, return the original type.
- DartType _toLegacyType(DartType type) {
+ DartType _toLegacyElementIfOptOut(DartType type) {
if (isNonNullableByDefault) return type;
return NullabilityEliminator.perform(typeProvider, type);
}
@@ -542,8 +547,10 @@
bool get isDownwards => origin is! _TypeConstraintFromArgument;
- bool isSatisifedBy(TypeSystemImpl ts, DartType type) =>
- ts.isSubtypeOf2(lowerBound, type) && ts.isSubtypeOf2(type, upperBound);
+ bool isSatisfiedBy(TypeSystemImpl ts, DartType type) {
+ return ts.isSubtypeOf2(lowerBound, type) &&
+ ts.isSubtypeOf2(type, upperBound);
+ }
/// Converts this constraint to a message suitable for a type inference error.
@override
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 655578d..29c863b 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -211,8 +211,6 @@
@override
void visitChildren(ElementVisitor visitor) {
- // TODO(brianwilkerson) We need to finish implementing the accessors used
- // below so that we can safely invoke them.
super.visitChildren(visitor);
safelyVisitChildren(parameters, visitor);
}
@@ -296,6 +294,9 @@
}
@override
+ bool get hasDefaultValue => declaration.hasDefaultValue;
+
+ @override
bool get isCovariant => declaration.isCovariant;
@override
@@ -334,6 +335,9 @@
}
@override
+ bool get hasInitializer => declaration.hasInitializer;
+
+ @override
bool get isAbstract => declaration.isAbstract;
@override
@@ -772,6 +776,9 @@
Element get enclosingElement => declaration.enclosingElement;
@override
+ bool get hasDefaultValue => declaration.hasDefaultValue;
+
+ @override
int get hashCode => declaration.hashCode;
@override
@@ -951,6 +958,9 @@
}
@override
+ bool get hasInitializer => declaration.hasInitializer;
+
+ @override
bool get isExternal => declaration.isExternal;
@override
@@ -1039,9 +1049,8 @@
@override
void visitChildren(ElementVisitor visitor) {
- // TODO(brianwilkerson) We need to finish implementing the accessors used
- // below so that we can safely invoke them.
super.visitChildren(visitor);
+ // ignore: deprecated_member_use_from_same_package
declaration.initializer?.accept(visitor);
}
}
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 92e70c1..1c2938f1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -344,7 +344,7 @@
bool isLocalVariableWithoutDeclaredType(PromotableElement variable) {
return variable is LocalVariableElement &&
variable.hasImplicitType &&
- variable.initializer == null;
+ !variable.hasInitializer;
}
@override
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 7dd4335..81255f6 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -369,14 +369,7 @@
var defaultValue = node.defaultValue;
if (defaultValue != null) {
_withElementWalker(null, () {
- var offset = defaultValue.offset;
- var initializer = FunctionElementImpl.forOffset(offset);
- element.initializer = initializer;
-
- initializer.hasImplicitReturnType = true;
- initializer.isSynthetic = true;
-
- _withElementHolder(ElementHolder(initializer), () {
+ _withElementHolder(ElementHolder(element), () {
defaultValue.accept(this);
});
});
@@ -962,19 +955,13 @@
VariableDeclarationList varList = node.parent;
localElement.hasImplicitType = varList.type == null;
+ localElement.hasInitializer = initializerNode != null;
localElement.type = varList.type?.type ?? _dynamicType;
}
if (initializerNode != null) {
_withElementWalker(null, () {
- var offset = initializerNode.offset;
- var initializer = FunctionElementImpl.forOffset(offset);
- element.initializer = initializer;
-
- initializer.hasImplicitReturnType = true;
- initializer.isSynthetic = true;
-
- _withElementHolder(ElementHolder(initializer), () {
+ _withElementHolder(ElementHolder(element), () {
initializerNode.accept(this);
});
});
diff --git a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
index ce9ed26..fb59963 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
@@ -61,11 +61,6 @@
_setInferredType(element, initializer.staticType);
}
- if (element.initializer != null) {
- var initializerFunction = element.initializer as FunctionElementImpl;
- initializerFunction.returnType = initializer.staticType;
- }
-
if (isTopLevel) {
_flowAnalysis?.topLevelDeclaration_exit();
}
diff --git a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
index efefa53..f3cea21 100644
--- a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
+++ b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
@@ -98,9 +98,9 @@
_initialFieldMap = <FieldElement, _InitState>{};
for (var field in element.fields) {
if (!field.isSynthetic) {
- _initialFieldMap[field] = field.initializer == null
- ? _InitState.notInit
- : _InitState.initInDeclaration;
+ _initialFieldMap[field] = field.hasInitializer
+ ? _InitState.initInDeclaration
+ : _InitState.notInit;
}
}
}
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index cac6440..159b36d 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -422,13 +422,13 @@
var derivedElement = derivedOptionalElements[i];
if (_isNonNullableByDefault &&
derivedIsAbstract &&
- derivedElement.initializer == null) {
+ !derivedElement.hasDefaultValue) {
continue;
}
var name = derivedElement.name;
for (var j = 0; j < baseOptionalElements.length; j++) {
var baseParameter = baseOptionalElements[j];
- if (name == baseParameter.name && baseParameter.initializer != null) {
+ if (name == baseParameter.name && baseParameter.hasDefaultValue) {
var baseValue = baseParameter.computeConstantValue();
var derivedResult = derivedElement.evaluationResult;
if (!_constantValuesEqual(derivedResult.value, baseValue)) {
@@ -453,11 +453,11 @@
var derivedElement = derivedOptionalElements[i];
if (_isNonNullableByDefault &&
derivedIsAbstract &&
- derivedElement.initializer == null) {
+ !derivedElement.hasDefaultValue) {
continue;
}
var baseElement = baseOptionalElements[i];
- if (baseElement.initializer != null) {
+ if (baseElement.hasDefaultValue) {
var baseValue = baseElement.computeConstantValue();
var derivedResult = derivedElement.evaluationResult;
if (!_constantValuesEqual(derivedResult.value, baseValue)) {
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 32fd184..3b5fb67 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1003,10 +1003,6 @@
super.visitDefaultFormalParameter(node);
ParameterElement element = node.declaredElement;
- if (element.initializer != null && node.defaultValue != null) {
- (element.initializer as FunctionElementImpl).returnType =
- node.defaultValue.staticType;
- }
// Clone the ASTs for default formal parameters, so that we can use them
// during constant evaluation.
if (element is ConstVariableElement &&
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index 2bd5727..0918c70 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -11,7 +11,6 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_demotion.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/generated/element_type_provider.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
@@ -197,31 +196,6 @@
}
}
-class _FunctionElementForLink_Initializer
- implements FunctionElementImpl, ElementImplWithFunctionType {
- final _VariableInferenceNode _node;
-
- @override
- Element enclosingElement;
-
- _FunctionElementForLink_Initializer(this._node);
-
- @override
- DartType get returnType =>
- ElementTypeProvider.current.getExecutableReturnType(this);
-
- @override
- DartType get returnTypeInternal {
- if (!_node.isEvaluated) {
- _node._walker.walk(_node);
- }
- return LazyAst.getType(_node._node);
- }
-
- @override
- dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
class _InferenceDependenciesCollector extends RecursiveAstVisitor<void> {
final Set<Element> _set = Set.identity();
@@ -356,14 +330,28 @@
var inferenceNode =
_VariableInferenceNode(_walker, _unitElement, _scope, node);
_walker._nodes[element] = inferenceNode;
- (element as PropertyInducingElementImpl).initializer =
- _FunctionElementForLink_Initializer(inferenceNode);
+ (element as PropertyInducingElementImpl).typeInference =
+ _PropertyInducingElementTypeInference(inferenceNode);
} else {
LazyAst.setType(node, DynamicTypeImpl.instance);
}
}
}
+class _PropertyInducingElementTypeInference
+ implements PropertyInducingElementTypeInference {
+ final _VariableInferenceNode _node;
+
+ _PropertyInducingElementTypeInference(this._node);
+
+ @override
+ void perform() {
+ if (!_node.isEvaluated) {
+ _node._walker.walk(_node);
+ }
+ }
+}
+
class _VariableInferenceNode extends _InferenceNode {
final _InferenceWalker _walker;
final CompilationUnitElement _unitElement;
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index d4f9bc9..7e2636a 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -292,15 +292,7 @@
// Otherwise, declarations of static variables and fields that omit a
// type will be inferred from their initializer if present.
- var initializer = field.initializer;
- if (initializer != null) {
- var initializerType = initializer.returnType;
- if (initializerType == null || initializerType.isDartCoreNull) {
- initializerType = _dynamicType;
- }
- field.type = initializerType;
- return;
- }
+ field.typeInference?.perform();
return;
}
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index e2d78c9..ce9a46b 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.40.0
+version: 0.40.1-dev
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/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 33c55da..0aae50a 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -1056,12 +1056,11 @@
ClassDeclaration c = unit.declarations[0];
FieldDeclaration declaration = c.members[0];
VariableDeclaration field = declaration.fields.variables[0];
- FunctionElement fieldInitializer = field.declaredElement.initializer;
FunctionExpressionInvocation invocation = field.initializer;
FunctionExpression closure = invocation.function.unParenthesized;
FunctionElementImpl closureElement = closure.declaredElement;
- expect(closureElement.enclosingElement, same(fieldInitializer));
+ expect(closureElement, isNotNull);
}
test_closure_inTopLevelVariable() async {
@@ -1073,13 +1072,11 @@
TopLevelVariableDeclaration declaration = unit.declarations[0];
VariableDeclaration variable = declaration.variables.variables[0];
- TopLevelVariableElement variableElement = variable.declaredElement;
- FunctionElement variableInitializer = variableElement.initializer;
FunctionExpressionInvocation invocation = variable.initializer;
FunctionExpression closure = invocation.function.unParenthesized;
FunctionElementImpl closureElement = closure.declaredElement;
- expect(closureElement.enclosingElement, same(variableInitializer));
+ expect(closureElement, isNotNull);
}
test_conditionalExpression() async {
diff --git a/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart b/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
index bc84dbd..970191b 100644
--- a/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
+++ b/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
@@ -192,6 +192,27 @@
);
}
+ void test_fromLegacy_nonNullableBound() {
+ typeSystem = analysisContext.typeSystemLegacy;
+
+ // void Function<T extends Object>(T)
+ var T = typeParameter('T', bound: objectNone);
+ var rawType = functionTypeNone(
+ typeFormals: [T],
+ parameters: [
+ requiredParameter(
+ type: typeParameterTypeNone(T),
+ ),
+ ],
+ returnType: voidNone,
+ );
+
+ _assertTypes(
+ _inferCall(rawType, [dynamicNone]),
+ [dynamicNone],
+ );
+ }
+
void test_genericCastFunction() {
// <TFrom, TTo>(TFrom) -> TTo
var tFrom = typeParameter('TFrom');
diff --git a/pkg/analyzer/test/src/diagnostics/could_not_infer_test.dart b/pkg/analyzer/test/src/diagnostics/could_not_infer_test.dart
index 73ddb62..951fcbd 100644
--- a/pkg/analyzer/test/src/diagnostics/could_not_infer_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/could_not_infer_test.dart
@@ -10,6 +10,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(CouldNotInferTest);
+ defineReflectiveTests(CouldNotInferWithNullSafetyTest);
});
}
@@ -229,10 +230,10 @@
U method<U extends T>(U u) => u;
}
main() {
- new Foo<String>()./*error:COULD_NOT_INFER*/method(42);
+ new Foo<String>().method(42);
}
''', [
- error(CompileTimeErrorCode.COULD_NOT_INFER, 122, 6),
+ error(CompileTimeErrorCode.COULD_NOT_INFER, 97, 6),
]);
}
@@ -247,3 +248,24 @@
]);
}
}
+
+@reflectiveTest
+class CouldNotInferWithNullSafetyTest extends PubPackageResolutionTest
+ with WithNullSafetyMixin {
+ test_constructor_nullSafe_fromLegacy() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+class C<T extends Object> {
+ C(T t);
+}
+''');
+
+ await assertNoErrorsInCode('''
+// @dart = 2.8
+import 'a.dart';
+
+void f(dynamic a) {
+ C(a);
+}
+''');
+ }
+}
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 43f38c7..3484cc7 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -354,26 +354,19 @@
}
test_bottom() async {
- // When a type is inferred from the expression `null`, the inferred type is
- // `dynamic`, but the inferred type of the initializer is `bottom`.
- // TODO(paulberry): Is this intentional/desirable?
await assertNoErrorsInCode('''
var v = null;
''');
var v = _resultUnitElement.topLevelVariables[0];
_assertTypeStr(v.type, 'dynamic');
- _assertTypeStr(v.initializer.type, 'Null Function()');
}
test_bottom_inClosure() async {
- // When a closure's return type is inferred from the expression `null`, the
- // inferred type is `dynamic`.
await assertNoErrorsInCode('''
var v = () => null;
''');
var v = _resultUnitElement.topLevelVariables[0];
_assertTypeStr(v.type, 'Null Function()');
- _assertTypeStr(v.initializer.type, 'Null Function() Function()');
}
test_circularReference_viaClosures() async {
@@ -406,8 +399,8 @@
var y = _resultUnitElement.topLevelVariables[1];
expect(x.name, 'x');
expect(y.name, 'y');
- _assertTypeStr(x.initializer.returnType, 'dynamic Function()');
- _assertTypeStr(y.initializer.returnType, 'dynamic Function()');
+ _assertTypeStr(x.type, 'dynamic');
+ _assertTypeStr(y.type, 'dynamic');
}
test_conflictsCanHappen2() async {
@@ -4117,7 +4110,7 @@
]);
var y = findLocalVariable(_resultUnit, 'y');
- _assertTypeStr(y.initializer.returnType, 'List<num>');
+ _assertTypeStr(y.type, 'List<num>');
}
test_nullLiteralShouldNotInferAsBottom() async {
diff --git a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
index 9dc19fc..8414450 100644
--- a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
@@ -46,6 +46,11 @@
static AbstractBool maybeOrFalse(bool value) => value ? Maybe : False;
+ static AbstractBool strengthen(AbstractBool a, AbstractBool b) {
+ //TODO(coam): Assert arguments a and b are consistent
+ return a.isDefinitelyTrue ? True : (a.isDefinitelyFalse ? False : b);
+ }
+
AbstractBool operator &(AbstractBool other) {
if (isDefinitelyTrue) return other;
if (other.isDefinitelyTrue) return this;
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
new file mode 100644
index 0000000..2078d8a
--- /dev/null
+++ b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
@@ -0,0 +1,326 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../../common_elements.dart' show CommonElements;
+import '../../constants/values.dart';
+import '../../elements/entities.dart';
+import '../../elements/names.dart';
+import '../../elements/types.dart' show DartType, InterfaceType;
+import '../../ir/static_type.dart';
+import '../../universe/selector.dart';
+import '../../world.dart';
+import '../abstract_value_domain.dart';
+
+class PowersetBitsDomain {
+ // This class is used as an API by the powerset abstract value domain to help implement some queries.
+ // It stores the bitmasks as integers and has the advantage that the operations needed
+ // are relatively fast. This will pack multiple powerset domains into a single integer
+
+ final JClosedWorld _closedWorld;
+
+ static const int _trueIndex = 0;
+ static const int _falseIndex = 1;
+ static const int _nullIndex = 2;
+ static const int _otherIndex = 3;
+
+ const PowersetBitsDomain(this._closedWorld);
+
+ CommonElements get commonElements => _closedWorld.commonElements;
+
+ int get trueMask => 1 << _trueIndex;
+ int get falseMask => 1 << _falseIndex;
+ int get nullMask => 1 << _nullIndex;
+ int get otherMask => 1 << _otherIndex;
+ int get boolMask => trueMask | falseMask;
+ int get boolOrNullMask => boolMask | nullMask;
+ int get nullOrOtherMask => nullMask | otherMask;
+ int get boolNullOtherMask => boolOrNullMask | otherMask;
+
+ int get powersetBottom => 0;
+ int get powersetTop => boolNullOtherMask;
+
+ bool isPotentiallyBoolean(int value) => (value & boolMask) != 0;
+ bool isPotentiallyOther(int value) => (value & otherMask) != 0;
+ bool isPotentiallyNull(int value) => (value & nullMask) != 0;
+ bool isPotentiallyBooleanOrNull(int value) => (value & boolOrNullMask) != 0;
+ bool isPotentiallyNullOrOther(int value) => (value & nullOrOtherMask) != 0;
+
+ bool isDefinitelyTrue(int value) => (value & boolNullOtherMask) == trueMask;
+ bool isDefinitelyFalse(int value) => (value & boolNullOtherMask) == falseMask;
+ bool isDefinitelyNull(int value) => (value & boolNullOtherMask) == nullMask;
+ bool isSingleton(int value) =>
+ isDefinitelyTrue(value) ||
+ isDefinitelyFalse(value) ||
+ isDefinitelyNull(value);
+
+ AbstractBool isOther(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+ AbstractBool isNotOther(int value) =>
+ AbstractBool.trueOrMaybe(!isPotentiallyOther(value));
+
+ AbstractBool needsNoSuchMethodHandling(int receiver, Selector selector) =>
+ AbstractBool.Maybe;
+
+ AbstractBool isTargetingMember(
+ int receiver, MemberEntity member, Name name) =>
+ AbstractBool.Maybe;
+
+ int computeReceiver(Iterable<MemberEntity> members) {
+ return powersetTop;
+ }
+
+ // TODO(coam): This currently returns null if we are not sure if it's a primitive.
+ // It could be improved because we can also tell when we're certain it's not a primitive.
+ PrimitiveConstantValue getPrimitiveValue(int value) {
+ if (isDefinitelyTrue(value)) {
+ return TrueConstantValue();
+ }
+ if (isDefinitelyFalse(value)) {
+ return FalseConstantValue();
+ }
+ if (isDefinitelyNull(value)) {
+ return NullConstantValue();
+ }
+ return null;
+ }
+
+ int createPrimitiveValue(PrimitiveConstantValue value) {
+ if (value is TrueConstantValue) {
+ return trueMask;
+ }
+ if (value is FalseConstantValue) {
+ return falseMask;
+ }
+ if (value is NullConstantValue) {
+ return nullMask;
+ }
+ return otherMask;
+ }
+
+ // TODO(coam): Same as getPrimitiveValue above.
+ bool isPrimitiveValue(int value) => isSingleton(value);
+
+ AbstractBool areDisjoint(int a, int b) =>
+ AbstractBool.trueOrMaybe(a & b == powersetBottom);
+
+ int intersection(int a, int b) {
+ return a & b;
+ }
+
+ int union(int a, int b) {
+ return a | b;
+ }
+
+ AbstractBool isPrimitiveOrNull(int value) =>
+ isPrimitive(value) | isNull(value);
+
+ AbstractBool isStringOrNull(int value) => isString(value) | isNull(value);
+
+ AbstractBool isString(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isBooleanOrNull(int value) => isBoolean(value) | isNull(value);
+
+ AbstractBool isBoolean(int value) => isPotentiallyBoolean(value)
+ ? AbstractBool.trueOrMaybe(!isPotentiallyNullOrOther(value))
+ : AbstractBool.False;
+
+ AbstractBool isDoubleOrNull(int value) => isDouble(value) | isNull(value);
+
+ AbstractBool isDouble(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isNumberOrNull(int value) => isNumber(value) | isNull(value);
+
+ AbstractBool isNumber(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isIntegerOrNull(int value) => isDouble(value) | isNull(value);
+
+ AbstractBool isPositiveIntegerOrNull(int value) =>
+ isPositiveInteger(value) | isNull(value);
+
+ AbstractBool isPositiveInteger(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isUInt31(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isUInt32(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isInteger(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isInterceptor(int value) => AbstractBool.Maybe;
+
+ AbstractBool isPrimitiveString(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isArray(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isMutableIndexable(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isMutableArray(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isExtendableArray(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isFixedArray(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isIndexablePrimitive(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isPrimitiveArray(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isPrimitiveBoolean(int value) => isPotentiallyBoolean(value)
+ ? AbstractBool.trueOrMaybe(
+ isDefinitelyTrue(value) || isDefinitelyFalse(value))
+ : AbstractBool.False;
+
+ AbstractBool isPrimitiveNumber(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isPrimitive(int value) =>
+ AbstractBool.trueOrMaybe(isSingleton(value));
+
+ AbstractBool isNull(int value) => isDefinitelyNull(value)
+ ? AbstractBool.True
+ : (isPotentiallyNull(value) ? AbstractBool.Maybe : AbstractBool.False);
+
+ AbstractBool isExactOrNull(int value) => AbstractBool.Maybe;
+
+ AbstractBool isExact(int value) => AbstractBool.Maybe;
+
+ AbstractBool isEmpty(int value) =>
+ AbstractBool.trueOrFalse(value == powersetBottom);
+
+ AbstractBool isInstanceOf(int value, ClassEntity cls) => AbstractBool.Maybe;
+
+ AbstractBool isInstanceOfOrNull(int value, ClassEntity cls) =>
+ AbstractBool.Maybe;
+
+ AbstractBool containsOnlyType(int value, ClassEntity cls) =>
+ AbstractBool.Maybe;
+
+ AbstractBool containsType(int value, ClassEntity cls) => AbstractBool.Maybe;
+
+ int includeNull(int value) {
+ return value | nullMask;
+ }
+
+ int excludeNull(int value) {
+ return value & (powersetTop - nullMask);
+ }
+
+ AbstractBool couldBeTypedArray(int value) =>
+ AbstractBool.maybeOrFalse(isPotentiallyOther(value));
+
+ AbstractBool isTypedArray(int value) => AbstractBool.Maybe;
+
+ bool isBoolSubtype(ClassEntity cls) {
+ return cls == commonElements.jsBoolClass || cls == commonElements.boolClass;
+ }
+
+ int createNullableSubtype(ClassEntity cls) {
+ if (isBoolSubtype(cls)) {
+ return boolOrNullMask;
+ }
+ return nullOrOtherMask;
+ }
+
+ int createNonNullSubtype(ClassEntity cls) {
+ if (isBoolSubtype(cls)) {
+ return boolMask;
+ }
+ return otherMask;
+ }
+
+ int createNonNullSubclass(ClassEntity cls) {
+ if (isBoolSubtype(cls)) {
+ return boolMask;
+ }
+ return otherMask;
+ }
+
+ int createNullableExact(ClassEntity cls) {
+ if (isBoolSubtype(cls)) {
+ return boolOrNullMask;
+ }
+ return nullOrOtherMask;
+ }
+
+ int createNonNullExact(ClassEntity cls) {
+ if (isBoolSubtype(cls)) {
+ return boolMask;
+ }
+ return otherMask;
+ }
+
+ int createFromStaticType(DartType type,
+ {ClassRelation classRelation = ClassRelation.subtype, bool nullable}) {
+ // TODO(coam): This only works for bool
+ int bits = otherMask;
+ if (type is InterfaceType && isBoolSubtype(type.element)) {
+ bits = boolMask;
+ }
+ if (nullable) {
+ bits = bits | nullMask;
+ }
+ return bits;
+ }
+
+ int get asyncStarStreamType => powersetTop;
+
+ int get asyncFutureType => powersetTop;
+
+ int get syncStarIterableType => powersetTop;
+
+ int get emptyType => powersetBottom;
+
+ int get constMapType => otherMask;
+
+ int get constSetType => otherMask;
+
+ int get constListType => otherMask;
+
+ int get positiveIntType => otherMask;
+
+ int get uint32Type => otherMask;
+
+ int get uint31Type => otherMask;
+
+ int get fixedListType => otherMask;
+
+ int get growableListType => otherMask;
+
+ int get nullType => nullMask;
+
+ int get nonNullType => otherMask;
+
+ int get mapType => otherMask;
+
+ int get setType => otherMask;
+
+ int get listType => otherMask;
+
+ int get stringType => otherMask;
+
+ int get numType => otherMask;
+
+ int get doubleType => otherMask;
+
+ int get intType => otherMask;
+
+ int get boolType => boolMask;
+
+ int get functionType => otherMask;
+
+ int get typeType => otherMask;
+}
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powersets.dart b/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
index 60f9253..91eb49a 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
@@ -13,12 +13,16 @@
import '../../universe/use.dart';
import '../../world.dart';
import '../abstract_value_domain.dart';
+import 'powerset_bits.dart';
class PowersetValue implements AbstractValue {
final AbstractValue _abstractValue;
final int _powersetBits;
const PowersetValue(this._abstractValue, this._powersetBits);
+ AbstractValue get abstractValue => _abstractValue;
+ int get powersetBits => _powersetBits;
+
@override
bool operator ==(var other) {
if (identical(this, other)) return true;
@@ -51,15 +55,19 @@
class PowersetDomain implements AbstractValueDomain {
final AbstractValueDomain _abstractValueDomain;
- const PowersetDomain(this._abstractValueDomain);
+ final PowersetBitsDomain _powersetBitsDomain;
+
+ const PowersetDomain(this._abstractValueDomain, this._powersetBitsDomain);
+
+ PowersetBitsDomain get powersetBitsDomain => _powersetBitsDomain;
@override
AbstractValue get dynamicType {
- int powersetBits = 0;
AbstractValue abstractValue = _abstractValueDomain.dynamicType;
- return PowersetValue(abstractValue, powersetBits);
+ return PowersetValue(abstractValue, _powersetBitsDomain.powersetTop);
}
+ //TODO(coam)
@override
void writeAbstractValueToDataSink(
DataSink sink, covariant PowersetValue value) {
@@ -67,29 +75,37 @@
sink, value._abstractValue);
}
+ //TODO(coam)
@override
AbstractValue readAbstractValueFromDataSource(DataSource source) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.powersetTop;
AbstractValue abstractValue =
_abstractValueDomain.readAbstractValueFromDataSource(source);
return PowersetValue(abstractValue, powersetBits);
}
+ //TODO(coam)
@override
String getCompactText(covariant PowersetValue value) =>
_abstractValueDomain.getCompactText(value._abstractValue);
@override
AbstractBool isFixedLengthJsIndexable(covariant PowersetValue value) =>
- _abstractValueDomain.isFixedLengthJsIndexable(value._abstractValue);
+ _powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue
+ ? AbstractBool.False
+ : _abstractValueDomain.isFixedLengthJsIndexable(value._abstractValue);
@override
AbstractBool isJsIndexableAndIterable(covariant PowersetValue value) =>
- _abstractValueDomain.isJsIndexableAndIterable(unwrapOrNull(value));
+ _powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue
+ ? AbstractBool.False
+ : _abstractValueDomain.isJsIndexableAndIterable(unwrapOrNull(value));
@override
AbstractBool isJsIndexable(covariant PowersetValue value) =>
- _abstractValueDomain.isJsIndexable(value._abstractValue);
+ _powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue
+ ? AbstractBool.False
+ : _abstractValueDomain.isJsIndexable(value._abstractValue);
@override
MemberEntity locateSingleMember(
@@ -97,10 +113,14 @@
_abstractValueDomain.locateSingleMember(
receiver._abstractValue, selector);
+ //TODO(coam): for now we are delegating this implementation to the CommonMasks domain
@override
AbstractBool isIn(
- covariant PowersetValue subset, covariant PowersetValue superset) =>
- _abstractValueDomain.isIn(subset._abstractValue, superset._abstractValue);
+ covariant PowersetValue subset, covariant PowersetValue superset) {
+ AbstractBool wrappedBool = _abstractValueDomain.isIn(
+ subset._abstractValue, superset._abstractValue);
+ return wrappedBool;
+ }
@override
AbstractBool needsNoSuchMethodHandling(
@@ -116,19 +136,20 @@
@override
AbstractValue computeReceiver(Iterable<MemberEntity> members) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.powersetTop;
AbstractValue abstractValue = _abstractValueDomain.computeReceiver(members);
return PowersetValue(abstractValue, powersetBits);
}
@override
PrimitiveConstantValue getPrimitiveValue(covariant PowersetValue value) =>
+ _powersetBitsDomain.getPrimitiveValue(value.powersetBits) ??
_abstractValueDomain.getPrimitiveValue(value._abstractValue);
@override
AbstractValue createPrimitiveValue(
covariant PowersetValue originalValue, PrimitiveConstantValue value) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.createPrimitiveValue(value);
AbstractValue abstractValue = _abstractValueDomain.createPrimitiveValue(
originalValue._abstractValue, value);
return PowersetValue(abstractValue, powersetBits);
@@ -136,6 +157,7 @@
@override
bool isPrimitiveValue(covariant PowersetValue value) =>
+ _powersetBitsDomain.isPrimitiveValue(value.powersetBits) ||
_abstractValueDomain.isPrimitiveValue(value._abstractValue);
@override
@@ -148,7 +170,7 @@
@override
AbstractValue getGeneralization(covariant PowersetValue value) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.powersetTop;
AbstractValue abstractValue =
_abstractValueDomain.getGeneralization(unwrapOrNull(value));
return PowersetValue(abstractValue, powersetBits);
@@ -163,14 +185,17 @@
@override
AbstractValue getDictionaryValueForKey(
covariant PowersetValue value, String key) {
- int powersetBits = 0;
+ if (_powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue) {
+ return dynamicType;
+ }
AbstractValue abstractValue = _abstractValueDomain.getDictionaryValueForKey(
value._abstractValue, key);
- return PowersetValue(abstractValue, powersetBits);
+ return PowersetValue(abstractValue, _powersetBitsDomain.powersetTop);
}
@override
bool containsDictionaryKey(covariant PowersetValue value, String key) =>
+ _powersetBitsDomain.isNotOther(value._powersetBits).isPotentiallyFalse &&
_abstractValueDomain.containsDictionaryKey(value._abstractValue, key);
@override
@@ -181,7 +206,7 @@
covariant PowersetValue key,
covariant PowersetValue value,
covariant Map<String, AbstractValue> mappings) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.otherMask;
AbstractValue abstractValue = _abstractValueDomain.createDictionaryValue(
originalValue._abstractValue,
allocationNode,
@@ -196,22 +221,27 @@
@override
bool isDictionary(covariant PowersetValue value) =>
+ !_powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue &&
_abstractValueDomain.isDictionary(value._abstractValue);
@override
AbstractValue getMapValueType(covariant PowersetValue value) {
- int powersetBits = 0;
+ if (_powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue) {
+ return dynamicType;
+ }
AbstractValue abstractValue =
_abstractValueDomain.getMapValueType(value._abstractValue);
- return PowersetValue(abstractValue, powersetBits);
+ return PowersetValue(abstractValue, _powersetBitsDomain.powersetTop);
}
@override
AbstractValue getMapKeyType(covariant PowersetValue value) {
- int powersetBits = 0;
+ if (_powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue) {
+ return dynamicType;
+ }
AbstractValue abstractValue =
- _abstractValueDomain.getMapKeyType(value._abstractValue);
- return PowersetValue(abstractValue, powersetBits);
+ _abstractValueDomain.getMapValueType(value._abstractValue);
+ return PowersetValue(abstractValue, _powersetBitsDomain.powersetTop);
}
@override
@@ -221,7 +251,7 @@
MemberEntity allocationElement,
covariant PowersetValue key,
covariant PowersetValue value) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.otherMask;
AbstractValue abstractValue = _abstractValueDomain.createMapValue(
originalValue._abstractValue,
allocationNode,
@@ -233,14 +263,17 @@
@override
bool isMap(covariant PowersetValue value) =>
+ !_powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue &&
_abstractValueDomain.isMap(value._abstractValue);
@override
AbstractValue getSetElementType(covariant PowersetValue value) {
- int powersetBits = 0;
+ if (_powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue) {
+ return dynamicType;
+ }
AbstractValue abstractValue =
_abstractValueDomain.getSetElementType(value._abstractValue);
- return PowersetValue(abstractValue, powersetBits);
+ return PowersetValue(abstractValue, _powersetBitsDomain.powersetTop);
}
@override
@@ -249,7 +282,7 @@
Object allocationNode,
MemberEntity allocationElement,
covariant PowersetValue elementType) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.otherMask;
AbstractValue abstractValue = _abstractValueDomain.createSetValue(
originalValue._abstractValue,
allocationNode,
@@ -260,18 +293,23 @@
@override
bool isSet(covariant PowersetValue value) =>
+ !_powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue &&
_abstractValueDomain.isSet(value._abstractValue);
@override
int getContainerLength(covariant PowersetValue value) =>
- _abstractValueDomain.getContainerLength(value._abstractValue);
+ _powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue
+ ? null
+ : _abstractValueDomain.getContainerLength(value._abstractValue);
@override
AbstractValue getContainerElementType(covariant PowersetValue value) {
- int powersetBits = 0;
+ if (_powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue) {
+ return dynamicType;
+ }
AbstractValue abstractValue =
_abstractValueDomain.getContainerElementType(value._abstractValue);
- return PowersetValue(abstractValue, powersetBits);
+ return PowersetValue(abstractValue, _powersetBitsDomain.powersetTop);
}
@override
@@ -281,7 +319,7 @@
MemberEntity allocationElement,
covariant PowersetValue elementType,
int length) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.otherMask;
AbstractValue abstractValue = _abstractValueDomain.createContainerValue(
originalValue._abstractValue,
allocationNode,
@@ -293,11 +331,14 @@
@override
bool isContainer(covariant PowersetValue value) =>
+ !_powersetBitsDomain.isNotOther(value._powersetBits).isDefinitelyTrue &&
_abstractValueDomain.isContainer(value._abstractValue);
+ // TODO(coam): this can be more precise if we build a ConstantValue visitor
+ // that can tell us information about the bits given a ConstantValue
@override
AbstractValue computeAbstractValueForConstant(covariant ConstantValue value) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.powersetTop;
AbstractValue abstractValue =
_abstractValueDomain.computeAbstractValueForConstant(value);
return PowersetValue(abstractValue, powersetBits);
@@ -305,7 +346,7 @@
@override
AbstractValue getAbstractValueForNativeMethodParameterType(DartType type) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.powersetTop;
AbstractValue abstractValue =
_abstractValueDomain.getAbstractValueForNativeMethodParameterType(type);
return wrapOrNull(abstractValue, powersetBits);
@@ -313,17 +354,22 @@
@override
AbstractBool containsAll(covariant PowersetValue a) =>
- _abstractValueDomain.containsAll(a._abstractValue);
+ a._powersetBits != _powersetBitsDomain.powersetTop
+ ? AbstractBool.False
+ : _abstractValueDomain.containsAll(a._abstractValue);
@override
AbstractBool areDisjoint(
covariant PowersetValue a, covariant PowersetValue b) =>
- _abstractValueDomain.areDisjoint(a._abstractValue, b._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.areDisjoint(a._powersetBits, b._powersetBits),
+ _abstractValueDomain.areDisjoint(a._abstractValue, b._abstractValue));
@override
AbstractValue intersection(
covariant PowersetValue a, covariant PowersetValue b) {
- int powersetBits = 0;
+ int powersetBits =
+ _powersetBitsDomain.intersection(a._powersetBits, b._powersetBits);
AbstractValue abstractValue =
_abstractValueDomain.intersection(a._abstractValue, b._abstractValue);
return PowersetValue(abstractValue, powersetBits);
@@ -331,18 +377,18 @@
@override
AbstractValue unionOfMany(covariant Iterable<AbstractValue> values) {
- List<AbstractValue> unwrapped_Values = values
- .map((element) => (element as PowersetValue)._abstractValue)
- .toList();
- int powersetBits = 0;
- AbstractValue abstractValue =
- _abstractValueDomain.unionOfMany(unwrapped_Values);
- return PowersetValue(abstractValue, powersetBits);
+ PowersetValue result = PowersetValue(
+ _abstractValueDomain.emptyType, _powersetBitsDomain.powersetBottom);
+ for (PowersetValue value in values) {
+ result = union(result, value);
+ }
+ return result;
}
@override
AbstractValue union(covariant PowersetValue a, covariant PowersetValue b) {
- int powersetBits = 0;
+ int powersetBits =
+ _powersetBitsDomain.union(a._powersetBits, b._powersetBits);
AbstractValue abstractValue =
_abstractValueDomain.union(a._abstractValue, b._abstractValue);
return PowersetValue(abstractValue, powersetBits);
@@ -350,115 +396,164 @@
@override
AbstractBool isPrimitiveOrNull(covariant PowersetValue value) =>
- _abstractValueDomain.isPrimitiveOrNull(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isPrimitiveOrNull(value._powersetBits),
+ _abstractValueDomain.isPrimitiveOrNull(value._abstractValue));
@override
AbstractBool isStringOrNull(covariant PowersetValue value) =>
- _abstractValueDomain.isStringOrNull(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isStringOrNull(value._powersetBits),
+ _abstractValueDomain.isStringOrNull(value._abstractValue));
@override
AbstractBool isString(covariant PowersetValue value) =>
- _abstractValueDomain.isString(value._abstractValue);
+ AbstractBool.strengthen(_powersetBitsDomain.isString(value._powersetBits),
+ _abstractValueDomain.isString(value._abstractValue));
@override
AbstractBool isBooleanOrNull(covariant PowersetValue value) =>
- _abstractValueDomain.isBooleanOrNull(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isBooleanOrNull(value._powersetBits),
+ _abstractValueDomain.isBooleanOrNull(value._abstractValue));
@override
AbstractBool isBoolean(covariant PowersetValue value) =>
- _abstractValueDomain.isBoolean(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isBoolean(value._powersetBits),
+ _abstractValueDomain.isBoolean(value._abstractValue));
@override
AbstractBool isDoubleOrNull(covariant PowersetValue value) =>
- _abstractValueDomain.isDoubleOrNull(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isDoubleOrNull(value._powersetBits),
+ _abstractValueDomain.isDoubleOrNull(value._abstractValue));
@override
AbstractBool isDouble(covariant PowersetValue value) =>
- _abstractValueDomain.isDouble(value._abstractValue);
+ AbstractBool.strengthen(_powersetBitsDomain.isDouble(value._powersetBits),
+ _abstractValueDomain.isDouble(value._abstractValue));
@override
AbstractBool isNumberOrNull(covariant PowersetValue value) =>
- _abstractValueDomain.isNumberOrNull(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isNumberOrNull(value._powersetBits),
+ _abstractValueDomain.isNumberOrNull(value._abstractValue));
@override
AbstractBool isNumber(covariant PowersetValue value) =>
- _abstractValueDomain.isNumber(value._abstractValue);
+ AbstractBool.strengthen(_powersetBitsDomain.isNumber(value._powersetBits),
+ _abstractValueDomain.isNumber(value._abstractValue));
@override
AbstractBool isIntegerOrNull(covariant PowersetValue value) =>
- _abstractValueDomain.isIntegerOrNull(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isIntegerOrNull(value._powersetBits),
+ _abstractValueDomain.isIntegerOrNull(value._abstractValue));
@override
AbstractBool isPositiveIntegerOrNull(covariant PowersetValue value) =>
- _abstractValueDomain.isPositiveIntegerOrNull(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isPositiveIntegerOrNull(value._powersetBits),
+ _abstractValueDomain.isPositiveIntegerOrNull(value._abstractValue));
@override
AbstractBool isPositiveInteger(covariant PowersetValue value) =>
- _abstractValueDomain.isPositiveInteger(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isPositiveInteger(value._powersetBits),
+ _abstractValueDomain.isPositiveInteger(value._abstractValue));
@override
AbstractBool isUInt31(covariant PowersetValue value) =>
- _abstractValueDomain.isUInt31(value._abstractValue);
+ AbstractBool.strengthen(_powersetBitsDomain.isUInt31(value._powersetBits),
+ _abstractValueDomain.isUInt31(value._abstractValue));
@override
AbstractBool isUInt32(covariant PowersetValue value) =>
- _abstractValueDomain.isUInt32(value._abstractValue);
+ AbstractBool.strengthen(_powersetBitsDomain.isUInt32(value._powersetBits),
+ _abstractValueDomain.isUInt32(value._abstractValue));
@override
AbstractBool isInteger(covariant PowersetValue value) =>
- _abstractValueDomain.isInteger(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isInteger(value._powersetBits),
+ _abstractValueDomain.isInteger(value._abstractValue));
@override
AbstractBool isInterceptor(covariant PowersetValue value) =>
- _abstractValueDomain.isInterceptor(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isInterceptor(value._powersetBits),
+ _abstractValueDomain.isInterceptor(value._abstractValue));
@override
AbstractBool isPrimitiveString(covariant PowersetValue value) =>
- _abstractValueDomain.isPrimitiveString(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isPrimitiveString(value._powersetBits),
+ _abstractValueDomain.isPrimitiveString(value._abstractValue));
@override
AbstractBool isArray(covariant PowersetValue value) =>
- _abstractValueDomain.isArray(value._abstractValue);
+ AbstractBool.strengthen(_powersetBitsDomain.isArray(value._powersetBits),
+ _abstractValueDomain.isArray(value._abstractValue));
@override
AbstractBool isMutableIndexable(covariant PowersetValue value) =>
- _abstractValueDomain.isMutableIndexable(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isMutableIndexable(value._powersetBits),
+ _abstractValueDomain.isMutableIndexable(value._abstractValue));
@override
AbstractBool isMutableArray(covariant PowersetValue value) =>
- _abstractValueDomain.isMutableArray(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isMutableArray(value._powersetBits),
+ _abstractValueDomain.isMutableArray(value._abstractValue));
@override
AbstractBool isExtendableArray(covariant PowersetValue value) =>
- _abstractValueDomain.isExtendableArray(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isExtendableArray(value._powersetBits),
+ _abstractValueDomain.isExtendableArray(value._abstractValue));
@override
AbstractBool isFixedArray(covariant PowersetValue value) =>
- _abstractValueDomain.isFixedArray(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isFixedArray(value._powersetBits),
+ _abstractValueDomain.isFixedArray(value._abstractValue));
@override
AbstractBool isIndexablePrimitive(covariant PowersetValue value) =>
- _abstractValueDomain.isIndexablePrimitive(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isIndexablePrimitive(value._powersetBits),
+ _abstractValueDomain.isIndexablePrimitive(value._abstractValue));
@override
AbstractBool isPrimitiveArray(covariant PowersetValue value) =>
- _abstractValueDomain.isPrimitiveArray(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isPrimitiveArray(value._powersetBits),
+ _abstractValueDomain.isPrimitiveArray(value._abstractValue));
@override
AbstractBool isPrimitiveBoolean(covariant PowersetValue value) =>
- _abstractValueDomain.isPrimitiveBoolean(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isPrimitiveBoolean(value._powersetBits),
+ _abstractValueDomain.isPrimitiveBoolean(value._abstractValue));
@override
AbstractBool isPrimitiveNumber(covariant PowersetValue value) =>
- _abstractValueDomain.isPrimitiveNumber(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isPrimitiveNumber(value._powersetBits),
+ _abstractValueDomain.isPrimitiveNumber(value._abstractValue));
@override
AbstractBool isPrimitive(covariant PowersetValue value) =>
- _abstractValueDomain.isPrimitive(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isPrimitive(value._powersetBits),
+ _abstractValueDomain.isPrimitive(value._abstractValue));
@override
- AbstractBool isNull(covariant PowersetValue value) =>
- _abstractValueDomain.isNull(value._abstractValue);
+ AbstractBool isNull(covariant PowersetValue value) => AbstractBool.strengthen(
+ _powersetBitsDomain.isNull(value._powersetBits),
+ _abstractValueDomain.isNull(value._abstractValue));
@override
ClassEntity getExactClass(covariant PowersetValue value) =>
@@ -466,37 +561,50 @@
@override
AbstractBool isExactOrNull(covariant PowersetValue value) =>
- _abstractValueDomain.isExactOrNull(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isExactOrNull(value._powersetBits),
+ _abstractValueDomain.isExactOrNull(value._abstractValue));
@override
AbstractBool isExact(covariant PowersetValue value) =>
- _abstractValueDomain.isExact(value._abstractValue);
+ AbstractBool.strengthen(_powersetBitsDomain.isExact(value._powersetBits),
+ _abstractValueDomain.isExact(value._abstractValue));
+ // TODO(coam): For now we delegate this to the CommonMasks domain
@override
- AbstractBool isEmpty(covariant PowersetValue value) =>
- _abstractValueDomain.isEmpty(value._abstractValue);
+ AbstractBool isEmpty(covariant PowersetValue value) {
+ return _abstractValueDomain.isEmpty(value._abstractValue);
+ }
@override
AbstractBool isInstanceOf(covariant PowersetValue value, ClassEntity cls) =>
- _abstractValueDomain.isInstanceOf(value._abstractValue, cls);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isInstanceOf(value._powersetBits, cls),
+ _abstractValueDomain.isInstanceOf(value._abstractValue, cls));
@override
AbstractBool isInstanceOfOrNull(
covariant PowersetValue value, ClassEntity cls) =>
- _abstractValueDomain.isInstanceOfOrNull(value._abstractValue, cls);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isInstanceOfOrNull(value._powersetBits, cls),
+ _abstractValueDomain.isInstanceOfOrNull(value._abstractValue, cls));
@override
AbstractBool containsOnlyType(
covariant PowersetValue value, ClassEntity cls) =>
- _abstractValueDomain.containsOnlyType(value._abstractValue, cls);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.containsOnlyType(value._powersetBits, cls),
+ _abstractValueDomain.containsOnlyType(value._abstractValue, cls));
@override
AbstractBool containsType(covariant PowersetValue value, ClassEntity cls) =>
- _abstractValueDomain.containsType(value._abstractValue, cls);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.containsType(value._powersetBits, cls),
+ _abstractValueDomain.containsType(value._abstractValue, cls));
@override
AbstractValue includeNull(covariant PowersetValue value) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.includeNull(value._powersetBits);
AbstractValue abstractValue =
_abstractValueDomain.includeNull(value._abstractValue);
return PowersetValue(abstractValue, powersetBits);
@@ -504,7 +612,7 @@
@override
AbstractValue excludeNull(covariant PowersetValue value) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.excludeNull(value._powersetBits);
AbstractValue abstractValue =
_abstractValueDomain.excludeNull(value._abstractValue);
return PowersetValue(abstractValue, powersetBits);
@@ -512,15 +620,19 @@
@override
AbstractBool couldBeTypedArray(covariant PowersetValue value) =>
- _abstractValueDomain.couldBeTypedArray(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.couldBeTypedArray(value._powersetBits),
+ _abstractValueDomain.couldBeTypedArray(value._abstractValue));
@override
AbstractBool isTypedArray(covariant PowersetValue value) =>
- _abstractValueDomain.isTypedArray(value._abstractValue);
+ AbstractBool.strengthen(
+ _powersetBitsDomain.isTypedArray(value._powersetBits),
+ _abstractValueDomain.isTypedArray(value._abstractValue));
@override
AbstractValue createNullableSubtype(ClassEntity cls) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.createNullableSubtype(cls);
AbstractValue abstractValue =
_abstractValueDomain.createNullableSubtype(cls);
return PowersetValue(abstractValue, powersetBits);
@@ -528,7 +640,7 @@
@override
AbstractValue createNonNullSubtype(ClassEntity cls) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.createNonNullSubtype(cls);
AbstractValue abstractValue =
_abstractValueDomain.createNonNullSubtype(cls);
return PowersetValue(abstractValue, powersetBits);
@@ -536,7 +648,7 @@
@override
AbstractValue createNonNullSubclass(ClassEntity cls) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.createNonNullSubclass(cls);
AbstractValue abstractValue =
_abstractValueDomain.createNonNullSubclass(cls);
return PowersetValue(abstractValue, powersetBits);
@@ -544,14 +656,14 @@
@override
AbstractValue createNullableExact(ClassEntity cls) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.createNullableExact(cls);
AbstractValue abstractValue = _abstractValueDomain.createNullableExact(cls);
return PowersetValue(abstractValue, powersetBits);
}
@override
AbstractValue createNonNullExact(ClassEntity cls) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.createNonNullExact(cls);
AbstractValue abstractValue = _abstractValueDomain.createNonNullExact(cls);
return PowersetValue(abstractValue, powersetBits);
}
@@ -559,7 +671,8 @@
@override
AbstractValueWithPrecision createFromStaticType(DartType type,
{ClassRelation classRelation = ClassRelation.subtype, bool nullable}) {
- int powersetBits = 0;
+ int powersetBits = _powersetBitsDomain.createFromStaticType(type,
+ classRelation: classRelation, nullable: nullable);
var unwrapped = _abstractValueDomain.createFromStaticType(type,
classRelation: classRelation, nullable: nullable);
return AbstractValueWithPrecision(
@@ -568,92 +681,105 @@
}
@override
- AbstractValue get asyncStarStreamType =>
- PowersetValue(_abstractValueDomain.asyncStarStreamType, 0);
+ AbstractValue get asyncStarStreamType => PowersetValue(
+ _abstractValueDomain.asyncStarStreamType,
+ _powersetBitsDomain.asyncStarStreamType);
@override
- AbstractValue get asyncFutureType =>
- PowersetValue(_abstractValueDomain.asyncFutureType, 0);
+ AbstractValue get asyncFutureType => PowersetValue(
+ _abstractValueDomain.asyncFutureType,
+ _powersetBitsDomain.asyncFutureType);
@override
- AbstractValue get syncStarIterableType =>
- PowersetValue(_abstractValueDomain.syncStarIterableType, 0);
+ AbstractValue get syncStarIterableType => PowersetValue(
+ _abstractValueDomain.syncStarIterableType,
+ _powersetBitsDomain.syncStarIterableType);
@override
- AbstractValue get emptyType =>
- PowersetValue(_abstractValueDomain.emptyType, 0);
+ AbstractValue get emptyType => PowersetValue(
+ _abstractValueDomain.emptyType, _powersetBitsDomain.emptyType);
@override
- AbstractValue get constMapType =>
- PowersetValue(_abstractValueDomain.constMapType, 0);
+ AbstractValue get constMapType => PowersetValue(
+ _abstractValueDomain.constMapType, _powersetBitsDomain.constMapType);
@override
- AbstractValue get constSetType =>
- PowersetValue(_abstractValueDomain.constSetType, 0);
+ AbstractValue get constSetType => PowersetValue(
+ _abstractValueDomain.constSetType, _powersetBitsDomain.constSetType);
@override
- AbstractValue get constListType =>
- PowersetValue(_abstractValueDomain.constListType, 0);
+ AbstractValue get constListType => PowersetValue(
+ _abstractValueDomain.constListType, _powersetBitsDomain.constListType);
@override
- AbstractValue get positiveIntType =>
- PowersetValue(_abstractValueDomain.positiveIntType, 0);
+ AbstractValue get positiveIntType => PowersetValue(
+ _abstractValueDomain.positiveIntType,
+ _powersetBitsDomain.positiveIntType);
@override
- AbstractValue get uint32Type =>
- PowersetValue(_abstractValueDomain.uint32Type, 0);
+ AbstractValue get uint32Type => PowersetValue(
+ _abstractValueDomain.uint32Type, _powersetBitsDomain.uint32Type);
@override
- AbstractValue get uint31Type =>
- PowersetValue(_abstractValueDomain.uint31Type, 0);
+ AbstractValue get uint31Type => PowersetValue(
+ _abstractValueDomain.uint31Type, _powersetBitsDomain.uint31Type);
@override
- AbstractValue get fixedListType =>
- PowersetValue(_abstractValueDomain.fixedListType, 0);
+ AbstractValue get fixedListType => PowersetValue(
+ _abstractValueDomain.fixedListType, _powersetBitsDomain.fixedListType);
@override
- AbstractValue get growableListType =>
- PowersetValue(_abstractValueDomain.growableListType, 0);
+ AbstractValue get growableListType => PowersetValue(
+ _abstractValueDomain.growableListType,
+ _powersetBitsDomain.growableListType);
@override
- AbstractValue get nullType => PowersetValue(_abstractValueDomain.nullType, 0);
+ AbstractValue get nullType => PowersetValue(
+ _abstractValueDomain.nullType, _powersetBitsDomain.nullType);
@override
- AbstractValue get nonNullType =>
- PowersetValue(_abstractValueDomain.nonNullType, 0);
+ AbstractValue get nonNullType => PowersetValue(
+ _abstractValueDomain.nonNullType, _powersetBitsDomain.nonNullType);
@override
- AbstractValue get mapType => PowersetValue(_abstractValueDomain.mapType, 0);
+ AbstractValue get mapType =>
+ PowersetValue(_abstractValueDomain.mapType, _powersetBitsDomain.mapType);
@override
- AbstractValue get setType => PowersetValue(_abstractValueDomain.setType, 0);
+ AbstractValue get setType =>
+ PowersetValue(_abstractValueDomain.setType, _powersetBitsDomain.setType);
@override
- AbstractValue get listType => PowersetValue(_abstractValueDomain.listType, 0);
+ AbstractValue get listType => PowersetValue(
+ _abstractValueDomain.listType, _powersetBitsDomain.listType);
@override
- AbstractValue get stringType =>
- PowersetValue(_abstractValueDomain.stringType, 0);
+ AbstractValue get stringType => PowersetValue(
+ _abstractValueDomain.stringType, _powersetBitsDomain.stringType);
@override
- AbstractValue get numType => PowersetValue(_abstractValueDomain.numType, 0);
+ AbstractValue get numType =>
+ PowersetValue(_abstractValueDomain.numType, _powersetBitsDomain.numType);
@override
- AbstractValue get doubleType =>
- PowersetValue(_abstractValueDomain.doubleType, 0);
+ AbstractValue get doubleType => PowersetValue(
+ _abstractValueDomain.doubleType, _powersetBitsDomain.doubleType);
@override
- AbstractValue get intType => PowersetValue(_abstractValueDomain.intType, 0);
+ AbstractValue get intType =>
+ PowersetValue(_abstractValueDomain.intType, _powersetBitsDomain.intType);
@override
- AbstractValue get boolType => PowersetValue(_abstractValueDomain.boolType, 0);
+ AbstractValue get boolType => PowersetValue(
+ _abstractValueDomain.boolType, _powersetBitsDomain.boolType);
@override
- AbstractValue get functionType =>
- PowersetValue(_abstractValueDomain.functionType, 0);
+ AbstractValue get functionType => PowersetValue(
+ _abstractValueDomain.functionType, _powersetBitsDomain.functionType);
@override
- AbstractValue get typeType => PowersetValue(_abstractValueDomain.typeType, 0);
+ AbstractValue get typeType => PowersetValue(
+ _abstractValueDomain.typeType, _powersetBitsDomain.typeType);
}
class PowersetStrategy implements AbstractValueStrategy {
@@ -662,7 +788,8 @@
@override
AbstractValueDomain createDomain(JClosedWorld closedWorld) {
- return PowersetDomain(_abstractValueStrategy.createDomain(closedWorld));
+ return PowersetDomain(_abstractValueStrategy.createDomain(closedWorld),
+ PowersetBitsDomain(closedWorld));
}
@override
diff --git a/pkg/compiler/test/inference/powerset_bits_test.dart b/pkg/compiler/test/inference/powerset_bits_test.dart
new file mode 100644
index 0000000..4e37897
--- /dev/null
+++ b/pkg/compiler/test/inference/powerset_bits_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.7
+
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/common.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/inferrer/powersets/powersets.dart';
+import 'package:compiler/src/inferrer/powersets/powerset_bits.dart';
+import 'package:compiler/src/world.dart';
+import 'package:expect/expect.dart';
+import '../helpers/element_lookup.dart';
+import '../helpers/memory_compiler.dart';
+
+const String CODE = """
+var a = true;
+var b = true;
+var c = true;
+var d = true;
+var e = func();
+
+bool func() {
+ return false;
+}
+
+main() {
+ b = func();
+ c = b && a;
+ d = a || b;
+ e = false;
+}
+""";
+
+main() {
+ retainDataForTesting = true;
+
+ runTests() async {
+ CompilationResult result = await runCompiler(
+ memorySourceFiles: {'main.dart': CODE},
+ options: ['--experimental-powersets']);
+ Expect.isTrue(result.isSuccess);
+ Compiler compiler = result.compiler;
+ var results = compiler.globalInference.resultsForTesting;
+ JClosedWorld closedWorld = results.closedWorld;
+ PowersetDomain powersetDomain = closedWorld.abstractValueDomain;
+ PowersetBitsDomain powersetBitsDomain = powersetDomain.powersetBitsDomain;
+
+ checkBits(String name, bits) {
+ var element = findMember(closedWorld, name);
+ PowersetValue mask = results.resultOfMember(element).type;
+ Expect.equals(bits, mask.powersetBits);
+ }
+
+ checkBits('a', powersetBitsDomain.trueMask);
+ checkBits('b', powersetBitsDomain.boolMask);
+ checkBits('c', powersetBitsDomain.boolMask);
+ checkBits('d', powersetBitsDomain.boolMask);
+ checkBits('e', powersetBitsDomain.falseMask | powersetBitsDomain.nullMask);
+ }
+
+ asyncTest(() async {
+ print('--test from kernel------------------------------------------------');
+ await runTests();
+ });
+}
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index f77f40f..48ed14f 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -33,6 +33,7 @@
path: ../modular_test
package_config: any
pedantic: ^1.8.0
+ pub_semver: any
sourcemap_testing:
path: ../sourcemap_testing
stack_trace: any
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index 6713b64..1732869 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -8,9 +8,9 @@
environment:
sdk: '>=2.2.2 <3.0.0'
dependencies:
- args: '>=0.13.4 <2.0.0'
meta: ^1.0.0
dev_dependencies:
+ args: '>=0.13.4 <2.0.0'
expect:
path: ../expect
front_end:
diff --git a/pkg/nnbd_migration/lib/instrumentation.dart b/pkg/nnbd_migration/lib/instrumentation.dart
index 187ffff..387d666 100644
--- a/pkg/nnbd_migration/lib/instrumentation.dart
+++ b/pkg/nnbd_migration/lib/instrumentation.dart
@@ -266,6 +266,7 @@
fieldFormalParameter,
fieldNotInitialized,
forEachVariable,
+ getterSetterCorrespondence,
greatestLowerBound,
ifNull,
implicitMixinSuperCall,
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index af3f31d..a376634 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -838,6 +838,23 @@
_flowAnalysis = null;
_assignedVariables = null;
}
+ var declaredElement = node.declaredElement;
+ if (declaredElement is PropertyAccessorElement) {
+ if (declaredElement.isGetter) {
+ var setter = declaredElement.correspondingSetter;
+ if (setter != null) {
+ _handleGetterSetterCorrespondence(
+ node, null, declaredElement, setter.declaration);
+ }
+ } else {
+ assert(declaredElement.isSetter);
+ var getter = declaredElement.correspondingGetter;
+ if (getter != null) {
+ _handleGetterSetterCorrespondence(
+ node, null, getter.declaration, declaredElement);
+ }
+ }
+ }
}
return null;
}
@@ -2341,6 +2358,63 @@
_handleExecutableOverriddenDeclaration(node, returnType, parameters,
enclosingElement, overriddenElement);
}
+ if (declaredElement is PropertyAccessorElement) {
+ if (declaredElement.isGetter) {
+ var setters = [declaredElement.correspondingSetter];
+ if (setters[0] == null && !declaredElement.isStatic) {
+ // No corresponding setter in this class; look for inherited
+ // setters.
+ var getterName = declaredElement.name;
+ var setterName = '$getterName=';
+ var inheritedMembers = _inheritanceManager.getOverridden2(
+ enclosingElement,
+ Name(enclosingElement.library.source.uri, setterName));
+ if (inheritedMembers != null) {
+ setters = [
+ for (var setter in inheritedMembers)
+ if (setter is PropertyAccessorElement) setter
+ ];
+ }
+ }
+ for (var setter in setters) {
+ if (setter != null) {
+ _handleGetterSetterCorrespondence(
+ node,
+ declaredElement.isStatic ? null : enclosingElement,
+ declaredElement,
+ setter.declaration);
+ }
+ }
+ } else {
+ assert(declaredElement.isSetter);
+ assert(declaredElement.name.endsWith('='));
+ var getters = [declaredElement.correspondingGetter];
+ if (getters[0] == null && !declaredElement.isStatic) {
+ // No corresponding getter in this class; look for inherited
+ // getters.
+ var setterName = declaredElement.name;
+ var getterName = setterName.substring(0, setterName.length - 1);
+ var inheritedMembers = _inheritanceManager.getOverridden2(
+ enclosingElement,
+ Name(enclosingElement.library.source.uri, getterName));
+ if (inheritedMembers != null) {
+ getters = [
+ for (var getter in inheritedMembers)
+ if (getter is PropertyAccessorElement) getter
+ ];
+ }
+ }
+ for (var getter in getters) {
+ if (getter != null) {
+ _handleGetterSetterCorrespondence(
+ node,
+ declaredElement.isStatic ? null : enclosingElement,
+ getter.declaration,
+ declaredElement);
+ }
+ }
+ }
+ }
}
}
_flowAnalysis.finish();
@@ -2566,6 +2640,48 @@
});
}
+ void _handleGetterSetterCorrespondence(Declaration node, ClassElement class_,
+ PropertyAccessorElement getter, PropertyAccessorElement setter) {
+ DecoratedType getType;
+ if (getter.isSynthetic) {
+ var field = getter.variable;
+ if (field == null || field.isSynthetic) return;
+ getType = _variables.decoratedElementType(field);
+ } else {
+ getType = _variables.decoratedElementType(getter).returnType;
+ }
+ DecoratedType setType;
+ if (setter.isSynthetic) {
+ var field = setter.variable;
+ if (field == null || field.isSynthetic) return;
+ setType = _variables.decoratedElementType(field);
+ } else {
+ setType =
+ _variables.decoratedElementType(setter).positionalParameters.single;
+ }
+ Map<TypeParameterElement, DecoratedType> getterSubstitution = const {};
+ Map<TypeParameterElement, DecoratedType> setterSubstitution = const {};
+ if (class_ != null) {
+ var getterClass = getter.enclosingElement as ClassElement;
+ if (!identical(class_, getterClass)) {
+ getterSubstitution = _decoratedClassHierarchy
+ .getDecoratedSupertype(class_, getterClass)
+ .asSubstitution;
+ }
+ var setterClass = setter.enclosingElement as ClassElement;
+ if (!identical(class_, setterClass)) {
+ setterSubstitution = _decoratedClassHierarchy
+ .getDecoratedSupertype(class_, setterClass)
+ .asSubstitution;
+ }
+ }
+ _checkAssignment(
+ GetterSetterCorrespondenceOrigin(source, node), FixReasonTarget.root,
+ source: getType.substitute(getterSubstitution),
+ destination: setType.substitute(setterSubstitution),
+ hard: true);
+ }
+
/// Instantiate [type] with [argumentTypes], assigning [argumentTypes] to
/// [bounds].
DecoratedType _handleInstantiation(DecoratedType type,
diff --git a/pkg/nnbd_migration/lib/src/edge_origin.dart b/pkg/nnbd_migration/lib/src/edge_origin.dart
index 4c43bf7..61c6837 100644
--- a/pkg/nnbd_migration/lib/src/edge_origin.dart
+++ b/pkg/nnbd_migration/lib/src/edge_origin.dart
@@ -64,6 +64,27 @@
EdgeOriginKind get kind => EdgeOriginKind.alwaysNullableType;
}
+/// Edge origin resulting from the presence of a call to
+/// `ArgumentError.checkNotNull`.
+///
+/// For example, in the following code snippet:
+/// void f(int i) {
+/// ArgumentError.checkNotNull(i);
+/// }
+///
+/// this class is used for the edge connecting the type of f's `i` parameter to
+/// `never`, due to the `checkNotNull` call proclaiming that `i` is not `null`.
+class ArgumentErrorCheckNotNullOrigin extends EdgeOrigin {
+ ArgumentErrorCheckNotNullOrigin(Source source, SimpleIdentifier node)
+ : super(source, node);
+
+ @override
+ String get description => 'value checked to be non-null';
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.argumentErrorCheckNotNull;
+}
+
/// Edge origin resulting from the use of a value on the LHS of a compound
/// assignment.
class CompoundAssignmentOrigin extends EdgeOrigin {
@@ -80,6 +101,18 @@
AssignmentExpression get node => super.node as AssignmentExpression;
}
+/// Edge origin resulting from the use of an element which does not affect the
+/// nullability graph in other ways.
+class DummyOrigin extends EdgeOrigin {
+ DummyOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ String get description => 'dummy';
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.dummy;
+}
+
/// An edge origin used for edges that originated because of an assignment
/// involving a value with a dynamic type.
class DynamicAssignmentOrigin extends EdgeOrigin {
@@ -184,6 +217,18 @@
EdgeOriginKind get kind => EdgeOriginKind.forEachVariable;
}
+/// Edge origin resulting from the relationship between a getter and a setter.
+class GetterSetterCorrespondenceOrigin extends EdgeOrigin {
+ GetterSetterCorrespondenceOrigin(Source source, AstNode node)
+ : super(source, node);
+
+ @override
+ String get description => 'getter/setter correspondence';
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.getterSetterCorrespondence;
+}
+
/// Edge origin resulting from the use of greatest lower bound.
///
/// For example, in the following code snippet:
@@ -430,49 +475,6 @@
EdgeOriginKind get kind => EdgeOriginKind.nonNullAssertion;
}
-/// Edge origin resulting from the presence of a call to quiver's
-/// `checkNotNull`.
-///
-/// For example, in the following code snippet:
-/// import 'package:quiver/check.dart';
-/// void f(int i) {
-/// checkNotNull(i);
-/// }
-///
-/// this class is used for the edge connecting the type of f's `i` parameter to
-/// `never`, due to the `checkNotNull` call proclaiming that `i` is not `null`.
-class QuiverCheckNotNullOrigin extends EdgeOrigin {
- QuiverCheckNotNullOrigin(Source source, SimpleIdentifier node)
- : super(source, node);
-
- @override
- String get description => 'value checked to be non-null';
-
- @override
- EdgeOriginKind get kind => EdgeOriginKind.quiverCheckNotNull;
-}
-
-/// Edge origin resulting from the presence of a call to
-/// `ArgumentError.checkNotNull`.
-///
-/// For example, in the following code snippet:
-/// void f(int i) {
-/// ArgumentError.checkNotNull(i);
-/// }
-///
-/// this class is used for the edge connecting the type of f's `i` parameter to
-/// `never`, due to the `checkNotNull` call proclaiming that `i` is not `null`.
-class ArgumentErrorCheckNotNullOrigin extends EdgeOrigin {
- ArgumentErrorCheckNotNullOrigin(Source source, SimpleIdentifier node)
- : super(source, node);
-
- @override
- String get description => 'value checked to be non-null';
-
- @override
- EdgeOriginKind get kind => EdgeOriginKind.argumentErrorCheckNotNull;
-}
-
/// Edge origin resulting from the presence of an explicit nullability hint
/// comment.
///
@@ -518,18 +520,6 @@
EdgeOriginKind get kind => EdgeOriginKind.optionalFormalParameter;
}
-/// Edge origin resulting from the use of an element which does not affect the
-/// nullability graph in other ways.
-class DummyOrigin extends EdgeOrigin {
- DummyOrigin(Source source, AstNode node) : super(source, node);
-
- @override
- String get description => 'dummy';
-
- @override
- EdgeOriginKind get kind => EdgeOriginKind.dummy;
-}
-
/// Edge origin resulting from an inheritance relationship between two method
/// parameters.
class ParameterInheritanceOrigin extends EdgeOrigin {
@@ -542,6 +532,28 @@
EdgeOriginKind get kind => EdgeOriginKind.parameterInheritance;
}
+/// Edge origin resulting from the presence of a call to quiver's
+/// `checkNotNull`.
+///
+/// For example, in the following code snippet:
+/// import 'package:quiver/check.dart';
+/// void f(int i) {
+/// checkNotNull(i);
+/// }
+///
+/// this class is used for the edge connecting the type of f's `i` parameter to
+/// `never`, due to the `checkNotNull` call proclaiming that `i` is not `null`.
+class QuiverCheckNotNullOrigin extends EdgeOrigin {
+ QuiverCheckNotNullOrigin(Source source, SimpleIdentifier node)
+ : super(source, node);
+
+ @override
+ String get description => 'value checked to be non-null';
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.quiverCheckNotNull;
+}
+
/// Edge origin resulting from an inheritance relationship between two method
/// return types.
class ReturnTypeInheritanceOrigin extends EdgeOrigin {
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index f7d889e..a4ab81c 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -3256,6 +3256,280 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_getter_setter_getter_in_interface() async {
+ var content = '''
+class B {
+ int get x => null;
+}
+abstract class C implements B {
+ void set x(int value) {}
+}
+''';
+ var expected = '''
+class B {
+ int? get x => null;
+}
+abstract class C implements B {
+ void set x(int? value) {}
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_getter_in_interface_field() async {
+ var content = '''
+class B {
+ final int x = null;
+}
+abstract class C implements B {
+ void set x(int value) {}
+}
+''';
+ var expected = '''
+class B {
+ final int? x = null;
+}
+abstract class C implements B {
+ void set x(int? value) {}
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_getter_in_interfaces() async {
+ var content = '''
+class B1 {
+ int get x => null;
+}
+class B2 {
+ int get x => null;
+}
+abstract class C implements B1, B2 {
+ void set x(int value) {}
+}
+''';
+ var expected = '''
+class B1 {
+ int? get x => null;
+}
+class B2 {
+ int? get x => null;
+}
+abstract class C implements B1, B2 {
+ void set x(int? value) {}
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_getter_in_superclass() async {
+ var content = '''
+class B {
+ int get x => null;
+}
+class C extends B {
+ void set x(int value) {}
+}
+''';
+ var expected = '''
+class B {
+ int? get x => null;
+}
+class C extends B {
+ void set x(int? value) {}
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_getter_in_superclass_substituted() async {
+ var content = '''
+class B<T> {
+ T get x => throw '';
+}
+class C extends B<List<int/*?*/>> {
+ void set x(List<int> value) {}
+}
+''';
+ var expected = '''
+class B<T> {
+ T get x => throw '';
+}
+class C extends B<List<int?>> {
+ void set x(List<int?> value) {}
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_setter_in_interface() async {
+ var content = '''
+class B {
+ void set x(int value) {}
+}
+abstract class C implements B {
+ int get x => null;
+}
+''';
+ var expected = '''
+class B {
+ void set x(int? value) {}
+}
+abstract class C implements B {
+ int? get x => null;
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_setter_in_interface_field() async {
+ var content = '''
+class B {
+ int x;
+ B(this.x);
+}
+abstract class C implements B {
+ int get x => null;
+}
+''';
+ var expected = '''
+class B {
+ int? x;
+ B(this.x);
+}
+abstract class C implements B {
+ int? get x => null;
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_setter_in_interfaces() async {
+ var content = '''
+class B1 {
+ void set x(int value) {}
+}
+class B2 {
+ void set x(int value) {}
+}
+abstract class C implements B1, B2 {
+ int get x => null;
+}
+''';
+ var expected = '''
+class B1 {
+ void set x(int? value) {}
+}
+class B2 {
+ void set x(int? value) {}
+}
+abstract class C implements B1, B2 {
+ int? get x => null;
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_setter_in_superclass() async {
+ var content = '''
+class B {
+ void set x(int value) {}
+}
+class C extends B {
+ int get x => null;
+}
+''';
+ var expected = '''
+class B {
+ void set x(int? value) {}
+}
+class C extends B {
+ int? get x => null;
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_setter_in_superclass_substituted() async {
+ var content = '''
+class B<T> {
+ void set x(T value) {}
+}
+class C extends B<List<int>> {
+ List<int> get x => [null];
+}
+''';
+ var expected = '''
+class B<T> {
+ void set x(T value) {}
+}
+class C extends B<List<int?>> {
+ List<int?> get x => [null];
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_single_class() async {
+ var content = '''
+class C {
+ int get x => null;
+ void set x(int value) {}
+}
+''';
+ var expected = '''
+class C {
+ int? get x => null;
+ void set x(int? value) {}
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_single_class_generic() async {
+ var content = '''
+class C<T extends Object/*!*/> {
+ T get x => null;
+ void set x(T value) {}
+}
+''';
+ var expected = '''
+class C<T extends Object> {
+ T? get x => null;
+ void set x(T? value) {}
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_static() async {
+ var content = '''
+class C {
+ static int get x => null;
+ static void set x(int value) {}
+}
+''';
+ var expected = '''
+class C {
+ static int? get x => null;
+ static void set x(int? value) {}
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_getter_setter_top_level() async {
+ var content = '''
+int get x => null;
+void set x(int value) {}
+''';
+ var expected = '''
+int? get x => null;
+void set x(int? value) {}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
Future<void> test_getter_topLevel() async {
var content = '''
int get g => 0;
diff --git a/pkg/status_file/lib/status_file_linter.dart b/pkg/status_file/lib/status_file_linter.dart
index c8e08c6..d1282ab 100644
--- a/pkg/status_file/lib/status_file_linter.dart
+++ b/pkg/status_file/lib/status_file_linter.dart
@@ -98,7 +98,7 @@
Iterable<LintingError> lintAlphabeticalOrderingOfPaths(StatusSection section) {
var entries = section.entries
.whereType<StatusEntry>()
- .map((entry) => (entry as StatusEntry).path)
+ .map((entry) => entry.path)
.toList();
var sortedList = entries.toList()..sort((a, b) => a.compareTo(b));
var witness = _findNotEqualWitness<String>(sortedList, entries);
@@ -132,9 +132,8 @@
/// Checks for duplicate section entries in the body of a section.
Iterable<LintingError> lintSectionEntryDuplicates(StatusSection section) {
var errors = <LintingError>[];
- List<StatusEntry> statusEntries = section.entries
- .whereType<StatusEntry>()
- .toList();
+ List<StatusEntry> statusEntries =
+ section.entries.whereType<StatusEntry>().toList();
for (var i = 0; i < statusEntries.length; i++) {
var entry = statusEntries[i];
for (var j = i + 1; j < statusEntries.length; j++) {
diff --git a/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart b/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart
index a63524f..78a1ac6 100644
--- a/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart
+++ b/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart
@@ -2,11 +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 'dart:convert';
import 'dart:io';
import 'package:test/test.dart';
-
import 'package:vm_snapshot_analysis/instruction_sizes.dart'
as instruction_sizes;
import 'package:vm_snapshot_analysis/program_info.dart';
diff --git a/pkg/wasm/.gitignore b/pkg/wasm/.gitignore
new file mode 100644
index 0000000..49ce72d
--- /dev/null
+++ b/pkg/wasm/.gitignore
@@ -0,0 +1,3 @@
+.dart_tool/
+.packages
+pubspec.lock
diff --git a/pkg/wasm/AUTHORS b/pkg/wasm/AUTHORS
new file mode 100644
index 0000000..846e4a1
--- /dev/null
+++ b/pkg/wasm/AUTHORS
@@ -0,0 +1,6 @@
+# Below is a list of people and organizations that have contributed
+# to the Dart project. Names should be added to the list like so:
+#
+# Name/Organization <email address>
+
+Google LLC
diff --git a/pkg/wasm/LICENSE b/pkg/wasm/LICENSE
new file mode 100644
index 0000000..18daf2b
--- /dev/null
+++ b/pkg/wasm/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2020, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of Google Inc. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/wasm/README.md b/pkg/wasm/README.md
new file mode 100644
index 0000000..8bf6c4b
--- /dev/null
+++ b/pkg/wasm/README.md
@@ -0,0 +1,4 @@
+# wasm
+
+This package provides utilities for loading and running WASM modules. It is
+built on top of the [Wasmer](https://github.com/wasmerio/wasmer) runtime.
diff --git a/pkg/wasm/analysis_options.yaml b/pkg/wasm/analysis_options.yaml
new file mode 100644
index 0000000..84a5e26
--- /dev/null
+++ b/pkg/wasm/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:pedantic/analysis_options.1.8.0.yaml
diff --git a/pkg/wasm/lib/module.dart b/pkg/wasm/lib/module.dart
new file mode 100644
index 0000000..4b9cde4
--- /dev/null
+++ b/pkg/wasm/lib/module.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'runtime.dart';
+import 'dart:typed_data';
+import 'dart:ffi';
+
+class WasmModule {
+ Pointer<WasmerModule> _module;
+
+ WasmModule(Uint8List data) {
+ _module = WasmRuntime().compile(data);
+ }
+}
diff --git a/pkg/wasm/lib/runtime.dart b/pkg/wasm/lib/runtime.dart
new file mode 100644
index 0000000..f26689c
--- /dev/null
+++ b/pkg/wasm/lib/runtime.dart
@@ -0,0 +1,101 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'dart:io';
+import 'dart:typed_data';
+import 'package:ffi/ffi.dart';
+import 'package:path/path.dart' as path;
+
+const int WasmerResultOk = 1;
+const int WasmerResultError = 2;
+
+const int WasmerValueTagI32 = 0;
+const int WasmerValueTagI64 = 1;
+const int WasmerValueTagF32 = 2;
+const int WasmerValueTagF64 = 3;
+
+class WasmerModule extends Struct {}
+
+typedef NativeWasmerCompileFn = Uint32 Function(
+ Pointer<Pointer<WasmerModule>>, Pointer<Uint8>, Uint32);
+typedef WasmerCompileFn = int Function(
+ Pointer<Pointer<WasmerModule>>, Pointer<Uint8>, int);
+
+class WasmRuntime {
+ static WasmRuntime _inst;
+
+ DynamicLibrary _lib;
+ WasmerCompileFn _compile;
+
+ factory WasmRuntime() {
+ if (_inst == null) {
+ _inst = WasmRuntime._init();
+ }
+ return _inst;
+ }
+
+ static String _getLibName() {
+ if (Platform.isMacOS) return "libwasmer.dylib";
+ if (Platform.isLinux) return "libwasmer.so";
+ throw Exception("Wasm not currently supported on this platform");
+ }
+
+ static String _getLibDir() {
+ // The common case, and how cli_util.dart computes the Dart SDK directory,
+ // path.dirname called twice on Platform.resolvedExecutable.
+ var commonLibDir = path.join(
+ path.absolute(path.dirname(path.dirname(Platform.resolvedExecutable))),
+ 'bin',
+ 'third_party',
+ 'wasmer');
+ if (Directory(commonLibDir).existsSync()) {
+ return commonLibDir;
+ }
+
+ // This is the less common case where the user is in the checked out Dart
+ // SDK, and is executing dart via:
+ // ./out/ReleaseX64/dart ...
+ var checkedOutLibDir = path.join(
+ path.absolute(path.dirname(Platform.resolvedExecutable)),
+ 'dart-sdk',
+ 'bin',
+ 'third_party',
+ 'wasmer');
+ if (Directory(checkedOutLibDir).existsSync()) {
+ return checkedOutLibDir;
+ }
+
+ // If neither returned above, we return the common case:
+ return commonLibDir;
+ }
+
+ WasmRuntime._init() {
+ var libPath = path.join(_getLibDir(), _getLibName());
+ _lib = DynamicLibrary.open(libPath);
+ _compile = _lib
+ .lookup<NativeFunction<NativeWasmerCompileFn>>('wasmer_compile')
+ .asFunction();
+ }
+
+ Pointer<WasmerModule> compile(Uint8List data) {
+ var dataPtr = allocate<Uint8>(count: data.length);
+ for (int i = 0; i < data.length; ++i) {
+ dataPtr[i] = data[i];
+ }
+
+ var modulePtrPtr = allocate<Pointer<WasmerModule>>();
+ int result = _compile(modulePtrPtr, dataPtr, data.length);
+ Pointer<WasmerModule> modulePtr = modulePtrPtr.value;
+
+ free(modulePtrPtr);
+ free(dataPtr);
+
+ if (result != WasmerResultOk) {
+ throw Exception("Wasm module compile failed");
+ }
+
+ return modulePtr;
+ }
+}
diff --git a/pkg/wasm/lib/wasm.dart b/pkg/wasm/lib/wasm.dart
new file mode 100644
index 0000000..56b2f4b
--- /dev/null
+++ b/pkg/wasm/lib/wasm.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'module.dart';
diff --git a/pkg/wasm/pubspec.yaml b/pkg/wasm/pubspec.yaml
new file mode 100644
index 0000000..04f9586
--- /dev/null
+++ b/pkg/wasm/pubspec.yaml
@@ -0,0 +1,12 @@
+name: wasm
+version: 0.1.0
+description: Load and run wasm bytecode.
+author: Dart Team <misc@dartlang.org>
+homepage: https://github.com/dart-lang/sdk/tree/master/pkg/wasm
+# This package is not intended for consumption on pub.dev. DO NOT publish.
+publish_to: none
+environment:
+ sdk: ">=2.6.0"
+dependencies:
+ ffi: ^0.1.3
+ path: ^1.0.0
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 20efa72..332a586 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -221,10 +221,6 @@
":generate_version_cc_file",
"third_party/double-conversion/src:libdouble_conversion",
]
- if (dart_enable_wasm) {
- extra_deps += [ "//third_party/wasmer" ]
- defines = [ "DART_ENABLE_WASM" ]
- }
if (is_fuchsia) {
if (using_fuchsia_gn_sdk) {
extra_deps += [
diff --git a/runtime/lib/developer.cc b/runtime/lib/developer.cc
index 2b875cc..fafd0ca 100644
--- a/runtime/lib/developer.cc
+++ b/runtime/lib/developer.cc
@@ -136,18 +136,19 @@
#endif
}
-DEFINE_NATIVE_ENTRY(Developer_webServerControl, 0, 2) {
+DEFINE_NATIVE_ENTRY(Developer_webServerControl, 0, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0));
#if defined(PRODUCT)
SendNull(port);
return Object::null();
#else
GET_NON_NULL_NATIVE_ARGUMENT(Bool, enabled, arguments->NativeArgAt(1));
+ GET_NATIVE_ARGUMENT(Bool, silence_output, arguments->NativeArgAt(2));
ServiceIsolate::WaitForServiceIsolateStartup();
if (!ServiceIsolate::IsRunning()) {
SendNull(port);
} else {
- ServiceIsolate::ControlWebServer(port, enabled.value());
+ ServiceIsolate::ControlWebServer(port, enabled.value(), silence_output);
}
return Object::null();
#endif
diff --git a/runtime/observatory/lib/service_html.dart b/runtime/observatory/lib/service_html.dart
index 2bf441f..cf93d5e 100644
--- a/runtime/observatory/lib/service_html.dart
+++ b/runtime/observatory/lib/service_html.dart
@@ -22,7 +22,11 @@
// The VM service will attempt to redirect our websocket connection request
// to DDS, but the dart:html WebSocket doesn't follow redirects. Instead of
// relying on a redirect, we'll request the websocket URI from the service.
- Uri getWebSocketUriRequest = Uri.parse(target.networkAddress);
+
+ // TODO(bkonyi): re-enable when DDS is enabled. Currently causing Observatory
+ // failures when running with Flutter (see
+ // https://github.com/flutter/flutter/issues/64333)
+ /*Uri getWebSocketUriRequest = Uri.parse(target.networkAddress);
getWebSocketUriRequest =
getWebSocketUriRequest.replace(scheme: 'http', pathSegments: [
...getWebSocketUriRequest.pathSegments.where((e) => e != 'ws'),
@@ -36,10 +40,9 @@
onError();
return;
}
- _webSocket = new WebSocket(
- response['result']['uri'],
- );
- target.networkAddress = _webSocket.url;
+ target.networkAddress = response['result']['uri'];
+ */
+ _webSocket = new WebSocket(target.networkAddress);
_webSocket.onClose.listen((CloseEvent) => onClose());
_webSocket.onError.listen((Event) => onError());
_webSocket.onOpen.listen((Event) => onOpen());
diff --git a/runtime/observatory/tests/service/developer_server_control_test.dart b/runtime/observatory/tests/service/developer_server_control_test.dart
index 24347ea..03aa74a 100644
--- a/runtime/observatory/tests/service/developer_server_control_test.dart
+++ b/runtime/observatory/tests/service/developer_server_control_test.dart
@@ -25,7 +25,8 @@
{
// Now, start the web server and store the URI which is expected to be
// non NULL in the top level variable.
- ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+ ServiceProtocolInfo info =
+ await Service.controlWebServer(enable: true, silenceOutput: true);
Expect.equals(info.majorVersion, majorVersion);
Expect.equals(info.minorVersion, minorVersion);
Expect.isNotNull(info.serverUri);
diff --git a/runtime/runtime_args.gni b/runtime/runtime_args.gni
index dca02cf..1d7c539 100644
--- a/runtime/runtime_args.gni
+++ b/runtime/runtime_args.gni
@@ -91,7 +91,7 @@
# Whether libdart should export the symbols of the Dart API.
dart_lib_export_symbols = true
- # Whether dart:wasm should be enabled.
+ # Whether package:wasm should be enabled.
dart_enable_wasm = false
}
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index 0d1d129f..c7a33f1 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -156,9 +156,6 @@
]
}
}
- if (dart_enable_wasm) {
- defines = [ "DART_ENABLE_WASM" ]
- }
include_dirs = [ ".." ]
allsources = async_runtime_cc_files + collection_runtime_cc_files +
core_runtime_cc_files + developer_runtime_cc_files +
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 00f2e1c..a9e7f65 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -78,7 +78,7 @@
V(Developer_registerExtension, 2) \
V(Developer_log, 8) \
V(Developer_postEvent, 2) \
- V(Developer_webServerControl, 2) \
+ V(Developer_webServerControl, 3) \
V(Double_hashCode, 1) \
V(Double_getIsNegative, 1) \
V(Double_getIsInfinite, 1) \
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 83edc77..eab2e16 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1751,6 +1751,16 @@
}
static AbstractTypePtr GetElementTypeFromArray(Value* array) {
+ // Sometimes type of definition may contain a static type
+ // which is useful to extract element type, but reaching type
+ // only has a cid. So try out type of definition, if any.
+ if (array->definition()->HasType()) {
+ auto& elem_type = AbstractType::Handle(ExtractElementTypeFromArrayType(
+ *(array->definition()->Type()->ToAbstractType())));
+ if (!elem_type.IsDynamicType()) {
+ return elem_type.raw();
+ }
+ }
return ExtractElementTypeFromArrayType(*(array->Type()->ToAbstractType()));
}
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index f787fb3..068d478 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -65,12 +65,14 @@
static ArrayPtr MakeServerControlMessage(const SendPort& sp,
intptr_t code,
- bool enable = false) {
- const Array& list = Array::Handle(Array::New(3));
+ bool enable,
+ const Bool& silenceOutput) {
+ const Array& list = Array::Handle(Array::New(4));
ASSERT(!list.IsNull());
list.SetAt(0, Integer::Handle(Integer::New(code)));
list.SetAt(1, sp);
list.SetAt(2, Bool::Get(enable));
+ list.SetAt(3, silenceOutput);
return list.raw();
}
@@ -86,16 +88,19 @@
void ServiceIsolate::RequestServerInfo(const SendPort& sp) {
const Array& message = Array::Handle(MakeServerControlMessage(
- sp, VM_SERVICE_SERVER_INFO_MESSAGE_ID, false /* ignored */));
+ sp, VM_SERVICE_SERVER_INFO_MESSAGE_ID, false /* ignored */,
+ Bool::Handle() /* ignored */));
ASSERT(!message.IsNull());
MessageWriter writer(false);
PortMap::PostMessage(
writer.WriteMessage(message, port_, Message::kNormalPriority));
}
-void ServiceIsolate::ControlWebServer(const SendPort& sp, bool enable) {
+void ServiceIsolate::ControlWebServer(const SendPort& sp,
+ bool enable,
+ const Bool& silenceOutput) {
const Array& message = Array::Handle(MakeServerControlMessage(
- sp, VM_SERVICE_WEB_SERVER_CONTROL_MESSAGE_ID, enable));
+ sp, VM_SERVICE_WEB_SERVER_CONTROL_MESSAGE_ID, enable, silenceOutput));
ASSERT(!message.IsNull());
MessageWriter writer(false);
PortMap::PostMessage(
diff --git a/runtime/vm/service_isolate.h b/runtime/vm/service_isolate.h
index b8dd6b4..44cbd78 100644
--- a/runtime/vm/service_isolate.h
+++ b/runtime/vm/service_isolate.h
@@ -8,6 +8,7 @@
#include "include/dart_api.h"
#include "vm/allocation.h"
+#include "vm/object.h"
#include "vm/os_thread.h"
namespace dart {
@@ -50,7 +51,9 @@
static void BootVmServiceLibrary();
static void RequestServerInfo(const SendPort& sp);
- static void ControlWebServer(const SendPort& sp, bool enable);
+ static void ControlWebServer(const SendPort& sp,
+ bool enable,
+ const Bool& silenceOutput);
static void SetServerAddress(const char* address);
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 00e51e3..72f9851 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -582,6 +582,22 @@
outputs = [ "$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}" ]
}
+copy("copy_wasmer") {
+ visibility = [ ":create_common_sdk" ]
+ deps = [
+ ":copy_libraries",
+ "../third_party/wasmer:wasmer_lib",
+ ]
+ outputs = [ "$root_out_dir/dart-sdk/bin/third_party/wasmer/{{source_file_part}}" ]
+ if (is_win) {
+ sources = [ "$target_out_dir/../third_party/wasmer/wasmer.dll" ]
+ } else if (is_mac) {
+ sources = [ "$target_out_dir/../third_party/wasmer/libwasmer.dylib" ]
+ } else {
+ sources = [ "$target_out_dir/../third_party/wasmer/libwasmer.so" ]
+ }
+}
+
# This rule copies dill files to lib/_internal.
copy("copy_vm_dill_files") {
visibility = [ ":create_common_sdk" ]
@@ -902,6 +918,14 @@
if (target_cpu == "x64") {
public_deps += [ ":copy_libtensorflowlite_c" ]
}
+
+ # CIPD only has versions of the Rust compiler for linux and mac x64 hosts.
+ # We also disallow cross-compialtion (it may be possible in future, but it
+ # isn't ready yet).
+ if (host_cpu == "x64" && (host_os == "linux" || host_os == "mac") &&
+ host_cpu == current_cpu && host_os == current_os && dart_enable_wasm) {
+ public_deps += [ ":copy_wasmer" ]
+ }
}
# Parts specific to the platform SDK.
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart
index d67b6c8..73935cf 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart
@@ -147,7 +147,7 @@
}
@patch
-void _webServerControl(SendPort sendPort, bool enable) {
+void _webServerControl(SendPort sendPort, bool enable, bool? silenceOutput) {
sendPort.send(null);
}
diff --git a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
index aff3f55..e7833f5 100644
--- a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
@@ -103,7 +103,7 @@
}
@patch
-void _webServerControl(SendPort sendPort, bool enable) {
+void _webServerControl(SendPort sendPort, bool enable, bool? silenceOutput) {
sendPort.send(null);
}
diff --git a/sdk/lib/_internal/vm/bin/vmservice_io.dart b/sdk/lib/_internal/vm/bin/vmservice_io.dart
index 5718d46..329e505 100644
--- a/sdk/lib/_internal/vm/bin/vmservice_io.dart
+++ b/sdk/lib/_internal/vm/bin/vmservice_io.dart
@@ -192,7 +192,10 @@
Uri? serverInformationCallback() => _lazyServerBoot().serverAddress;
-Future<Uri?> webServerControlCallback(bool enable) async {
+Future<Uri?> webServerControlCallback(bool enable, bool? silenceOutput) async {
+ if (silenceOutput != null) {
+ silentObservatory = silenceOutput;
+ }
final _server = _lazyServerBoot();
if (_server.running != enable) {
if (enable) {
diff --git a/sdk/lib/_internal/vm/bin/vmservice_server.dart b/sdk/lib/_internal/vm/bin/vmservice_server.dart
index 09ec391..f084f29 100644
--- a/sdk/lib/_internal/vm/bin/vmservice_server.dart
+++ b/sdk/lib/_internal/vm/bin/vmservice_server.dart
@@ -4,7 +4,7 @@
part of vmservice_io;
-final bool silentObservatory = bool.fromEnvironment('SILENT_OBSERVATORY');
+bool silentObservatory = bool.fromEnvironment('SILENT_OBSERVATORY');
void serverPrint(String s) {
if (silentObservatory) {
diff --git a/sdk/lib/_internal/vm/lib/developer.dart b/sdk/lib/_internal/vm/lib/developer.dart
index 82eac19..f0b2a1c 100644
--- a/sdk/lib/_internal/vm/lib/developer.dart
+++ b/sdk/lib/_internal/vm/lib/developer.dart
@@ -161,7 +161,7 @@
void _getServerInfo(SendPort sendPort) native "Developer_getServerInfo";
@patch
-void _webServerControl(SendPort sendPort, bool enable)
+void _webServerControl(SendPort sendPort, bool enable, bool? silenceOutput)
native "Developer_webServerControl";
@patch
diff --git a/sdk/lib/developer/service.dart b/sdk/lib/developer/service.dart
index 6d90667..a563f39 100644
--- a/sdk/lib/developer/service.dart
+++ b/sdk/lib/developer/service.dart
@@ -54,10 +54,11 @@
}
/// Control the web server that the service protocol is accessed through.
- /// The [enable] argument must be a boolean and is used as a toggle to
- /// enable (true) or disable (false) the web server servicing requests.
+ /// [enable] is used as a toggle to enable or disable the web server
+ /// servicing requests. If [silenceOutput] is provided and is true,
+ /// the server will not output information to the console.
static Future<ServiceProtocolInfo> controlWebServer(
- {bool enable: false}) async {
+ {bool enable = false, bool? silenceOutput}) async {
// TODO: When NNBD is complete, delete the following line.
ArgumentError.checkNotNull(enable, 'enable');
// Port to receive response from service isolate.
@@ -65,7 +66,7 @@
final Completer<Uri> uriCompleter = new Completer<Uri>();
receivePort.handler = (Uri uri) => uriCompleter.complete(uri);
// Request the information from the service isolate.
- _webServerControl(receivePort.sendPort, enable);
+ _webServerControl(receivePort.sendPort, enable, silenceOutput);
// Await the response from the service isolate.
Uri uri = await uriCompleter.future;
// Close the port.
@@ -88,7 +89,8 @@
external void _getServerInfo(SendPort sendPort);
/// [sendPort] will receive a Uri or null.
-external void _webServerControl(SendPort sendPort, bool enable);
+external void _webServerControl(
+ SendPort sendPort, bool enable, bool? silenceOutput);
/// Returns the major version of the service protocol.
external int _getServiceMajorVersion();
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index c404a78..1581e70 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -169,8 +169,9 @@
/// Called when we need information about the server.
typedef Uri? ServerInformationCallback();
-/// Called when we want to [enable] or disable the web server.
-typedef Future<Uri?> WebServerControlCallback(bool enable);
+/// Called when we want to [enable] or disable the web server or silence VM
+/// service console messages.
+typedef Future<Uri?> WebServerControlCallback(bool enable, bool? silenceOutput);
/// Called when we want to [enable] or disable new websocket connections to the
/// server.
@@ -436,7 +437,8 @@
}
}
- Future<void> _serverMessageHandler(int code, SendPort sp, bool enable) async {
+ Future<void> _serverMessageHandler(
+ int code, SendPort sp, bool enable, bool? silenceOutput) async {
switch (code) {
case Constants.WEB_SERVER_CONTROL_MESSAGE_ID:
final webServerControl = VMServiceEmbedderHooks.webServerControl;
@@ -444,7 +446,7 @@
sp.send(null);
return;
}
- final uri = await webServerControl(enable);
+ final uri = await webServerControl(enable, silenceOutput);
sp.send(uri);
break;
case Constants.SERVER_INFO_MESSAGE_ID:
@@ -532,27 +534,27 @@
_exit();
return;
}
- if (message.length == 3) {
- final opcode = message[0];
- if (opcode == Constants.METHOD_CALL_FROM_NATIVE) {
- _handleNativeRpcCall(message[1], message[2]);
+ final opcode = message[0];
+ if (message.length == 3 && opcode == Constants.METHOD_CALL_FROM_NATIVE) {
+ _handleNativeRpcCall(message[1], message[2]);
+ return;
+ }
+ if (message.length == 4) {
+ if ((opcode == Constants.WEB_SERVER_CONTROL_MESSAGE_ID) ||
+ (opcode == Constants.SERVER_INFO_MESSAGE_ID)) {
+ // This is a message interacting with the web server.
+ _serverMessageHandler(message[0], message[1], message[2], message[3]);
return;
} else {
- // This is a message interacting with the web server.
- assert((opcode == Constants.WEB_SERVER_CONTROL_MESSAGE_ID) ||
- (opcode == Constants.SERVER_INFO_MESSAGE_ID));
- _serverMessageHandler(message[0], message[1], message[2]);
+ // This is a message informing us of the birth or death of an
+ // isolate.
+ _controlMessageHandler(
+ message[0], message[1], message[2], message[3]);
return;
}
}
- if (message.length == 4) {
- // This is a message informing us of the birth or death of an
- // isolate.
- _controlMessageHandler(message[0], message[1], message[2], message[3]);
- return;
- }
+ print('Internal vm-service error: ignoring illegal message: $message');
}
- print('Internal vm-service error: ignoring illegal message: $message');
}
VMService._internal() : eventPort = isolateControlPort {
diff --git a/tests/dart2js/internal/rti/constant_type_test.dart b/tests/dart2js/internal/rti/constant_type_test.dart
index cd08db5..7e71eb7 100644
--- a/tests/dart2js/internal/rti/constant_type_test.dart
+++ b/tests/dart2js/internal/rti/constant_type_test.dart
@@ -26,9 +26,9 @@
check<Generic<int>>(const Generic<int>());
check<Generic<dynamic>>(const Generic<dynamic>());
- check<Generic<Object>>(const Generic<Object>());
- check<Generic<Object>>(const Generic<dynamic>());
- check<Generic<dynamic>>(const Generic<Object>());
+ check<Generic<Object?>>(const Generic<Object?>());
+ check<Generic<Object?>>(const Generic<dynamic>());
+ check<Generic<dynamic>>(const Generic<Object?>());
check<List<int>>(const [1]);
check<List<String>>(const ['one']);
diff --git a/tests/dart2js/internal/rti/simple_is_test.dart b/tests/dart2js/internal/rti/simple_is_test.dart
index 6b79c94..fb82ac4 100644
--- a/tests/dart2js/internal/rti/simple_is_test.dart
+++ b/tests/dart2js/internal/rti/simple_is_test.dart
@@ -25,9 +25,9 @@
check<Generic<int>>(Generic<int>());
check<Generic<dynamic>>(Generic<dynamic>());
- check<Generic<Object>>(Generic<Object>());
- check<Generic<Object>>(Generic<dynamic>());
- check<Generic<dynamic>>(Generic<Object>());
+ check<Generic<Object?>>(Generic<Object?>());
+ check<Generic<Object?>>(Generic<dynamic>());
+ check<Generic<dynamic>>(Generic<Object?>());
Expect.isTrue(Generic<Thingy>().checkMethod(Thingy()));
Expect.isTrue(Generic<Object>().checkMethod(Object()));
diff --git a/tests/dart2js/internal/rti/subtype_test.dart b/tests/dart2js/internal/rti/subtype_test.dart
index e4222c4..68f4de7 100644
--- a/tests/dart2js/internal/rti/subtype_test.dart
+++ b/tests/dart2js/internal/rti/subtype_test.dart
@@ -5,6 +5,7 @@
import 'dart:_foreign_helper' show JS, JS_GET_NAME, TYPE_REF;
import 'dart:_js_embedded_names' show JsGetName;
import 'dart:_rti' as rti;
+import 'package:expect/expect.dart';
import 'subtype_utils.dart';
@@ -12,6 +13,8 @@
final String futureName = JS_GET_NAME(JsGetName.FUTURE_CLASS_TYPE_NAME);
final String nullName = JS_GET_NAME(JsGetName.NULL_CLASS_TYPE_NAME);
+final String nullableObject = "$objectName?";
+
const typeRulesJson = r'''
{
"int": {"num": []},
@@ -27,6 +30,8 @@
main() {
rti.testingAddRules(universe, typeRules);
+ rti.testingUniverseEvalOverride(
+ universe, nullableObject, TYPE_REF<Object?>());
rti.testingUniverseEvalOverride(universe, objectName, TYPE_REF<Object>());
rti.testingUniverseEvalOverride(universe, nullName, TYPE_REF<Null>());
runTests();
@@ -53,35 +58,46 @@
}
void testTopTypes() {
- strictSubtype('List<int>', objectName);
- equivalent(objectName, objectName);
+ strictSubtype('List<int>', nullableObject);
+ equivalent(nullableObject, nullableObject);
equivalent('@', '@');
equivalent('~', '~');
equivalent('1&', '1&');
- equivalent(objectName, '@');
- equivalent(objectName, '~');
- equivalent(objectName, '1&');
+ equivalent(nullableObject, '@');
+ equivalent(nullableObject, '~');
+ equivalent(nullableObject, '1&');
equivalent('@', '~');
equivalent('@', '1&');
equivalent('~', '1&');
- equivalent('List<$objectName>', 'List<@>');
- equivalent('List<$objectName>', 'List<~>');
- equivalent('List<$objectName>', 'List<1&>');
+ equivalent('List<$nullableObject>', 'List<@>');
+ equivalent('List<$nullableObject>', 'List<~>');
+ equivalent('List<$nullableObject>', 'List<1&>');
equivalent('List<@>', 'List<~>');
equivalent('List<@>', 'List<1&>');
equivalent('List<~>', 'List<1&>');
}
void testNull() {
- strictSubtype(nullName, 'int');
- strictSubtype(nullName, 'Iterable<CodeUnits>');
- strictSubtype(nullName, objectName);
+ if (isStrongMode) {
+ unrelated(nullName, 'int');
+ unrelated(nullName, 'Iterable<CodeUnits>');
+ unrelated(nullName, objectName);
+ } else {
+ strictSubtype(nullName, 'int');
+ strictSubtype(nullName, 'Iterable<CodeUnits>');
+ strictSubtype(nullName, objectName);
+ }
+ strictSubtype(nullName, nullableObject);
equivalent(nullName, nullName);
}
void testBottom() {
String never = '0&';
- equivalent(nullName, never); // This test is run with legacy subtyping
+ if (isStrongMode) {
+ strictSubtype(never, nullName);
+ } else {
+ equivalent(never, nullName);
+ }
}
void testFutureOr() {
diff --git a/third_party/wasmer/BUILD.gn b/third_party/wasmer/BUILD.gn
index 09093b6..5549fc6 100644
--- a/third_party/wasmer/BUILD.gn
+++ b/third_party/wasmer/BUILD.gn
@@ -1,4 +1,4 @@
-import("//build/rust/rust.gni")
+import("../../build/rust/rust.gni")
component("wasmer") {
public = [ "wasmer.hh" ]
@@ -7,4 +7,5 @@
rust_library("wasmer_lib") {
lib_name = "wasmer"
+ shared = true
}
diff --git a/third_party/wasmer/Cargo.toml b/third_party/wasmer/Cargo.toml
index bfe6172..67c601b 100644
--- a/third_party/wasmer/Cargo.toml
+++ b/third_party/wasmer/Cargo.toml
@@ -4,7 +4,7 @@
[lib]
name = "wasmer"
-crate-type = ["staticlib"]
+crate-type = ["dylib"]
path = "wasmer.rs"
[dependencies]
diff --git a/tools/VERSION b/tools/VERSION
index 87839ca..3392be0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 10
PATCH 0
-PRERELEASE 50
+PRERELEASE 51
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 0ae5512..41dbd25 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -2971,41 +2971,41 @@
},
{
"name": "analyze pkg/analysis_server",
- "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
- "--fatal-warnings",
+ "analyze",
"pkg/analysis_server"
]
},
{
"name": "analyze pkg/analysis_server_client",
- "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
- "--fatal-warnings",
+ "analyze",
"pkg/analysis_server_client"
]
},
{
"name": "analyze pkg/analyzer",
- "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
- "--fatal-warnings",
+ "analyze",
"pkg/analyzer"
]
},
{
"name": "analyze pkg/analyzer_cli",
- "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
- "--fatal-warnings",
+ "analyze",
"pkg/analyzer_cli"
]
},
{
"name": "analyze pkg/analyzer_plugin",
- "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
- "--fatal-warnings",
+ "analyze",
"pkg/analyzer_plugin"
]
},
@@ -3035,9 +3035,10 @@
},
{
"name": "analyze pkg/dartdev",
- "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
- "--fatal-warnings",
+ "analyze",
+ "--fatal-infos",
"pkg/dartdev"
]
},
@@ -3140,25 +3141,25 @@
},
{
"name": "analyze pkg/status_file",
- "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
- "--fatal-warnings",
+ "analyze",
"pkg/status_file"
]
},
{
"name": "analyze pkg/telemetry",
- "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
- "--fatal-warnings",
+ "analyze",
"pkg/telemetry"
]
},
{
"name": "analyze pkg/test_runner",
- "script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
- "--fatal-warnings",
+ "analyze",
"pkg/test_runner"
]
},
@@ -3187,6 +3188,14 @@
]
},
{
+ "name": "analyze pkg/vm_snapshot_analysis",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
+ "arguments": [
+ "analyze",
+ "pkg/vm_snapshot_analysis"
+ ]
+ },
+ {
"name": "analyze pkg/dds",
"script": "out/ReleaseX64/dart-sdk/bin/dartanalyzer",
"arguments": [
diff --git a/tools/package_deps/bin/package_deps.dart b/tools/package_deps/bin/package_deps.dart
index 97eb5d1..e177485 100644
--- a/tools/package_deps/bin/package_deps.dart
+++ b/tools/package_deps/bin/package_deps.dart
@@ -1,10 +1,9 @@
import 'dart:io';
+import 'package:cli_util/cli_logging.dart';
import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart' as yaml;
-// TODO(devoncarew): Use bold ansi chars for emphasis.
-
// TODO(devoncarew): Validate that publishable packages don't use relative sdk
// paths in their pubspecs.
@@ -12,16 +11,16 @@
const validateDEPS = false;
void main(List<String> arguments) {
+ Logger logger = Logger.standard();
+
// validate the cwd
if (!FileSystemEntity.isFileSync('DEPS') ||
!FileSystemEntity.isDirectorySync('pkg')) {
- print('Please run this tool from the root of the Dart repo.');
+ logger.stderr('Please run this tool from the root of the Dart repo.');
exit(1);
}
- // TODO(devoncarew): Support manually added directories (outside of pkg/).
-
- // locate all packages
+ // locate all pkg/ packages
final packages = <Package>[];
for (var entity in Directory('pkg').listSync()) {
if (entity is Directory) {
@@ -32,6 +31,15 @@
}
}
+ // Manually added directories (outside of pkg/).
+ List<String> alsoValidate = [
+ 'tools/package_deps',
+ ];
+
+ for (String p in alsoValidate) {
+ packages.add(Package(p));
+ }
+
packages.sort();
var validateFailure = false;
@@ -41,7 +49,7 @@
print('validating ${package.dir}'
'${package.publishable ? ' [publishable]' : ''}');
- if (!package.validate()) {
+ if (!package.validate(logger)) {
validateFailure = true;
}
@@ -101,13 +109,11 @@
FileSystemEntity.isFileSync(path.join(dir, 'pubspec.yaml'));
@override
- int compareTo(Package other) {
- return dirName.compareTo(other.dirName);
- }
+ int compareTo(Package other) => dir.compareTo(other.dir);
- bool validate() {
+ bool validate(Logger logger) {
_parseImports();
- return _validatePubspecDeps();
+ return _validatePubspecDeps(logger);
}
void _parseImports() {
@@ -163,7 +169,7 @@
}
}
- bool _validatePubspecDeps() {
+ bool _validatePubspecDeps(Logger logger) {
var fail = false;
if (dirName != packageName) {
@@ -184,10 +190,14 @@
// print(' dev deps: ${devdeps}');
// }
+ var out = (String message) {
+ logger.stdout(logger.ansi.emphasized(message));
+ };
+
var undeclaredRegularUses = Set<String>.from(deps)
..removeAll(_declaredDependencies);
if (undeclaredRegularUses.isNotEmpty) {
- print(' ${_printSet(undeclaredRegularUses)} used in lib/ but not '
+ out(' ${_printSet(undeclaredRegularUses)} used in lib/ but not '
"declared in 'dependencies:'.");
fail = true;
}
@@ -196,7 +206,7 @@
..removeAll(_declaredDependencies)
..removeAll(_declaredDevDependencies);
if (undeclaredDevUses.isNotEmpty) {
- print(' ${_printSet(undeclaredDevUses)} used in dev dirs but not '
+ out(' ${_printSet(undeclaredDevUses)} used in dev dirs but not '
"declared in 'dev_dependencies:'.");
fail = true;
}
@@ -204,7 +214,7 @@
var extraRegularDeclarations = Set<String>.from(_declaredDependencies)
..removeAll(deps);
if (extraRegularDeclarations.isNotEmpty) {
- print(' ${_printSet(extraRegularDeclarations)} declared in '
+ out(' ${_printSet(extraRegularDeclarations)} declared in '
"'dependencies:' but not used in lib/.");
fail = true;
}
@@ -215,7 +225,7 @@
// order to bring in its analysis_options.yaml file.
extraDevDeclarations.remove('pedantic');
if (extraDevDeclarations.isNotEmpty) {
- print(' ${_printSet(extraDevDeclarations)} declared in '
+ out(' ${_printSet(extraDevDeclarations)} declared in '
"'dev_dependencies:' but not used in dev dirs.");
fail = true;
}
@@ -225,7 +235,7 @@
var misplacedDeps =
extraRegularDeclarations.intersection(Set.from(devdeps));
if (misplacedDeps.isNotEmpty) {
- print(" ${_printSet(misplacedDeps)} declared in 'dependencies:' but "
+ out(" ${_printSet(misplacedDeps)} declared in 'dependencies:' but "
'only used in dev dirs.');
fail = true;
}
diff --git a/tools/package_deps/pubspec.yaml b/tools/package_deps/pubspec.yaml
index f581f76..ef104c9 100644
--- a/tools/package_deps/pubspec.yaml
+++ b/tools/package_deps/pubspec.yaml
@@ -8,6 +8,7 @@
sdk: '>=2.8.1 <3.0.0'
dependencies:
+ cli_util: any
path: any
yaml: any