Version 1.13.0-dev.3.0
Merge commit '8d96919609c6f1916fafbcbbc7a0639131606fc4' into dev
diff --git a/.gitattributes b/.gitattributes
index 9dfc906..8378d02 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,6 @@
# Explicitly declare text files we want to be normalized.
*.c text
+*.cc text
*.cpp text
*.h text
*.gyp text
diff --git a/.gitignore b/.gitignore
index 116adee..eaa131d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,12 +15,12 @@
/xcodebuild
/.flaky.log
/.debug.log
-/*.Makefile
+*.Makefile
*.opensdf
*.sdf
*.sln
*.suo
-/*.target.mk
+*.target.mk
*.host.mk
*.vcproj
*.vcxproj
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 80077f2..d7daf24 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,7 @@
as all `allMatches` implementations are intended to be.
* `dart:io`
- * `HttpClient` no longer sends URI fragments in the requeust. This is not
+ * `HttpClient` no longer sends URI fragments in the request. This is not
allowed by the HTTP protocol.
The `HttpServer` still gracefully receives fragments, but discards them
before delivering the request.
diff --git a/DEPS b/DEPS
index a111db0..948d24c 100644
--- a/DEPS
+++ b/DEPS
@@ -51,7 +51,7 @@
"crypto_rev" : "@2df57a1e26dd88e8d0614207d4b062c73209917d",
"csslib_tag" : "@0.12.0",
"dart2js_info_rev" : "@bad01369f1f605ab688d505c135db54de927318f",
- "dartdoc_rev" : "@8ef4cae550ea7ad47c5eb997b36ad2ba14ff53f7",
+ "dartdoc_rev" : "@ae12ca7aa2ea15535fac9e262cab65e3c2b66a04",
"dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
"dart_style_tag": "@0.2.0",
"dev_compiler_rev": "@0.1.7",
@@ -68,15 +68,13 @@
"intl_rev": "@32047558bd220a53c1f4d93a26d54b83533b1475",
"jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_tag": "@1.1.1",
- "linter_tag": "@0.1.0",
+ "linter_rev": "@140ee2d1d7a255cf1265e990e528c6575ab2d5bb",
"logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
"markdown_rev": "@9a1071a859df9c9edd4f556e948f898f70bf1e5e",
"matcher_tag": "@0.12.0",
"metatest_rev": "@e5aa8e4e19fc4188ac2f6d38368a47d8f07c3df1",
"mime_rev": "@75890811d4af5af080351ba8a2853ad4c8df98dd",
"mustache4dart_rev" : "@5724cfd85151e5b6b53ddcd3380daf188fe47f92",
- "net_nss_rev": "@f81948e9a402db94287a43bb34a07ee0daf56cb5",
- "nss_rev": "@87b96db4268293187d7cf741907a6d5d1d8080e0",
"oauth2_rev": "@1bff41f4d54505c36f2d1a001b83b8b745c452f5",
"observe_rev": "@eee2b8ec34236fa46982575fbccff84f61202ac6",
"observatory_pub_packages_rev": "@cdc4b3d4c15b9c0c8e7702dff127b440afbb7485",
@@ -86,22 +84,21 @@
"ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
"plugin_tag": "@0.1.0",
"pool_rev": "@e454b4b54d2987e8d2f0fbd3ac519641ada9bd0f",
- "pub_rev": "@d90268693d1a9dbe5ea11cd9c80b842e3bf1581c",
+ "pub_rev": "@1c08b841158e33b8090bb07e5c39df830db58d44",
"pub_cache_tag": "@v0.1.0",
"pub_semver_tag": "@1.2.1",
"quiver_tag": "@0.21.4",
"root_certificates_rev": "@c3a41df63afacec62fcb8135196177e35fe72f71",
"scheduled_test_tag": "@0.12.1+2",
- "shelf_rev": "@1e87b79b21ac5e6fa2f93576d6c06eaa65285ef4",
+ "shelf_tag": "@0.6.2+1",
"smoke_rev" : "@f3361191cc2a85ebc1e4d4c33aec672d7915aba9",
"source_maps_tag": "@0.10.1",
- "sqlite_rev": "@38811b79f42801662adc0458a25270ab690a6b81",
- "shelf_static_rev": "@v0.2.1",
- "shelf_web_socket_rev": "@ff170cec2c0e4e5722cdf47c557be63b5035a602",
+ "shelf_static_tag": "@0.2.3+1",
+ "shelf_web_socket_tag": "@0.0.1+4",
"source_map_stack_trace_tag": "@1.0.4",
- "source_span_tag": "@1.1.2",
+ "source_span_tag": "@1.2.0",
"stack_trace_tag": "@1.3.4",
- "string_scanner_rev": "@3e7617d6f74ba382e9b6130b1cc12091d89a9bc5",
+ "string_scanner_tag": "@0.1.4",
"sunflower_rev": "@879b704933413414679396b129f5dfa96f7a0b1e",
"test_tag": "@0.12.3+8",
"test_reflective_loader_tag": "@0.0.3",
@@ -113,7 +110,7 @@
"which_tag": "@0.1.3+1",
"web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
"WebCore_rev" : "@44061",
- "yaml_rev": "@563a5ffd4a800a2897b8f4dd6b19f2a370df2f2b",
+ "yaml_tag": "@2.1.5",
"zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
"font_awesome_rev": "@31824",
"barback-0.13.0_rev": "@34853",
@@ -130,21 +127,10 @@
Var("dart_root") + "/tests/co19/src":
(Var("github_mirror") % "co19") + Var("co19_rev"),
- Var("dart_root") + "/third_party/nss":
- Var("chromium_git") + "/chromium/deps/nss.git" + Var("nss_rev"),
-
- Var("dart_root") + "/third_party/sqlite":
- Var("chromium_git") + "/chromium/src/third_party/sqlite.git" +
- Var("sqlite_rev"),
-
Var("dart_root") + "/third_party/zlib":
Var("chromium_git") + "/chromium/src/third_party/zlib.git" +
Var("zlib_rev"),
- Var("dart_root") + "/third_party/net_nss":
- Var("chromium_git") + "/chromium/src/net/third_party/nss.git" +
- Var("net_nss_rev"),
-
Var("dart_root") + "/third_party/boringssl/src":
"https://boringssl.googlesource.com/boringssl.git" +
Var("boringssl_rev"),
@@ -231,7 +217,7 @@
Var("dart_root") + "/third_party/pkg/json_rpc_2":
(Var("github_mirror") % "json_rpc_2") + Var("json_rpc_2_tag"),
Var("dart_root") + "/third_party/pkg/linter":
- (Var("github_mirror") % "linter") + Var("linter_tag"),
+ (Var("github_mirror") % "linter") + Var("linter_rev"),
Var("dart_root") + "/third_party/pkg/logging":
(Var("github_mirror") % "logging") + Var("logging_rev"),
Var("dart_root") + "/third_party/pkg/markdown":
@@ -275,12 +261,12 @@
Var("dart_root") + "/third_party/pkg/scheduled_test":
(Var("github_mirror") % "scheduled_test") + Var("scheduled_test_tag"),
Var("dart_root") + "/third_party/pkg/shelf":
- (Var("github_mirror") % "shelf") + Var("shelf_rev"),
+ (Var("github_mirror") % "shelf") + Var("shelf_tag"),
Var("dart_root") + "/third_party/pkg/shelf_static":
- (Var("github_mirror") % "shelf_static") + Var("shelf_static_rev"),
+ (Var("github_mirror") % "shelf_static") + Var("shelf_static_tag"),
Var("dart_root") + "/third_party/pkg/shelf_web_socket":
(Var("github_mirror") % "shelf_web_socket") +
- Var("shelf_web_socket_rev"),
+ Var("shelf_web_socket_tag"),
Var("dart_root") + "/third_party/pkg/smoke":
(Var("github_mirror") % "smoke") + Var("smoke_rev"),
Var("dart_root") + "/third_party/pkg/source_maps":
@@ -294,7 +280,7 @@
(Var("github_mirror") % "stack_trace") + Var("stack_trace_tag"),
Var("dart_root") + "/third_party/pkg/string_scanner":
(Var("github_mirror") % "string_scanner") +
- Var("string_scanner_rev"),
+ Var("string_scanner_tag"),
Var("dart_root") + "/third_party/sunflower":
(Var("github_mirror") % "sample-sunflower") +
Var("sunflower_rev"),
@@ -319,7 +305,7 @@
Var("dart_root") + "/third_party/pkg/which":
(Var("github_mirror") % "which") + Var("which_tag"),
Var("dart_root") + "/third_party/pkg/yaml":
- (Var("github_mirror") % "yaml") + Var("yaml_rev"),
+ (Var("github_mirror") % "yaml") + Var("yaml_tag"),
# These specific versions of barback and source_maps are used for testing and
# should be pulled from bleeding_edge even on channels.
diff --git a/pkg/analysis_server/benchmark/integration/driver.dart b/pkg/analysis_server/benchmark/integration/driver.dart
index a3167810..80aec4c1 100644
--- a/pkg/analysis_server/benchmark/integration/driver.dart
+++ b/pkg/analysis_server/benchmark/integration/driver.dart
@@ -264,6 +264,7 @@
m.printSummary(keyLen);
}
}
+
/// TODO(danrubel) *** print warnings if driver caches are not empty ****
print('''
diff --git a/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart b/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
index 790da05..a43d4b4 100644
--- a/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
+++ b/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
@@ -29,8 +29,7 @@
*/
StringBuffer readBuffer = null;
- InstrumentationInputConverter(
- String tmpSrcDirPath, PathMap srcPathMap)
+ InstrumentationInputConverter(String tmpSrcDirPath, PathMap srcPathMap)
: super(tmpSrcDirPath, srcPathMap);
@override
diff --git a/pkg/analysis_server/benchmark/integration/local_runner.dart b/pkg/analysis_server/benchmark/integration/local_runner.dart
index 78d8c2a..bd0ff6b 100644
--- a/pkg/analysis_server/benchmark/integration/local_runner.dart
+++ b/pkg/analysis_server/benchmark/integration/local_runner.dart
@@ -51,11 +51,8 @@
if (!new Directory(join(gitDir.path, outDirName)).existsSync()) {
throw 'failed to find out or xcodebuild directory';
}
- result = Process.runSync('ln', [
- '-s',
- join(gitDir.path, outDirName),
- join(tmpSrcDirPath, outDirName)
- ]);
+ result = Process.runSync('ln',
+ ['-s', join(gitDir.path, outDirName), join(tmpSrcDirPath, outDirName)]);
if (result.exitCode != 0) throw 'failed to link out or xcodebuild: $result';
/*
* Collect arguments
diff --git a/pkg/analysis_server/benchmark/integration/main.dart b/pkg/analysis_server/benchmark/integration/main.dart
index 7cfb299..100ab6f 100644
--- a/pkg/analysis_server/benchmark/integration/main.dart
+++ b/pkg/analysis_server/benchmark/integration/main.dart
@@ -74,9 +74,11 @@
ArgParser get argParser {
_argParser = new ArgParser();
- _argParser.addOption(INPUT_CMDLINE_OPTION, abbr: 'i', help: '<filePath>\n'
- 'The input file specifying how this client should interact with the server.\n'
- 'If the input file name is "stdin", then the instructions are read from standard input.');
+ _argParser.addOption(INPUT_CMDLINE_OPTION,
+ abbr: 'i',
+ help: '<filePath>\n'
+ 'The input file specifying how this client should interact with the server.\n'
+ 'If the input file name is "stdin", then the instructions are read from standard input.');
_argParser.addOption(MAP_OPTION,
abbr: 'm',
allowMultiple: true,
@@ -87,9 +89,11 @@
'to the target source directory <newSrcPath> used during performance testing.\n'
'Multiple mappings can be specified.\n'
'WARNING: The contents of the target directory will be modified');
- _argParser.addOption(TMP_SRC_DIR_OPTION, abbr: 't', help: '<dirPath>\n'
- 'The temporary directory containing source used during performance measurement.\n'
- 'WARNING: The contents of the target directory will be modified');
+ _argParser.addOption(TMP_SRC_DIR_OPTION,
+ abbr: 't',
+ help: '<dirPath>\n'
+ 'The temporary directory containing source used during performance measurement.\n'
+ 'WARNING: The contents of the target directory will be modified');
_argParser.addFlag(NEW_TASK_MODEL_OPTION,
help: "enable the use of the new task model",
defaultsTo: false,
@@ -119,7 +123,9 @@
inputRaw = new File(args.inputPath).openRead();
}
for (PathMapEntry entry in args.srcPathMap.entries) {
- logger.log(Level.INFO, 'mapping source path\n'
+ logger.log(
+ Level.INFO,
+ 'mapping source path\n'
' from ${entry.oldSrcPrefix}\n to ${entry.newSrcPrefix}');
}
logger.log(Level.INFO, 'tmpSrcDir: ${args.tmpSrcDirPath}');
@@ -224,7 +230,6 @@
* The performance measurement arguments specified on the command line.
*/
class PerfArgs {
-
/**
* The file path of the instrumentation or log file
* used to drive performance measurement,
diff --git a/pkg/analysis_server/benchmark/integration/operation.dart b/pkg/analysis_server/benchmark/integration/operation.dart
index 9e408d8..761698e 100644
--- a/pkg/analysis_server/benchmark/integration/operation.dart
+++ b/pkg/analysis_server/benchmark/integration/operation.dart
@@ -87,8 +87,8 @@
void recordResult(bool success, result) {
Duration elapsed = stopwatch.elapsed;
driver.results.record(method, elapsed, success: success);
- driver.logger.log(
- Level.FINE, 'Response received: $method : $elapsed\n $result');
+ driver.logger
+ .log(Level.FINE, 'Response received: $method : $elapsed\n $result');
}
driver.send(method, json['params']).then((Map<String, dynamic> result) {
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 901200f..feaa424 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -3142,7 +3142,7 @@
<p>
The indexes of the targets (in the enclosing navigation response)
to which the given region is bound. By opening the target, clients
- can implement one form of navigation.
+ can implement one form of navigation. This list cannot be empty.
</p>
</dd></dl></dd><dt class="typeDefinition"><a name="type_NavigationTarget">NavigationTarget: object</a></dt><dd>
<p>
diff --git a/pkg/analysis_server/lib/analysis/analysis_domain.dart b/pkg/analysis_server/lib/analysis/analysis_domain.dart
index 27e8678..a046665 100644
--- a/pkg/analysis_server/lib/analysis/analysis_domain.dart
+++ b/pkg/analysis_server/lib/analysis/analysis_domain.dart
@@ -3,7 +3,27 @@
// BSD-style license that can be found in the LICENSE file.
/**
- * Support for client code that extends the analysis aspect of analysis server.
+ * Support for client code that interacts with the analysis domain of an
+ * analysis server.
+ *
+ * Plugins can gain access to the request handler that implements the analysis
+ * domain in order to extend the functionality of that domain. The class
+ * [AnalysisDomain] defines the API of the analysis domain that plugins can use.
+ *
+ * If a plugin is interested in gaining access to the analysis domain, it should
+ * register a function by including code like the following in the plugin's
+ * registerExtensions method:
+ *
+ * AnalysisDomain analysisDomain;
+ *
+ * @override
+ * void registerExtensions(RegisterExtension registerExtension) {
+ * ...
+ * registerExtension(
+ * SET_ANALYSIS_DOMAIN_EXTENSION_POINT_ID,
+ * (AnalysisDomain domain) => analysisDomain = domain);
+ * ...
+ * }
*/
library analysis_server.analysis;
@@ -18,31 +38,37 @@
import 'package:plugin/plugin.dart';
/**
- * The identifier of the extension point that allows plugins to get access to
- * `AnalysisSite`. The object used as an extension must be
- * a [SetAnalysisDomain].
+ * The identifier of the extension point that allows plugins to get access to an
+ * [AnalysisDomain]. The object used as an extension must be a
+ * [SetAnalysisDomain].
*/
final String SET_ANALYSIS_DOMAIN_EXTENSION_POINT_ID = Plugin.join(
ServerPlugin.UNIQUE_IDENTIFIER,
ServerPlugin.SET_ANALISYS_DOMAIN_EXTENSION_POINT);
/**
- * A function that is invoked on the `analysis` domain creation.
+ * A function that is invoked after the analysis domain has been created and is
+ * initialized.
*/
-typedef void SetAnalysisDomain(AnalysisDomain site);
+typedef void SetAnalysisDomain(AnalysisDomain domain);
/**
- * An object that gives [SetAnalysisDomain]s access to the `analysis` domain
- * of the analysis server.
+ * An object that gives plugins access to the analysis domain of the analysis
+ * server.
*
* Clients are not expected to subtype this class.
*/
abstract class AnalysisDomain {
/**
* Return the stream that is notified when a new value for the given
- * [descriptor] is computed.
+ * [result] is computed.
+ *
+ * This method should be used by plugins that need to perform some additional
+ * processing after analysis has completed. One example would be a plugin that
+ * needed to send a notification to the client because some data was now
+ * invalidated.
*/
- Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor);
+ Stream<ComputedResult> onResultComputed(ResultDescriptor result);
/**
* Schedule sending the given [service] notifications for the given [source]
diff --git a/pkg/analysis_server/lib/analysis/navigation/navigation_core.dart b/pkg/analysis_server/lib/analysis/navigation_core.dart
similarity index 69%
rename from pkg/analysis_server/lib/analysis/navigation/navigation_core.dart
rename to pkg/analysis_server/lib/analysis/navigation_core.dart
index c708d9a..e2f56f8 100644
--- a/pkg/analysis_server/lib/analysis/navigation/navigation_core.dart
+++ b/pkg/analysis_server/lib/analysis/navigation_core.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library analysis_server.analysis.navigation.navigation_core;
+library analysis_server.analysis.navigation_core;
import 'package:analysis_server/src/protocol.dart'
show ElementKind, Location, NavigationRegion, NavigationTarget;
@@ -16,11 +16,11 @@
*/
abstract class NavigationContributor {
/**
- * Contribute navigation regions for a part of the given [source] into the
- * given [holder]. The part is specified by the [offset] and [length].
- * The [context] can be used to get analysis results.
+ * Contribute navigation regions for a subset of the content of the given
+ * [source] into the given [collector]. The subset is specified by the
+ * [offset] and [length]. The [context] can be used to access analysis results.
*/
- void computeNavigation(NavigationHolder holder, AnalysisContext context,
+ void computeNavigation(NavigationCollector collector, AnalysisContext context,
Source source, int offset, int length);
}
@@ -30,10 +30,10 @@
*
* Clients are not expected to subtype this class.
*/
-abstract class NavigationHolder {
+abstract class NavigationCollector {
/**
* Record a new navigation region with the given [offset] and [length] that
- * should navigation to the given [targetLocation].
+ * should navigate to the given [targetLocation].
*/
void addRegion(
int offset, int length, ElementKind targetKind, Location targetLocation);
diff --git a/pkg/analysis_server/lib/analysis/occurrences_core.dart b/pkg/analysis_server/lib/analysis/occurrences_core.dart
new file mode 100644
index 0000000..2e24a9b
--- /dev/null
+++ b/pkg/analysis_server/lib/analysis/occurrences_core.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analysis_server.analysis.occurrences_core;
+
+import 'package:analysis_server/src/protocol.dart' show Element, Occurrences;
+import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/generated/source.dart' show Source;
+
+/**
+ * An object used to produce occurrences.
+ *
+ * Clients are expected to subtype this class when implementing plugins.
+ */
+abstract class OccurrencesContributor {
+ /**
+ * Contribute occurrences into the given [collector].
+ * The [context] can be used to get analysis results.
+ */
+ void computeOccurrences(
+ OccurrencesCollector collector, AnalysisContext context, Source source);
+}
+
+/**
+ * An object that [OccurrencesContributor]s use to record occurrences into.
+ *
+ * Clients are not expected to subtype this class.
+ */
+abstract class OccurrencesCollector {
+ /**
+ * Record a new element occurrences.
+ */
+ void addOccurrences(Occurrences occurrences);
+}
diff --git a/pkg/analysis_server/lib/edit/assist/assist_dart.dart b/pkg/analysis_server/lib/edit/assist/assist_dart.dart
index ec6718c..742655c 100644
--- a/pkg/analysis_server/lib/edit/assist/assist_dart.dart
+++ b/pkg/analysis_server/lib/edit/assist/assist_dart.dart
@@ -13,7 +13,7 @@
* An [AssistContributor] that can be used to contribute assists for Dart
* files.
*
- * Clients are expected to subtype this class when implementing plugins.
+ * Clients are expected to extend this class when implementing plugins.
*/
abstract class DartAssistContributor extends AssistContributor {
@override
diff --git a/pkg/analysis_server/lib/edit/fix/fix_dart.dart b/pkg/analysis_server/lib/edit/fix/fix_dart.dart
index c009e68..2229ed2 100644
--- a/pkg/analysis_server/lib/edit/fix/fix_dart.dart
+++ b/pkg/analysis_server/lib/edit/fix/fix_dart.dart
@@ -15,7 +15,7 @@
* A [FixContributor] that can be used to contribute fixes for errors in Dart
* files.
*
- * Clients are expected to subtype this class when implementing plugins.
+ * Clients are expected to extend this class when implementing plugins.
*/
abstract class DartFixContributor extends FixContributor {
@override
diff --git a/pkg/analysis_server/lib/plugin/analyzed_files.dart b/pkg/analysis_server/lib/plugin/analyzed_files.dart
index 12c9214..7eda12c 100644
--- a/pkg/analysis_server/lib/plugin/analyzed_files.dart
+++ b/pkg/analysis_server/lib/plugin/analyzed_files.dart
@@ -11,6 +11,20 @@
* The analysis server will invoke the contributed functions and analyze the
* file if at least one of the functions returns `true`. (The server is not
* required to invoke every function with every file.)
+ *
+ * If a plugin is interested in analyzing a certain kind of files, it needs to
+ * ensure that files of that kind will be analyzed. It should register a
+ * function by including code like the following in the plugin's
+ * registerExtensions method:
+ *
+ * @override
+ * void registerExtensions(RegisterExtension registerExtension) {
+ * ...
+ * registerExtension(
+ * ANALYZE_FILE_EXTENSION_POINT_ID,
+ * (File file) => file.path.endsWith(...));
+ * ...
+ * }
*/
library analysis_server.plugin.analyzed_files;
diff --git a/pkg/analysis_server/lib/plugin/assist.dart b/pkg/analysis_server/lib/plugin/assist.dart
index 393a479..0955d10 100644
--- a/pkg/analysis_server/lib/plugin/assist.dart
+++ b/pkg/analysis_server/lib/plugin/assist.dart
@@ -5,6 +5,22 @@
/**
* Support for client code that extends the analysis server by adding new assist
* contributors.
+ *
+ * Plugins can register assist contributors. The registered contributors will be
+ * used to get assists any time a client issues an 'edit.getAssists' request.
+ *
+ * If a plugin wants to add assists, it should implement the class
+ * [AssistContributor] and then register the contributor by including code like
+ * the following in the plugin's registerExtensions method:
+ *
+ * @override
+ * void registerExtensions(RegisterExtension registerExtension) {
+ * ...
+ * registerExtension(
+ * ASSIST_CONTRIBUTOR_EXTENSION_POINT_ID,
+ * new MyAssistContributor());
+ * ...
+ * }
*/
library analysis_server.plugin.assist;
diff --git a/pkg/analysis_server/lib/plugin/completion.dart b/pkg/analysis_server/lib/plugin/completion.dart
index 8fd6159..9b1c4b5 100644
--- a/pkg/analysis_server/lib/plugin/completion.dart
+++ b/pkg/analysis_server/lib/plugin/completion.dart
@@ -5,6 +5,23 @@
/**
* Support for client code that extends the analysis server by adding new code
* completion contributors.
+ *
+ * Plugins can register completion contributors. The registered contributors
+ * will be used to get completions any time a client issues a
+ * 'completion.getSuggestions' request.
+ *
+ * If a plugin wants to add completions, it should implement the class
+ * [CompletionContributor] and then register the contributor by including code
+ * like the following in the plugin's registerExtensions method:
+ *
+ * @override
+ * void registerExtensions(RegisterExtension registerExtension) {
+ * ...
+ * registerExtension(
+ * COMPLETION_CONTRIBUTOR_EXTENSION_POINT_ID,
+ * new MyCompletionContributor());
+ * ...
+ * }
*/
library analysis_server.plugin.completion;
diff --git a/pkg/analysis_server/lib/plugin/fix.dart b/pkg/analysis_server/lib/plugin/fix.dart
index 45f69a6..d274f61 100644
--- a/pkg/analysis_server/lib/plugin/fix.dart
+++ b/pkg/analysis_server/lib/plugin/fix.dart
@@ -5,6 +5,22 @@
/**
* Support for client code that extends the analysis server by adding new fix
* contributors.
+ *
+ * Plugins can register fix contributors. The registered contributors will be
+ * used to get fixes any time a client issues an 'edit.getFixes' request.
+ *
+ * If a plugin wants to add fixes, it should implement the class
+ * [FixContributor] and then register the contributor by including code like the
+ * following in the plugin's registerExtensions method:
+ *
+ * @override
+ * void registerExtensions(RegisterExtension registerExtension) {
+ * ...
+ * registerExtension(
+ * FIX_CONTRIBUTOR_EXTENSION_POINT_ID,
+ * new MyFixContributor());
+ * ...
+ * }
*/
library analysis_server.plugin.fix;
diff --git a/pkg/analysis_server/lib/plugin/index.dart b/pkg/analysis_server/lib/plugin/index.dart
index 096c28d..088ae52 100644
--- a/pkg/analysis_server/lib/plugin/index.dart
+++ b/pkg/analysis_server/lib/plugin/index.dart
@@ -5,6 +5,28 @@
/**
* Support for client code that extends the analysis server by adding new index
* contributors.
+ *
+ * Plugins can register index contributors. The registered contributors will be
+ * used to contribute relationships to the index when the analysis of a file has
+ * been completed.
+ *
+ * Typical relationships include things like "this variable is referenced here"
+ * or "this method is invoked here". The index is used to improve the
+ * performance of operations such as search or building a type hierarchy by
+ * pre-computing some of the information needed by those operations.
+ *
+ * If a plugin wants to contribute information to the index, it should implement
+ * the class [IndexContributor] and then register the contributor by including
+ * code like the following in the plugin's registerExtensions method:
+ *
+ * @override
+ * void registerExtensions(RegisterExtension registerExtension) {
+ * ...
+ * registerExtension(
+ * INDEX_CONTRIBUTOR_EXTENSION_POINT_ID,
+ * new MyIndexContributor());
+ * ...
+ * }
*/
library analysis_server.plugin.index;
diff --git a/pkg/analysis_server/lib/plugin/navigation.dart b/pkg/analysis_server/lib/plugin/navigation.dart
index 23603f0..4ef8f2d 100644
--- a/pkg/analysis_server/lib/plugin/navigation.dart
+++ b/pkg/analysis_server/lib/plugin/navigation.dart
@@ -5,10 +5,28 @@
/**
* Support for client code that extends the analysis server by adding new
* navigation contributors.
+ *
+ * Plugins can register navigation contributors. The registered contributors
+ * will be used to get navigation regions any time a client issues an
+ * 'analysis.getNavigation' request or the server is about to send an
+ * 'analysis.navigation' notification.
+ *
+ * If a plugin wants to add navigation regions, it should implement the class
+ * [NavigationContributor] and then register the contributor by including code
+ * like the following in the plugin's registerExtensions method:
+ *
+ * @override
+ * void registerExtensions(RegisterExtension registerExtension) {
+ * ...
+ * registerExtension(
+ * NAVIGATION_CONTRIBUTOR_EXTENSION_POINT_ID,
+ * new MyNavigationContributor());
+ * ...
+ * }
*/
library analysis_server.plugin.navigation;
-import 'package:analysis_server/analysis/navigation/navigation_core.dart';
+import 'package:analysis_server/analysis/navigation_core.dart';
import 'package:analysis_server/src/plugin/server_plugin.dart';
import 'package:plugin/plugin.dart';
diff --git a/pkg/analysis_server/lib/plugin/occurrences.dart b/pkg/analysis_server/lib/plugin/occurrences.dart
new file mode 100644
index 0000000..5339ccc
--- /dev/null
+++ b/pkg/analysis_server/lib/plugin/occurrences.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Support for client code that extends the analysis server by adding new
+ * occurrences contributors.
+ */
+library analysis_server.plugin.occurrences;
+
+import 'package:analysis_server/analysis/occurrences_core.dart';
+import 'package:analysis_server/src/plugin/server_plugin.dart';
+import 'package:plugin/plugin.dart';
+
+/**
+ * The identifier of the extension point that allows plugins to register
+ * element occurrences. The object used as an extension must be
+ * a [OccurrencesContributor].
+ */
+final String OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT_ID = Plugin.join(
+ ServerPlugin.UNIQUE_IDENTIFIER,
+ ServerPlugin.OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT);
diff --git a/pkg/analysis_server/lib/src/analysis_logger.dart b/pkg/analysis_server/lib/src/analysis_logger.dart
index 56f1435..9e751a4 100644
--- a/pkg/analysis_server/lib/src/analysis_logger.dart
+++ b/pkg/analysis_server/lib/src/analysis_logger.dart
@@ -21,7 +21,11 @@
AnalysisLogger() {
logging.Logger.root.onRecord.listen((logging.LogRecord record) {
AnalysisEngine.instance.instrumentationService.logLogEntry(
- record.level.name, record.time, record.message, record.error, record.stackTrace);
+ record.level.name,
+ record.time,
+ record.message,
+ record.error,
+ record.stackTrace);
});
}
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 5d0fb7d..1df76ad 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -284,9 +284,6 @@
* Initialize a newly created server to receive requests from and send
* responses to the given [channel].
*
- * If a [contextManager] is provided, then the [packageResolverProvider] will
- * be ignored.
- *
* If [rethrowExceptions] is true, then any exceptions thrown by analysis are
* propagated up the call stack. The default is true to allow analysis
* exceptions to show up in unit tests, but it should be set to false when
@@ -301,17 +298,14 @@
this.options,
this.defaultSdk,
this.instrumentationService,
- {ContextManager contextManager: null,
- ResolverProvider packageResolverProvider: null,
+ {ResolverProvider packageResolverProvider: null,
this.rethrowExceptions: true})
: index = _index,
searchEngine = _index != null ? createSearchEngine(_index) : null {
_performance = performanceDuringStartup;
operationQueue = new ServerOperationQueue();
- if (contextManager == null) {
- contextManager = new ContextManagerImpl(resourceProvider,
- packageResolverProvider, packageMapProvider, instrumentationService);
- }
+ contextManager = new ContextManagerImpl(resourceProvider,
+ packageResolverProvider, packageMapProvider, instrumentationService);
ServerContextManagerCallbacks contextManagerCallbacks =
new ServerContextManagerCallbacks(this, resourceProvider);
contextManager.callbacks = contextManagerCallbacks;
@@ -321,7 +315,6 @@
defaultContextOptions.incrementalValidation =
options.enableIncrementalResolutionValidation;
defaultContextOptions.generateImplicitErrors = false;
- this.contextManager = contextManager;
_noErrorNotification = options.noErrorNotification;
AnalysisEngine.instance.logger = new AnalysisLogger();
_onAnalysisStartedController = new StreamController.broadcast();
@@ -484,9 +477,9 @@
* first context that implicitly analyzes it.
*
* If the [path] is not analyzed by any context, a [ContextSourcePair] with
- * a `null` context and `file` [Source] is returned.
+ * a `null` context and a `file` [Source] is returned.
*
- * If the [path] dosn't represent a file, a [ContextSourcePair] with a `null`
+ * If the [path] doesn't represent a file, a [ContextSourcePair] with a `null`
* context and `null` [Source] is returned.
*
* Does not return `null`.
@@ -975,7 +968,7 @@
sendAnalysisNotificationNavigation(this, context, source);
break;
case AnalysisService.OCCURRENCES:
- sendAnalysisNotificationOccurrences(this, file, dartUnit);
+ sendAnalysisNotificationOccurrences(this, context, source);
break;
case AnalysisService.OUTLINE:
AnalysisContext context = dartUnit.element.context;
diff --git a/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart b/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
index bfcac2d..44d917e 100644
--- a/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
+++ b/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
@@ -30,7 +30,7 @@
ByteStreamClientChannel(this.input, this.output) {
Stream jsonStream = input
- .transform((new Utf8Codec()).decoder)
+ .transform(const Utf8Decoder())
.transform(new LineSplitter())
.transform(new JsonStreamDecoder())
.where((json) => json is Map)
@@ -106,7 +106,7 @@
void listen(void onRequest(Request request),
{Function onError, void onDone()}) {
_input
- .transform((new Utf8Codec()).decoder)
+ .transform(const Utf8Decoder())
.transform(new LineSplitter())
.listen((String data) => _readRequest(data, onRequest),
onError: onError, onDone: () {
diff --git a/pkg/analysis_server/lib/src/computer/computer_occurrences.dart b/pkg/analysis_server/lib/src/computer/computer_occurrences.dart
deleted file mode 100644
index 4897a1a..0000000
--- a/pkg/analysis_server/lib/src/computer/computer_occurrences.dart
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2014, 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.
-
-library computer.occurrences;
-
-import 'dart:collection';
-
-import 'package:analysis_server/src/protocol_server.dart' as protocol;
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/element.dart';
-
-/**
- * A computer for elements occurrences in a Dart [CompilationUnit].
- */
-class DartUnitOccurrencesComputer {
- final CompilationUnit _unit;
-
- final Map<Element, List<int>> _elementsOffsets =
- new HashMap<Element, List<int>>();
-
- DartUnitOccurrencesComputer(this._unit);
-
- /**
- * Returns the computed occurrences, not `null`.
- */
- List<protocol.Occurrences> compute() {
- _unit.accept(new _DartUnitOccurrencesComputerVisitor(this));
- List<protocol.Occurrences> occurrences = <protocol.Occurrences>[];
- _elementsOffsets.forEach((engineElement, offsets) {
- var serverElement = protocol.newElement_fromEngine(engineElement);
- var length = engineElement.displayName.length;
- occurrences.add(new protocol.Occurrences(serverElement, offsets, length));
- });
- return occurrences;
- }
-
- void _addOccurrence(Element element, int offset) {
- element = _canonicalizeElement(element);
- if (element == null || element == DynamicElementImpl.instance) {
- return;
- }
- List<int> offsets = _elementsOffsets[element];
- if (offsets == null) {
- offsets = <int>[];
- _elementsOffsets[element] = offsets;
- }
- offsets.add(offset);
- }
-
- Element _canonicalizeElement(Element element) {
- if (element is FieldFormalParameterElement) {
- element = (element as FieldFormalParameterElement).field;
- }
- if (element is PropertyAccessorElement) {
- element = (element as PropertyAccessorElement).variable;
- }
- if (element is Member) {
- element = (element as Member).baseElement;
- }
- return element;
- }
-}
-
-class _DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor {
- final DartUnitOccurrencesComputer computer;
-
- _DartUnitOccurrencesComputerVisitor(this.computer);
-
- @override
- visitSimpleIdentifier(SimpleIdentifier node) {
- Element element = node.bestElement;
- if (element != null) {
- computer._addOccurrence(element, node.offset);
- }
- return super.visitSimpleIdentifier(node);
- }
-}
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index ac5bced..153461a 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -531,6 +531,10 @@
Resource resource = resourceProvider.getResource(path);
if (resource is Folder) {
includedFolders.add(resource);
+ } else if (!resource.exists) {
+ // Non-existent resources are ignored. TODO(paulberry): we should set
+ // up a watcher to ensure that if the resource appears later, we will
+ // begin analyzing it.
} else {
// TODO(scheglov) implemented separate files analysis
throw new UnimplementedError('$path is not a folder. '
@@ -1353,8 +1357,10 @@
@override
Iterable<UriResolver> createPackageUriResolvers(
ResourceProvider resourceProvider) =>
- <UriResolver>[new SdkExtUriResolver(packageMap),
- new PackageMapUriResolver(resourceProvider, packageMap)];
+ <UriResolver>[
+ new SdkExtUriResolver(packageMap),
+ new PackageMapUriResolver(resourceProvider, packageMap)
+ ];
}
/**
@@ -1372,7 +1378,7 @@
@override
Iterable<UriResolver> createPackageUriResolvers(
- ResourceProvider resourceProvider) {
+ ResourceProvider resourceProvider) {
if (packages != null) {
// Construct package map for the SdkExtUriResolver.
Map<String, List<Folder>> packageMap = <String, List<Folder>>{};
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 5dd9feb..48dcc67 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -14,7 +14,10 @@
import 'package:analysis_server/src/context_manager.dart';
import 'package:analysis_server/src/domains/analysis/navigation.dart';
import 'package:analysis_server/src/operation/operation_analysis.dart'
- show sendAnalysisNotificationNavigation;
+ show
+ NavigationOperation,
+ OccurrencesOperation,
+ sendAnalysisNotificationNavigation;
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
import 'package:analyzer/file_system/file_system.dart';
@@ -136,14 +139,14 @@
server.sendResponse(new Response.getNavigationInvalidFile(request));
} else {
CompilationUnitElement unitElement = units.first.element;
- NavigationHolderImpl holder = computeNavigation(
+ NavigationCollectorImpl collector = computeNavigation(
server,
unitElement.context,
unitElement.source,
params.offset,
params.length);
server.sendResponse(new AnalysisGetNavigationResult(
- holder.files, holder.targets, holder.regions)
+ collector.files, collector.targets, collector.regions)
.toResponse(request.id));
}
break;
@@ -347,11 +350,13 @@
@override
void scheduleNotification(
engine.AnalysisContext context, Source source, AnalysisService service) {
- // TODO(scheglov) schedule, don't do it right now
String file = source.fullName;
if (server.hasAnalysisSubscription(service, file)) {
if (service == AnalysisService.NAVIGATION) {
- sendAnalysisNotificationNavigation(server, context, source);
+ server.scheduleOperation(new NavigationOperation(context, source));
+ }
+ if (service == AnalysisService.OCCURRENCES) {
+ server.scheduleOperation(new OccurrencesOperation(context, source));
}
}
}
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 23536e2..81d7bf2 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -236,8 +236,11 @@
/**
* Send completion notification results.
*/
- void sendCompletionNotification(String completionId, int replacementOffset,
- int replacementLength, Iterable<CompletionSuggestion> results,
+ void sendCompletionNotification(
+ String completionId,
+ int replacementOffset,
+ int replacementLength,
+ Iterable<CompletionSuggestion> results,
bool isLast) {
server.sendNotification(new CompletionResultsParams(
completionId, replacementOffset, replacementLength, results, isLast)
diff --git a/pkg/analysis_server/lib/src/domain_server.dart b/pkg/analysis_server/lib/src/domain_server.dart
index 81930b9..7bc7040 100644
--- a/pkg/analysis_server/lib/src/domain_server.dart
+++ b/pkg/analysis_server/lib/src/domain_server.dart
@@ -55,7 +55,8 @@
*/
Response setSubscriptions(Request request) {
server.serverServices =
- new ServerSetSubscriptionsParams.fromRequest(request).subscriptions
+ new ServerSetSubscriptionsParams.fromRequest(request)
+ .subscriptions
.toSet();
return new ServerSetSubscriptionsResult().toResponse(request.id);
}
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation.dart
index 859cd7c..cb21c3d 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/navigation.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -6,7 +6,7 @@
import 'dart:collection';
-import 'package:analysis_server/analysis/navigation/navigation_core.dart';
+import 'package:analysis_server/analysis/navigation_core.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/collections.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
@@ -18,28 +18,28 @@
/**
* Compute all known navigation information for the given part of [source].
*/
-NavigationHolderImpl computeNavigation(AnalysisServer server,
+NavigationCollectorImpl computeNavigation(AnalysisServer server,
AnalysisContext context, Source source, int offset, int length) {
- NavigationHolderImpl holder = new NavigationHolderImpl();
+ NavigationCollectorImpl collector = new NavigationCollectorImpl();
List<NavigationContributor> contributors =
server.serverPlugin.navigationContributors;
for (NavigationContributor contributor in contributors) {
try {
- contributor.computeNavigation(holder, context, source, offset, length);
+ contributor.computeNavigation(collector, context, source, offset, length);
} catch (exception, stackTrace) {
AnalysisEngine.instance.logger.logError(
'Exception from navigation contributor: ${contributor.runtimeType}',
new CaughtException(exception, stackTrace));
}
}
- holder.sortRegions();
- return holder;
+ collector.sortRegions();
+ return collector;
}
/**
- * A concrete implementation of [NavigationHolder].
+ * A concrete implementation of [NavigationCollector].
*/
-class NavigationHolderImpl implements NavigationHolder {
+class NavigationCollectorImpl implements NavigationCollector {
/**
* A list of navigation regions.
*/
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
index 37aaac1b..182f762 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
@@ -1,10 +1,10 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library domains.analysis.navigation_dart;
-import 'package:analysis_server/analysis/navigation/navigation_core.dart';
+import 'package:analysis_server/analysis/navigation_core.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
@@ -17,16 +17,17 @@
*/
class DartNavigationComputer implements NavigationContributor {
@override
- void computeNavigation(NavigationHolder holder, AnalysisContext context,
+ void computeNavigation(NavigationCollector collector, AnalysisContext context,
Source source, int offset, int length) {
List<Source> libraries = context.getLibrariesContaining(source);
if (libraries.isNotEmpty) {
CompilationUnit unit =
context.getResolvedCompilationUnit2(source, libraries.first);
if (unit != null) {
- _DartNavigationHolder dartHolder = new _DartNavigationHolder(holder);
+ _DartNavigationCollector dartCollector =
+ new _DartNavigationCollector(collector);
_DartNavigationComputerVisitor visitor =
- new _DartNavigationComputerVisitor(dartHolder);
+ new _DartNavigationComputerVisitor(dartCollector);
if (offset == null || length == null) {
unit.accept(visitor);
} else {
@@ -40,7 +41,7 @@
}
class _DartNavigationComputerVisitor extends RecursiveAstVisitor {
- final _DartNavigationHolder computer;
+ final _DartNavigationCollector computer;
_DartNavigationComputerVisitor(this.computer);
@@ -223,12 +224,12 @@
}
/**
- * A Dart specific wrapper around [NavigationHolder].
+ * A Dart specific wrapper around [NavigationCollector].
*/
-class _DartNavigationHolder {
- final NavigationHolder holder;
+class _DartNavigationCollector {
+ final NavigationCollector collector;
- _DartNavigationHolder(this.holder);
+ _DartNavigationCollector(this.collector);
void _addRegion(int offset, int length, Element element) {
if (element is FieldFormalParameterElement) {
@@ -246,7 +247,7 @@
if (location == null) {
return;
}
- holder.addRegion(offset, length, kind, location);
+ collector.addRegion(offset, length, kind, location);
}
void _addRegion_nodeStart_nodeEnd(AstNode a, AstNode b, Element element) {
diff --git a/pkg/analysis_server/lib/src/domains/analysis/occurrences.dart b/pkg/analysis_server/lib/src/domains/analysis/occurrences.dart
new file mode 100644
index 0000000..f0a9a1c
--- /dev/null
+++ b/pkg/analysis_server/lib/src/domains/analysis/occurrences.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library domains.analysis.occurrences;
+
+import 'package:analysis_server/analysis/occurrences_core.dart';
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/protocol_server.dart' as protocol;
+import 'package:analyzer/src/generated/engine.dart'
+ show AnalysisContext, AnalysisEngine;
+import 'package:analyzer/src/generated/java_engine.dart' show CaughtException;
+import 'package:analyzer/src/generated/source.dart' show Source;
+
+/**
+ * Compute all known occurrences for the given [source].
+ */
+OccurrencesCollectorImpl computeOccurrences(
+ AnalysisServer server, AnalysisContext context, Source source) {
+ OccurrencesCollectorImpl collector = new OccurrencesCollectorImpl();
+ List<OccurrencesContributor> contributors =
+ server.serverPlugin.occurrencesContributors;
+ for (OccurrencesContributor contributor in contributors) {
+ try {
+ contributor.computeOccurrences(collector, context, source);
+ } catch (exception, stackTrace) {
+ AnalysisEngine.instance.logger.logError(
+ 'Exception from occurrences contributor: ${contributor.runtimeType}',
+ new CaughtException(exception, stackTrace));
+ }
+ }
+ return collector;
+}
+
+/**
+ * A concrete implementation of [OccurrencesCollector].
+ */
+class OccurrencesCollectorImpl implements OccurrencesCollector {
+ Map<protocol.Element, protocol.Occurrences> elementOccurrences =
+ <protocol.Element, protocol.Occurrences>{};
+
+ List<protocol.Occurrences> get allOccurrences {
+ return elementOccurrences.values.toList();
+ }
+
+ @override
+ void addOccurrences(protocol.Occurrences current) {
+ protocol.Element element = current.element;
+ protocol.Occurrences existing = elementOccurrences[element];
+ if (existing != null) {
+ List<int> offsets = _merge(existing.offsets, current.offsets);
+ current = new protocol.Occurrences(element, offsets, existing.length);
+ }
+ elementOccurrences[element] = current;
+ }
+
+ static List<int> _merge(List<int> a, List<int> b) {
+ return <int>[]..addAll(a)..addAll(b);
+ }
+}
diff --git a/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart
new file mode 100644
index 0000000..ebefbfb
--- /dev/null
+++ b/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library domains.analysis.occurrences_dart;
+
+import 'package:analysis_server/analysis/occurrences_core.dart';
+import 'package:analysis_server/src/protocol_server.dart' as protocol;
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+/**
+ * A computer for occurrences in a Dart [CompilationUnit].
+ */
+class DartOccurrencesComputer implements OccurrencesContributor {
+ @override
+ void computeOccurrences(
+ OccurrencesCollector collector, AnalysisContext context, Source source) {
+ List<Source> libraries = context.getLibrariesContaining(source);
+ if (libraries.isNotEmpty) {
+ CompilationUnit unit =
+ context.getResolvedCompilationUnit2(source, libraries.first);
+ if (unit != null) {
+ _DartUnitOccurrencesComputerVisitor visitor =
+ new _DartUnitOccurrencesComputerVisitor();
+ unit.accept(visitor);
+ visitor.elementsOffsets.forEach((engineElement, offsets) {
+ int length = engineElement.displayName.length;
+ protocol.Element serverElement =
+ protocol.newElement_fromEngine(engineElement);
+ protocol.Occurrences occurrences =
+ new protocol.Occurrences(serverElement, offsets, length);
+ collector.addOccurrences(occurrences);
+ });
+ }
+ }
+ }
+}
+
+class _DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor {
+ final Map<Element, List<int>> elementsOffsets = <Element, List<int>>{};
+
+ @override
+ visitSimpleIdentifier(SimpleIdentifier node) {
+ Element element = node.bestElement;
+ if (element != null) {
+ _addOccurrence(element, node.offset);
+ }
+ return super.visitSimpleIdentifier(node);
+ }
+
+ void _addOccurrence(Element element, int offset) {
+ element = _canonicalizeElement(element);
+ if (element == null || element == DynamicElementImpl.instance) {
+ return;
+ }
+ List<int> offsets = elementsOffsets[element];
+ if (offsets == null) {
+ offsets = <int>[];
+ elementsOffsets[element] = offsets;
+ }
+ offsets.add(offset);
+ }
+
+ Element _canonicalizeElement(Element element) {
+ if (element is FieldFormalParameterElement) {
+ element = (element as FieldFormalParameterElement).field;
+ }
+ if (element is PropertyAccessorElement) {
+ element = (element as PropertyAccessorElement).variable;
+ }
+ if (element is Member) {
+ element = (element as Member).baseElement;
+ }
+ return element;
+ }
+}
diff --git a/pkg/analysis_server/lib/src/generated_protocol.dart b/pkg/analysis_server/lib/src/generated_protocol.dart
index 4ee4157..672e029 100644
--- a/pkg/analysis_server/lib/src/generated_protocol.dart
+++ b/pkg/analysis_server/lib/src/generated_protocol.dart
@@ -11153,14 +11153,14 @@
/**
* The indexes of the targets (in the enclosing navigation response) to which
* the given region is bound. By opening the target, clients can implement
- * one form of navigation.
+ * one form of navigation. This list cannot be empty.
*/
List<int> get targets => _targets;
/**
* The indexes of the targets (in the enclosing navigation response) to which
* the given region is bound. By opening the target, clients can implement
- * one form of navigation.
+ * one form of navigation. This list cannot be empty.
*/
void set targets(List<int> value) {
assert(value != null);
diff --git a/pkg/analysis_server/lib/src/get_handler.dart b/pkg/analysis_server/lib/src/get_handler.dart
index 7300d10..b527991 100644
--- a/pkg/analysis_server/lib/src/get_handler.dart
+++ b/pkg/analysis_server/lib/src/get_handler.dart
@@ -174,8 +174,8 @@
if (analysisServer == null) {
return null;
}
- return analysisServer.handlers.firstWhere(
- (h) => h is CompletionDomainHandler, orElse: () => null);
+ return analysisServer.handlers
+ .firstWhere((h) => h is CompletionDomainHandler, orElse: () => null);
}
/**
@@ -218,7 +218,8 @@
*/
Folder _findFolder(AnalysisServer analysisServer, String contextFilter) {
return analysisServer.folderMap.keys.firstWhere(
- (Folder folder) => folder.path == contextFilter, orElse: () => null);
+ (Folder folder) => folder.path == contextFilter,
+ orElse: () => null);
}
/**
@@ -299,12 +300,15 @@
buffer.write('<p><b>Task performace data</b></p>');
buffer.write(
'<table style="border-collapse: separate; border-spacing: 10px 5px;">');
- _writeRow(buffer, [
- 'Task Name',
- 'Count',
- 'Total Time (in ms)',
- 'Average Time (in ms)'
- ], header: true);
+ _writeRow(
+ buffer,
+ [
+ 'Task Name',
+ 'Count',
+ 'Total Time (in ms)',
+ 'Average Time (in ms)'
+ ],
+ header: true);
Map<Type, int> countMap = newTask.AnalysisTask.countMap;
Map<Type, Stopwatch> stopwatchMap = newTask.AnalysisTask.stopwatchMap;
@@ -324,7 +328,12 @@
count,
taskTime,
count <= 0 ? '-' : (taskTime / count).toStringAsFixed(3)
- ], classes: [null, "right", "right", "right"]);
+ ], classes: [
+ null,
+ "right",
+ "right",
+ "right"
+ ]);
});
_writeRow(buffer, ['Total', '-', totalTime, '-'],
classes: [null, "right", "right", "right"]);
@@ -392,10 +401,8 @@
AnalysisContextImpl context = analysisServer.folderMap[folder];
_writeResponse(request, (StringBuffer buffer) {
- _writePage(buffer, 'Analysis Server - AST Structure', [
- 'Context: $contextFilter',
- 'File: $sourceUri'
- ], (HttpResponse) {
+ _writePage(buffer, 'Analysis Server - AST Structure',
+ ['Context: $contextFilter', 'File: $sourceUri'], (HttpResponse) {
Source source = context.sourceFactory.forUri(sourceUri);
if (source == null) {
buffer.write('<p>Not found.</p>');
@@ -465,10 +472,8 @@
AnalysisContextImpl context = analysisServer.folderMap[folder];
_writeResponse(request, (StringBuffer buffer) {
- _writePage(buffer, 'Analysis Server - Cache Entry', [
- 'Context: $contextFilter',
- 'File: $sourceUri'
- ], (HttpResponse) {
+ _writePage(buffer, 'Analysis Server - Cache Entry',
+ ['Context: $contextFilter', 'File: $sourceUri'], (HttpResponse) {
buffer.write('<h3>Analyzing Contexts</h3><p>');
bool first = true;
allContexts.forEach((Folder folder) {
@@ -482,10 +487,13 @@
if (analyzingContext == context) {
buffer.write(folder.path);
} else {
- buffer.write(makeLink(CACHE_ENTRY_PATH, {
- CONTEXT_QUERY_PARAM: folder.path,
- SOURCE_QUERY_PARAM: sourceUri
- }, HTML_ESCAPE.convert(folder.path)));
+ buffer.write(makeLink(
+ CACHE_ENTRY_PATH,
+ {
+ CONTEXT_QUERY_PARAM: folder.path,
+ SOURCE_QUERY_PARAM: sourceUri
+ },
+ HTML_ESCAPE.convert(folder.path)));
}
if (entryMap[folder].explicitlyAdded) {
buffer.write(' (explicit)');
@@ -512,7 +520,9 @@
for (Source librarySource in entry.containingLibraries) {
String libraryName = HTML_ESCAPE.convert(librarySource.fullName);
buffer.write('<h3>In library $libraryName:</h3>');
- _writeDescriptorTable(buffer, entry.libraryDescriptors,
+ _writeDescriptorTable(
+ buffer,
+ entry.libraryDescriptors,
(DataDescriptor descriptor) =>
entry.getStateInLibrary(descriptor, librarySource),
(DataDescriptor descriptor) =>
@@ -575,10 +585,13 @@
if (state != stateFilter || rowDesc.toString() != descriptorFilter) {
return;
}
- String link = makeLink(CACHE_ENTRY_PATH, {
- CONTEXT_QUERY_PARAM: folder.path,
- SOURCE_QUERY_PARAM: source.uri.toString()
- }, HTML_ESCAPE.convert(source.fullName));
+ String link = makeLink(
+ CACHE_ENTRY_PATH,
+ {
+ CONTEXT_QUERY_PARAM: folder.path,
+ SOURCE_QUERY_PARAM: source.uri.toString()
+ },
+ HTML_ESCAPE.convert(source.fullName));
links.add(link);
});
@@ -717,10 +730,14 @@
if (exception != null) {
exceptions.add(exception);
}
- String link = makeLink(CACHE_ENTRY_PATH, {
- CONTEXT_QUERY_PARAM: folder.path,
- SOURCE_QUERY_PARAM: source.uri.toString()
- }, sourceName, exception != null);
+ String link = makeLink(
+ CACHE_ENTRY_PATH,
+ {
+ CONTEXT_QUERY_PARAM: folder.path,
+ SOURCE_QUERY_PARAM: source.uri.toString()
+ },
+ sourceName,
+ exception != null);
if (sourceEntry.explicitlyAdded) {
explicitNames.add(sourceName);
} else {
@@ -759,8 +776,9 @@
}
_writeResponse(request, (StringBuffer buffer) {
- _writePage(buffer, 'Analysis Server - Context',
- ['Context: $contextFilter'], (StringBuffer buffer) {
+ _writePage(
+ buffer, 'Analysis Server - Context', ['Context: $contextFilter'],
+ (StringBuffer buffer) {
List headerRowText = ['Context'];
headerRowText.addAll(CacheState.values);
buffer.write('<h3>Summary</h3>');
@@ -884,8 +902,8 @@
buffer.write('<table border="1">');
_writeRow(buffer, ['Element', 'Relationship', 'Location'],
header: true);
- relations.forEach((List<String> elementPath,
- List<InspectLocation> relations) {
+ relations.forEach(
+ (List<String> elementPath, List<InspectLocation> relations) {
String elementLocation = elementPath.join(' ');
relations.forEach((InspectLocation location) {
var relString = location.relationship.identifier;
@@ -1041,9 +1059,8 @@
buffer.write('<br>');
}
String key = folder.shortName;
- buffer.write(makeLink(CONTEXT_PATH, {
- CONTEXT_QUERY_PARAM: folder.path
- }, key, _hasException(folderMap[folder])));
+ buffer.write(makeLink(CONTEXT_PATH, {CONTEXT_QUERY_PARAM: folder.path},
+ key, _hasException(folderMap[folder])));
});
buffer.write('</p>');
@@ -1130,24 +1147,26 @@
return;
}
buffer.write('<table>');
- _writeRow(buffer, [
- 'Start Time',
- '',
- 'First (ms)',
- '',
- 'Complete (ms)',
- '',
- '# Notifications',
- '',
- '# Suggestions',
- '',
- 'Snippet'
- ], header: true);
+ _writeRow(
+ buffer,
+ [
+ 'Start Time',
+ '',
+ 'First (ms)',
+ '',
+ 'Complete (ms)',
+ '',
+ '# Notifications',
+ '',
+ '# Suggestions',
+ '',
+ 'Snippet'
+ ],
+ header: true);
int index = 0;
for (CompletionPerformance performance in handler.performanceList) {
- String link = makeLink(COMPLETION_PATH, {
- 'index': '$index'
- }, '${performance.startTimeAndMs}');
+ String link = makeLink(COMPLETION_PATH, {'index': '$index'},
+ '${performance.startTimeAndMs}');
_writeRow(buffer, [
link,
' ',
@@ -1189,9 +1208,12 @@
* [linkParameters] will be used if the value is too large to be displayed on
* the current page and needs to be linked to a separate page.
*/
- void _writeDescriptorTable(StringBuffer buffer,
- List<DataDescriptor> descriptors, CacheState getState(DataDescriptor),
- dynamic getValue(DataDescriptor), Map<String, String> linkParameters) {
+ void _writeDescriptorTable(
+ StringBuffer buffer,
+ List<DataDescriptor> descriptors,
+ CacheState getState(DataDescriptor),
+ dynamic getValue(DataDescriptor),
+ Map<String, String> linkParameters) {
buffer.write('<dl>');
for (DataDescriptor descriptor in descriptors) {
String descriptorName = HTML_ESCAPE.convert(descriptor.toString());
@@ -1363,9 +1385,9 @@
*/
void _writePluginStatus(StringBuffer buffer) {
void writePlugin(Plugin plugin) {
- buffer.write(_server.serverPlugin.uniqueIdentifier);
+ buffer.write(plugin.uniqueIdentifier);
buffer.write(' (');
- buffer.write(_server.serverPlugin.runtimeType);
+ buffer.write(plugin.runtimeType);
buffer.write(')<br>');
}
buffer.write('<h3>Plugin Status</h3><p>');
diff --git a/pkg/analysis_server/lib/src/operation/operation.dart b/pkg/analysis_server/lib/src/operation/operation.dart
index 6c5732d..1a43a188 100644
--- a/pkg/analysis_server/lib/src/operation/operation.dart
+++ b/pkg/analysis_server/lib/src/operation/operation.dart
@@ -9,6 +9,21 @@
import 'package:analyzer/src/generated/source.dart';
/**
+ * [MergeableOperation] can decide whether other operation can be merged into
+ * it, so that it should not be added as a separate operation.
+ */
+abstract class MergeableOperation extends ServerOperation {
+ MergeableOperation(AnalysisContext context) : super(context);
+
+ /**
+ * Attempt to merge the given [other] operation into this one, return `true`
+ * in case of success, so that [other] should not be added as a separate
+ * operation.
+ */
+ bool merge(ServerOperation other);
+}
+
+/**
* The class [ServerOperation] defines the behavior of objects used to perform
* operations on a [AnalysisServer].
*/
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index f18ad32..0270b27 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -7,10 +7,10 @@
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/computer/computer_highlights.dart';
import 'package:analysis_server/src/computer/computer_highlights2.dart';
-import 'package:analysis_server/src/computer/computer_occurrences.dart';
import 'package:analysis_server/src/computer/computer_outline.dart';
import 'package:analysis_server/src/computer/computer_overrides.dart';
import 'package:analysis_server/src/domains/analysis/navigation.dart';
+import 'package:analysis_server/src/domains/analysis/occurrences.dart';
import 'package:analysis_server/src/operation/operation.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
@@ -77,13 +77,13 @@
}
if (server.hasAnalysisSubscription(
protocol.AnalysisService.NAVIGATION, file)) {
- server.scheduleOperation(
- new _DartNavigationOperation(context, file, resolvedDartUnit));
+ Source source = resolvedDartUnit.element.source;
+ server.scheduleOperation(new NavigationOperation(context, source));
}
if (server.hasAnalysisSubscription(
protocol.AnalysisService.OCCURRENCES, file)) {
- server.scheduleOperation(
- new _DartOccurrencesOperation(context, file, resolvedDartUnit));
+ Source source = resolvedDartUnit.element.source;
+ server.scheduleOperation(new OccurrencesOperation(context, source));
}
if (server.hasAnalysisSubscription(
protocol.AnalysisService.OVERRIDES, file)) {
@@ -169,20 +169,23 @@
void sendAnalysisNotificationNavigation(
AnalysisServer server, AnalysisContext context, Source source) {
_sendNotification(server, () {
- NavigationHolderImpl holder =
+ NavigationCollectorImpl collector =
computeNavigation(server, context, source, null, null);
String file = source.fullName;
var params = new protocol.AnalysisNavigationParams(
- file, holder.regions, holder.targets, holder.files);
+ file, collector.regions, collector.targets, collector.files);
server.sendNotification(params.toNotification());
});
}
void sendAnalysisNotificationOccurrences(
- AnalysisServer server, String file, CompilationUnit dartUnit) {
+ AnalysisServer server, AnalysisContext context, Source source) {
_sendNotification(server, () {
- var occurrences = new DartUnitOccurrencesComputer(dartUnit).compute();
- var params = new protocol.AnalysisOccurrencesParams(file, occurrences);
+ OccurrencesCollectorImpl collector =
+ computeOccurrences(server, context, source);
+ String file = source.fullName;
+ var params =
+ new protocol.AnalysisOccurrencesParams(file, collector.allOccurrences);
server.sendNotification(params.toNotification());
});
}
@@ -229,6 +232,42 @@
});
}
+class NavigationOperation extends _NotificationOperation
+ implements MergeableOperation {
+ NavigationOperation(AnalysisContext context, Source source)
+ : super(context, source);
+
+ @override
+ bool merge(ServerOperation other) {
+ return other is NavigationOperation &&
+ other.context == context &&
+ other.source == source;
+ }
+
+ @override
+ void perform(AnalysisServer server) {
+ sendAnalysisNotificationNavigation(server, context, source);
+ }
+}
+
+class OccurrencesOperation extends _NotificationOperation
+ implements MergeableOperation {
+ OccurrencesOperation(AnalysisContext context, Source source)
+ : super(context, source);
+
+ @override
+ bool merge(ServerOperation other) {
+ return other is OccurrencesOperation &&
+ other.context == context &&
+ other.source == source;
+ }
+
+ @override
+ void perform(AnalysisServer server) {
+ sendAnalysisNotificationOccurrences(server, context, source);
+ }
+}
+
/**
* Instances of [PerformAnalysisOperation] perform a single analysis task.
*/
@@ -380,18 +419,6 @@
}
}
-class _DartNavigationOperation extends _DartNotificationOperation {
- _DartNavigationOperation(
- AnalysisContext context, String file, CompilationUnit unit)
- : super(context, file, unit);
-
- @override
- void perform(AnalysisServer server) {
- Source source = unit.element.source;
- sendAnalysisNotificationNavigation(server, context, source);
- }
-}
-
abstract class _DartNotificationOperation extends _SingleFileOperation {
final CompilationUnit unit;
@@ -404,17 +431,6 @@
}
}
-class _DartOccurrencesOperation extends _DartNotificationOperation {
- _DartOccurrencesOperation(
- AnalysisContext context, String file, CompilationUnit unit)
- : super(context, file, unit);
-
- @override
- void perform(AnalysisServer server) {
- sendAnalysisNotificationOccurrences(server, file, unit);
- }
-}
-
class _DartOutlineOperation extends _DartNotificationOperation {
final LineInfo lineInfo;
@@ -476,6 +492,22 @@
}
}
+abstract class _NotificationOperation extends SourceSensitiveOperation {
+ final Source source;
+
+ _NotificationOperation(AnalysisContext context, this.source) : super(context);
+
+ @override
+ ServerOperationPriority get priority {
+ return ServerOperationPriority.ANALYSIS_NOTIFICATION;
+ }
+
+ @override
+ bool shouldBeDiscardedOnSourceChange(Source source) {
+ return source == this.source;
+ }
+}
+
abstract class _SingleFileOperation extends SourceSensitiveOperation {
final String file;
diff --git a/pkg/analysis_server/lib/src/operation/operation_queue.dart b/pkg/analysis_server/lib/src/operation/operation_queue.dart
index ced4a8c..1687a4b 100644
--- a/pkg/analysis_server/lib/src/operation/operation_queue.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_queue.dart
@@ -39,6 +39,14 @@
void add(ServerOperation operation) {
int queueIndex = operation.priority.ordinal;
Queue<ServerOperation> queue = _queues[queueIndex];
+ // try to merge into an existing operation
+ for (ServerOperation existingOperation in queue) {
+ if (existingOperation is MergeableOperation &&
+ existingOperation.merge(operation)) {
+ return;
+ }
+ }
+ // add it
queue.addLast(operation);
}
@@ -119,7 +127,7 @@
*/
ServerOperation takeIf(bool test(ServerOperation operation)) {
for (Queue<ServerOperation> queue in _queues) {
- for (var operation in queue) {
+ for (ServerOperation operation in queue) {
if (test(operation)) {
queue.remove(operation);
return operation;
diff --git a/pkg/analysis_server/lib/src/plugin/server_plugin.dart b/pkg/analysis_server/lib/src/plugin/server_plugin.dart
index c1deee0..14b8c33 100644
--- a/pkg/analysis_server/lib/src/plugin/server_plugin.dart
+++ b/pkg/analysis_server/lib/src/plugin/server_plugin.dart
@@ -6,7 +6,8 @@
import 'package:analysis_server/analysis/analysis_domain.dart';
import 'package:analysis_server/analysis/index/index_core.dart';
-import 'package:analysis_server/analysis/navigation/navigation_core.dart';
+import 'package:analysis_server/analysis/navigation_core.dart';
+import 'package:analysis_server/analysis/occurrences_core.dart';
import 'package:analysis_server/completion/completion_core.dart';
import 'package:analysis_server/edit/assist/assist_core.dart';
import 'package:analysis_server/edit/fix/fix_core.dart';
@@ -14,12 +15,14 @@
import 'package:analysis_server/plugin/assist.dart';
import 'package:analysis_server/plugin/fix.dart';
import 'package:analysis_server/plugin/navigation.dart';
+import 'package:analysis_server/plugin/occurrences.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_analysis.dart';
import 'package:analysis_server/src/domain_completion.dart';
import 'package:analysis_server/src/domain_execution.dart';
import 'package:analysis_server/src/domain_server.dart';
import 'package:analysis_server/src/domains/analysis/navigation_dart.dart';
+import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart';
import 'package:analysis_server/src/edit/edit_domain.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analysis_server/src/search/search_domain.dart';
@@ -86,6 +89,13 @@
/**
* The simple identifier of the extension point that allows plugins to
+ * register element occurrences.
+ */
+ static const String OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT =
+ 'occurrencesContributor';
+
+ /**
+ * The simple identifier of the extension point that allows plugins to
* register analysis result listeners.
*/
static const String SET_ANALISYS_DOMAIN_EXTENSION_POINT = 'setAnalysisDomain';
@@ -130,11 +140,18 @@
ExtensionPoint indexContributorExtensionPoint;
/**
- * The extension point that allows plugins to register navigation contributors.
+ * The extension point that allows plugins to register navigation
+ * contributors.
*/
ExtensionPoint navigationContributorExtensionPoint;
/**
+ * The extension point that allows plugins to register occurrences
+ * contributors.
+ */
+ ExtensionPoint occurrencesContributorExtensionPoint;
+
+ /**
* The extension point that allows plugins to get access to the `analysis`
* domain.
*/
@@ -187,6 +204,13 @@
navigationContributorExtensionPoint.extensions;
/**
+ * Return a list containing all of the occurrences contributors that were
+ * contributed.
+ */
+ List<OccurrencesContributor> get occurrencesContributors =>
+ occurrencesContributorExtensionPoint.extensions;
+
+ /**
* Return a list containing all of the receivers of the `analysis` domain
* instance.
*/
@@ -231,6 +255,9 @@
navigationContributorExtensionPoint = registerExtensionPoint(
NAVIGATION_CONTRIBUTOR_EXTENSION_POINT,
_validateNavigationContributorExtension);
+ occurrencesContributorExtensionPoint = registerExtensionPoint(
+ OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT,
+ _validateOccurrencesContributorExtension);
}
@override
@@ -253,10 +280,12 @@
// TODO(brianwilkerson) Register the completion contributors.
// registerExtension(COMPLETION_CONTRIBUTOR_EXTENSION_POINT_ID, ???);
//
- // Register navigation contributors.
+ // Register analysis contributors.
//
registerExtension(NAVIGATION_CONTRIBUTOR_EXTENSION_POINT_ID,
new DartNavigationComputer());
+ registerExtension(OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT_ID,
+ new DartOccurrencesComputer());
//
// Register domains.
//
@@ -369,6 +398,18 @@
/**
* Validate the given extension by throwing an [ExtensionError] if it is not a
+ * valid occurrences contributor.
+ */
+ void _validateOccurrencesContributorExtension(Object extension) {
+ if (extension is! OccurrencesContributor) {
+ String id = occurrencesContributorExtensionPoint.uniqueIdentifier;
+ throw new ExtensionError(
+ 'Extensions to $id must be an OccurrencesContributor');
+ }
+ }
+
+ /**
+ * Validate the given extension by throwing an [ExtensionError] if it is not a
* valid analysis domain receiver.
*/
void _validateSetAnalysisDomainFunction(Object extension) {
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 8097f94..c5eb6bf 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -9,7 +9,6 @@
import 'dart:math';
import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/context_manager.dart';
import 'package:analysis_server/src/plugin/server_plugin.dart';
import 'package:analysis_server/src/server/http_server.dart';
import 'package:analysis_server/src/server/stdio_server.dart';
@@ -72,8 +71,13 @@
/// Defines a flag.
/// See [ArgParser.addFlag()].
- void addFlag(String name, {String abbr, String help, bool defaultsTo: false,
- bool negatable: true, void callback(bool value), bool hide: false}) {
+ void addFlag(String name,
+ {String abbr,
+ String help,
+ bool defaultsTo: false,
+ bool negatable: true,
+ void callback(bool value),
+ bool hide: false}) {
_knownFlags.add(name);
_parser.addFlag(name,
abbr: abbr,
@@ -86,8 +90,13 @@
/// Defines a value-taking option.
/// See [ArgParser.addOption()].
- void addOption(String name, {String abbr, String help, List<String> allowed,
- Map<String, String> allowedHelp, String defaultsTo, void callback(value),
+ void addOption(String name,
+ {String abbr,
+ String help,
+ List<String> allowed,
+ Map<String, String> allowedHelp,
+ String defaultsTo,
+ void callback(value),
bool allowMultiple: false}) {
_knownFlags.add(name);
_parser.addOption(name,
@@ -108,9 +117,9 @@
/// flags and options defined by this parser, and returns the result. The
/// values of any defined variables are captured in the given map.
/// See [ArgParser].
- ArgResults parse(
- List<String> args, Map<String, String> definedVariables) => _parser
- .parse(_filterUnknowns(parseDefinedVariables(args, definedVariables)));
+ ArgResults parse(List<String> args, Map<String, String> definedVariables) =>
+ _parser.parse(
+ _filterUnknowns(parseDefinedVariables(args, definedVariables)));
List<String> parseDefinedVariables(
List<String> args, Map<String, String> definedVariables) {
@@ -132,12 +141,10 @@
}
List<String> _filterUnknowns(List<String> args) {
-
// Only filter args if the ignore flag is specified, or if
// _alwaysIgnoreUnrecognized was set to true
if (_alwaysIgnoreUnrecognized ||
args.contains('--ignore-unrecognized-flags')) {
-
// Filter all unrecognized flags and options.
List<String> filtered = <String>[];
for (int i = 0; i < args.length; ++i) {
@@ -291,16 +298,9 @@
InstrumentationServer instrumentationServer;
/**
- * The context manager used to create analysis contexts within each of the
- * analysis roots.
- */
- ContextManager contextManager;
-
- /**
* The package resolver provider used to override the way package URI's are
* resolved in some contexts.
*/
- @deprecated
ResolverProvider packageResolverProvider;
/**
@@ -412,7 +412,7 @@
// Create the sockets and start listening for requests.
//
socketServer = new SocketServer(analysisServerOptions, defaultSdk, service,
- serverPlugin, contextManager, packageResolverProvider);
+ serverPlugin, packageResolverProvider);
httpServer = new HttpAnalysisServer(socketServer);
stdioServer = new StdioAnalysisServer(socketServer);
socketServer.userDefinedPlugins = _userDefinedPlugins;
@@ -430,9 +430,8 @@
exit(0);
});
},
- print: results[INTERNAL_PRINT_TO_CONSOLE]
- ? null
- : httpServer.recordPrint);
+ print:
+ results[INTERNAL_PRINT_TO_CONSOLE] ? null : httpServer.recordPrint);
}
/**
@@ -453,10 +452,10 @@
Function printFunction = print == null
? null
: (Zone self, ZoneDelegate parent, Zone zone, String line) {
- // Note: we don't pass the line on to stdout, because that is reserved
- // for communication to the client.
- print(line);
- };
+ // Note: we don't pass the line on to stdout, because that is reserved
+ // for communication to the client.
+ print(line);
+ };
ZoneSpecification zoneSpecification = new ZoneSpecification(
handleUncaughtError: errorFunction, print: printFunction);
return runZoned(callback, zoneSpecification: zoneSpecification);
@@ -495,14 +494,15 @@
defaultsTo: false,
negatable: false);
parser.addOption(INSTRUMENTATION_LOG_FILE,
- help: "the path of the file to which instrumentation data will be written");
+ help:
+ "the path of the file to which instrumentation data will be written");
parser.addFlag(INTERNAL_PRINT_TO_CONSOLE,
help: "enable sending `print` output to the console",
defaultsTo: false,
negatable: false);
parser.addOption(PORT_OPTION,
help: "the http diagnostic port on which the server provides"
- " status and performance information");
+ " status and performance information");
parser.addOption(INTERNAL_DELAY_FREQUENCY);
parser.addOption(SDK_OPTION, help: "[path] the path to the sdk");
parser.addFlag(NO_ERROR_NOTIFICATION,
@@ -521,10 +521,10 @@
"the file offset and range information incorrect.",
allowed: ["as-is", "normalize-eol-always"],
allowedHelp: {
- "as-is": "file contents are read as-is, no file changes occur",
- "normalize-eol-always":
- r'file contents normalize the end of line characters to the single character new line `\n`'
- },
+ "as-is": "file contents are read as-is, no file changes occur",
+ "normalize-eol-always":
+ r'file contents normalize the end of line characters to the single character new line `\n`'
+ },
defaultsTo: "as-is");
return parser;
@@ -546,7 +546,8 @@
String _readUuid(InstrumentationService service) {
File uuidFile = new File(PhysicalResourceProvider.INSTANCE
.getStateLocation('.instrumentation')
- .getChild('uuid.txt').path);
+ .getChild('uuid.txt')
+ .path);
try {
if (uuidFile.existsSync()) {
String uuid = uuidFile.readAsStringSync();
diff --git a/pkg/analysis_server/lib/src/services/completion/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/arglist_contributor.dart
index 3d8261a..61194fc 100644
--- a/pkg/analysis_server/lib/src/services/completion/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/arglist_contributor.dart
@@ -19,8 +19,13 @@
DartCompletionRequest request, List<String> namedArgs, String name) {
if (name != null && name.length > 0 && !namedArgs.contains(name)) {
request.addSuggestion(new CompletionSuggestion(
- CompletionSuggestionKind.NAMED_ARGUMENT, DART_RELEVANCE_NAMED_PARAMETER,
- '$name: ', name.length + 2, 0, false, false));
+ CompletionSuggestionKind.NAMED_ARGUMENT,
+ DART_RELEVANCE_NAMED_PARAMETER,
+ '$name: ',
+ name.length + 2,
+ 0,
+ false,
+ false));
}
}
@@ -216,8 +221,13 @@
}
completion.write(')');
CompletionSuggestion suggestion = new CompletionSuggestion(
- CompletionSuggestionKind.ARGUMENT_LIST, DART_RELEVANCE_HIGH,
- completion.toString(), completion.length, 0, false, false);
+ CompletionSuggestionKind.ARGUMENT_LIST,
+ DART_RELEVANCE_HIGH,
+ completion.toString(),
+ completion.length,
+ 0,
+ false,
+ false);
suggestion.parameterNames = paramNames;
suggestion.parameterTypes = paramTypes;
request.addSuggestion(suggestion);
@@ -353,8 +363,13 @@
}
completion.write(')');
CompletionSuggestion suggestion = new CompletionSuggestion(
- CompletionSuggestionKind.ARGUMENT_LIST, DART_RELEVANCE_HIGH,
- completion.toString(), completion.length, 0, false, false);
+ CompletionSuggestionKind.ARGUMENT_LIST,
+ DART_RELEVANCE_HIGH,
+ completion.toString(),
+ completion.length,
+ 0,
+ false,
+ false);
suggestion.parameterNames = paramNames;
suggestion.parameterTypes = paramTypes;
request.addSuggestion(suggestion);
diff --git a/pkg/analysis_server/lib/src/services/completion/common_usage_computer.dart b/pkg/analysis_server/lib/src/services/completion/common_usage_computer.dart
index 70f1542..11b4f1b 100644
--- a/pkg/analysis_server/lib/src/services/completion/common_usage_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/common_usage_computer.dart
@@ -99,7 +99,6 @@
* An [AstVisitor] used to determine the best defining type of a node.
*/
class _BestTypeVisitor extends GeneralizingAstVisitor {
-
/**
* The entity which the completed text will replace (or which will be
* displaced once the completed text is inserted). This may be an AstNode or
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_dart.dart b/pkg/analysis_server/lib/src/services/completion/completion_dart.dart
index 2dd4eeb..526d69d 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_dart.dart
@@ -30,5 +30,5 @@
DartCompletionRequestImpl(
CompletionRequest request, this.unit, this.isResolved)
: super(request.context, request.resourceProvider, request.source,
- request.offset);
+ request.offset);
}
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/completion_manager.dart
index 986cc8b..ebc5054 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_manager.dart
@@ -21,7 +21,6 @@
* for use in the next code completion.
*/
abstract class CompletionCache {
-
/**
* The context in which the completion was computed.
*/
@@ -39,7 +38,6 @@
* Manages completion contributors for a given completion request.
*/
abstract class CompletionManager {
-
/**
* The context in which the completion was computed.
*/
@@ -222,7 +220,6 @@
* Encapsulates information specific to a particular completion request.
*/
class CompletionRequestImpl implements CompletionRequest {
-
/**
* The underlying analysis server for this completion request.
*/
@@ -247,7 +244,6 @@
* Code completion result generated by an [CompletionManager].
*/
class CompletionResultImpl implements CompletionResult {
-
/**
* The length of the text to be replaced if the remainder of the identifier
* containing the cursor is to be replaced when the suggestion is applied
@@ -298,7 +294,6 @@
* The performance of an operation when computing code completion.
*/
class OperationPerformance {
-
/**
* The name of the operation
*/
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart
index 67a7245..7aa6704 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart
@@ -24,7 +24,6 @@
* completion operation.
*/
class DartCompletionCache extends CompletionCache {
-
/**
* A hash of the import directives
* or `null` if nothing has been cached.
@@ -262,9 +261,14 @@
CompletionSuggestion suggestion = null;
String completion = importElem.prefix.displayName;
if (completion != null && completion.length > 0) {
- suggestion = new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
- DART_RELEVANCE_DEFAULT, completion, completion.length, 0,
- importElem.isDeprecated, false);
+ suggestion = new CompletionSuggestion(
+ CompletionSuggestionKind.INVOCATION,
+ DART_RELEVANCE_DEFAULT,
+ completion,
+ completion.length,
+ 0,
+ importElem.isDeprecated,
+ false);
LibraryElement lib = importElem.importedLibrary;
if (lib != null) {
suggestion.element = newElement_fromEngine(lib);
@@ -280,7 +284,6 @@
*/
void _addNonImportedElementSuggestions(
List<SearchMatch> matches, Set<LibraryElement> excludedLibs) {
-
// Exclude internal Dart SDK libraries
for (var lib in context.sourceFactory.dartSdk.sdkLibraries) {
if (lib.isInternal) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
index 6186079..06c3c6a 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
@@ -322,17 +322,20 @@
Source source, int offset, this.cache)
: super(server, context, source, offset);
- factory DartCompletionRequest.from(CompletionRequestImpl request,
- DartCompletionCache cache) => new DartCompletionRequest(
- request.server, request.context, request.source, request.offset, cache);
+ factory DartCompletionRequest.from(
+ CompletionRequestImpl request, DartCompletionCache cache) =>
+ new DartCompletionRequest(request.server, request.context, request.source,
+ request.offset, cache);
/**
* Return the original text from the [replacementOffset] to the [offset]
* that can be used to filter the suggestions on the server side.
*/
String get filterText {
- return context.getContents(source).data.substring(
- replacementOffset, offset);
+ return context
+ .getContents(source)
+ .data
+ .substring(replacementOffset, offset);
}
/**
@@ -378,9 +381,12 @@
// because [DartCompletionCache] may be caching that suggestion
// for future completion requests
_suggestions[index] = new CompletionSuggestion(
- CompletionSuggestionKind.IDENTIFIER, suggestion.relevance,
- suggestion.completion, suggestion.selectionOffset,
- suggestion.selectionLength, suggestion.isDeprecated,
+ CompletionSuggestionKind.IDENTIFIER,
+ suggestion.relevance,
+ suggestion.completion,
+ suggestion.selectionOffset,
+ suggestion.selectionLength,
+ suggestion.isDeprecated,
suggestion.isPotential,
declaringType: suggestion.declaringType,
parameterNames: suggestion.parameterNames,
diff --git a/pkg/analysis_server/lib/src/services/completion/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/imported_reference_contributor.dart
index b6ea6ec..dac0056 100644
--- a/pkg/analysis_server/lib/src/services/completion/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/imported_reference_contributor.dart
@@ -25,7 +25,8 @@
bool suggestionsComputed;
_ImportedSuggestionBuilder builder;
- ImportedReferenceContributor({this.shouldWaitForLowPrioritySuggestions: false});
+ ImportedReferenceContributor(
+ {this.shouldWaitForLowPrioritySuggestions: false});
@override
bool computeFast(DartCompletionRequest request) {
@@ -40,7 +41,8 @@
shouldWaitForLowPrioritySuggestions;
// If target is an argument in an argument list
// then suggestions may need to be adjusted
- suggestionsComputed = builder.computeFast(request.target.containingNode);
+ suggestionsComputed =
+ builder.computeFast(request.target.containingNode);
return suggestionsComputed && request.target.argIndex == null;
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/local_suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/local_suggestion_builder.dart
index 324e1a7..74d5c95 100644
--- a/pkg/analysis_server/lib/src/services/completion/local_suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/local_suggestion_builder.dart
@@ -22,7 +22,9 @@
*/
protocol.Element createElement(
Source source, protocol.ElementKind kind, SimpleIdentifier id,
- {String parameters, TypeName returnType, bool isAbstract: false,
+ {String parameters,
+ TypeName returnType,
+ bool isAbstract: false,
bool isDeprecated: false}) {
String name;
Location location;
@@ -75,9 +77,14 @@
}
CompletionSuggestion suggestion = new CompletionSuggestion(
CompletionSuggestionKind.INVOCATION,
- isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance, completion,
- completion.length, 0, isDeprecated, false,
- returnType: nameForType(returnType), element: element);
+ isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
+ completion,
+ completion.length,
+ 0,
+ isDeprecated,
+ false,
+ returnType: nameForType(returnType),
+ element: element);
if (classDecl != null) {
SimpleIdentifier classId = classDecl.name;
if (classId != null) {
diff --git a/pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart b/pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart
index 0a6ca2c..1df4993 100644
--- a/pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart
@@ -404,8 +404,11 @@
bool typesOnly = node.parent is TypeName;
bool instCreation =
typesOnly && node.parent.parent is ConstructorName;
- LibraryElementSuggestionBuilder.suggestionsFor(request,
- CompletionSuggestionKind.INVOCATION, library, typesOnly,
+ LibraryElementSuggestionBuilder.suggestionsFor(
+ request,
+ CompletionSuggestionKind.INVOCATION,
+ library,
+ typesOnly,
instCreation);
modified = true;
if (directive.deferredKeyword != null) {
diff --git a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
index a2379ac..5a9f6c6 100644
--- a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
@@ -25,9 +25,11 @@
* If the suggestion is not currently in scope, then specify
* importForSource as the source to which an import should be added.
*/
-CompletionSuggestion createSuggestion(Element element, {String completion,
+CompletionSuggestion createSuggestion(Element element,
+ {String completion,
CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- int relevance: DART_RELEVANCE_DEFAULT, Source importForSource}) {
+ int relevance: DART_RELEVANCE_DEFAULT,
+ Source importForSource}) {
if (element is ExecutableElement && element.isOperator) {
// Do not include operators in suggestions
return null;
@@ -36,9 +38,14 @@
completion = element.displayName;
}
bool isDeprecated = element.isDeprecated;
- CompletionSuggestion suggestion = new CompletionSuggestion(kind,
- isDeprecated ? DART_RELEVANCE_LOW : relevance, completion,
- completion.length, 0, isDeprecated, false);
+ CompletionSuggestion suggestion = new CompletionSuggestion(
+ kind,
+ isDeprecated ? DART_RELEVANCE_LOW : relevance,
+ completion,
+ completion.length,
+ 0,
+ isDeprecated,
+ false);
suggestion.element = protocol.newElement_fromEngine(element);
Element enclosingElement = element.enclosingElement;
if (enclosingElement is ClassElement) {
@@ -52,9 +59,10 @@
suggestion.parameterTypes = element.parameters
.map((ParameterElement parameter) => parameter.type.displayName)
.toList();
- suggestion.requiredParameterCount = element.parameters.where(
- (ParameterElement parameter) =>
- parameter.parameterKind == ParameterKind.REQUIRED).length;
+ suggestion.requiredParameterCount = element.parameters
+ .where((ParameterElement parameter) =>
+ parameter.parameterKind == ParameterKind.REQUIRED)
+ .length;
suggestion.hasNamedParameters = element.parameters.any(
(ParameterElement parameter) =>
parameter.parameterKind == ParameterKind.NAMED);
@@ -177,7 +185,6 @@
* Common mixin for sharing behavior
*/
abstract class ElementSuggestionBuilder {
-
/**
* Return the kind of suggestions that should be built.
*/
@@ -434,8 +441,8 @@
type = request.cache.objectClassElement.type;
}
if (type is InterfaceType) {
- return new InterfaceTypeSuggestionBuilder(request)._buildSuggestions(
- type, library, isSuper, containingMethodName);
+ return new InterfaceTypeSuggestionBuilder(request)
+ ._buildSuggestions(type, library, isSuper, containingMethodName);
}
}
}
@@ -517,8 +524,11 @@
/**
* Add suggestions for the visible members in the given library
*/
- static void suggestionsFor(DartCompletionRequest request,
- CompletionSuggestionKind kind, LibraryElement library, bool typesOnly,
+ static void suggestionsFor(
+ DartCompletionRequest request,
+ CompletionSuggestionKind kind,
+ LibraryElement library,
+ bool typesOnly,
bool instCreation) {
if (library != null) {
library.visitChildren(new LibraryElementSuggestionBuilder(
@@ -532,7 +542,8 @@
* the visible named constructors in that class.
*/
class NamedConstructorSuggestionBuilder extends GeneralizingElementVisitor
- with ElementSuggestionBuilder implements SuggestionBuilder {
+ with ElementSuggestionBuilder
+ implements SuggestionBuilder {
final DartCompletionRequest request;
NamedConstructorSuggestionBuilder(this.request);
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 5bdbe24..6cc4739 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -82,10 +82,12 @@
static const REMOVE_TYPE_ANNOTATION =
const AssistKind('REMOVE_TYPE_ANNOTATION', 29, "Remove type annotation");
static const REPLACE_CONDITIONAL_WITH_IF_ELSE = const AssistKind(
- 'REPLACE_CONDITIONAL_WITH_IF_ELSE', 30,
+ 'REPLACE_CONDITIONAL_WITH_IF_ELSE',
+ 30,
"Replace conditional with 'if-else'");
static const REPLACE_IF_ELSE_WITH_CONDITIONAL = const AssistKind(
- 'REPLACE_IF_ELSE_WITH_CONDITIONAL', 30,
+ 'REPLACE_IF_ELSE_WITH_CONDITIONAL',
+ 30,
"Replace 'if-else' with conditional ('c ? x : y')");
static const SPLIT_AND_CONDITION =
const AssistKind('SPLIT_AND_CONDITION', 30, "Split && condition");
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index d1ec86e..eca515b 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -452,6 +452,9 @@
if (parent is PrefixedIdentifier) {
PrefixedIdentifier prefixedIdentifier = parent;
prefixElement = prefixedIdentifier.prefix.staticElement;
+ if (prefixElement == null) {
+ return;
+ }
parent = prefixedIdentifier.parent;
nameNode = prefixedIdentifier.identifier;
name = prefixedIdentifier.identifier.name;
diff --git a/pkg/analysis_server/lib/src/services/correction/namespace.dart b/pkg/analysis_server/lib/src/services/correction/namespace.dart
index 305052a..1ca99ba 100644
--- a/pkg/analysis_server/lib/src/services/correction/namespace.dart
+++ b/pkg/analysis_server/lib/src/services/correction/namespace.dart
@@ -57,8 +57,10 @@
* [element] - the referenced element.
* [importElementsMap] - the cache of [Element]s imported by [ImportElement]s.
*/
-ImportElement internal_getImportElement(LibraryElement libraryElement,
- String prefix, Element element,
+ImportElement internal_getImportElement(
+ LibraryElement libraryElement,
+ String prefix,
+ Element element,
Map<ImportElement, Set<Element>> importElementsMap) {
// validate Element
if (element == null) {
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
index de3da05..e7c8361 100644
--- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -190,7 +190,8 @@
AstNode lastNode = nodes.last;
SourceRange rangeAfterLastNode = rangeEndEnd(lastNode, selection);
if (_hasTokens(rangeAfterLastNode)) {
- invalidSelection("The end of the selection contains characters that "
+ invalidSelection(
+ "The end of the selection contains characters that "
"do not belong to a statement.",
newLocation_fromUnit(unit, rangeAfterLastNode));
}
diff --git a/pkg/analysis_server/lib/src/services/index/local_file_index.dart b/pkg/analysis_server/lib/src/services/index/local_file_index.dart
index c845c11..022fa1b 100644
--- a/pkg/analysis_server/lib/src/services/index/local_file_index.dart
+++ b/pkg/analysis_server/lib/src/services/index/local_file_index.dart
@@ -14,8 +14,12 @@
Index createLocalFileIndex() {
var fileManager = new TemporaryFolderFileManager();
var stringCodec = new StringCodec();
- var nodeManager = new FileNodeManager(fileManager,
- AnalysisEngine.instance.logger, stringCodec, new ContextCodec(),
- new ElementCodec(stringCodec), new RelationshipCodec(stringCodec));
+ var nodeManager = new FileNodeManager(
+ fileManager,
+ AnalysisEngine.instance.logger,
+ stringCodec,
+ new ContextCodec(),
+ new ElementCodec(stringCodec),
+ new RelationshipCodec(stringCodec));
return new LocalIndex(nodeManager);
}
diff --git a/pkg/analysis_server/lib/src/services/index/store/split_store.dart b/pkg/analysis_server/lib/src/services/index/store/split_store.dart
index ee5c3b8..8d94d74 100644
--- a/pkg/analysis_server/lib/src/services/index/store/split_store.dart
+++ b/pkg/analysis_server/lib/src/services/index/store/split_store.dart
@@ -482,8 +482,10 @@
RelationKeyData.forData(
this.elementId1, this.elementId2, this.elementId3, this.relationshipId);
- RelationKeyData.forObject(ElementCodec elementCodec,
- RelationshipCodec relationshipCodec, IndexableObject indexable,
+ RelationKeyData.forObject(
+ ElementCodec elementCodec,
+ RelationshipCodec relationshipCodec,
+ IndexableObject indexable,
RelationshipImpl relationship)
: elementId1 = elementCodec.encode1(indexable),
elementId2 = elementCodec.encode2(indexable),
@@ -1050,8 +1052,10 @@
factory _TopElementData(
ElementCodec elementCodec, IndexableObject indexable) {
- return new _TopElementData._(indexable.name,
- elementCodec.encode1(indexable), elementCodec.encode2(indexable),
+ return new _TopElementData._(
+ indexable.name,
+ elementCodec.encode1(indexable),
+ elementCodec.encode2(indexable),
elementCodec.encode3(indexable));
}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
index 3acc982..6cfd951 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -150,9 +150,11 @@
String declStatement = prefix + indent + declarationSource + eol;
String exprStatement = prefix + indent + 'return ';
Expression expr = target.expression;
- doSourceChange_addElementEdit(change, unitElement, new SourceEdit(
- target.offset, expr.offset - target.offset,
- '{' + eol + declStatement + exprStatement));
+ doSourceChange_addElementEdit(
+ change,
+ unitElement,
+ new SourceEdit(target.offset, expr.offset - target.offset,
+ '{' + eol + declStatement + exprStatement));
doSourceChange_addElementEdit(change, unitElement,
new SourceEdit(expr.end, 0, ';' + eol + prefix + '}'));
}
@@ -378,7 +380,8 @@
stringLiteralPart, excludedVariableNames));
} else if (singleExpression != null) {
names.addAll(getVariableNameSuggestionsForExpression(
- singleExpression.staticType, singleExpression,
+ singleExpression.staticType,
+ singleExpression,
excludedVariableNames));
}
}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index be9162d..da79930 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -731,7 +731,8 @@
names.clear();
if (_selectionExpression != null) {
names.addAll(getVariableNameSuggestionsForExpression(
- _selectionExpression.staticType, _selectionExpression,
+ _selectionExpression.staticType,
+ _selectionExpression,
_excludedNames));
}
}
@@ -817,8 +818,10 @@
Object visitConstructorInitializer(ConstructorInitializer node) {
super.visitConstructorInitializer(node);
if (_isFirstSelectedNode(node)) {
- invalidSelection('Cannot extract a constructor initializer. '
- 'Select expression part of initializer.', newLocation_fromNode(node));
+ invalidSelection(
+ 'Cannot extract a constructor initializer. '
+ 'Select expression part of initializer.',
+ newLocation_fromNode(node));
}
return null;
}
@@ -870,8 +873,10 @@
Object visitVariableDeclaration(VariableDeclaration node) {
super.visitVariableDeclaration(node);
if (_isFirstSelectedNode(node)) {
- invalidSelection('Cannot extract a variable declaration fragment. '
- 'Select whole declaration statement.', newLocation_fromNode(node));
+ invalidSelection(
+ 'Cannot extract a variable declaration fragment. '
+ 'Select whole declaration statement.',
+ newLocation_fromNode(node));
}
return null;
}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
index 35ba073..7c7e6356 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -45,13 +45,17 @@
* Returns the source which should replace given invocation with given
* arguments.
*/
-String _getMethodSourceForInvocation(RefactoringStatus status, _SourcePart part,
- CorrectionUtils utils, AstNode contextNode, Expression targetExpression,
+String _getMethodSourceForInvocation(
+ RefactoringStatus status,
+ _SourcePart part,
+ CorrectionUtils utils,
+ AstNode contextNode,
+ Expression targetExpression,
List<Expression> arguments) {
// prepare edits to replace parameters with arguments
List<SourceEdit> edits = <SourceEdit>[];
- part._parameters.forEach((ParameterElement parameter,
- List<_ParameterOccurrence> occurrences) {
+ part._parameters.forEach(
+ (ParameterElement parameter, List<_ParameterOccurrence> occurrences) {
// prepare argument
Expression argument = null;
for (Expression arg in arguments) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
index 849b9e1..d5663403 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
@@ -172,9 +172,11 @@
if (uri != null) {
String oldPrefix = 'package:$oldPackageName/';
if (uri.startsWith(oldPrefix)) {
- doSourceChange_addElementEdit(change, library, new SourceEdit(
- element.uriOffset + 1, oldPrefix.length,
- 'package:$newPackageName/'));
+ doSourceChange_addElementEdit(
+ change,
+ library,
+ new SourceEdit(element.uriOffset + 1, oldPrefix.length,
+ 'package:$newPackageName/'));
}
}
}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
index 1a29c3e..f589fe9 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
@@ -278,8 +278,11 @@
/**
* Returns a new [MoveFileRefactoring] instance.
*/
- factory MoveFileRefactoring(ResourceProvider resourceProvider,
- SearchEngine searchEngine, AnalysisContext context, Source source,
+ factory MoveFileRefactoring(
+ ResourceProvider resourceProvider,
+ SearchEngine searchEngine,
+ AnalysisContext context,
+ Source source,
String oldFile) {
return new MoveFileRefactoringImpl(
resourceProvider, searchEngine, context, source, oldFile);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
index 791f4b8..6799486 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
@@ -152,10 +152,13 @@
Future<RefactoringStatus> validate() async {
// check if there is a member with "newName" in the same ClassElement
for (Element newNameMember in getChildren(elementClass, name)) {
- result.addError(format(
- "Class '{0}' already declares {1} with name '{2}'.",
- elementClass.displayName, getElementKindName(newNameMember),
- name), newLocation_fromElement(newNameMember));
+ result.addError(
+ format(
+ "Class '{0}' already declares {1} with name '{2}'.",
+ elementClass.displayName,
+ getElementKindName(newNameMember),
+ name),
+ newLocation_fromElement(newNameMember));
}
// do chained computations
Set<ClassElement> superClasses = getSuperClasses(elementClass);
@@ -170,17 +173,23 @@
Element nameClass = nameElement.enclosingElement;
// renamed Element shadows member of superclass
if (superClasses.contains(nameClass)) {
- result.addError(format(isRename
+ result.addError(
+ format(
+ isRename
? "Renamed {0} will shadow {1} '{2}'."
: "Created {0} will shadow {1} '{2}'.",
- elementKind.displayName, getElementKindName(nameElement),
+ elementKind.displayName,
+ getElementKindName(nameElement),
getElementQualifiedName(nameElement)),
newLocation_fromElement(nameElement));
}
// renamed Element is shadowed by member of subclass
if (isRename && subClasses.contains(nameClass)) {
- result.addError(format("Renamed {0} will be shadowed by {1} '{2}'.",
- elementKind.displayName, getElementKindName(nameElement),
+ result.addError(
+ format(
+ "Renamed {0} will be shadowed by {1} '{2}'.",
+ elementKind.displayName,
+ getElementKindName(nameElement),
getElementQualifiedName(nameElement)),
newLocation_fromElement(nameElement));
}
@@ -193,10 +202,13 @@
subClasses.contains(enclosingClass)) {
for (SearchMatch reference in references) {
if (isReferenceInLocalRange(localElement, reference)) {
- result.addError(format(
- "Usage of renamed {0} will be shadowed by {1} '{2}'.",
- elementKind.displayName, getElementKindName(localElement),
- localElement.displayName), newLocation_fromMatch(reference));
+ result.addError(
+ format(
+ "Usage of renamed {0} will be shadowed by {1} '{2}'.",
+ elementKind.displayName,
+ getElementKindName(localElement),
+ localElement.displayName),
+ newLocation_fromMatch(reference));
}
}
}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
index 636c8bb..d5c489a 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
@@ -72,7 +72,9 @@
for (Element newNameMember in getChildren(parentClass, newName)) {
String message = format(
"Class '{0}' already declares {1} with name '{2}'.",
- parentClass.displayName, getElementKindName(newNameMember), newName);
+ parentClass.displayName,
+ getElementKindName(newNameMember),
+ newName);
result.addError(message, newLocation_fromElement(newNameMember));
}
}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
index 608eb73..6b73dd9 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
@@ -82,8 +82,11 @@
SimpleIdentifier interpolationIdentifier =
_getInterpolationIdentifier(reference);
if (interpolationIdentifier != null) {
- doSourceChange_addElementEdit(change, reference.element,
- new SourceEdit(interpolationIdentifier.offset,
+ doSourceChange_addElementEdit(
+ change,
+ reference.element,
+ new SourceEdit(
+ interpolationIdentifier.offset,
interpolationIdentifier.length,
'{$newName.${interpolationIdentifier.name}}'));
} else {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
index 2d2f797..8ab7de3 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
@@ -198,7 +198,8 @@
if (hasDisplayName(shadow, name)) {
String message = format(
"Reference to renamed {0} will be shadowed by {1} '{2}'.",
- getElementKindName(element), getElementKindName(shadow),
+ getElementKindName(element),
+ getElementKindName(shadow),
getElementQualifiedName(shadow));
result.addError(message, newLocation_fromElement(shadow));
}
@@ -249,10 +250,13 @@
continue;
}
// OK, reference will be shadowed be the element being renamed
- String message = format(isRename
+ String message = format(
+ isRename
? "Renamed {0} will shadow {1} '{2}'."
- : "Created {0} will shadow {1} '{2}'.", elementKind.displayName,
- getElementKindName(member), getElementQualifiedName(member));
+ : "Created {0} will shadow {1} '{2}'.",
+ elementKind.displayName,
+ getElementKindName(member),
+ getElementQualifiedName(member));
result.addError(message, newLocation_fromMatch(memberReference));
}
}
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
index be37a96..6126e14 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
@@ -207,9 +207,12 @@
for (LocationImpl location in locations) {
IndexableObject indexable = location.indexable;
if (indexable is IndexableElement) {
- matches.add(new SearchMatch(kind, indexable.element,
+ matches.add(new SearchMatch(
+ kind,
+ indexable.element,
new SourceRange(location.offset, location.length),
- location.isResolved, location.isQualified));
+ location.isResolved,
+ location.isQualified));
}
}
return matches;
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index d5abd12..7ec0a69 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -6,7 +6,6 @@
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/channel/channel.dart';
-import 'package:analysis_server/src/context_manager.dart';
import 'package:analysis_server/src/plugin/server_plugin.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analysis_server/src/services/index/index.dart';
@@ -29,7 +28,6 @@
final DirectoryBasedDartSdk defaultSdk;
final InstrumentationService instrumentationService;
final ServerPlugin serverPlugin;
- final ContextManager contextManager;
final ResolverProvider packageResolverProvider;
/**
@@ -43,8 +41,11 @@
*/
List<Plugin> userDefinedPlugins;
- SocketServer(this.analysisServerOptions, this.defaultSdk,
- this.instrumentationService, this.serverPlugin, this.contextManager,
+ SocketServer(
+ this.analysisServerOptions,
+ this.defaultSdk,
+ this.instrumentationService,
+ this.serverPlugin,
this.packageResolverProvider);
/**
@@ -80,10 +81,15 @@
index.run();
}
- analysisServer = new AnalysisServer(serverChannel, resourceProvider,
- new PubPackageMapProvider(resourceProvider, defaultSdk), index,
- serverPlugin, analysisServerOptions, defaultSdk, instrumentationService,
- contextManager: contextManager,
+ analysisServer = new AnalysisServer(
+ serverChannel,
+ resourceProvider,
+ new PubPackageMapProvider(resourceProvider, defaultSdk),
+ index,
+ serverPlugin,
+ analysisServerOptions,
+ defaultSdk,
+ instrumentationService,
packageResolverProvider: packageResolverProvider,
rethrowExceptions: false);
analysisServer.userDefinedPlugins = userDefinedPlugins;
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index 1f5f937..6a49946 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -179,8 +179,8 @@
if (analysisServer == null) {
return null;
}
- return analysisServer.handlers.firstWhere(
- (h) => h is CompletionDomainHandler, orElse: () => null);
+ return analysisServer.handlers
+ .firstWhere((h) => h is CompletionDomainHandler, orElse: () => null);
}
/**
@@ -223,7 +223,8 @@
*/
Folder _findFolder(AnalysisServer analysisServer, String contextFilter) {
return analysisServer.folderMap.keys.firstWhere(
- (Folder folder) => folder.path == contextFilter, orElse: () => null);
+ (Folder folder) => folder.path == contextFilter,
+ orElse: () => null);
}
/**
@@ -342,12 +343,15 @@
buffer.write('<p><b>Task performace data</b></p>');
buffer.write(
'<table style="border-collapse: separate; border-spacing: 10px 5px;">');
- _writeRow(buffer, [
- 'Task Name',
- 'Count',
- 'Total Time (in ms)',
- 'Average Time (in ms)'
- ], header: true);
+ _writeRow(
+ buffer,
+ [
+ 'Task Name',
+ 'Count',
+ 'Total Time (in ms)',
+ 'Average Time (in ms)'
+ ],
+ header: true);
Map<Type, int> countMap = AnalysisTask.countMap;
Map<Type, Stopwatch> stopwatchMap = AnalysisTask.stopwatchMap;
@@ -367,7 +371,12 @@
count,
taskTime,
count <= 0 ? '-' : (taskTime / count).toStringAsFixed(3)
- ], classes: [null, "right", "right", "right"]);
+ ], classes: [
+ null,
+ "right",
+ "right",
+ "right"
+ ]);
});
_writeRow(buffer, ['Total', '-', totalTaskTime, '-'],
classes: [null, "right", "right", "right"]);
@@ -402,10 +411,8 @@
InternalAnalysisContext context = analysisServer.folderMap[folder];
_writeResponse(request, (StringBuffer buffer) {
- _writePage(buffer, 'Analysis Server - AST Structure', [
- 'Context: $contextFilter',
- 'File: $sourceUri'
- ], (HttpResponse) {
+ _writePage(buffer, 'Analysis Server - AST Structure',
+ ['Context: $contextFilter', 'File: $sourceUri'], (HttpResponse) {
Source source = context.sourceFactory.forUri(sourceUri);
if (source == null) {
buffer.write('<p>Not found.</p>');
@@ -486,10 +493,8 @@
InternalAnalysisContext context = analysisServer.folderMap[folder];
_writeResponse(request, (StringBuffer buffer) {
- _writePage(buffer, 'Analysis Server - Cache Entry', [
- 'Context: $contextFilter',
- 'File: $sourceUri'
- ], (HttpResponse) {
+ _writePage(buffer, 'Analysis Server - Cache Entry',
+ ['Context: $contextFilter', 'File: $sourceUri'], (HttpResponse) {
buffer.write('<h3>Analyzing Contexts</h3><p>');
bool first = true;
allContexts.forEach((Folder folder) {
@@ -503,10 +508,13 @@
if (analyzingContext == context) {
buffer.write(folder.path);
} else {
- buffer.write(makeLink(CACHE_ENTRY_PATH, {
- CONTEXT_QUERY_PARAM: folder.path,
- SOURCE_QUERY_PARAM: sourceUri
- }, HTML_ESCAPE.convert(folder.path)));
+ buffer.write(makeLink(
+ CACHE_ENTRY_PATH,
+ {
+ CONTEXT_QUERY_PARAM: folder.path,
+ SOURCE_QUERY_PARAM: sourceUri
+ },
+ HTML_ESCAPE.convert(folder.path)));
}
if (entryMap[folder][0].explicitlyAdded) {
buffer.write(' (explicit)');
@@ -760,10 +768,14 @@
if (exception != null) {
exceptions.add(exception);
}
- String link = makeLink(CACHE_ENTRY_PATH, {
- CONTEXT_QUERY_PARAM: folder.path,
- SOURCE_QUERY_PARAM: source.uri.toString()
- }, sourceName, exception != null);
+ String link = makeLink(
+ CACHE_ENTRY_PATH,
+ {
+ CONTEXT_QUERY_PARAM: folder.path,
+ SOURCE_QUERY_PARAM: source.uri.toString()
+ },
+ sourceName,
+ exception != null);
if (entry.explicitlyAdded) {
explicitNames.add(sourceName);
} else {
@@ -803,8 +815,9 @@
}
_writeResponse(request, (StringBuffer buffer) {
- _writePage(buffer, 'Analysis Server - Context',
- ['Context: $contextFilter'], (StringBuffer buffer) {
+ _writePage(
+ buffer, 'Analysis Server - Context', ['Context: $contextFilter'],
+ (StringBuffer buffer) {
List headerRowText = ['Context'];
headerRowText.addAll(CacheState.values);
buffer.write('<h3>Summary</h3>');
@@ -928,8 +941,8 @@
buffer.write('<table border="1">');
_writeRow(buffer, ['Element', 'Relationship', 'Location'],
header: true);
- relations.forEach((List<String> elementPath,
- List<InspectLocation> relations) {
+ relations.forEach(
+ (List<String> elementPath, List<InspectLocation> relations) {
String elementLocation = elementPath.join(' ');
relations.forEach((InspectLocation location) {
var relString = location.relationship.identifier;
@@ -1085,9 +1098,8 @@
buffer.write('<br>');
}
String key = folder.shortName;
- buffer.write(makeLink(CONTEXT_PATH, {
- CONTEXT_QUERY_PARAM: folder.path
- }, key, _hasException(folderMap[folder])));
+ buffer.write(makeLink(CONTEXT_PATH, {CONTEXT_QUERY_PARAM: folder.path},
+ key, _hasException(folderMap[folder])));
});
buffer.write('</p>');
@@ -1174,24 +1186,26 @@
return;
}
buffer.write('<table>');
- _writeRow(buffer, [
- 'Start Time',
- '',
- 'First (ms)',
- '',
- 'Complete (ms)',
- '',
- '# Notifications',
- '',
- '# Suggestions',
- '',
- 'Snippet'
- ], header: true);
+ _writeRow(
+ buffer,
+ [
+ 'Start Time',
+ '',
+ 'First (ms)',
+ '',
+ 'Complete (ms)',
+ '',
+ '# Notifications',
+ '',
+ '# Suggestions',
+ '',
+ 'Snippet'
+ ],
+ header: true);
int index = 0;
for (CompletionPerformance performance in handler.performanceList) {
- String link = makeLink(COMPLETION_PATH, {
- 'index': '$index'
- }, '${performance.startTimeAndMs}');
+ String link = makeLink(COMPLETION_PATH, {'index': '$index'},
+ '${performance.startTimeAndMs}');
_writeRow(buffer, [
link,
' ',
diff --git a/pkg/analysis_server/lib/src/status/tree_writer.dart b/pkg/analysis_server/lib/src/status/tree_writer.dart
index ec9fb85..4b5b3a4 100644
--- a/pkg/analysis_server/lib/src/status/tree_writer.dart
+++ b/pkg/analysis_server/lib/src/status/tree_writer.dart
@@ -124,9 +124,8 @@
String name = value.name;
if (name != null) {
buffer.write(' [');
- buffer.write(GetHandler.makeLink(GetHandler.INDEX_ELEMENT_BY_NAME, {
- 'name': name
- }, 'search index'));
+ buffer.write(GetHandler.makeLink(GetHandler.INDEX_ELEMENT_BY_NAME,
+ {'name': name}, 'search index'));
buffer.write(']');
}
}
diff --git a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
index e6b1de9..14a2efc 100644
--- a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
+++ b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
@@ -58,9 +58,13 @@
DartFileEditBuilderImpl get dartFileEditBuilder => fileEditBuilder;
@override
- void writeClassDeclaration(String name, {Iterable<DartType> interfaces,
- bool isAbstract: false, void memberWriter(), Iterable<DartType> mixins,
- String nameGroupName, DartType superclass}) {
+ void writeClassDeclaration(String name,
+ {Iterable<DartType> interfaces,
+ bool isAbstract: false,
+ void memberWriter(),
+ Iterable<DartType> mixins,
+ String nameGroupName,
+ DartType superclass}) {
// TODO(brianwilkerson) Add support for type parameters, probably as a
// parameterWriter parameter.
// TODO(brianwilkerson) Add a superclassGroupName parameter.
@@ -95,7 +99,8 @@
//@override
void writeConstructorDeclaration(ClassElement classElement,
- {ArgumentList argumentList, SimpleIdentifier constructorName,
+ {ArgumentList argumentList,
+ SimpleIdentifier constructorName,
bool isConst: false}) {
// TODO(brianwilkerson) Clean up the API and add it to the public API.
//
@@ -134,9 +139,14 @@
}
@override
- void writeFieldDeclaration(String name, {void initializerWriter(),
- bool isConst: false, bool isFinal: false, bool isStatic: false,
- String nameGroupName, DartType type, String typeGroupName}) {
+ void writeFieldDeclaration(String name,
+ {void initializerWriter(),
+ bool isConst: false,
+ bool isFinal: false,
+ bool isStatic: false,
+ String nameGroupName,
+ DartType type,
+ String typeGroupName}) {
if (isStatic) {
write(Keyword.STATIC.syntax);
write(' ');
@@ -170,8 +180,11 @@
}
@override
- void writeGetterDeclaration(String name, {void bodyWriter(),
- bool isStatic: false, String nameGroupName, DartType returnType,
+ void writeGetterDeclaration(String name,
+ {void bodyWriter(),
+ bool isStatic: false,
+ String nameGroupName,
+ DartType returnType,
String returnTypeGroupName}) {
if (isStatic) {
write(Keyword.STATIC.syntax);
@@ -349,8 +362,10 @@
}
@override
- bool writeType(DartType type, {bool addSupertypeProposals: false,
- String groupName, bool required: false}) {
+ bool writeType(DartType type,
+ {bool addSupertypeProposals: false,
+ String groupName,
+ bool required: false}) {
if (type != null && !type.isDynamic) {
String typeSource =
utils.getTypeSource(type, dartFileEditBuilder.librariesToImport);
diff --git a/pkg/analysis_server/lib/starter.dart b/pkg/analysis_server/lib/starter.dart
index 87821c1..dc0b6ad 100644
--- a/pkg/analysis_server/lib/starter.dart
+++ b/pkg/analysis_server/lib/starter.dart
@@ -4,7 +4,6 @@
library driver;
-import 'package:analysis_server/src/context_manager.dart';
import 'package:analysis_server/src/server/driver.dart';
import 'package:analysis_server/uri/resolver_provider.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
@@ -12,6 +11,8 @@
/**
* An object that can be used to start an analysis server.
+ *
+ * Clients are not expected to subtype this class.
*/
abstract class ServerStarter {
/**
@@ -20,12 +21,6 @@
factory ServerStarter() = Driver;
/**
- * Set the context manager used to create analysis contexts within each of the
- * analysis roots.
- */
- void set contextManager(ContextManager manager);
-
- /**
* Set the instrumentation [server] that is to be used by the analysis server.
*/
void set instrumentationServer(InstrumentationServer server);
@@ -35,7 +30,6 @@
* are resolved in some contexts. The provider should return `null` if the
* default package resolution scheme should be used instead.
*/
- @deprecated
void set packageResolverProvider(ResolverProvider provider);
/**
diff --git a/pkg/analysis_server/lib/utilities/change_builder_dart.dart b/pkg/analysis_server/lib/utilities/change_builder_dart.dart
index b81b22a..74ca528 100644
--- a/pkg/analysis_server/lib/utilities/change_builder_dart.dart
+++ b/pkg/analysis_server/lib/utilities/change_builder_dart.dart
@@ -56,9 +56,13 @@
* list of [mixins] is provided but no [superclass] is given then the class
* will extend `Object`.)
*/
- void writeClassDeclaration(String name, {Iterable<DartType> interfaces,
- bool isAbstract: false, void memberWriter(), Iterable<DartType> mixins,
- String nameGroupName, DartType superclass});
+ void writeClassDeclaration(String name,
+ {Iterable<DartType> interfaces,
+ bool isAbstract: false,
+ void memberWriter(),
+ Iterable<DartType> mixins,
+ String nameGroupName,
+ DartType superclass});
/**
* Write the code for a declaration of a field with the given [name]. If an
@@ -76,9 +80,14 @@
* required.) If a [typeGroupName] is provided, then if a type was written
* it will be in the linked edit group with that name.
*/
- void writeFieldDeclaration(String name, {void initializerWriter(),
- bool isConst: false, bool isFinal: false, bool isStatic: false,
- String nameGroupName, DartType type, String typeGroupName});
+ void writeFieldDeclaration(String name,
+ {void initializerWriter(),
+ bool isConst: false,
+ bool isFinal: false,
+ bool isStatic: false,
+ String nameGroupName,
+ DartType type,
+ String typeGroupName});
/**
* Write the code for a declaration of a getter with the given [name]. If a
@@ -91,8 +100,11 @@
* getter. If a [returnTypeGroupName] is provided, then if a return type was
* written it will be in the linked edit group with that name.
*/
- void writeGetterDeclaration(String name, {void bodyWriter(),
- bool isStatic: false, String nameGroupName, DartType returnType,
+ void writeGetterDeclaration(String name,
+ {void bodyWriter(),
+ bool isStatic: false,
+ String nameGroupName,
+ DartType returnType,
String returnTypeGroupName});
/**
@@ -130,8 +142,10 @@
* `true`, then all of the supertypes of the [type] will be added as
* suggestions for alternatives to the type name.
*/
- bool writeType(DartType type, {bool addSupertypeProposals: false,
- String groupName, bool required: false});
+ bool writeType(DartType type,
+ {bool addSupertypeProposals: false,
+ String groupName,
+ bool required: false});
}
/**
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index 0cebf2f..d602bde 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -1595,13 +1595,13 @@
var v2 = p is!4;
}''',
<String>[
- "1+MyClass",
- "2+MyClass",
- "3+MyClass",
- "3-v1",
- "4+is",
- "4-isVariable"
- ]);
+ "1+MyClass",
+ "2+MyClass",
+ "3+MyClass",
+ "3-v1",
+ "4+is",
+ "4-isVariable"
+ ]);
buildTests(
'testCompletion_is_asIdentifierStart',
diff --git a/pkg/analysis_server/test/completion_test_support.dart b/pkg/analysis_server/test/completion_test_support.dart
index 8d002eb..800a6f2 100644
--- a/pkg/analysis_server/test/completion_test_support.dart
+++ b/pkg/analysis_server/test/completion_test_support.dart
@@ -190,18 +190,14 @@
if (!badPoints.isEmpty) {
err.write("No test location for tests:");
for (String ch in badPoints) {
- err
- ..write(' ')
- ..write(ch);
+ err..write(' ')..write(ch);
}
err.write(' ');
}
if (!badResults.isEmpty) {
err.write("No results for tests:");
for (String ch in badResults) {
- err
- ..write(' ')
- ..write(ch);
+ err..write(' ')..write(ch);
}
}
throw new IllegalStateException(err.toString());
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 4045228..20327de 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -366,8 +366,8 @@
''');
// Setup .packages file
newFile(
- [projPath, '.packages'],
- r'''
+ [projPath, '.packages'],
+ r'''
test_pack:lib/
''');
// Setup context.
@@ -382,7 +382,6 @@
expect(source.fullName, equals('/my/proj/sdk_ext/entry.dart'));
}
-
test_refresh_folder_with_packagespec() {
// create a context with a .packages file
String packagespecFile = posix.join(projPath, '.packages');
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index d90922b..afcff2d 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -95,6 +95,18 @@
expect(units, hasLength(1));
});
});
+
+ test('nonexistent folder', () async {
+ String fileB = '/project_b/b.dart';
+ resourceProvider.newFile(fileB, '// b');
+ var response = testSetAnalysisRoots(['/project_a', '/project_b'], []);
+ var serverRef = server;
+ expect(response, isResponseSuccess('0'));
+ // Non-existence of /project_a should not prevent files in /project_b
+ // from being analyzed.
+ await server.onAnalysisComplete;
+ expect(serverRef.getResolvedCompilationUnits(fileB), hasLength(1));
+ });
});
});
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index f09af0e..3c3306e 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -55,9 +55,14 @@
ExtensionManager manager = new ExtensionManager();
ServerPlugin serverPlugin = new ServerPlugin();
manager.processPlugins([serverPlugin]);
- return new Test_AnalysisServer(super.serverChannel, super.resourceProvider,
- super.packageMapProvider, index, serverPlugin,
- new AnalysisServerOptions(), new MockSdk(),
+ return new Test_AnalysisServer(
+ super.serverChannel,
+ super.resourceProvider,
+ super.packageMapProvider,
+ index,
+ serverPlugin,
+ new AnalysisServerOptions(),
+ new MockSdk(),
InstrumentationService.NULL_SERVICE);
}
@@ -422,8 +427,9 @@
{testFile: new AddContentOverlay(revisedContent)}).toRequest('add1'));
// Request code completion immediately after edit
- Response response = handleSuccessfulRequest(new CompletionGetSuggestionsParams(
- testFile, completionOffset).toRequest('0'));
+ Response response = handleSuccessfulRequest(
+ new CompletionGetSuggestionsParams(testFile, completionOffset)
+ .toRequest('0'));
completionId = response.id;
assertValidId(completionId);
await waitForTasksFinished();
@@ -536,7 +542,9 @@
}
test_partFile() {
- addFile('/project/bin/testA.dart', '''
+ addFile(
+ '/project/bin/testA.dart',
+ '''
library libA;
part "$testFile";
import 'dart:html';
@@ -556,7 +564,9 @@
}
test_partFile2() {
- addFile('/testA.dart', '''
+ addFile(
+ '/testA.dart',
+ '''
part of libA;
class A { }''');
addTestFile('''
@@ -716,14 +726,24 @@
class Test_AnalysisServer extends AnalysisServer {
final MockContext mockContext = new MockContext();
- Test_AnalysisServer(ServerCommunicationChannel channel,
+ Test_AnalysisServer(
+ ServerCommunicationChannel channel,
ResourceProvider resourceProvider,
- PubPackageMapProvider packageMapProvider, Index index,
- ServerPlugin serverPlugin, AnalysisServerOptions analysisServerOptions,
- DartSdk defaultSdk, InstrumentationService instrumentationService)
- : super(channel, resourceProvider, packageMapProvider, index,
- serverPlugin, analysisServerOptions, defaultSdk,
- instrumentationService);
+ PubPackageMapProvider packageMapProvider,
+ Index index,
+ ServerPlugin serverPlugin,
+ AnalysisServerOptions analysisServerOptions,
+ DartSdk defaultSdk,
+ InstrumentationService instrumentationService)
+ : super(
+ channel,
+ resourceProvider,
+ packageMapProvider,
+ index,
+ serverPlugin,
+ analysisServerOptions,
+ defaultSdk,
+ instrumentationService);
@override
AnalysisContext getAnalysisContext(String path) {
diff --git a/pkg/analysis_server/test/integration/integration_tests.dart b/pkg/analysis_server/test/integration/integration_tests.dart
index 3345554..08fb56d 100644
--- a/pkg/analysis_server/test/integration/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/integration_tests.dart
@@ -349,8 +349,8 @@
if (requiredFields != null) {
requiredFields.forEach((String key, Matcher valueMatcher) {
if (!item.containsKey(key)) {
- mismatches.add(
- (Description mismatchDescription) => mismatchDescription
+ mismatches.add((Description mismatchDescription) =>
+ mismatchDescription
.add('is missing field ')
.addDescriptionOf(key)
.add(' (')
@@ -381,7 +381,10 @@
*/
void _checkField(String key, value, Matcher valueMatcher,
List<MismatchDescriber> mismatches) {
- checkSubstructure(value, valueMatcher, mismatches,
+ checkSubstructure(
+ value,
+ valueMatcher,
+ mismatches,
(Description description) =>
description.add('field ').addDescriptionOf(key));
}
@@ -590,8 +593,11 @@
* `true`, the server will be started with "--observe" and
* "--pause-isolates-on-exit", allowing the observatory to be used.
*/
- Future start({bool debugServer: false, int diagnosticPort,
- bool profileServer: false, bool newTaskModel: false,
+ Future start(
+ {bool debugServer: false,
+ int diagnosticPort,
+ bool profileServer: false,
+ bool newTaskModel: false,
bool useAnalysisHighlight2: false}) {
if (_process != null) {
throw new Exception('Process already started');
@@ -696,8 +702,8 @@
Description describeMismatch(
item, Description mismatchDescription, Map matchState, bool verbose) {
if (item is! List) {
- return super.describeMismatch(
- item, mismatchDescription, matchState, verbose);
+ return super
+ .describeMismatch(item, mismatchDescription, matchState, verbose);
} else {
return iterableMatcher.describeMismatch(
item, mismatchDescription, matchState, verbose);
@@ -744,10 +750,16 @@
return;
}
item.forEach((key, value) {
- checkSubstructure(key, keyMatcher, mismatches,
+ checkSubstructure(
+ key,
+ keyMatcher,
+ mismatches,
(Description description) =>
description.add('key ').addDescriptionOf(key));
- checkSubstructure(value, valueMatcher, mismatches,
+ checkSubstructure(
+ value,
+ valueMatcher,
+ mismatches,
(Description description) =>
description.add('field ').addDescriptionOf(key));
});
@@ -850,8 +862,8 @@
}
return mismatchDescription;
} else {
- return super.describeMismatch(
- item, mismatchDescription, matchState, verbose);
+ return super
+ .describeMismatch(item, mismatchDescription, matchState, verbose);
}
}
@@ -878,6 +890,6 @@
*/
MismatchDescriber simpleDescription(String description) =>
(Description mismatchDescription) {
- mismatchDescription.add(description);
- };
+ mismatchDescription.add(description);
+ };
}
diff --git a/pkg/analysis_server/test/mock_sdk.dart b/pkg/analysis_server/test/mock_sdk.dart
index 78ee244..6d41c97 100644
--- a/pkg/analysis_server/test/mock_sdk.dart
+++ b/pkg/analysis_server/test/mock_sdk.dart
@@ -12,8 +12,10 @@
import 'package:analyzer/src/generated/source.dart';
class MockSdk implements DartSdk {
- static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary('dart:core',
- '/lib/core/core.dart', '''
+ static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary(
+ 'dart:core',
+ '/lib/core/core.dart',
+ '''
library dart.core;
import 'dart:async';
@@ -112,8 +114,10 @@
}
''');
- static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary('dart:async',
- '/lib/async/async.dart', '''
+ static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary(
+ 'dart:async',
+ '/lib/async/async.dart',
+ '''
library dart.async;
import 'dart:math';
@@ -130,14 +134,18 @@
''');
static const _MockSdkLibrary LIB_COLLECTION = const _MockSdkLibrary(
- 'dart:collection', '/lib/collection/collection.dart', '''
+ 'dart:collection',
+ '/lib/collection/collection.dart',
+ '''
library dart.collection;
abstract class HashMap<K, V> implements Map<K, V> {}
''');
static const _MockSdkLibrary LIB_CONVERT = const _MockSdkLibrary(
- 'dart:convert', '/lib/convert/convert.dart', '''
+ 'dart:convert',
+ '/lib/convert/convert.dart',
+ '''
library dart.convert;
import 'dart:async';
@@ -146,8 +154,10 @@
class JsonDecoder extends Converter<String, Object> {}
''');
- static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary('dart:math',
- '/lib/math/math.dart', '''
+ static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary(
+ 'dart:math',
+ '/lib/math/math.dart',
+ '''
library dart.math;
const double E = 2.718281828459045;
const double PI = 3.1415926535897932;
@@ -165,14 +175,18 @@
}
''');
- static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary('dart:html',
- '/lib/html/dartium/html_dartium.dart', '''
+ static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary(
+ 'dart:html',
+ '/lib/html/dartium/html_dartium.dart',
+ '''
library dart.html;
class HtmlElement {}
''');
static const _MockSdkLibrary LIB_INTERNAL = const _MockSdkLibrary(
- 'dart:_internal', '/lib/internal/internal.dart', '''
+ 'dart:_internal',
+ '/lib/internal/internal.dart',
+ '''
library dart._internal;
external void printToConsole(String line);
''');
diff --git a/pkg/analysis_server/test/operation/operation_queue_test.dart b/pkg/analysis_server/test/operation/operation_queue_test.dart
index 0be1a73..ed7fbca 100644
--- a/pkg/analysis_server/test/operation/operation_queue_test.dart
+++ b/pkg/analysis_server/test/operation/operation_queue_test.dart
@@ -60,6 +60,23 @@
class ServerOperationQueueTest {
ServerOperationQueue queue = new ServerOperationQueue();
+ void test_add_withMerge() {
+ var opA = new _MergeableOperationMock();
+ var opB = new _MergeableOperationMock();
+ var opC = new _MergeableOperationMock();
+ when(opA.merge(opC)).thenReturn(true);
+ when(opA.merge(anyObject)).thenReturn(false);
+ when(opB.merge(anyObject)).thenReturn(false);
+ when(opC.merge(anyObject)).thenReturn(false);
+ queue.add(opA);
+ queue.add(opB);
+ queue.add(opC);
+ expect(queue.take(), same(opA));
+ expect(queue.take(), same(opB));
+ // no opC, it was merged into opA
+ expect(queue.isEmpty, isTrue);
+ }
+
void test_clear() {
var operationA = mockOperation(ServerOperationPriority.ANALYSIS);
var operationB = mockOperation(ServerOperationPriority.ANALYSIS_CONTINUE);
@@ -106,6 +123,20 @@
expect(queue.isEmpty, isTrue);
}
+ void test_peek() {
+ var operationA = mockOperation(ServerOperationPriority.ANALYSIS);
+ var operationB = mockOperation(ServerOperationPriority.ANALYSIS);
+ queue.add(operationA);
+ queue.add(operationB);
+ expect(queue.peek(), operationA);
+ expect(queue.peek(), operationA);
+ expect(queue.peek(), operationA);
+ }
+
+ void test_peek_empty() {
+ expect(queue.peek(), isNull);
+ }
+
void test_reschedule() {
var prioritySource = new MockSource();
var analysisContextA = new AnalysisContextMock();
@@ -180,6 +211,27 @@
expect(queue.take(), operationA);
expect(queue.take(), isNull);
}
+
+ void test_takeIf() {
+ var operationA = mockOperation(ServerOperationPriority.ANALYSIS);
+ var operationB = mockOperation(ServerOperationPriority.ANALYSIS);
+ queue.add(operationA);
+ queue.add(operationB);
+ expect(queue.takeIf((_) => false), isNull);
+ expect(queue.takeIf((operation) => operation == operationB), operationB);
+ expect(queue.takeIf((operation) => operation == operationB), isNull);
+ expect(queue.takeIf((operation) => operation == operationA), operationA);
+ expect(queue.isEmpty, isTrue);
+ }
+}
+
+class _MergeableOperationMock extends TypedMock implements MergeableOperation {
+ @override
+ ServerOperationPriority get priority {
+ return ServerOperationPriority.ANALYSIS_NOTIFICATION;
+ }
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
class _ServerOperationMock extends TypedMock implements ServerOperation {
diff --git a/pkg/analysis_server/test/plugin/set_analysis_domain_test.dart b/pkg/analysis_server/test/plugin/set_analysis_domain_test.dart
index 38953fa0..02200c0 100644
--- a/pkg/analysis_server/test/plugin/set_analysis_domain_test.dart
+++ b/pkg/analysis_server/test/plugin/set_analysis_domain_test.dart
@@ -7,8 +7,10 @@
import 'dart:async';
import 'package:analysis_server/analysis/analysis_domain.dart';
-import 'package:analysis_server/analysis/navigation/navigation_core.dart';
+import 'package:analysis_server/analysis/navigation_core.dart';
+import 'package:analysis_server/analysis/occurrences_core.dart';
import 'package:analysis_server/plugin/navigation.dart';
+import 'package:analysis_server/plugin/occurrences.dart';
import 'package:analysis_server/src/constants.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -37,11 +39,9 @@
@reflectiveTest
class SetAnalysisDomainTest extends AbstractAnalysisTest {
final Set<String> parsedUnitFiles = new Set<String>();
- bool contributorMayAddRegion = false;
- List<NavigationRegion> regions;
- List<NavigationTarget> targets;
- List<String> targetFiles;
+ AnalysisNavigationParams navigationParams;
+ AnalysisOccurrencesParams occurrencesParams;
@override
void addServerPlugins(List<Plugin> plugins) {
@@ -53,15 +53,14 @@
void processNotification(Notification notification) {
if (notification.event == ANALYSIS_NAVIGATION) {
var params = new AnalysisNavigationParams.fromNotification(notification);
- // TODO(scheglov) we check for "params.regions.isNotEmpty" because
- // normal, Dart only, navigation notifications are scheduled as
- // operations, but plugins use "notificationSite.scheduleNavigation"
- // which is not scheduled yet. So, it comes *before* the Dart one, and
- // gets lost.
- if (params.file == testFile && params.regions.isNotEmpty) {
- regions = params.regions;
- targets = params.targets;
- targetFiles = params.files;
+ if (params.file == testFile) {
+ navigationParams = params;
+ }
+ }
+ if (notification.event == ANALYSIS_OCCURRENCES) {
+ var params = new AnalysisOccurrencesParams.fromNotification(notification);
+ if (params.file == testFile) {
+ occurrencesParams = params;
}
}
}
@@ -69,27 +68,38 @@
Future test_contributorIsInvoked() async {
createProject();
addAnalysisSubscription(AnalysisService.NAVIGATION, testFile);
+ addAnalysisSubscription(AnalysisService.OCCURRENCES, testFile);
addTestFile('// usually no navigation');
await server.onAnalysisComplete;
// we have PARSED_UNIT
expect(parsedUnitFiles, contains(testFile));
// we have an additional navigation region/target
- expect(regions, hasLength(1));
{
- NavigationRegion region = regions.single;
- expect(region.offset, 1);
- expect(region.length, 5);
- expect(region.targets.single, 0);
+ expect(navigationParams.regions, hasLength(1));
+ {
+ NavigationRegion region = navigationParams.regions.single;
+ expect(region.offset, 1);
+ expect(region.length, 5);
+ expect(region.targets.single, 0);
+ }
+ {
+ NavigationTarget target = navigationParams.targets.single;
+ expect(target.fileIndex, 0);
+ expect(target.offset, 1);
+ expect(target.length, 2);
+ expect(target.startLine, 3);
+ expect(target.startColumn, 4);
+ }
+ expect(navigationParams.files.single, '/testLocation.dart');
}
+ // we have additional occurrences
{
- NavigationTarget target = targets.single;
- expect(target.fileIndex, 0);
- expect(target.offset, 1);
- expect(target.length, 2);
- expect(target.startLine, 3);
- expect(target.startColumn, 4);
+ expect(occurrencesParams.occurrences, hasLength(1));
+ Occurrences occurrences = occurrencesParams.occurrences.single;
+ expect(occurrences.element.name, 'TestElement');
+ expect(occurrences.length, 5);
+ expect(occurrences.offsets, unorderedEquals([1, 2, 3]));
}
- expect(targetFiles.single, '/testLocation.dart');
}
}
@@ -99,12 +109,24 @@
TestNavigationContributor(this.test);
@override
- void computeNavigation(NavigationHolder holder, AnalysisContext context,
+ void computeNavigation(NavigationCollector collector, AnalysisContext context,
Source source, int offset, int length) {
- if (test.contributorMayAddRegion) {
- holder.addRegion(1, 5, ElementKind.CLASS,
- new Location('/testLocation.dart', 1, 2, 3, 4));
- }
+ collector.addRegion(1, 5, ElementKind.CLASS,
+ new Location('/testLocation.dart', 1, 2, 3, 4));
+ }
+}
+
+class TestOccurrencesContributor implements OccurrencesContributor {
+ final SetAnalysisDomainTest test;
+
+ TestOccurrencesContributor(this.test);
+
+ @override
+ void computeOccurrences(
+ OccurrencesCollector collector, AnalysisContext context, Source source) {
+ Element element = new Element(ElementKind.UNKNOWN, 'TestElement', 0);
+ collector.addOccurrences(new Occurrences(element, <int>[1, 2], 5));
+ collector.addOccurrences(new Occurrences(element, <int>[3], 5));
}
}
@@ -124,6 +146,8 @@
register(SET_ANALYSIS_DOMAIN_EXTENSION_POINT_ID, _setAnalysisDomain);
register(NAVIGATION_CONTRIBUTOR_EXTENSION_POINT_ID,
new TestNavigationContributor(test));
+ register(OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT_ID,
+ new TestOccurrencesContributor(test));
}
void _setAnalysisDomain(AnalysisDomain domain) {
@@ -133,14 +157,10 @@
expect(result.value, isNotNull);
Source source = result.target.source;
test.parsedUnitFiles.add(source.fullName);
- // let the navigation contributor to work
- test.contributorMayAddRegion = true;
- try {
- domain.scheduleNotification(
- result.context, source, AnalysisService.NAVIGATION);
- } finally {
- test.contributorMayAddRegion = false;
- }
+ domain.scheduleNotification(
+ result.context, source, AnalysisService.NAVIGATION);
+ domain.scheduleNotification(
+ result.context, source, AnalysisService.OCCURRENCES);
});
}
}
diff --git a/pkg/analysis_server/test/services/completion/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/arglist_contributor_test.dart
index 0f391e8..433448b 100644
--- a/pkg/analysis_server/test/services/completion/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/arglist_contributor_test.dart
@@ -42,8 +42,10 @@
assertNoOtherSuggestions([cs]);
}
- void assertSuggestArgumentList_params(List<String> expectedNames,
- List<String> expectedTypes, List<String> actualNames,
+ void assertSuggestArgumentList_params(
+ List<String> expectedNames,
+ List<String> expectedTypes,
+ List<String> actualNames,
List<String> actualTypes) {
if (actualNames != null &&
actualNames.length == expectedNames.length &&
@@ -118,7 +120,9 @@
test_ArgumentList_imported_function_0() {
// ArgumentList MethodInvocation ExpressionStatement Block
- addSource('/libA.dart', '''
+ addSource(
+ '/libA.dart',
+ '''
library A;
bool hasLength(int expected) { }
expect() { }
@@ -136,7 +140,9 @@
test_ArgumentList_imported_function_1() {
// ArgumentList MethodInvocation ExpressionStatement Block
- addSource('/libA.dart', '''
+ addSource(
+ '/libA.dart',
+ '''
library A;
bool hasLength(int expected) { }
expect(String arg) { }
@@ -154,7 +160,9 @@
test_ArgumentList_imported_function_2() {
// ArgumentList MethodInvocation ExpressionStatement Block
- addSource('/libA.dart', '''
+ addSource(
+ '/libA.dart',
+ '''
library A;
bool hasLength(int expected) { }
expect(String arg1, int arg2) { }
@@ -172,7 +180,9 @@
test_ArgumentList_imported_function_3() {
// ArgumentList MethodInvocation ExpressionStatement Block
- addSource('/libA.dart', '''
+ addSource(
+ '/libA.dart',
+ '''
library A;
bool hasLength(int expected) { }
expect(String arg1, int arg2, {bool arg3}) { }
@@ -190,7 +200,9 @@
test_ArgumentList_imported_function_3a() {
// ArgumentList MethodInvocation ExpressionStatement Block
- addSource('/libA.dart', '''
+ addSource(
+ '/libA.dart',
+ '''
library A;
bool hasLength(int expected) { }
expect(String arg1, int arg2, {bool arg3}) { }
@@ -208,7 +220,9 @@
test_ArgumentList_imported_function_3b() {
// ArgumentList MethodInvocation ExpressionStatement Block
- addSource('/libA.dart', '''
+ addSource(
+ '/libA.dart',
+ '''
library A;
bool hasLength(int expected) { }
expect(String arg1, int arg2, {bool arg3}) { }
@@ -226,7 +240,9 @@
test_ArgumentList_imported_function_3c() {
// ArgumentList MethodInvocation ExpressionStatement Block
- addSource('/libA.dart', '''
+ addSource(
+ '/libA.dart',
+ '''
library A;
bool hasLength(int expected) { }
expect(String arg1, int arg2, {bool arg3}) { }
@@ -244,7 +260,9 @@
test_ArgumentList_imported_function_3d() {
// ArgumentList MethodInvocation ExpressionStatement Block
- addSource('/libA.dart', '''
+ addSource(
+ '/libA.dart',
+ '''
library A;
bool hasLength(int expected) { }
expect(String arg1, int arg2, {bool arg3}) { }
@@ -462,7 +480,9 @@
test_ArgumentList_local_method_0() {
// ArgumentList MethodInvocation ExpressionStatement Block
- addSource('/libA.dart', '''
+ addSource(
+ '/libA.dart',
+ '''
library A;
bool hasLength(int expected) { }
void baz() { }''');
@@ -480,7 +500,9 @@
test_ArgumentList_local_method_2() {
// ArgumentList MethodInvocation ExpressionStatement Block
- addSource('/libA.dart', '''
+ addSource(
+ '/libA.dart',
+ '''
library A;
bool hasLength(int expected) { }
void baz() { }''');
diff --git a/pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart
index 2a537ed..cb29f97 100644
--- a/pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart
@@ -25,8 +25,10 @@
@override
CompletionSuggestion assertSuggestLocalClass(String name,
{CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- int relevance: DART_RELEVANCE_DEFAULT, bool isDeprecated: false,
- String elemFile, int elemOffset}) {
+ int relevance: DART_RELEVANCE_DEFAULT,
+ bool isDeprecated: false,
+ String elemFile,
+ int elemOffset}) {
return assertSuggestClass(name,
elemFile: elemFile,
elemOffset: elemOffset,
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 5735dec..393c2f3 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -541,6 +541,15 @@
_assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']);
}
+ void test_createClass_BAD_hasUnresolvedPrefix() {
+ resolveTestUnit('''
+main() {
+ prefix.Test v = null;
+}
+''');
+ assertNoFix(DartFixKind.CREATE_CLASS);
+ }
+
void test_createClass_inLibraryOfPrefix() {
String libCode = r'''
library my.lib;
@@ -2612,44 +2621,6 @@
''');
}
- void test_importLibraryPrefix_withClass() {
- resolveTestUnit('''
-import 'dart:async' as pref;
-main() {
- pref.Stream s = null;
- Future f = null;
-}
-''');
- assertHasFix(
- DartFixKind.IMPORT_LIBRARY_PREFIX,
- '''
-import 'dart:async' as pref;
-main() {
- pref.Stream s = null;
- pref.Future f = null;
-}
-''');
- }
-
- void test_importLibraryPrefix_withTopLevelVariable() {
- resolveTestUnit('''
-import 'dart:math' as pref;
-main() {
- print(pref.E);
- print(PI);
-}
-''');
- assertHasFix(
- DartFixKind.IMPORT_LIBRARY_PREFIX,
- '''
-import 'dart:math' as pref;
-main() {
- print(pref.E);
- print(pref.PI);
-}
-''');
- }
-
void test_importLibraryProject_withClass_annotation() {
addSource(
'/lib.dart',
@@ -4364,6 +4335,44 @@
''');
}
+ void test_useImportPrefix_withClass() {
+ resolveTestUnit('''
+import 'dart:async' as pref;
+main() {
+ pref.Stream s = null;
+ Future f = null;
+}
+''');
+ assertHasFix(
+ DartFixKind.IMPORT_LIBRARY_PREFIX,
+ '''
+import 'dart:async' as pref;
+main() {
+ pref.Stream s = null;
+ pref.Future f = null;
+}
+''');
+ }
+
+ void test_useImportPrefix_withTopLevelVariable() {
+ resolveTestUnit('''
+import 'dart:math' as pref;
+main() {
+ print(pref.E);
+ print(PI);
+}
+''');
+ assertHasFix(
+ DartFixKind.IMPORT_LIBRARY_PREFIX,
+ '''
+import 'dart:math' as pref;
+main() {
+ print(pref.E);
+ print(pref.PI);
+}
+''');
+ }
+
/**
* Computes fixes and verifies that there is a fix of the given kind.
*/
diff --git a/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart b/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
index 8ed4913..81d13c0 100644
--- a/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
+++ b/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
@@ -92,7 +92,8 @@
*/
void assertRefactoringStatus(
RefactoringStatus status, RefactoringProblemSeverity expectedSeverity,
- {String expectedMessage, SourceRange expectedContextRange,
+ {String expectedMessage,
+ SourceRange expectedContextRange,
String expectedContextSearch}) {
expect(status.severity, expectedSeverity, reason: status.toString());
if (expectedSeverity != null) {
diff --git a/pkg/analysis_server/test/socket_server_test.dart b/pkg/analysis_server/test/socket_server_test.dart
index a961aae..f1ef37e 100644
--- a/pkg/analysis_server/test/socket_server_test.dart
+++ b/pkg/analysis_server/test/socket_server_test.dart
@@ -116,7 +116,6 @@
DirectoryBasedDartSdk.defaultSdk,
InstrumentationService.NULL_SERVICE,
serverPlugin,
- null,
null);
}
}
diff --git a/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart b/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart
index 913b9b2..c7e387b 100644
--- a/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart
+++ b/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart
@@ -35,8 +35,8 @@
'deprecated': '0x20'
};
-final GeneratedFile target = new GeneratedFile(
- '../../lib/src/generated_protocol.dart', () {
+final GeneratedFile target =
+ new GeneratedFile('../../lib/src/generated_protocol.dart', () {
CodegenProtocolVisitor visitor = new CodegenProtocolVisitor(readApi());
return visitor.collectCode(visitor.visitApi);
});
@@ -563,8 +563,8 @@
writeln('factory RefactoringOptions.fromJson(JsonDecoder jsonDecoder, '
'String jsonPath, Object json, RefactoringKind kind) {');
indent(() {
- writeln(
- 'return _refactoringOptionsFromJson(jsonDecoder, jsonPath, ' 'json, kind);');
+ writeln('return _refactoringOptionsFromJson(jsonDecoder, jsonPath, '
+ 'json, kind);');
});
writeln('}');
return;
diff --git a/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart b/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart
index bc7bce6..38b3f20 100644
--- a/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart
+++ b/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart
@@ -160,11 +160,9 @@
visitNotification(Notification notification) {
String streamName =
camelJoin(['on', notification.domainName, notification.event]);
- String className = camelJoin([
- notification.domainName,
- notification.event,
- 'params'
- ], doCapitalize: true);
+ String className = camelJoin(
+ [notification.domainName, notification.event, 'params'],
+ doCapitalize: true);
writeln();
docComment(toHtmlVisitor.collectHtml(() {
toHtmlVisitor.translateHtml(notification.html);
@@ -234,7 +232,8 @@
writeln('$futureClass $methodName(${args.join(', ')}) {');
indent(() {
String requestClass = camelJoin(
- [request.domainName, request.method, 'params'], doCapitalize: true);
+ [request.domainName, request.method, 'params'],
+ doCapitalize: true);
String paramsVar = 'null';
if (request.params != null) {
paramsVar = 'params';
diff --git a/pkg/analysis_server/tool/spec/codegen_matchers.dart b/pkg/analysis_server/tool/spec/codegen_matchers.dart
index e0e6448..5786493 100644
--- a/pkg/analysis_server/tool/spec/codegen_matchers.dart
+++ b/pkg/analysis_server/tool/spec/codegen_matchers.dart
@@ -15,8 +15,8 @@
import 'implied_types.dart';
import 'to_html.dart';
-final GeneratedFile target = new GeneratedFile(
- '../../test/integration/protocol_matchers.dart', () {
+final GeneratedFile target =
+ new GeneratedFile('../../test/integration/protocol_matchers.dart', () {
CodegenMatchersVisitor visitor = new CodegenMatchersVisitor(readApi());
return visitor.collectCode(visitor.visitApi);
});
diff --git a/pkg/analysis_server/tool/spec/codegen_tools.dart b/pkg/analysis_server/tool/spec/codegen_tools.dart
index 45dd4be..f3fcb5d 100644
--- a/pkg/analysis_server/tool/spec/codegen_tools.dart
+++ b/pkg/analysis_server/tool/spec/codegen_tools.dart
@@ -77,7 +77,8 @@
try {
_state = new _CodeGeneratorState();
callback();
- var text = _state.buffer.toString().replaceAll(trailingSpacesInLineRegExp, '');
+ var text =
+ _state.buffer.toString().replaceAll(trailingSpacesInLineRegExp, '');
if (!removeTrailingNewLine) {
return text;
} else {
@@ -101,7 +102,7 @@
bool javadocStyle = codeGeneratorSettings.languageName == 'java';
indentBy(codeGeneratorSettings.docCommentLineLeader, () {
write(nodesToText(docs, width - _state.indent.length, javadocStyle,
- removeTrailingNewLine: removeTrailingNewLine));
+ removeTrailingNewLine: removeTrailingNewLine));
});
writeln(codeGeneratorSettings.docCommentEndMarker);
}
@@ -110,8 +111,8 @@
* Execute [callback], indenting any code it outputs.
*/
void indent(void callback()) {
- indentSpecial(codeGeneratorSettings.indent, codeGeneratorSettings.indent,
- callback);
+ indentSpecial(
+ codeGeneratorSettings.indent, codeGeneratorSettings.indent, callback);
}
/**
@@ -250,10 +251,14 @@
*/
String indent;
- CodeGeneratorSettings({this.languageName: 'java',
- this.lineCommentLineLeader: '// ', this.docCommentStartMarker: '/**',
- this.docCommentLineLeader: ' * ', this.docCommentEndMarker: ' */',
- this.commentLineLength: 99, this.indent: ' '});
+ CodeGeneratorSettings(
+ {this.languageName: 'java',
+ this.lineCommentLineLeader: '// ',
+ this.docCommentStartMarker: '/**',
+ this.docCommentLineLeader: ' * ',
+ this.docCommentEndMarker: ' */',
+ this.commentLineLength: 99,
+ this.indent: ' '});
}
abstract class GeneratedContent {
@@ -267,7 +272,6 @@
* generated HTML). No other content should exist in the directory.
*/
class GeneratedDirectory extends GeneratedContent {
-
/**
* The path to the directory that will have the generated content.
*/
@@ -308,8 +312,9 @@
}
}
int nonHiddenFileCount = 0;
- outputFile.listSync(recursive: false, followLinks: false).forEach(
- (FileSystemEntity fileSystemEntity) {
+ outputFile
+ .listSync(recursive: false, followLinks: false)
+ .forEach((FileSystemEntity fileSystemEntity) {
if (fileSystemEntity is File &&
!basename(fileSystemEntity.path).startsWith('.')) {
nonHiddenFileCount++;
diff --git a/pkg/analysis_server/tool/spec/from_html.dart b/pkg/analysis_server/tool/spec/from_html.dart
index 458142b..c3e3010 100644
--- a/pkg/analysis_server/tool/spec/from_html.dart
+++ b/pkg/analysis_server/tool/spec/from_html.dart
@@ -123,6 +123,7 @@
'$context: Expected $expectedName, found ${element.localName}');
}
}
+
/**
* Create a [Domain] object from an HTML representation such as:
*
@@ -419,6 +420,7 @@
TypeDecl type = processContentsAsType(html, context);
return new TypeDefinition(name, type, html);
}
+
/**
* Create a [TypeEnum] from an HTML description.
*/
@@ -480,8 +482,8 @@
checkName(html, 'field', context);
String name = html.attributes['name'];
context = '$context.${name != null ? name : 'field'}';
- checkAttributes(
- html, ['name'], context, optionalAttributes: ['optional', 'value']);
+ checkAttributes(html, ['name'], context,
+ optionalAttributes: ['optional', 'value']);
bool optional = false;
String optionalString = html.attributes['optional'];
if (optionalString != null) {
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/NavigationRegion.java b/pkg/analysis_server/tool/spec/generated/java/types/NavigationRegion.java
index b42bdc7..8500056 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/NavigationRegion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/NavigationRegion.java
@@ -55,7 +55,8 @@
/**
* The indexes of the targets (in the enclosing navigation response) to which the given region is
- * bound. By opening the target, clients can implement one form of navigation.
+ * bound. By opening the target, clients can implement one form of navigation. This list cannot be
+ * empty.
*/
private final int[] targets;
@@ -125,7 +126,8 @@
/**
* The indexes of the targets (in the enclosing navigation response) to which the given region is
- * bound. By opening the target, clients can implement one form of navigation.
+ * bound. By opening the target, clients can implement one form of navigation. This list cannot be
+ * empty.
*/
public int[] getTargets() {
return targets;
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 974eb97..5b0a431 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -3054,7 +3054,7 @@
<p>
The indexes of the targets (in the enclosing navigation response)
to which the given region is bound. By opening the target, clients
- can implement one form of navigation.
+ can implement one form of navigation. This list cannot be empty.
</p>
</field>
</object>
diff --git a/pkg/analysis_server/tool/spec/text_formatter.dart b/pkg/analysis_server/tool/spec/text_formatter.dart
index 44c9ba0..a4eb82c 100644
--- a/pkg/analysis_server/tool/spec/text_formatter.dart
+++ b/pkg/analysis_server/tool/spec/text_formatter.dart
@@ -19,8 +19,8 @@
* If [javadocStyle] is true, then the output is compatable with Javadoc,
* which understands certain HTML constructs.
*/
-String nodesToText(List<dom.Node> desc, int width, bool javadocStyle, {
- bool removeTrailingNewLine: false}) {
+String nodesToText(List<dom.Node> desc, int width, bool javadocStyle,
+ {bool removeTrailingNewLine: false}) {
_TextFormatter formatter = new _TextFormatter(width, javadocStyle);
return formatter.collectCode(() {
formatter.addAll(desc);
diff --git a/pkg/analysis_server/tool/spec/to_html.dart b/pkg/analysis_server/tool/spec/to_html.dart
index 005ce6a..3d35b01 100644
--- a/pkg/analysis_server/tool/spec/to_html.dart
+++ b/pkg/analysis_server/tool/spec/to_html.dart
@@ -125,6 +125,7 @@
void box(void callback()) {
element('div', {'class': 'box'}, callback);
}
+
void br() => element('br', {});
void dd(void callback()) => element('dd', {}, callback);
void dl(void callback()) => element('dl', {}, callback);
@@ -140,6 +141,7 @@
}
return element('h2', {'class': cls}, callback);
}
+
void h3(void callback()) => element('h3', {}, callback);
void h4(void callback()) => element('h4', {}, callback);
void h5(void callback()) => element('h5', {}, callback);
@@ -151,6 +153,7 @@
void link(String id, void callback()) {
element('a', {'href': '#$id'}, callback);
}
+
void p(void callback()) => element('p', {}, callback);
void pre(void callback()) => element('pre', {}, callback);
void title(void callback()) => element('title', {}, callback);
@@ -526,8 +529,11 @@
h5(() => write("Requests"));
element('ul', {}, () {
for (var request in requests) {
- element('li', {}, () => link('request_${request.longMethod}', () =>
- write(request.method)));
+ element(
+ 'li',
+ {},
+ () => link(
+ 'request_${request.longMethod}', () => write(request.method)));
}
});
}
@@ -537,8 +543,11 @@
element('div', {'class': 'subindex'}, () {
element('ul', {}, () {
for (var notification in notifications) {
- element('li', {}, () => link('notification_${notification.longEvent}',
- () => write(notification.event)));
+ element(
+ 'li',
+ {},
+ () => link('notification_${notification.longEvent}',
+ () => write(notification.event)));
}
});
});
@@ -571,8 +580,11 @@
element('div', {'class': 'subindex'}, () {
element('ul', {}, () {
for (var refactoring in refactorings) {
- element('li', {}, () => link('refactoring_${refactoring.kind}',
- () => write(refactoring.kind)));
+ element(
+ 'li',
+ {},
+ () => link('refactoring_${refactoring.kind}',
+ () => write(refactoring.kind)));
}
});
});
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index b8fdcf1..303d175 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -19,8 +19,8 @@
* A `dart:io` based implementation of [ResourceProvider].
*/
class PhysicalResourceProvider implements ResourceProvider {
- static final NORMALIZE_EOL_ALWAYS =
- (String string) => string.replaceAll(new RegExp('\r\n?'), '\n');
+ static final NORMALIZE_EOL_ALWAYS = (String string) =>
+ string.replaceAll(new RegExp('\r\n?'), '\n');
static final PhysicalResourceProvider INSTANCE =
new PhysicalResourceProvider(null);
diff --git a/pkg/analyzer/lib/instrumentation/instrumentation.dart b/pkg/analyzer/lib/instrumentation/instrumentation.dart
index 40db35e..18772de 100644
--- a/pkg/analyzer/lib/instrumentation/instrumentation.dart
+++ b/pkg/analyzer/lib/instrumentation/instrumentation.dart
@@ -150,14 +150,21 @@
* entry has the given [level] and [message], and was created at the given
* [time].
*/
- void logLogEntry(String level, DateTime time, String message, Object exception, StackTrace stackTrace) {
+ void logLogEntry(String level, DateTime time, String message,
+ Object exception, StackTrace stackTrace) {
if (_instrumentationServer != null) {
String timeStamp =
time == null ? 'null' : time.millisecondsSinceEpoch.toString();
String exceptionText = exception.toString();
String stackTraceText = stackTrace.toString();
- _instrumentationServer
- .log(_join([TAG_LOG_ENTRY, level, timeStamp, message, exceptionText, stackTraceText]));
+ _instrumentationServer.log(_join([
+ TAG_LOG_ENTRY,
+ level,
+ timeStamp,
+ message,
+ exceptionText,
+ stackTraceText
+ ]));
}
}
diff --git a/pkg/analyzer/lib/plugin/options.dart b/pkg/analyzer/lib/plugin/options.dart
index cc0b88d..65775e1 100644
--- a/pkg/analyzer/lib/plugin/options.dart
+++ b/pkg/analyzer/lib/plugin/options.dart
@@ -18,7 +18,7 @@
OptionsPlugin.OPTIONS_PROCESSOR_EXTENSION_POINT);
/// Processes options defined in the analysis options file.
-///
+///
/// The options file format is intentionally very open-ended, giving clients
/// utmost flexibility in defining their own options. The only hardfast
/// expectation is that options files will contain a mapping from Strings
@@ -45,7 +45,6 @@
/// bool useMultiPackage =
/// options['compiler']['resolver']['useMultiPackage'];
abstract class OptionsProcessor {
-
/// Called when an error occurs in processing options.
void onError(Exception exception);
diff --git a/pkg/analyzer/lib/plugin/task.dart b/pkg/analyzer/lib/plugin/task.dart
index 72c33fa..fd4dd7c 100644
--- a/pkg/analyzer/lib/plugin/task.dart
+++ b/pkg/analyzer/lib/plugin/task.dart
@@ -15,6 +15,32 @@
/**
* The identifier of the extension point that allows plugins to register new
+ * analysis error results to compute for a Dart source. The object used as an
+ * extension must be a [ResultDescriptor].
+ */
+final String DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID = Plugin.join(
+ EnginePlugin.UNIQUE_IDENTIFIER,
+ EnginePlugin.DART_ERRORS_FOR_SOURCE_EXTENSION_POINT);
+
+/**
+ * The identifier of the extension point that allows plugins to register new
+ * analysis error results to compute for a Dart library specific unit. The
+ * object used as an extension must be a [ResultDescriptor].
+ */
+final String DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID = Plugin.join(
+ EnginePlugin.UNIQUE_IDENTIFIER,
+ EnginePlugin.DART_ERRORS_FOR_UNIT_EXTENSION_POINT);
+
+/**
+ * The identifier of the extension point that allows plugins to register new
+ * analysis error results to compute for an HTML source. The object used as an
+ * extension must be a [ResultDescriptor].
+ */
+final String HTML_ERRORS_EXTENSION_POINT_ID = Plugin.join(
+ EnginePlugin.UNIQUE_IDENTIFIER, EnginePlugin.HTML_ERRORS_EXTENSION_POINT);
+
+/**
+ * The identifier of the extension point that allows plugins to register new
* analysis tasks with the analysis engine. The object used as an extension must
* be a [TaskDescriptor].
*/
diff --git a/pkg/analyzer/lib/source/pub_package_map_provider.dart b/pkg/analyzer/lib/source/pub_package_map_provider.dart
index 3e9936d..07fdba7 100644
--- a/pkg/analyzer/lib/source/pub_package_map_provider.dart
+++ b/pkg/analyzer/lib/source/pub_package_map_provider.dart
@@ -162,8 +162,8 @@
String workingDirectory = folder.path;
int subprocessId = AnalysisEngine.instance.instrumentationService
.logSubprocessStart(executablePath, arguments, workingDirectory);
- io.ProcessResult result = io.Process.runSync(executablePath, arguments,
- workingDirectory: workingDirectory);
+ io.ProcessResult result = io.Process
+ .runSync(executablePath, arguments, workingDirectory: workingDirectory);
AnalysisEngine.instance.instrumentationService.logSubprocessResult(
subprocessId, result.exitCode, result.stdout, result.stderr);
return result;
diff --git a/pkg/analyzer/lib/source/sdk_ext.dart b/pkg/analyzer/lib/source/sdk_ext.dart
index d16bb47..646a19f 100644
--- a/pkg/analyzer/lib/source/sdk_ext.dart
+++ b/pkg/analyzer/lib/source/sdk_ext.dart
@@ -27,7 +27,7 @@
static const String SDK_EXT_NAME = '_sdkext';
static const String DART_COLON_PREFIX = 'dart:';
- final Map<String, String> _urlMappings = <String,String>{};
+ final Map<String, String> _urlMappings = <String, String>{};
/// Construct a [SdkExtUriResolver] from a package map
/// (see [PackageMapProvider]).
@@ -42,7 +42,7 @@
int get length => _urlMappings.length;
/// Return the path mapping for [libName] or null if there is none.
- String operator[](String libName) => _urlMappings[libName];
+ String operator [](String libName) => _urlMappings[libName];
/// Programmatically add a new SDK extension given a JSON description
/// ([sdkExtJSON]) and a lib directory ([libDir]).
diff --git a/pkg/analyzer/lib/src/cancelable_future.dart b/pkg/analyzer/lib/src/cancelable_future.dart
index 4ec7b26..733cac5 100644
--- a/pkg/analyzer/lib/src/cancelable_future.dart
+++ b/pkg/analyzer/lib/src/cancelable_future.dart
@@ -259,8 +259,8 @@
Future timeout(Duration timeLimit, {onTimeout()}) {
// TODO(paulberry): Implement this in such a way that a timeout cancels
// the future.
- return _completer._outerCompleter.future.timeout(timeLimit,
- onTimeout: onTimeout);
+ return _completer._outerCompleter.future
+ .timeout(timeLimit, onTimeout: onTimeout);
}
@override
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index d45c729..01ae4ea 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -38,8 +38,8 @@
/**
* The [StreamController] reporting [InvalidatedResult]s.
*/
- final StreamController<InvalidatedResult> _onResultInvalidated =
- new StreamController<InvalidatedResult>.broadcast(sync: true);
+ final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated =
+ new ReentrantSynchronousStream<InvalidatedResult>();
/**
* Initialize a newly created cache to have the given [partitions]. The
@@ -50,17 +50,11 @@
AnalysisCache(this._partitions) {
for (CachePartition partition in _partitions) {
partition.onResultInvalidated.listen((InvalidatedResult event) {
- _onResultInvalidated.add(event);
+ onResultInvalidated.add(event);
});
}
}
- /**
- * Return the stream that is notified when a value is invalidated.
- */
- Stream<InvalidatedResult> get onResultInvalidated =>
- _onResultInvalidated.stream;
-
// TODO(brianwilkerson) Implement or delete this.
// /**
// * Return information about each of the partitions in this cache.
@@ -465,8 +459,11 @@
* Set the value of the result represented by the given [descriptor] to the
* given [value].
*/
- /*<V>*/ void setValue(ResultDescriptor /*<V>*/ descriptor, dynamic /*V*/
- value, List<TargetedResult> dependedOn) {
+ /*<V>*/ void setValue(
+ ResultDescriptor /*<V>*/ descriptor,
+ dynamic /*V*/
+ value,
+ List<TargetedResult> dependedOn) {
// {
// String valueStr = '$value';
// if (valueStr.length > 20) {
@@ -493,9 +490,9 @@
*/
void setValueIncremental(ResultDescriptor descriptor, dynamic value) {
ResultData data = getResultData(descriptor);
- List<TargetedResult> dependedOn = data.dependedOnResults;
- _invalidate(descriptor, null);
- setValue(descriptor, value, dependedOn);
+ _invalidateDependentResults(data, null);
+ data.state = CacheState.VALID;
+ data.value = value;
}
@override
@@ -538,26 +535,20 @@
TargetedResult thisResult = new TargetedResult(target, descriptor);
for (TargetedResult dependedOnResult in thisData.dependedOnResults) {
ResultData data = _partition._getDataFor(dependedOnResult);
- if (data != null) {
+ if (data != null && deltaResult != DeltaResult.KEEP_CONTINUE) {
data.dependentResults.remove(thisResult);
}
}
// Invalidate results that depend on this result.
- List<TargetedResult> dependentResults = thisData.dependentResults.toList();
- for (TargetedResult dependentResult in dependentResults) {
- CacheEntry entry = _partition.get(dependentResult.target);
- if (entry != null) {
- entry._invalidate(dependentResult.result, delta);
- }
- }
+ _invalidateDependentResults(thisData, delta);
// If empty, remove the entry altogether.
if (_resultMap.isEmpty) {
_partition._targetMap.remove(target);
_partition._removeIfSource(target);
}
// Notify controller.
- _partition._onResultInvalidated
- .add(new InvalidatedResult(this, descriptor));
+ _partition.onResultInvalidated
+ .add(new InvalidatedResult(this, descriptor, thisData.value));
}
/**
@@ -571,6 +562,19 @@
}
/**
+ * Invalidate results that depend on [thisData].
+ */
+ void _invalidateDependentResults(ResultData thisData, Delta delta) {
+ List<TargetedResult> dependentResults = thisData.dependentResults.toList();
+ for (TargetedResult dependentResult in dependentResults) {
+ CacheEntry entry = _partition.get(dependentResult.target);
+ if (entry != null) {
+ entry._invalidate(dependentResult.result, delta);
+ }
+ }
+ }
+
+ /**
* Set the [dependedOn] on which this result depends.
*/
void _setDependedOnResults(ResultData thisData, TargetedResult thisResult,
@@ -804,8 +808,8 @@
/**
* The [StreamController] reporting [InvalidatedResult]s.
*/
- final StreamController<InvalidatedResult> _onResultInvalidated =
- new StreamController<InvalidatedResult>.broadcast(sync: true);
+ final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated =
+ new ReentrantSynchronousStream<InvalidatedResult>();
/**
* A table mapping the targets belonging to this partition to the information
@@ -840,12 +844,6 @@
Map<AnalysisTarget, CacheEntry> get map => _targetMap;
/**
- * Return the stream that is notified when a value is invalidated.
- */
- Stream<InvalidatedResult> get onResultInvalidated =>
- _onResultInvalidated.stream;
-
- /**
* Notifies the partition that the client is going to stop using it.
*/
void dispose() {
@@ -1039,13 +1037,47 @@
*/
final ResultDescriptor descriptor;
- InvalidatedResult(this.entry, this.descriptor);
+ /**
+ * The value of the result which was invalidated.
+ */
+ final Object value;
+
+ InvalidatedResult(this.entry, this.descriptor, this.value);
@override
String toString() => '$descriptor of ${entry.target}';
}
/**
+ * A Stream-like interface, which broadcasts events synchronously.
+ * If a second event is fired while delivering a first event, then the second
+ * event will be delivered first, and then delivering of the first will be
+ * continued.
+ */
+class ReentrantSynchronousStream<T> {
+ final List<Function> listeners = <Function>[];
+
+ /**
+ * Send the given [event] to the stream.
+ */
+ void add(T event) {
+ List<Function> listeners = this.listeners.toList();
+ for (Function listener in listeners) {
+ listener(event);
+ }
+ }
+
+ /**
+ * Listen for the events in this stream.
+ * Note that if the [listener] fires a new event, then the [listener] will be
+ * invoked again before returning from the [add] invocation.
+ */
+ void listen(void listener(T event)) {
+ listeners.add(listener);
+ }
+}
+
+/**
* The data about a single analysis result that is stored in a [CacheEntry].
*/
// TODO(brianwilkerson) Consider making this a generic class so that the value
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index d90b091..c6a81da 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -252,6 +252,7 @@
(this._options.hint && !options.hint) ||
(this._options.lint && !options.lint) ||
this._options.preserveComments != options.preserveComments ||
+ this._options.strongMode != options.strongMode ||
this._options.enableStrictCallChecks !=
options.enableStrictCallChecks ||
this._options.enableSuperMixins != options.enableSuperMixins;
@@ -272,6 +273,7 @@
this._options.incrementalValidation = options.incrementalValidation;
this._options.lint = options.lint;
this._options.preserveComments = options.preserveComments;
+ this._options.strongMode = options.strongMode;
if (needsRecompute) {
for (WorkManager workManager in workManagers) {
workManager.onAnalysisOptionsChanged();
diff --git a/pkg/analyzer/lib/src/generated/ast.dart b/pkg/analyzer/lib/src/generated/ast.dart
index 0c5dfc2..6d47cf7 100644
--- a/pkg/analyzer/lib/src/generated/ast.dart
+++ b/pkg/analyzer/lib/src/generated/ast.dart
@@ -963,7 +963,8 @@
* cloning AST nodes if [cloneTokens] is `true`.
*/
AstCloner(
- [this.cloneTokens = false]); // TODO(brianwilkerson) Change this to be a named parameter.
+ [this.cloneTokens =
+ false]); // TODO(brianwilkerson) Change this to be a named parameter.
/**
* Return a clone of the given [node].
@@ -1015,23 +1016,30 @@
@override
Annotation visitAnnotation(Annotation node) => new Annotation(
- cloneToken(node.atSign), cloneNode(node.name), cloneToken(node.period),
- cloneNode(node.constructorName), cloneNode(node.arguments));
+ cloneToken(node.atSign),
+ cloneNode(node.name),
+ cloneToken(node.period),
+ cloneNode(node.constructorName),
+ cloneNode(node.arguments));
@override
ArgumentList visitArgumentList(ArgumentList node) => new ArgumentList(
- cloneToken(node.leftParenthesis), cloneNodeList(node.arguments),
+ cloneToken(node.leftParenthesis),
+ cloneNodeList(node.arguments),
cloneToken(node.rightParenthesis));
@override
AsExpression visitAsExpression(AsExpression node) => new AsExpression(
- cloneNode(node.expression), cloneToken(node.asOperator),
+ cloneNode(node.expression),
+ cloneToken(node.asOperator),
cloneNode(node.type));
@override
AstNode visitAssertStatement(AssertStatement node) => new AssertStatement(
- cloneToken(node.assertKeyword), cloneToken(node.leftParenthesis),
- cloneNode(node.condition), cloneToken(node.rightParenthesis),
+ cloneToken(node.assertKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.condition),
+ cloneToken(node.rightParenthesis),
cloneToken(node.semicolon));
@override
@@ -1054,9 +1062,9 @@
cloneNodeList(node.statements), cloneToken(node.rightBracket));
@override
- BlockFunctionBody visitBlockFunctionBody(
- BlockFunctionBody node) => new BlockFunctionBody(
- cloneToken(node.keyword), cloneToken(node.star), cloneNode(node.block));
+ BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
+ new BlockFunctionBody(cloneToken(node.keyword), cloneToken(node.star),
+ cloneNode(node.block));
@override
BooleanLiteral visitBooleanLiteral(BooleanLiteral node) =>
@@ -1064,7 +1072,8 @@
@override
BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement(
- cloneToken(node.breakKeyword), cloneNode(node.label),
+ cloneToken(node.breakKeyword),
+ cloneNode(node.label),
cloneToken(node.semicolon));
@override
@@ -1074,32 +1083,47 @@
@override
CatchClause visitCatchClause(CatchClause node) => new CatchClause(
- cloneToken(node.onKeyword), cloneNode(node.exceptionType),
- cloneToken(node.catchKeyword), cloneToken(node.leftParenthesis),
- cloneNode(node.exceptionParameter), cloneToken(node.comma),
- cloneNode(node.stackTraceParameter), cloneToken(node.rightParenthesis),
+ cloneToken(node.onKeyword),
+ cloneNode(node.exceptionType),
+ cloneToken(node.catchKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.exceptionParameter),
+ cloneToken(node.comma),
+ cloneNode(node.stackTraceParameter),
+ cloneToken(node.rightParenthesis),
cloneNode(node.body));
@override
ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
ClassDeclaration copy = new ClassDeclaration(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneToken(node.abstractKeyword), cloneToken(node.classKeyword),
- cloneNode(node.name), cloneNode(node.typeParameters),
- cloneNode(node.extendsClause), cloneNode(node.withClause),
- cloneNode(node.implementsClause), cloneToken(node.leftBracket),
- cloneNodeList(node.members), cloneToken(node.rightBracket));
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.abstractKeyword),
+ cloneToken(node.classKeyword),
+ cloneNode(node.name),
+ cloneNode(node.typeParameters),
+ cloneNode(node.extendsClause),
+ cloneNode(node.withClause),
+ cloneNode(node.implementsClause),
+ cloneToken(node.leftBracket),
+ cloneNodeList(node.members),
+ cloneToken(node.rightBracket));
copy.nativeClause = cloneNode(node.nativeClause);
return copy;
}
@override
ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneToken(node.typedefKeyword), cloneNode(node.name),
- cloneNode(node.typeParameters), cloneToken(node.equals),
- cloneToken(node.abstractKeyword), cloneNode(node.superclass),
- cloneNode(node.withClause), cloneNode(node.implementsClause),
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.typedefKeyword),
+ cloneNode(node.name),
+ cloneNode(node.typeParameters),
+ cloneToken(node.equals),
+ cloneToken(node.abstractKeyword),
+ cloneNode(node.superclass),
+ cloneNode(node.withClause),
+ cloneNode(node.implementsClause),
cloneToken(node.semicolon));
@override
@@ -1120,36 +1144,53 @@
@override
CompilationUnit visitCompilationUnit(CompilationUnit node) {
- CompilationUnit clone = new CompilationUnit(cloneToken(node.beginToken),
- cloneNode(node.scriptTag), cloneNodeList(node.directives),
- cloneNodeList(node.declarations), cloneToken(node.endToken));
+ CompilationUnit clone = new CompilationUnit(
+ cloneToken(node.beginToken),
+ cloneNode(node.scriptTag),
+ cloneNodeList(node.directives),
+ cloneNodeList(node.declarations),
+ cloneToken(node.endToken));
clone.lineInfo = node.lineInfo;
return clone;
}
@override
ConditionalExpression visitConditionalExpression(
- ConditionalExpression node) => new ConditionalExpression(
- cloneNode(node.condition), cloneToken(node.question),
- cloneNode(node.thenExpression), cloneToken(node.colon),
- cloneNode(node.elseExpression));
+ ConditionalExpression node) =>
+ new ConditionalExpression(
+ cloneNode(node.condition),
+ cloneToken(node.question),
+ cloneNode(node.thenExpression),
+ cloneToken(node.colon),
+ cloneNode(node.elseExpression));
@override
ConstructorDeclaration visitConstructorDeclaration(
- ConstructorDeclaration node) => new ConstructorDeclaration(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneToken(node.externalKeyword), cloneToken(node.constKeyword),
- cloneToken(node.factoryKeyword), cloneNode(node.returnType),
- cloneToken(node.period), cloneNode(node.name), cloneNode(node.parameters),
- cloneToken(node.separator), cloneNodeList(node.initializers),
- cloneNode(node.redirectedConstructor), cloneNode(node.body));
+ ConstructorDeclaration node) =>
+ new ConstructorDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.externalKeyword),
+ cloneToken(node.constKeyword),
+ cloneToken(node.factoryKeyword),
+ cloneNode(node.returnType),
+ cloneToken(node.period),
+ cloneNode(node.name),
+ cloneNode(node.parameters),
+ cloneToken(node.separator),
+ cloneNodeList(node.initializers),
+ cloneNode(node.redirectedConstructor),
+ cloneNode(node.body));
@override
ConstructorFieldInitializer visitConstructorFieldInitializer(
- ConstructorFieldInitializer node) => new ConstructorFieldInitializer(
- cloneToken(node.thisKeyword), cloneToken(node.period),
- cloneNode(node.fieldName), cloneToken(node.equals),
- cloneNode(node.expression));
+ ConstructorFieldInitializer node) =>
+ new ConstructorFieldInitializer(
+ cloneToken(node.thisKeyword),
+ cloneToken(node.period),
+ cloneNode(node.fieldName),
+ cloneToken(node.equals),
+ cloneNode(node.expression));
@override
ConstructorName visitConstructorName(ConstructorName node) =>
@@ -1163,21 +1204,27 @@
@override
DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
- new DeclaredIdentifier(cloneNode(node.documentationComment),
- cloneNodeList(node.metadata), cloneToken(node.keyword),
- cloneNode(node.type), cloneNode(node.identifier));
+ new DeclaredIdentifier(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.type),
+ cloneNode(node.identifier));
@override
DefaultFormalParameter visitDefaultFormalParameter(
- DefaultFormalParameter node) => new DefaultFormalParameter(
- cloneNode(node.parameter), node.kind, cloneToken(node.separator),
- cloneNode(node.defaultValue));
+ DefaultFormalParameter node) =>
+ new DefaultFormalParameter(cloneNode(node.parameter), node.kind,
+ cloneToken(node.separator), cloneNode(node.defaultValue));
@override
DoStatement visitDoStatement(DoStatement node) => new DoStatement(
- cloneToken(node.doKeyword), cloneNode(node.body),
- cloneToken(node.whileKeyword), cloneToken(node.leftParenthesis),
- cloneNode(node.condition), cloneToken(node.rightParenthesis),
+ cloneToken(node.doKeyword),
+ cloneNode(node.body),
+ cloneToken(node.whileKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.condition),
+ cloneToken(node.rightParenthesis),
cloneToken(node.semicolon));
@override
@@ -1199,17 +1246,24 @@
@override
EnumDeclaration visitEnumDeclaration(EnumDeclaration node) =>
- new EnumDeclaration(cloneNode(node.documentationComment),
- cloneNodeList(node.metadata), cloneToken(node.enumKeyword),
- cloneNode(node.name), cloneToken(node.leftBracket),
- cloneNodeList(node.constants), cloneToken(node.rightBracket));
+ new EnumDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.enumKeyword),
+ cloneNode(node.name),
+ cloneToken(node.leftBracket),
+ cloneNodeList(node.constants),
+ cloneToken(node.rightBracket));
@override
ExportDirective visitExportDirective(ExportDirective node) {
ExportDirective directive = new ExportDirective(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneToken(node.keyword), cloneNode(node.uri),
- cloneNodeList(node.combinators), cloneToken(node.semicolon));
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.uri),
+ cloneNodeList(node.combinators),
+ cloneToken(node.semicolon));
directive.source = node.source;
directive.uriContent = node.uriContent;
return directive;
@@ -1217,9 +1271,12 @@
@override
ExpressionFunctionBody visitExpressionFunctionBody(
- ExpressionFunctionBody node) => new ExpressionFunctionBody(
- cloneToken(node.keyword), cloneToken(node.functionDefinition),
- cloneNode(node.expression), cloneToken(node.semicolon));
+ ExpressionFunctionBody node) =>
+ new ExpressionFunctionBody(
+ cloneToken(node.keyword),
+ cloneToken(node.functionDefinition),
+ cloneNode(node.expression),
+ cloneToken(node.semicolon));
@override
ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
@@ -1232,55 +1289,83 @@
@override
FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
- new FieldDeclaration(cloneNode(node.documentationComment),
- cloneNodeList(node.metadata), cloneToken(node.staticKeyword),
- cloneNode(node.fields), cloneToken(node.semicolon));
+ new FieldDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.staticKeyword),
+ cloneNode(node.fields),
+ cloneToken(node.semicolon));
@override
FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
- new FieldFormalParameter(cloneNode(node.documentationComment),
- cloneNodeList(node.metadata), cloneToken(node.keyword),
- cloneNode(node.type), cloneToken(node.thisKeyword),
- cloneToken(node.period), cloneNode(node.identifier),
- cloneNode(node.typeParameters), cloneNode(node.parameters));
+ new FieldFormalParameter(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.type),
+ cloneToken(node.thisKeyword),
+ cloneToken(node.period),
+ cloneNode(node.identifier),
+ cloneNode(node.typeParameters),
+ cloneNode(node.parameters));
@override
ForEachStatement visitForEachStatement(ForEachStatement node) {
DeclaredIdentifier loopVariable = node.loopVariable;
if (loopVariable == null) {
- return new ForEachStatement.withReference(cloneToken(node.awaitKeyword),
- cloneToken(node.forKeyword), cloneToken(node.leftParenthesis),
- cloneNode(node.identifier), cloneToken(node.inKeyword),
- cloneNode(node.iterable), cloneToken(node.rightParenthesis),
+ return new ForEachStatement.withReference(
+ cloneToken(node.awaitKeyword),
+ cloneToken(node.forKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.identifier),
+ cloneToken(node.inKeyword),
+ cloneNode(node.iterable),
+ cloneToken(node.rightParenthesis),
cloneNode(node.body));
}
- return new ForEachStatement.withDeclaration(cloneToken(node.awaitKeyword),
- cloneToken(node.forKeyword), cloneToken(node.leftParenthesis),
- cloneNode(loopVariable), cloneToken(node.inKeyword),
- cloneNode(node.iterable), cloneToken(node.rightParenthesis),
+ return new ForEachStatement.withDeclaration(
+ cloneToken(node.awaitKeyword),
+ cloneToken(node.forKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(loopVariable),
+ cloneToken(node.inKeyword),
+ cloneNode(node.iterable),
+ cloneToken(node.rightParenthesis),
cloneNode(node.body));
}
@override
FormalParameterList visitFormalParameterList(FormalParameterList node) =>
- new FormalParameterList(cloneToken(node.leftParenthesis),
- cloneNodeList(node.parameters), cloneToken(node.leftDelimiter),
- cloneToken(node.rightDelimiter), cloneToken(node.rightParenthesis));
+ new FormalParameterList(
+ cloneToken(node.leftParenthesis),
+ cloneNodeList(node.parameters),
+ cloneToken(node.leftDelimiter),
+ cloneToken(node.rightDelimiter),
+ cloneToken(node.rightParenthesis));
@override
ForStatement visitForStatement(ForStatement node) => new ForStatement(
- cloneToken(node.forKeyword), cloneToken(node.leftParenthesis),
- cloneNode(node.variables), cloneNode(node.initialization),
- cloneToken(node.leftSeparator), cloneNode(node.condition),
- cloneToken(node.rightSeparator), cloneNodeList(node.updaters),
- cloneToken(node.rightParenthesis), cloneNode(node.body));
+ cloneToken(node.forKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.variables),
+ cloneNode(node.initialization),
+ cloneToken(node.leftSeparator),
+ cloneNode(node.condition),
+ cloneToken(node.rightSeparator),
+ cloneNodeList(node.updaters),
+ cloneToken(node.rightParenthesis),
+ cloneNode(node.body));
@override
FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
- new FunctionDeclaration(cloneNode(node.documentationComment),
- cloneNodeList(node.metadata), cloneToken(node.externalKeyword),
- cloneNode(node.returnType), cloneToken(node.propertyKeyword),
- cloneNode(node.name), cloneNode(node.functionExpression));
+ new FunctionDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.externalKeyword),
+ cloneNode(node.returnType),
+ cloneToken(node.propertyKeyword),
+ cloneNode(node.name),
+ cloneNode(node.functionExpression));
@override
FunctionDeclarationStatement visitFunctionDeclarationStatement(
@@ -1294,24 +1379,32 @@
@override
FunctionExpressionInvocation visitFunctionExpressionInvocation(
- FunctionExpressionInvocation node) => new FunctionExpressionInvocation(
- cloneNode(node.function), cloneNode(node.typeArguments),
- cloneNode(node.argumentList));
+ FunctionExpressionInvocation node) =>
+ new FunctionExpressionInvocation(cloneNode(node.function),
+ cloneNode(node.typeArguments), cloneNode(node.argumentList));
@override
FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
- new FunctionTypeAlias(cloneNode(node.documentationComment),
- cloneNodeList(node.metadata), cloneToken(node.typedefKeyword),
- cloneNode(node.returnType), cloneNode(node.name),
- cloneNode(node.typeParameters), cloneNode(node.parameters),
+ new FunctionTypeAlias(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.typedefKeyword),
+ cloneNode(node.returnType),
+ cloneNode(node.name),
+ cloneNode(node.typeParameters),
+ cloneNode(node.parameters),
cloneToken(node.semicolon));
@override
FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
- FunctionTypedFormalParameter node) => new FunctionTypedFormalParameter(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneNode(node.returnType), cloneNode(node.identifier),
- cloneNode(node.typeParameters), cloneNode(node.parameters));
+ FunctionTypedFormalParameter node) =>
+ new FunctionTypedFormalParameter(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneNode(node.returnType),
+ cloneNode(node.identifier),
+ cloneNode(node.typeParameters),
+ cloneNode(node.parameters));
@override
HideCombinator visitHideCombinator(HideCombinator node) => new HideCombinator(
@@ -1319,9 +1412,12 @@
@override
IfStatement visitIfStatement(IfStatement node) => new IfStatement(
- cloneToken(node.ifKeyword), cloneToken(node.leftParenthesis),
- cloneNode(node.condition), cloneToken(node.rightParenthesis),
- cloneNode(node.thenStatement), cloneToken(node.elseKeyword),
+ cloneToken(node.ifKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.condition),
+ cloneToken(node.rightParenthesis),
+ cloneNode(node.thenStatement),
+ cloneToken(node.elseKeyword),
cloneNode(node.elseStatement));
@override
@@ -1332,10 +1428,14 @@
@override
ImportDirective visitImportDirective(ImportDirective node) {
ImportDirective directive = new ImportDirective(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneToken(node.keyword), cloneNode(node.uri),
- cloneToken(node.deferredKeyword), cloneToken(node.asKeyword),
- cloneNode(node.prefix), cloneNodeList(node.combinators),
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.uri),
+ cloneToken(node.deferredKeyword),
+ cloneToken(node.asKeyword),
+ cloneNode(node.prefix),
+ cloneNodeList(node.combinators),
cloneToken(node.semicolon));
directive.source = node.source;
directive.uriContent = node.uriContent;
@@ -1346,21 +1446,25 @@
IndexExpression visitIndexExpression(IndexExpression node) {
Token period = node.period;
if (period == null) {
- return new IndexExpression.forTarget(cloneNode(node.target),
- cloneToken(node.leftBracket), cloneNode(node.index),
+ return new IndexExpression.forTarget(
+ cloneNode(node.target),
+ cloneToken(node.leftBracket),
+ cloneNode(node.index),
cloneToken(node.rightBracket));
} else {
- return new IndexExpression.forCascade(cloneToken(period),
- cloneToken(node.leftBracket), cloneNode(node.index),
+ return new IndexExpression.forCascade(
+ cloneToken(period),
+ cloneToken(node.leftBracket),
+ cloneNode(node.index),
cloneToken(node.rightBracket));
}
}
@override
InstanceCreationExpression visitInstanceCreationExpression(
- InstanceCreationExpression node) => new InstanceCreationExpression(
- cloneToken(node.keyword), cloneNode(node.constructorName),
- cloneNode(node.argumentList));
+ InstanceCreationExpression node) =>
+ new InstanceCreationExpression(cloneToken(node.keyword),
+ cloneNode(node.constructorName), cloneNode(node.argumentList));
@override
IntegerLiteral visitIntegerLiteral(IntegerLiteral node) =>
@@ -1368,9 +1472,9 @@
@override
InterpolationExpression visitInterpolationExpression(
- InterpolationExpression node) => new InterpolationExpression(
- cloneToken(node.leftBracket), cloneNode(node.expression),
- cloneToken(node.rightBracket));
+ InterpolationExpression node) =>
+ new InterpolationExpression(cloneToken(node.leftBracket),
+ cloneNode(node.expression), cloneToken(node.rightBracket));
@override
InterpolationString visitInterpolationString(InterpolationString node) =>
@@ -1378,8 +1482,10 @@
@override
IsExpression visitIsExpression(IsExpression node) => new IsExpression(
- cloneNode(node.expression), cloneToken(node.isOperator),
- cloneToken(node.notOperator), cloneNode(node.type));
+ cloneNode(node.expression),
+ cloneToken(node.isOperator),
+ cloneToken(node.notOperator),
+ cloneNode(node.type));
@override
Label visitLabel(Label node) =>
@@ -1392,9 +1498,12 @@
@override
LibraryDirective visitLibraryDirective(LibraryDirective node) =>
- new LibraryDirective(cloneNode(node.documentationComment),
- cloneNodeList(node.metadata), cloneToken(node.libraryKeyword),
- cloneNode(node.name), cloneToken(node.semicolon));
+ new LibraryDirective(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.libraryKeyword),
+ cloneNode(node.name),
+ cloneToken(node.semicolon));
@override
LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) =>
@@ -1402,34 +1511,47 @@
@override
ListLiteral visitListLiteral(ListLiteral node) => new ListLiteral(
- cloneToken(node.constKeyword), cloneNode(node.typeArguments),
- cloneToken(node.leftBracket), cloneNodeList(node.elements),
+ cloneToken(node.constKeyword),
+ cloneNode(node.typeArguments),
+ cloneToken(node.leftBracket),
+ cloneNodeList(node.elements),
cloneToken(node.rightBracket));
@override
MapLiteral visitMapLiteral(MapLiteral node) => new MapLiteral(
- cloneToken(node.constKeyword), cloneNode(node.typeArguments),
- cloneToken(node.leftBracket), cloneNodeList(node.entries),
+ cloneToken(node.constKeyword),
+ cloneNode(node.typeArguments),
+ cloneToken(node.leftBracket),
+ cloneNodeList(node.entries),
cloneToken(node.rightBracket));
@override
- MapLiteralEntry visitMapLiteralEntry(
- MapLiteralEntry node) => new MapLiteralEntry(
- cloneNode(node.key), cloneToken(node.separator), cloneNode(node.value));
+ MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
+ new MapLiteralEntry(cloneNode(node.key), cloneToken(node.separator),
+ cloneNode(node.value));
@override
MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
- new MethodDeclaration(cloneNode(node.documentationComment),
- cloneNodeList(node.metadata), cloneToken(node.externalKeyword),
- cloneToken(node.modifierKeyword), cloneNode(node.returnType),
- cloneToken(node.propertyKeyword), cloneToken(node.operatorKeyword),
- cloneNode(node.name), cloneNode(node.typeParameters),
- cloneNode(node.parameters), cloneNode(node.body));
+ new MethodDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.externalKeyword),
+ cloneToken(node.modifierKeyword),
+ cloneNode(node.returnType),
+ cloneToken(node.propertyKeyword),
+ cloneToken(node.operatorKeyword),
+ cloneNode(node.name),
+ cloneNode(node.typeParameters),
+ cloneNode(node.parameters),
+ cloneNode(node.body));
@override
MethodInvocation visitMethodInvocation(MethodInvocation node) =>
- new MethodInvocation(cloneNode(node.target), cloneToken(node.operator),
- cloneNode(node.methodName), cloneNode(node.typeArguments),
+ new MethodInvocation(
+ cloneNode(node.target),
+ cloneToken(node.operator),
+ cloneNode(node.methodName),
+ cloneNode(node.typeArguments),
cloneNode(node.argumentList));
@override
@@ -1451,15 +1573,17 @@
@override
ParenthesizedExpression visitParenthesizedExpression(
- ParenthesizedExpression node) => new ParenthesizedExpression(
- cloneToken(node.leftParenthesis), cloneNode(node.expression),
- cloneToken(node.rightParenthesis));
+ ParenthesizedExpression node) =>
+ new ParenthesizedExpression(cloneToken(node.leftParenthesis),
+ cloneNode(node.expression), cloneToken(node.rightParenthesis));
@override
PartDirective visitPartDirective(PartDirective node) {
PartDirective directive = new PartDirective(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneToken(node.partKeyword), cloneNode(node.uri),
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.partKeyword),
+ cloneNode(node.uri),
cloneToken(node.semicolon));
directive.source = node.source;
directive.uriContent = node.uriContent;
@@ -1468,9 +1592,12 @@
@override
PartOfDirective visitPartOfDirective(PartOfDirective node) =>
- new PartOfDirective(cloneNode(node.documentationComment),
- cloneNodeList(node.metadata), cloneToken(node.partKeyword),
- cloneToken(node.ofKeyword), cloneNode(node.libraryName),
+ new PartOfDirective(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.partKeyword),
+ cloneToken(node.ofKeyword),
+ cloneNode(node.libraryName),
cloneToken(node.semicolon));
@override
@@ -1488,14 +1615,17 @@
@override
PropertyAccess visitPropertyAccess(PropertyAccess node) => new PropertyAccess(
- cloneNode(node.target), cloneToken(node.operator),
+ cloneNode(node.target),
+ cloneToken(node.operator),
cloneNode(node.propertyName));
@override
RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
RedirectingConstructorInvocation node) =>
- new RedirectingConstructorInvocation(cloneToken(node.thisKeyword),
- cloneToken(node.period), cloneNode(node.constructorName),
+ new RedirectingConstructorInvocation(
+ cloneToken(node.thisKeyword),
+ cloneToken(node.period),
+ cloneNode(node.constructorName),
cloneNode(node.argumentList));
@override
@@ -1517,10 +1647,13 @@
@override
SimpleFormalParameter visitSimpleFormalParameter(
- SimpleFormalParameter node) => new SimpleFormalParameter(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneToken(node.keyword), cloneNode(node.type),
- cloneNode(node.identifier));
+ SimpleFormalParameter node) =>
+ new SimpleFormalParameter(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.type),
+ cloneNode(node.identifier));
@override
SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) =>
@@ -1536,9 +1669,12 @@
@override
SuperConstructorInvocation visitSuperConstructorInvocation(
- SuperConstructorInvocation node) => new SuperConstructorInvocation(
- cloneToken(node.superKeyword), cloneToken(node.period),
- cloneNode(node.constructorName), cloneNode(node.argumentList));
+ SuperConstructorInvocation node) =>
+ new SuperConstructorInvocation(
+ cloneToken(node.superKeyword),
+ cloneToken(node.period),
+ cloneNode(node.constructorName),
+ cloneNode(node.argumentList));
@override
SuperExpression visitSuperExpression(SuperExpression node) =>
@@ -1546,21 +1682,29 @@
@override
SwitchCase visitSwitchCase(SwitchCase node) => new SwitchCase(
- cloneNodeList(node.labels), cloneToken(node.keyword),
- cloneNode(node.expression), cloneToken(node.colon),
+ cloneNodeList(node.labels),
+ cloneToken(node.keyword),
+ cloneNode(node.expression),
+ cloneToken(node.colon),
cloneNodeList(node.statements));
@override
SwitchDefault visitSwitchDefault(SwitchDefault node) => new SwitchDefault(
- cloneNodeList(node.labels), cloneToken(node.keyword),
- cloneToken(node.colon), cloneNodeList(node.statements));
+ cloneNodeList(node.labels),
+ cloneToken(node.keyword),
+ cloneToken(node.colon),
+ cloneNodeList(node.statements));
@override
SwitchStatement visitSwitchStatement(SwitchStatement node) =>
- new SwitchStatement(cloneToken(node.switchKeyword),
- cloneToken(node.leftParenthesis), cloneNode(node.expression),
- cloneToken(node.rightParenthesis), cloneToken(node.leftBracket),
- cloneNodeList(node.members), cloneToken(node.rightBracket));
+ new SwitchStatement(
+ cloneToken(node.switchKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.expression),
+ cloneToken(node.rightParenthesis),
+ cloneToken(node.leftBracket),
+ cloneNodeList(node.members),
+ cloneToken(node.rightBracket));
@override
SymbolLiteral visitSymbolLiteral(SymbolLiteral node) => new SymbolLiteral(
@@ -1577,14 +1721,19 @@
@override
TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
- TopLevelVariableDeclaration node) => new TopLevelVariableDeclaration(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneNode(node.variables), cloneToken(node.semicolon));
+ TopLevelVariableDeclaration node) =>
+ new TopLevelVariableDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneNode(node.variables),
+ cloneToken(node.semicolon));
@override
TryStatement visitTryStatement(TryStatement node) => new TryStatement(
- cloneToken(node.tryKeyword), cloneNode(node.body),
- cloneNodeList(node.catchClauses), cloneToken(node.finallyKeyword),
+ cloneToken(node.tryKeyword),
+ cloneNode(node.body),
+ cloneNodeList(node.catchClauses),
+ cloneToken(node.finallyKeyword),
cloneNode(node.finallyBlock));
@override
@@ -1598,8 +1747,10 @@
@override
TypeParameter visitTypeParameter(TypeParameter node) => new TypeParameter(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneNode(node.name), cloneToken(node.extendsKeyword),
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneNode(node.name),
+ cloneToken(node.extendsKeyword),
cloneNode(node.bound));
@override
@@ -1614,20 +1765,26 @@
@override
VariableDeclarationList visitVariableDeclarationList(
- VariableDeclarationList node) => new VariableDeclarationList(
- cloneNode(node.documentationComment), cloneNodeList(node.metadata),
- cloneToken(node.keyword), cloneNode(node.type),
- cloneNodeList(node.variables));
+ VariableDeclarationList node) =>
+ new VariableDeclarationList(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.type),
+ cloneNodeList(node.variables));
@override
VariableDeclarationStatement visitVariableDeclarationStatement(
- VariableDeclarationStatement node) => new VariableDeclarationStatement(
- cloneNode(node.variables), cloneToken(node.semicolon));
+ VariableDeclarationStatement node) =>
+ new VariableDeclarationStatement(
+ cloneNode(node.variables), cloneToken(node.semicolon));
@override
WhileStatement visitWhileStatement(WhileStatement node) => new WhileStatement(
- cloneToken(node.whileKeyword), cloneToken(node.leftParenthesis),
- cloneNode(node.condition), cloneToken(node.rightParenthesis),
+ cloneToken(node.whileKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.condition),
+ cloneToken(node.rightParenthesis),
cloneNode(node.body));
@override
@@ -1636,8 +1793,10 @@
@override
YieldStatement visitYieldStatement(YieldStatement node) => new YieldStatement(
- cloneToken(node.yieldKeyword), cloneToken(node.star),
- cloneNode(node.expression), cloneToken(node.semicolon));
+ cloneToken(node.yieldKeyword),
+ cloneToken(node.star),
+ cloneNode(node.expression),
+ cloneToken(node.semicolon));
/**
* Return a clone of the given [node].
@@ -2726,8 +2885,8 @@
* the same offset, and a positive value if the offset of the first node is
* greater than the offset of the second node.
*/
- static Comparator<AstNode> LEXICAL_ORDER =
- (AstNode first, AstNode second) => first.offset - second.offset;
+ static Comparator<AstNode> LEXICAL_ORDER = (AstNode first, AstNode second) =>
+ first.offset - second.offset;
/**
* The parent of the node, or `null` if the node is the root of an AST
@@ -3851,9 +4010,16 @@
* [comma] and [stackTraceParameter] can be `null` if the stack trace is not
* referencable within the body.
*/
- CatchClause(this.onKeyword, TypeName exceptionType, this.catchKeyword,
- this.leftParenthesis, SimpleIdentifier exceptionParameter, this.comma,
- SimpleIdentifier stackTraceParameter, this.rightParenthesis, Block body) {
+ CatchClause(
+ this.onKeyword,
+ TypeName exceptionType,
+ this.catchKeyword,
+ this.leftParenthesis,
+ SimpleIdentifier exceptionParameter,
+ this.comma,
+ SimpleIdentifier stackTraceParameter,
+ this.rightParenthesis,
+ Block body) {
_exceptionType = _becomeParentOf(exceptionType);
_exceptionParameter = _becomeParentOf(exceptionParameter);
_stackTraceParameter = _becomeParentOf(stackTraceParameter);
@@ -4056,11 +4222,19 @@
* corresponding clause. The list of [members] can be `null` if the class does
* not have any members.
*/
- ClassDeclaration(Comment comment, List<Annotation> metadata,
- this.abstractKeyword, this.classKeyword, SimpleIdentifier name,
- TypeParameterList typeParameters, ExtendsClause extendsClause,
- WithClause withClause, ImplementsClause implementsClause,
- this.leftBracket, List<ClassMember> members, this.rightBracket)
+ ClassDeclaration(
+ Comment comment,
+ List<Annotation> metadata,
+ this.abstractKeyword,
+ this.classKeyword,
+ SimpleIdentifier name,
+ TypeParameterList typeParameters,
+ ExtendsClause extendsClause,
+ WithClause withClause,
+ ImplementsClause implementsClause,
+ this.leftBracket,
+ List<ClassMember> members,
+ this.rightBracket)
: super(comment, metadata, name) {
_typeParameters = _becomeParentOf(typeParameters);
_extendsClause = _becomeParentOf(extendsClause);
@@ -4312,10 +4486,18 @@
* `null` if the class is not abstract. The [implementsClause] can be `null`
* if the class does not implement any interfaces.
*/
- ClassTypeAlias(Comment comment, List<Annotation> metadata, Token keyword,
- SimpleIdentifier name, TypeParameterList typeParameters, this.equals,
- this.abstractKeyword, TypeName superclass, WithClause withClause,
- ImplementsClause implementsClause, Token semicolon)
+ ClassTypeAlias(
+ Comment comment,
+ List<Annotation> metadata,
+ Token keyword,
+ SimpleIdentifier name,
+ TypeParameterList typeParameters,
+ this.equals,
+ this.abstractKeyword,
+ TypeName superclass,
+ WithClause withClause,
+ ImplementsClause implementsClause,
+ Token semicolon)
: super(comment, metadata, keyword, name, semicolon) {
_typeParameters = _becomeParentOf(typeParameters);
_superclass = _becomeParentOf(superclass);
@@ -4702,8 +4884,11 @@
* are no directives in the compilation unit. The list of [declarations] can
* be `null` if there are no declarations in the compilation unit.
*/
- CompilationUnit(this.beginToken, ScriptTag scriptTag,
- List<Directive> directives, List<CompilationUnitMember> declarations,
+ CompilationUnit(
+ this.beginToken,
+ ScriptTag scriptTag,
+ List<Directive> directives,
+ List<CompilationUnitMember> declarations,
this.endToken) {
_scriptTag = _becomeParentOf(scriptTag);
_directives = new NodeList<Directive>(this, directives);
@@ -5374,12 +5559,20 @@
* does not redirect to a different constructor. The [body] can be `null` if
* the constructor does not have a body.
*/
- ConstructorDeclaration(Comment comment, List<Annotation> metadata,
- this.externalKeyword, this.constKeyword, this.factoryKeyword,
- Identifier returnType, this.period, SimpleIdentifier name,
- FormalParameterList parameters, this.separator,
+ ConstructorDeclaration(
+ Comment comment,
+ List<Annotation> metadata,
+ this.externalKeyword,
+ this.constKeyword,
+ this.factoryKeyword,
+ Identifier returnType,
+ this.period,
+ SimpleIdentifier name,
+ FormalParameterList parameters,
+ this.separator,
List<ConstructorInitializer> initializers,
- ConstructorName redirectedConstructor, FunctionBody body)
+ ConstructorName redirectedConstructor,
+ FunctionBody body)
: super(comment, metadata) {
_returnType = _becomeParentOf(returnType);
_name = _becomeParentOf(name);
@@ -6160,8 +6353,13 @@
/**
* Initialize a newly created do loop.
*/
- DoStatement(this.doKeyword, Statement body, this.whileKeyword,
- this.leftParenthesis, Expression condition, this.rightParenthesis,
+ DoStatement(
+ this.doKeyword,
+ Statement body,
+ this.whileKeyword,
+ this.leftParenthesis,
+ Expression condition,
+ this.rightParenthesis,
this.semicolon) {
_body = _becomeParentOf(body);
_condition = _becomeParentOf(condition);
@@ -6567,9 +6765,14 @@
* corresponding attribute. The list of [constants] must contain at least one
* value.
*/
- EnumDeclaration(Comment comment, List<Annotation> metadata, this.enumKeyword,
- SimpleIdentifier name, this.leftBracket,
- List<EnumConstantDeclaration> constants, this.rightBracket)
+ EnumDeclaration(
+ Comment comment,
+ List<Annotation> metadata,
+ this.enumKeyword,
+ SimpleIdentifier name,
+ this.leftBracket,
+ List<EnumConstantDeclaration> constants,
+ this.rightBracket)
: super(comment, metadata, name) {
_constants = new NodeList<EnumConstantDeclaration>(this, constants);
}
@@ -7184,9 +7387,16 @@
* [parameters] can be `null` if this is not a function-typed field formal
* parameter.
*/
- FieldFormalParameter(Comment comment, List<Annotation> metadata, this.keyword,
- TypeName type, this.thisKeyword, this.period, SimpleIdentifier identifier,
- TypeParameterList typeParameters, FormalParameterList parameters)
+ FieldFormalParameter(
+ Comment comment,
+ List<Annotation> metadata,
+ this.keyword,
+ TypeName type,
+ this.thisKeyword,
+ this.period,
+ SimpleIdentifier identifier,
+ TypeParameterList typeParameters,
+ FormalParameterList parameters)
: super(comment, metadata, identifier) {
_type = _becomeParentOf(type);
_typeParameters = _becomeParentOf(typeParameters);
@@ -7358,9 +7568,15 @@
* `null` if this is not an asynchronous for loop.
*/
@deprecated // Use new ForEachStatement.withDeclaration(...)
- ForEachStatement.con1(this.awaitKeyword, this.forKeyword,
- this.leftParenthesis, DeclaredIdentifier loopVariable, this.inKeyword,
- Expression iterator, this.rightParenthesis, Statement body) {
+ ForEachStatement.con1(
+ this.awaitKeyword,
+ this.forKeyword,
+ this.leftParenthesis,
+ DeclaredIdentifier loopVariable,
+ this.inKeyword,
+ Expression iterator,
+ this.rightParenthesis,
+ Statement body) {
_loopVariable = _becomeParentOf(loopVariable);
_iterable = _becomeParentOf(iterator);
_body = _becomeParentOf(body);
@@ -7371,9 +7587,15 @@
* `null` if this is not an asynchronous for loop.
*/
@deprecated // Use new ForEachStatement.withReference(...)
- ForEachStatement.con2(this.awaitKeyword, this.forKeyword,
- this.leftParenthesis, SimpleIdentifier identifier, this.inKeyword,
- Expression iterator, this.rightParenthesis, Statement body) {
+ ForEachStatement.con2(
+ this.awaitKeyword,
+ this.forKeyword,
+ this.leftParenthesis,
+ SimpleIdentifier identifier,
+ this.inKeyword,
+ Expression iterator,
+ this.rightParenthesis,
+ Statement body) {
_identifier = _becomeParentOf(identifier);
_iterable = _becomeParentOf(iterator);
_body = _becomeParentOf(body);
@@ -7384,9 +7606,15 @@
* is declared internally (in the for-loop part). The [awaitKeyword] can be
* `null` if this is not an asynchronous for loop.
*/
- ForEachStatement.withDeclaration(this.awaitKeyword, this.forKeyword,
- this.leftParenthesis, DeclaredIdentifier loopVariable, this.inKeyword,
- Expression iterator, this.rightParenthesis, Statement body) {
+ ForEachStatement.withDeclaration(
+ this.awaitKeyword,
+ this.forKeyword,
+ this.leftParenthesis,
+ DeclaredIdentifier loopVariable,
+ this.inKeyword,
+ Expression iterator,
+ this.rightParenthesis,
+ Statement body) {
_loopVariable = _becomeParentOf(loopVariable);
_iterable = _becomeParentOf(iterator);
_body = _becomeParentOf(body);
@@ -7397,9 +7625,15 @@
* is declared outside the for loop. The [awaitKeyword] can be `null` if this
* is not an asynchronous for loop.
*/
- ForEachStatement.withReference(this.awaitKeyword, this.forKeyword,
- this.leftParenthesis, SimpleIdentifier identifier, this.inKeyword,
- Expression iterator, this.rightParenthesis, Statement body) {
+ ForEachStatement.withReference(
+ this.awaitKeyword,
+ this.forKeyword,
+ this.leftParenthesis,
+ SimpleIdentifier identifier,
+ this.inKeyword,
+ Expression iterator,
+ this.rightParenthesis,
+ Statement body) {
_identifier = _becomeParentOf(identifier);
_iterable = _becomeParentOf(iterator);
_body = _becomeParentOf(body);
@@ -7730,10 +7964,17 @@
* [updaters] can be `null` if the loop does not have the corresponding
* attribute.
*/
- ForStatement(this.forKeyword, this.leftParenthesis,
- VariableDeclarationList variableList, Expression initialization,
- this.leftSeparator, Expression condition, this.rightSeparator,
- List<Expression> updaters, this.rightParenthesis, Statement body) {
+ ForStatement(
+ this.forKeyword,
+ this.leftParenthesis,
+ VariableDeclarationList variableList,
+ Expression initialization,
+ this.leftSeparator,
+ Expression condition,
+ this.rightSeparator,
+ List<Expression> updaters,
+ this.rightParenthesis,
+ Statement body) {
_variableList = _becomeParentOf(variableList);
_initialization = _becomeParentOf(initialization);
_condition = _becomeParentOf(condition);
@@ -7908,9 +8149,14 @@
* return type was specified. The [propertyKeyword] can be `null` if the
* function is neither a getter or a setter.
*/
- FunctionDeclaration(Comment comment, List<Annotation> metadata,
- this.externalKeyword, TypeName returnType, this.propertyKeyword,
- SimpleIdentifier name, FunctionExpression functionExpression)
+ FunctionDeclaration(
+ Comment comment,
+ List<Annotation> metadata,
+ this.externalKeyword,
+ TypeName returnType,
+ this.propertyKeyword,
+ SimpleIdentifier name,
+ FunctionExpression functionExpression)
: super(comment, metadata, name) {
_returnType = _becomeParentOf(returnType);
_functionExpression = _becomeParentOf(functionExpression);
@@ -8326,9 +8572,14 @@
* was specified. The [typeParameters] can be `null` if the function has no
* type parameters.
*/
- FunctionTypeAlias(Comment comment, List<Annotation> metadata, Token keyword,
- TypeName returnType, SimpleIdentifier name,
- TypeParameterList typeParameters, FormalParameterList parameters,
+ FunctionTypeAlias(
+ Comment comment,
+ List<Annotation> metadata,
+ Token keyword,
+ TypeName returnType,
+ SimpleIdentifier name,
+ TypeParameterList typeParameters,
+ FormalParameterList parameters,
Token semicolon)
: super(comment, metadata, keyword, name, semicolon) {
_returnType = _becomeParentOf(returnType);
@@ -8433,9 +8684,13 @@
* corresponding attribute. The [returnType] can be `null` if no return type
* was specified.
*/
- FunctionTypedFormalParameter(Comment comment, List<Annotation> metadata,
- TypeName returnType, SimpleIdentifier identifier,
- TypeParameterList typeParameters, FormalParameterList parameters)
+ FunctionTypedFormalParameter(
+ Comment comment,
+ List<Annotation> metadata,
+ TypeName returnType,
+ SimpleIdentifier identifier,
+ TypeParameterList typeParameters,
+ FormalParameterList parameters)
: super(comment, metadata, identifier) {
_returnType = _becomeParentOf(returnType);
_typeParameters = _becomeParentOf(typeParameters);
@@ -9092,8 +9347,13 @@
* Initialize a newly created if statement. The [elseKeyword] and
* [elseStatement] can be `null` if there is no else clause.
*/
- IfStatement(this.ifKeyword, this.leftParenthesis, Expression condition,
- this.rightParenthesis, Statement thenStatement, this.elseKeyword,
+ IfStatement(
+ this.ifKeyword,
+ this.leftParenthesis,
+ Expression condition,
+ this.rightParenthesis,
+ Statement thenStatement,
+ this.elseKeyword,
Statement elseStatement) {
_condition = _becomeParentOf(condition);
_thenStatement = _becomeParentOf(thenStatement);
@@ -9247,8 +9507,8 @@
* > | [Annotation] 'import' [StringLiteral] 'deferred' 'as' identifier [Combinator]* ';'
*/
class ImportDirective extends NamespaceDirective {
- static Comparator<ImportDirective> COMPARATOR = (ImportDirective import1,
- ImportDirective import2) {
+ static Comparator<ImportDirective> COMPARATOR =
+ (ImportDirective import1, ImportDirective import2) {
//
// uri
//
@@ -9367,9 +9627,16 @@
* does not specify a prefix. The list of [combinators] can be `null` if there
* are no combinators.
*/
- ImportDirective(Comment comment, List<Annotation> metadata, Token keyword,
- StringLiteral libraryUri, this.deferredKeyword, this.asKeyword,
- SimpleIdentifier prefix, List<Combinator> combinators, Token semicolon)
+ ImportDirective(
+ Comment comment,
+ List<Annotation> metadata,
+ Token keyword,
+ StringLiteral libraryUri,
+ this.deferredKeyword,
+ this.asKeyword,
+ SimpleIdentifier prefix,
+ List<Combinator> combinators,
+ Token semicolon)
: super(comment, metadata, keyword, libraryUri, combinators, semicolon) {
_prefix = _becomeParentOf(prefix);
}
@@ -9484,16 +9751,20 @@
@override
Annotation visitAnnotation(Annotation node) {
- Annotation copy = new Annotation(_mapToken(node.atSign),
- _cloneNode(node.name), _mapToken(node.period),
- _cloneNode(node.constructorName), _cloneNode(node.arguments));
+ Annotation copy = new Annotation(
+ _mapToken(node.atSign),
+ _cloneNode(node.name),
+ _mapToken(node.period),
+ _cloneNode(node.constructorName),
+ _cloneNode(node.arguments));
copy.element = node.element;
return copy;
}
@override
ArgumentList visitArgumentList(ArgumentList node) => new ArgumentList(
- _mapToken(node.leftParenthesis), _cloneNodeList(node.arguments),
+ _mapToken(node.leftParenthesis),
+ _cloneNodeList(node.arguments),
_mapToken(node.rightParenthesis));
@override
@@ -9507,14 +9778,17 @@
@override
AstNode visitAssertStatement(AssertStatement node) => new AssertStatement(
- _mapToken(node.assertKeyword), _mapToken(node.leftParenthesis),
- _cloneNode(node.condition), _mapToken(node.rightParenthesis),
+ _mapToken(node.assertKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.condition),
+ _mapToken(node.rightParenthesis),
_mapToken(node.semicolon));
@override
AssignmentExpression visitAssignmentExpression(AssignmentExpression node) {
AssignmentExpression copy = new AssignmentExpression(
- _cloneNode(node.leftHandSide), _mapToken(node.operator),
+ _cloneNode(node.leftHandSide),
+ _mapToken(node.operator),
_cloneNode(node.rightHandSide));
copy.propagatedElement = node.propagatedElement;
copy.propagatedType = node.propagatedType;
@@ -9544,9 +9818,9 @@
_cloneNodeList(node.statements), _mapToken(node.rightBracket));
@override
- BlockFunctionBody visitBlockFunctionBody(
- BlockFunctionBody node) => new BlockFunctionBody(
- _mapToken(node.keyword), _mapToken(node.star), _cloneNode(node.block));
+ BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
+ new BlockFunctionBody(_mapToken(node.keyword), _mapToken(node.star),
+ _cloneNode(node.block));
@override
BooleanLiteral visitBooleanLiteral(BooleanLiteral node) {
@@ -9559,7 +9833,8 @@
@override
BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement(
- _mapToken(node.breakKeyword), _cloneNode(node.label),
+ _mapToken(node.breakKeyword),
+ _cloneNode(node.label),
_mapToken(node.semicolon));
@override
@@ -9573,32 +9848,47 @@
@override
CatchClause visitCatchClause(CatchClause node) => new CatchClause(
- _mapToken(node.onKeyword), _cloneNode(node.exceptionType),
- _mapToken(node.catchKeyword), _mapToken(node.leftParenthesis),
- _cloneNode(node.exceptionParameter), _mapToken(node.comma),
- _cloneNode(node.stackTraceParameter), _mapToken(node.rightParenthesis),
+ _mapToken(node.onKeyword),
+ _cloneNode(node.exceptionType),
+ _mapToken(node.catchKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.exceptionParameter),
+ _mapToken(node.comma),
+ _cloneNode(node.stackTraceParameter),
+ _mapToken(node.rightParenthesis),
_cloneNode(node.body));
@override
ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
ClassDeclaration copy = new ClassDeclaration(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _mapToken(node.abstractKeyword), _mapToken(node.classKeyword),
- _cloneNode(node.name), _cloneNode(node.typeParameters),
- _cloneNode(node.extendsClause), _cloneNode(node.withClause),
- _cloneNode(node.implementsClause), _mapToken(node.leftBracket),
- _cloneNodeList(node.members), _mapToken(node.rightBracket));
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.abstractKeyword),
+ _mapToken(node.classKeyword),
+ _cloneNode(node.name),
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.extendsClause),
+ _cloneNode(node.withClause),
+ _cloneNode(node.implementsClause),
+ _mapToken(node.leftBracket),
+ _cloneNodeList(node.members),
+ _mapToken(node.rightBracket));
copy.nativeClause = _cloneNode(node.nativeClause);
return copy;
}
@override
ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _mapToken(node.typedefKeyword), _cloneNode(node.name),
- _cloneNode(node.typeParameters), _mapToken(node.equals),
- _mapToken(node.abstractKeyword), _cloneNode(node.superclass),
- _cloneNode(node.withClause), _cloneNode(node.implementsClause),
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.typedefKeyword),
+ _cloneNode(node.name),
+ _cloneNode(node.typeParameters),
+ _mapToken(node.equals),
+ _mapToken(node.abstractKeyword),
+ _cloneNode(node.superclass),
+ _cloneNode(node.withClause),
+ _cloneNode(node.implementsClause),
_mapToken(node.semicolon));
@override
@@ -9619,9 +9909,12 @@
@override
CompilationUnit visitCompilationUnit(CompilationUnit node) {
- CompilationUnit copy = new CompilationUnit(_mapToken(node.beginToken),
- _cloneNode(node.scriptTag), _cloneNodeList(node.directives),
- _cloneNodeList(node.declarations), _mapToken(node.endToken));
+ CompilationUnit copy = new CompilationUnit(
+ _mapToken(node.beginToken),
+ _cloneNode(node.scriptTag),
+ _cloneNodeList(node.directives),
+ _cloneNodeList(node.declarations),
+ _mapToken(node.endToken));
copy.lineInfo = node.lineInfo;
copy.element = node.element;
return copy;
@@ -9630,8 +9923,10 @@
@override
ConditionalExpression visitConditionalExpression(ConditionalExpression node) {
ConditionalExpression copy = new ConditionalExpression(
- _cloneNode(node.condition), _mapToken(node.question),
- _cloneNode(node.thenExpression), _mapToken(node.colon),
+ _cloneNode(node.condition),
+ _mapToken(node.question),
+ _cloneNode(node.thenExpression),
+ _mapToken(node.colon),
_cloneNode(node.elseExpression));
copy.propagatedType = node.propagatedType;
copy.staticType = node.staticType;
@@ -9642,23 +9937,32 @@
ConstructorDeclaration visitConstructorDeclaration(
ConstructorDeclaration node) {
ConstructorDeclaration copy = new ConstructorDeclaration(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _mapToken(node.externalKeyword), _mapToken(node.constKeyword),
- _mapToken(node.factoryKeyword), _cloneNode(node.returnType),
- _mapToken(node.period), _cloneNode(node.name),
- _cloneNode(node.parameters), _mapToken(node.separator),
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.externalKeyword),
+ _mapToken(node.constKeyword),
+ _mapToken(node.factoryKeyword),
+ _cloneNode(node.returnType),
+ _mapToken(node.period),
+ _cloneNode(node.name),
+ _cloneNode(node.parameters),
+ _mapToken(node.separator),
_cloneNodeList(node.initializers),
- _cloneNode(node.redirectedConstructor), _cloneNode(node.body));
+ _cloneNode(node.redirectedConstructor),
+ _cloneNode(node.body));
copy.element = node.element;
return copy;
}
@override
ConstructorFieldInitializer visitConstructorFieldInitializer(
- ConstructorFieldInitializer node) => new ConstructorFieldInitializer(
- _mapToken(node.thisKeyword), _mapToken(node.period),
- _cloneNode(node.fieldName), _mapToken(node.equals),
- _cloneNode(node.expression));
+ ConstructorFieldInitializer node) =>
+ new ConstructorFieldInitializer(
+ _mapToken(node.thisKeyword),
+ _mapToken(node.period),
+ _cloneNode(node.fieldName),
+ _mapToken(node.equals),
+ _cloneNode(node.expression));
@override
ConstructorName visitConstructorName(ConstructorName node) {
@@ -9675,21 +9979,27 @@
@override
DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
- new DeclaredIdentifier(_cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata), _mapToken(node.keyword),
- _cloneNode(node.type), _cloneNode(node.identifier));
+ new DeclaredIdentifier(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.type),
+ _cloneNode(node.identifier));
@override
DefaultFormalParameter visitDefaultFormalParameter(
- DefaultFormalParameter node) => new DefaultFormalParameter(
- _cloneNode(node.parameter), node.kind, _mapToken(node.separator),
- _cloneNode(node.defaultValue));
+ DefaultFormalParameter node) =>
+ new DefaultFormalParameter(_cloneNode(node.parameter), node.kind,
+ _mapToken(node.separator), _cloneNode(node.defaultValue));
@override
DoStatement visitDoStatement(DoStatement node) => new DoStatement(
- _mapToken(node.doKeyword), _cloneNode(node.body),
- _mapToken(node.whileKeyword), _mapToken(node.leftParenthesis),
- _cloneNode(node.condition), _mapToken(node.rightParenthesis),
+ _mapToken(node.doKeyword),
+ _cloneNode(node.body),
+ _mapToken(node.whileKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.condition),
+ _mapToken(node.rightParenthesis),
_mapToken(node.semicolon));
@override
@@ -9715,26 +10025,35 @@
@override
AstNode visitEnumDeclaration(EnumDeclaration node) => new EnumDeclaration(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _mapToken(node.enumKeyword), _cloneNode(node.name),
- _mapToken(node.leftBracket), _cloneNodeList(node.constants),
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.enumKeyword),
+ _cloneNode(node.name),
+ _mapToken(node.leftBracket),
+ _cloneNodeList(node.constants),
_mapToken(node.rightBracket));
@override
ExportDirective visitExportDirective(ExportDirective node) {
ExportDirective copy = new ExportDirective(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _mapToken(node.keyword), _cloneNode(node.uri),
- _cloneNodeList(node.combinators), _mapToken(node.semicolon));
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.uri),
+ _cloneNodeList(node.combinators),
+ _mapToken(node.semicolon));
copy.element = node.element;
return copy;
}
@override
ExpressionFunctionBody visitExpressionFunctionBody(
- ExpressionFunctionBody node) => new ExpressionFunctionBody(
- _mapToken(node.keyword), _mapToken(node.functionDefinition),
- _cloneNode(node.expression), _mapToken(node.semicolon));
+ ExpressionFunctionBody node) =>
+ new ExpressionFunctionBody(
+ _mapToken(node.keyword),
+ _mapToken(node.functionDefinition),
+ _cloneNode(node.expression),
+ _mapToken(node.semicolon));
@override
ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
@@ -9747,55 +10066,83 @@
@override
FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
- new FieldDeclaration(_cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata), _mapToken(node.staticKeyword),
- _cloneNode(node.fields), _mapToken(node.semicolon));
+ new FieldDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.staticKeyword),
+ _cloneNode(node.fields),
+ _mapToken(node.semicolon));
@override
FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
- new FieldFormalParameter(_cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata), _mapToken(node.keyword),
- _cloneNode(node.type), _mapToken(node.thisKeyword),
- _mapToken(node.period), _cloneNode(node.identifier),
- _cloneNode(node.typeParameters), _cloneNode(node.parameters));
+ new FieldFormalParameter(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.type),
+ _mapToken(node.thisKeyword),
+ _mapToken(node.period),
+ _cloneNode(node.identifier),
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.parameters));
@override
ForEachStatement visitForEachStatement(ForEachStatement node) {
DeclaredIdentifier loopVariable = node.loopVariable;
if (loopVariable == null) {
- return new ForEachStatement.withReference(_mapToken(node.awaitKeyword),
- _mapToken(node.forKeyword), _mapToken(node.leftParenthesis),
- _cloneNode(node.identifier), _mapToken(node.inKeyword),
- _cloneNode(node.iterable), _mapToken(node.rightParenthesis),
+ return new ForEachStatement.withReference(
+ _mapToken(node.awaitKeyword),
+ _mapToken(node.forKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.identifier),
+ _mapToken(node.inKeyword),
+ _cloneNode(node.iterable),
+ _mapToken(node.rightParenthesis),
_cloneNode(node.body));
}
- return new ForEachStatement.withDeclaration(_mapToken(node.awaitKeyword),
- _mapToken(node.forKeyword), _mapToken(node.leftParenthesis),
- _cloneNode(loopVariable), _mapToken(node.inKeyword),
- _cloneNode(node.iterable), _mapToken(node.rightParenthesis),
+ return new ForEachStatement.withDeclaration(
+ _mapToken(node.awaitKeyword),
+ _mapToken(node.forKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(loopVariable),
+ _mapToken(node.inKeyword),
+ _cloneNode(node.iterable),
+ _mapToken(node.rightParenthesis),
_cloneNode(node.body));
}
@override
FormalParameterList visitFormalParameterList(FormalParameterList node) =>
- new FormalParameterList(_mapToken(node.leftParenthesis),
- _cloneNodeList(node.parameters), _mapToken(node.leftDelimiter),
- _mapToken(node.rightDelimiter), _mapToken(node.rightParenthesis));
+ new FormalParameterList(
+ _mapToken(node.leftParenthesis),
+ _cloneNodeList(node.parameters),
+ _mapToken(node.leftDelimiter),
+ _mapToken(node.rightDelimiter),
+ _mapToken(node.rightParenthesis));
@override
ForStatement visitForStatement(ForStatement node) => new ForStatement(
- _mapToken(node.forKeyword), _mapToken(node.leftParenthesis),
- _cloneNode(node.variables), _cloneNode(node.initialization),
- _mapToken(node.leftSeparator), _cloneNode(node.condition),
- _mapToken(node.rightSeparator), _cloneNodeList(node.updaters),
- _mapToken(node.rightParenthesis), _cloneNode(node.body));
+ _mapToken(node.forKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.variables),
+ _cloneNode(node.initialization),
+ _mapToken(node.leftSeparator),
+ _cloneNode(node.condition),
+ _mapToken(node.rightSeparator),
+ _cloneNodeList(node.updaters),
+ _mapToken(node.rightParenthesis),
+ _cloneNode(node.body));
@override
FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
- new FunctionDeclaration(_cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata), _mapToken(node.externalKeyword),
- _cloneNode(node.returnType), _mapToken(node.propertyKeyword),
- _cloneNode(node.name), _cloneNode(node.functionExpression));
+ new FunctionDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.externalKeyword),
+ _cloneNode(node.returnType),
+ _mapToken(node.propertyKeyword),
+ _cloneNode(node.name),
+ _cloneNode(node.functionExpression));
@override
FunctionDeclarationStatement visitFunctionDeclarationStatement(
@@ -9805,7 +10152,8 @@
@override
FunctionExpression visitFunctionExpression(FunctionExpression node) {
FunctionExpression copy = new FunctionExpression(
- _cloneNode(node.typeParameters), _cloneNode(node.parameters),
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.parameters),
_cloneNode(node.body));
copy.element = node.element;
copy.propagatedType = node.propagatedType;
@@ -9817,7 +10165,8 @@
FunctionExpressionInvocation visitFunctionExpressionInvocation(
FunctionExpressionInvocation node) {
FunctionExpressionInvocation copy = new FunctionExpressionInvocation(
- _cloneNode(node.function), _cloneNode(node.typeArguments),
+ _cloneNode(node.function),
+ _cloneNode(node.typeArguments),
_cloneNode(node.argumentList));
copy.propagatedElement = node.propagatedElement;
copy.propagatedType = node.propagatedType;
@@ -9828,18 +10177,26 @@
@override
FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
- new FunctionTypeAlias(_cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata), _mapToken(node.typedefKeyword),
- _cloneNode(node.returnType), _cloneNode(node.name),
- _cloneNode(node.typeParameters), _cloneNode(node.parameters),
+ new FunctionTypeAlias(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.typedefKeyword),
+ _cloneNode(node.returnType),
+ _cloneNode(node.name),
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.parameters),
_mapToken(node.semicolon));
@override
FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
- FunctionTypedFormalParameter node) => new FunctionTypedFormalParameter(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _cloneNode(node.returnType), _cloneNode(node.identifier),
- _cloneNode(node.typeParameters), _cloneNode(node.parameters));
+ FunctionTypedFormalParameter node) =>
+ new FunctionTypedFormalParameter(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _cloneNode(node.returnType),
+ _cloneNode(node.identifier),
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.parameters));
@override
HideCombinator visitHideCombinator(HideCombinator node) => new HideCombinator(
@@ -9847,9 +10204,12 @@
@override
IfStatement visitIfStatement(IfStatement node) => new IfStatement(
- _mapToken(node.ifKeyword), _mapToken(node.leftParenthesis),
- _cloneNode(node.condition), _mapToken(node.rightParenthesis),
- _cloneNode(node.thenStatement), _mapToken(node.elseKeyword),
+ _mapToken(node.ifKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.condition),
+ _mapToken(node.rightParenthesis),
+ _cloneNode(node.thenStatement),
+ _mapToken(node.elseKeyword),
_cloneNode(node.elseStatement));
@override
@@ -9859,19 +10219,26 @@
@override
ImportDirective visitImportDirective(ImportDirective node) =>
- new ImportDirective(_cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata), _mapToken(node.keyword),
- _cloneNode(node.uri), _mapToken(node.deferredKeyword),
- _mapToken(node.asKeyword), _cloneNode(node.prefix),
- _cloneNodeList(node.combinators), _mapToken(node.semicolon));
+ new ImportDirective(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.uri),
+ _mapToken(node.deferredKeyword),
+ _mapToken(node.asKeyword),
+ _cloneNode(node.prefix),
+ _cloneNodeList(node.combinators),
+ _mapToken(node.semicolon));
@override
IndexExpression visitIndexExpression(IndexExpression node) {
Token period = _mapToken(node.period);
IndexExpression copy;
if (period == null) {
- copy = new IndexExpression.forTarget(_cloneNode(node.target),
- _mapToken(node.leftBracket), _cloneNode(node.index),
+ copy = new IndexExpression.forTarget(
+ _cloneNode(node.target),
+ _mapToken(node.leftBracket),
+ _cloneNode(node.index),
_mapToken(node.rightBracket));
} else {
copy = new IndexExpression.forCascade(period, _mapToken(node.leftBracket),
@@ -9889,7 +10256,8 @@
InstanceCreationExpression visitInstanceCreationExpression(
InstanceCreationExpression node) {
InstanceCreationExpression copy = new InstanceCreationExpression(
- _mapToken(node.keyword), _cloneNode(node.constructorName),
+ _mapToken(node.keyword),
+ _cloneNode(node.constructorName),
_cloneNode(node.argumentList));
copy.propagatedType = node.propagatedType;
copy.staticElement = node.staticElement;
@@ -9908,9 +10276,9 @@
@override
InterpolationExpression visitInterpolationExpression(
- InterpolationExpression node) => new InterpolationExpression(
- _mapToken(node.leftBracket), _cloneNode(node.expression),
- _mapToken(node.rightBracket));
+ InterpolationExpression node) =>
+ new InterpolationExpression(_mapToken(node.leftBracket),
+ _cloneNode(node.expression), _mapToken(node.rightBracket));
@override
InterpolationString visitInterpolationString(InterpolationString node) =>
@@ -9918,8 +10286,10 @@
@override
IsExpression visitIsExpression(IsExpression node) {
- IsExpression copy = new IsExpression(_cloneNode(node.expression),
- _mapToken(node.isOperator), _mapToken(node.notOperator),
+ IsExpression copy = new IsExpression(
+ _cloneNode(node.expression),
+ _mapToken(node.isOperator),
+ _mapToken(node.notOperator),
_cloneNode(node.type));
copy.propagatedType = node.propagatedType;
copy.staticType = node.staticType;
@@ -9937,9 +10307,12 @@
@override
LibraryDirective visitLibraryDirective(LibraryDirective node) =>
- new LibraryDirective(_cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata), _mapToken(node.libraryKeyword),
- _cloneNode(node.name), _mapToken(node.semicolon));
+ new LibraryDirective(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.libraryKeyword),
+ _cloneNode(node.name),
+ _mapToken(node.semicolon));
@override
LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) {
@@ -9952,9 +10325,12 @@
@override
ListLiteral visitListLiteral(ListLiteral node) {
- ListLiteral copy = new ListLiteral(_mapToken(node.constKeyword),
- _cloneNode(node.typeArguments), _mapToken(node.leftBracket),
- _cloneNodeList(node.elements), _mapToken(node.rightBracket));
+ ListLiteral copy = new ListLiteral(
+ _mapToken(node.constKeyword),
+ _cloneNode(node.typeArguments),
+ _mapToken(node.leftBracket),
+ _cloneNodeList(node.elements),
+ _mapToken(node.rightBracket));
copy.propagatedType = node.propagatedType;
copy.staticType = node.staticType;
return copy;
@@ -9962,33 +10338,45 @@
@override
MapLiteral visitMapLiteral(MapLiteral node) {
- MapLiteral copy = new MapLiteral(_mapToken(node.constKeyword),
- _cloneNode(node.typeArguments), _mapToken(node.leftBracket),
- _cloneNodeList(node.entries), _mapToken(node.rightBracket));
+ MapLiteral copy = new MapLiteral(
+ _mapToken(node.constKeyword),
+ _cloneNode(node.typeArguments),
+ _mapToken(node.leftBracket),
+ _cloneNodeList(node.entries),
+ _mapToken(node.rightBracket));
copy.propagatedType = node.propagatedType;
copy.staticType = node.staticType;
return copy;
}
@override
- MapLiteralEntry visitMapLiteralEntry(
- MapLiteralEntry node) => new MapLiteralEntry(
- _cloneNode(node.key), _mapToken(node.separator), _cloneNode(node.value));
+ MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
+ new MapLiteralEntry(_cloneNode(node.key), _mapToken(node.separator),
+ _cloneNode(node.value));
@override
MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
- new MethodDeclaration(_cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata), _mapToken(node.externalKeyword),
- _mapToken(node.modifierKeyword), _cloneNode(node.returnType),
- _mapToken(node.propertyKeyword), _mapToken(node.operatorKeyword),
- _cloneNode(node.name), _cloneNode(node._typeParameters),
- _cloneNode(node.parameters), _cloneNode(node.body));
+ new MethodDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.externalKeyword),
+ _mapToken(node.modifierKeyword),
+ _cloneNode(node.returnType),
+ _mapToken(node.propertyKeyword),
+ _mapToken(node.operatorKeyword),
+ _cloneNode(node.name),
+ _cloneNode(node._typeParameters),
+ _cloneNode(node.parameters),
+ _cloneNode(node.body));
@override
MethodInvocation visitMethodInvocation(MethodInvocation node) {
- MethodInvocation copy = new MethodInvocation(_cloneNode(node.target),
- _mapToken(node.operator), _cloneNode(node.methodName),
- _cloneNode(node.typeArguments), _cloneNode(node.argumentList));
+ MethodInvocation copy = new MethodInvocation(
+ _cloneNode(node.target),
+ _mapToken(node.operator),
+ _cloneNode(node.methodName),
+ _cloneNode(node.typeArguments),
+ _cloneNode(node.argumentList));
copy.propagatedType = node.propagatedType;
copy.staticType = node.staticType;
return copy;
@@ -10024,7 +10412,8 @@
ParenthesizedExpression visitParenthesizedExpression(
ParenthesizedExpression node) {
ParenthesizedExpression copy = new ParenthesizedExpression(
- _mapToken(node.leftParenthesis), _cloneNode(node.expression),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.expression),
_mapToken(node.rightParenthesis));
copy.propagatedType = node.propagatedType;
copy.staticType = node.staticType;
@@ -10034,8 +10423,10 @@
@override
PartDirective visitPartDirective(PartDirective node) {
PartDirective copy = new PartDirective(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _mapToken(node.partKeyword), _cloneNode(node.uri),
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.partKeyword),
+ _cloneNode(node.uri),
_mapToken(node.semicolon));
copy.element = node.element;
return copy;
@@ -10044,9 +10435,12 @@
@override
PartOfDirective visitPartOfDirective(PartOfDirective node) {
PartOfDirective copy = new PartOfDirective(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _mapToken(node.partKeyword), _mapToken(node.ofKeyword),
- _cloneNode(node.libraryName), _mapToken(node.semicolon));
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.partKeyword),
+ _mapToken(node.ofKeyword),
+ _cloneNode(node.libraryName),
+ _mapToken(node.semicolon));
copy.element = node.element;
return copy;
}
@@ -10095,8 +10489,10 @@
RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
RedirectingConstructorInvocation node) {
RedirectingConstructorInvocation copy =
- new RedirectingConstructorInvocation(_mapToken(node.thisKeyword),
- _mapToken(node.period), _cloneNode(node.constructorName),
+ new RedirectingConstructorInvocation(
+ _mapToken(node.thisKeyword),
+ _mapToken(node.period),
+ _cloneNode(node.constructorName),
_cloneNode(node.argumentList));
copy.staticElement = node.staticElement;
return copy;
@@ -10126,10 +10522,13 @@
@override
SimpleFormalParameter visitSimpleFormalParameter(
- SimpleFormalParameter node) => new SimpleFormalParameter(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _mapToken(node.keyword), _cloneNode(node.type),
- _cloneNode(node.identifier));
+ SimpleFormalParameter node) =>
+ new SimpleFormalParameter(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.type),
+ _cloneNode(node.identifier));
@override
SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
@@ -10173,8 +10572,10 @@
SuperConstructorInvocation visitSuperConstructorInvocation(
SuperConstructorInvocation node) {
SuperConstructorInvocation copy = new SuperConstructorInvocation(
- _mapToken(node.superKeyword), _mapToken(node.period),
- _cloneNode(node.constructorName), _cloneNode(node.argumentList));
+ _mapToken(node.superKeyword),
+ _mapToken(node.period),
+ _cloneNode(node.constructorName),
+ _cloneNode(node.argumentList));
copy.staticElement = node.staticElement;
return copy;
}
@@ -10189,21 +10590,29 @@
@override
SwitchCase visitSwitchCase(SwitchCase node) => new SwitchCase(
- _cloneNodeList(node.labels), _mapToken(node.keyword),
- _cloneNode(node.expression), _mapToken(node.colon),
+ _cloneNodeList(node.labels),
+ _mapToken(node.keyword),
+ _cloneNode(node.expression),
+ _mapToken(node.colon),
_cloneNodeList(node.statements));
@override
SwitchDefault visitSwitchDefault(SwitchDefault node) => new SwitchDefault(
- _cloneNodeList(node.labels), _mapToken(node.keyword),
- _mapToken(node.colon), _cloneNodeList(node.statements));
+ _cloneNodeList(node.labels),
+ _mapToken(node.keyword),
+ _mapToken(node.colon),
+ _cloneNodeList(node.statements));
@override
SwitchStatement visitSwitchStatement(SwitchStatement node) =>
- new SwitchStatement(_mapToken(node.switchKeyword),
- _mapToken(node.leftParenthesis), _cloneNode(node.expression),
- _mapToken(node.rightParenthesis), _mapToken(node.leftBracket),
- _cloneNodeList(node.members), _mapToken(node.rightBracket));
+ new SwitchStatement(
+ _mapToken(node.switchKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.expression),
+ _mapToken(node.rightParenthesis),
+ _mapToken(node.leftBracket),
+ _cloneNodeList(node.members),
+ _mapToken(node.rightBracket));
@override
AstNode visitSymbolLiteral(SymbolLiteral node) {
@@ -10233,14 +10642,19 @@
@override
TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
- TopLevelVariableDeclaration node) => new TopLevelVariableDeclaration(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _cloneNode(node.variables), _mapToken(node.semicolon));
+ TopLevelVariableDeclaration node) =>
+ new TopLevelVariableDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _cloneNode(node.variables),
+ _mapToken(node.semicolon));
@override
TryStatement visitTryStatement(TryStatement node) => new TryStatement(
- _mapToken(node.tryKeyword), _cloneNode(node.body),
- _cloneNodeList(node.catchClauses), _mapToken(node.finallyKeyword),
+ _mapToken(node.tryKeyword),
+ _cloneNode(node.body),
+ _cloneNodeList(node.catchClauses),
+ _mapToken(node.finallyKeyword),
_cloneNode(node.finallyBlock));
@override
@@ -10258,8 +10672,10 @@
@override
TypeParameter visitTypeParameter(TypeParameter node) => new TypeParameter(
- _cloneNode(node.documentationComment), _cloneNodeList(node.metadata),
- _cloneNode(node.name), _mapToken(node.extendsKeyword),
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _cloneNode(node.name),
+ _mapToken(node.extendsKeyword),
_cloneNode(node.bound));
@override
@@ -10274,19 +10690,26 @@
@override
VariableDeclarationList visitVariableDeclarationList(
- VariableDeclarationList node) => new VariableDeclarationList(null,
- _cloneNodeList(node.metadata), _mapToken(node.keyword),
- _cloneNode(node.type), _cloneNodeList(node.variables));
+ VariableDeclarationList node) =>
+ new VariableDeclarationList(
+ null,
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.type),
+ _cloneNodeList(node.variables));
@override
VariableDeclarationStatement visitVariableDeclarationStatement(
- VariableDeclarationStatement node) => new VariableDeclarationStatement(
- _cloneNode(node.variables), _mapToken(node.semicolon));
+ VariableDeclarationStatement node) =>
+ new VariableDeclarationStatement(
+ _cloneNode(node.variables), _mapToken(node.semicolon));
@override
WhileStatement visitWhileStatement(WhileStatement node) => new WhileStatement(
- _mapToken(node.whileKeyword), _mapToken(node.leftParenthesis),
- _cloneNode(node.condition), _mapToken(node.rightParenthesis),
+ _mapToken(node.whileKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.condition),
+ _mapToken(node.rightParenthesis),
_cloneNode(node.body));
@override
@@ -10295,8 +10718,10 @@
@override
YieldStatement visitYieldStatement(YieldStatement node) => new YieldStatement(
- _mapToken(node.yieldKeyword), _mapToken(node.star),
- _cloneNode(node.expression), _mapToken(node.semicolon));
+ _mapToken(node.yieldKeyword),
+ _mapToken(node.star),
+ _cloneNode(node.expression),
+ _mapToken(node.semicolon));
AstNode _cloneNode(AstNode node) {
if (node == null) {
@@ -11579,10 +12004,17 @@
* method does not implement an operator. The [parameters] must be `null` if
* this method declares a getter.
*/
- MethodDeclaration(Comment comment, List<Annotation> metadata,
- this.externalKeyword, this.modifierKeyword, TypeName returnType,
- this.propertyKeyword, this.operatorKeyword, SimpleIdentifier name,
- TypeParameterList typeParameters, FormalParameterList parameters,
+ MethodDeclaration(
+ Comment comment,
+ List<Annotation> metadata,
+ this.externalKeyword,
+ this.modifierKeyword,
+ TypeName returnType,
+ this.propertyKeyword,
+ this.operatorKeyword,
+ SimpleIdentifier name,
+ TypeParameterList typeParameters,
+ FormalParameterList parameters,
FunctionBody body)
: super(comment, metadata) {
_returnType = _becomeParentOf(returnType);
@@ -11786,8 +12218,11 @@
* Initialize a newly created method invocation. The [target] and [operator]
* can be `null` if there is no target.
*/
- MethodInvocation(Expression target, this.operator,
- SimpleIdentifier methodName, TypeArgumentList typeArguments,
+ MethodInvocation(
+ Expression target,
+ this.operator,
+ SimpleIdentifier methodName,
+ TypeArgumentList typeArguments,
ArgumentList argumentList) {
_target = _becomeParentOf(target);
_methodName = _becomeParentOf(methodName);
@@ -16014,7 +16449,8 @@
@override
R visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) => null;
+ RedirectingConstructorInvocation node) =>
+ null;
@override
R visitRethrowExpression(RethrowExpression node) => null;
@@ -17235,9 +17671,14 @@
* Initialize a newly created switch statement. The list of [members] can be
* `null` if there are no switch members.
*/
- SwitchStatement(this.switchKeyword, this.leftParenthesis,
- Expression expression, this.rightParenthesis, this.leftBracket,
- List<SwitchMember> members, this.rightBracket) {
+ SwitchStatement(
+ this.switchKeyword,
+ this.leftParenthesis,
+ Expression expression,
+ this.rightParenthesis,
+ this.leftBracket,
+ List<SwitchMember> members,
+ this.rightBracket) {
_expression = _becomeParentOf(expression);
_members = new NodeList<SwitchMember>(this, members);
}
@@ -19458,7 +19899,8 @@
@override
R visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) => visitNode(node);
+ RedirectingConstructorInvocation node) =>
+ visitNode(node);
@override
R visitRethrowExpression(RethrowExpression node) => visitNode(node);
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 999ae5b..93186c6 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -240,8 +240,8 @@
ConstantEvaluationEngine(TypeProvider typeProvider, this._declaredVariables,
{ConstantEvaluationValidator validator})
: validator = validator != null
- ? validator
- : new ConstantEvaluationValidator_ForProduction(),
+ ? validator
+ : new ConstantEvaluationValidator_ForProduction(),
typeSystem = new TypeSystemImpl(typeProvider);
/**
@@ -258,7 +258,8 @@
* "defaultValue" is always allowed to be null. Return `true` if the arguments
* are correct, `false` if there is an error.
*/
- bool checkFromEnvironmentArguments(NodeList<Expression> arguments,
+ bool checkFromEnvironmentArguments(
+ NodeList<Expression> arguments,
List<DartObjectImpl> argumentValues,
HashMap<String, DartObjectImpl> namedArgumentValues,
InterfaceType expectedDefaultValueType) {
@@ -297,7 +298,8 @@
* named arguments. Return `true` if the arguments are correct, `false` if
* there is an error.
*/
- bool checkSymbolArguments(NodeList<Expression> arguments,
+ bool checkSymbolArguments(
+ NodeList<Expression> arguments,
List<DartObjectImpl> argumentValues,
HashMap<String, DartObjectImpl> namedArgumentValues) {
if (arguments.length != 1) {
@@ -349,7 +351,8 @@
if (!runtimeTypeMatch(dartObject, constant.type)) {
errorReporter.reportErrorForElement(
CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
- constant, [dartObject.type, constant.type]);
+ constant,
+ [dartObject.type, constant.type]);
}
}
(constant as VariableElementImpl).evaluationResult =
@@ -397,8 +400,11 @@
errorListener, sourceCompilationUnit.element.source);
ConstantVisitor constantVisitor =
new ConstantVisitor(this, errorReporter);
- DartObjectImpl result = evaluateConstructorCall(constNode,
- constNode.arguments.arguments, element, constantVisitor,
+ DartObjectImpl result = evaluateConstructorCall(
+ constNode,
+ constNode.arguments.arguments,
+ element,
+ constantVisitor,
errorReporter);
elementAnnotation.evaluationResult =
new EvaluationResultImpl(result, errorListener.errors);
@@ -543,7 +549,8 @@
* fromEnvironment(). Return a [DartObjectImpl] object corresponding to the
* evaluated result.
*/
- DartObjectImpl computeValueFromEnvironment(DartObject environmentValue,
+ DartObjectImpl computeValueFromEnvironment(
+ DartObject environmentValue,
DartObjectImpl builtInDefaultValue,
HashMap<String, DartObjectImpl> namedArgumentValues) {
DartObjectImpl value = environmentValue as DartObjectImpl;
@@ -570,9 +577,12 @@
return value;
}
- DartObjectImpl evaluateConstructorCall(AstNode node,
- NodeList<Expression> arguments, ConstructorElement constructor,
- ConstantVisitor constantVisitor, ErrorReporter errorReporter) {
+ DartObjectImpl evaluateConstructorCall(
+ AstNode node,
+ NodeList<Expression> arguments,
+ ConstructorElement constructor,
+ ConstantVisitor constantVisitor,
+ ErrorReporter errorReporter) {
if (!_getConstructorBase(constructor).isCycleFree) {
// It's not safe to evaluate this constructor, so bail out.
// TODO(paulberry): ensure that a reasonable error message is produced
@@ -621,21 +631,24 @@
DartObject valueFromEnvironment;
valueFromEnvironment =
_declaredVariables.getBool(typeProvider, variableName);
- return computeValueFromEnvironment(valueFromEnvironment,
+ return computeValueFromEnvironment(
+ valueFromEnvironment,
new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE),
namedArgumentValues);
} else if (identical(definingClass, typeProvider.intType)) {
DartObject valueFromEnvironment;
valueFromEnvironment =
_declaredVariables.getInt(typeProvider, variableName);
- return computeValueFromEnvironment(valueFromEnvironment,
+ return computeValueFromEnvironment(
+ valueFromEnvironment,
new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
namedArgumentValues);
} else if (identical(definingClass, typeProvider.stringType)) {
DartObject valueFromEnvironment;
valueFromEnvironment =
_declaredVariables.getString(typeProvider, variableName);
- return computeValueFromEnvironment(valueFromEnvironment,
+ return computeValueFromEnvironment(
+ valueFromEnvironment,
new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
namedArgumentValues);
}
@@ -687,7 +700,8 @@
if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) {
errorReporter.reportErrorForNode(
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
- node, [fieldValue.type, field.name, fieldType]);
+ node,
+ [fieldValue.type, field.name, fieldType]);
}
fieldMap[field.name] = evaluationResult.value;
}
@@ -734,7 +748,8 @@
if (!runtimeTypeMatch(argumentValue, parameter.type)) {
errorReporter.reportErrorForNode(
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
- errorTarget, [argumentValue.type, parameter.type]);
+ errorTarget,
+ [argumentValue.type, parameter.type]);
}
if (baseParameter.isInitializingFormal) {
FieldElement field = (parameter as FieldFormalParameterElement).field;
@@ -747,7 +762,8 @@
if (!runtimeTypeMatch(argumentValue, fieldType)) {
errorReporter.reportErrorForNode(
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
- errorTarget, [argumentValue.type, fieldType]);
+ errorTarget,
+ [argumentValue.type, fieldType]);
}
}
String fieldName = field.name;
@@ -764,7 +780,8 @@
}
}
ConstantVisitor initializerVisitor = new ConstantVisitor(
- this, errorReporter, lexicalEnvironment: parameterMap);
+ this, errorReporter,
+ lexicalEnvironment: parameterMap);
String superName = null;
NodeList<Expression> superArguments = null;
for (ConstructorInitializer initializer in initializers) {
@@ -787,7 +804,8 @@
if (!runtimeTypeMatch(evaluationResult, field.type)) {
errorReporter.reportErrorForNode(
CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
- node, [evaluationResult.type, fieldName, field.type]);
+ node,
+ [evaluationResult.type, fieldName, field.type]);
}
}
}
@@ -803,9 +821,12 @@
// it redirects to.
ConstructorElement constructor = initializer.staticElement;
if (constructor != null && constructor.isConst) {
- return evaluateConstructorCall(node,
- initializer.argumentList.arguments, constructor,
- initializerVisitor, errorReporter);
+ return evaluateConstructorCall(
+ node,
+ initializer.argumentList.arguments,
+ constructor,
+ initializerVisitor,
+ errorReporter);
}
}
}
@@ -825,10 +846,13 @@
return new DartObjectImpl(definingClass, new GenericState(fieldMap));
}
- void evaluateSuperConstructorCall(AstNode node,
+ void evaluateSuperConstructorCall(
+ AstNode node,
HashMap<String, DartObjectImpl> fieldMap,
- ConstructorElement superConstructor, NodeList<Expression> superArguments,
- ConstantVisitor initializerVisitor, ErrorReporter errorReporter) {
+ ConstructorElement superConstructor,
+ NodeList<Expression> superArguments,
+ ConstantVisitor initializerVisitor,
+ ErrorReporter errorReporter) {
if (superConstructor != null && superConstructor.isConst) {
DartObjectImpl evaluationResult = evaluateConstructorCall(node,
superArguments, superConstructor, initializerVisitor, errorReporter);
@@ -1282,7 +1306,8 @@
DeclaredVariables declaredVariables,
[ConstantEvaluationValidator validator])
: evaluationEngine = new ConstantEvaluationEngine(
- typeProvider, declaredVariables, validator: validator);
+ typeProvider, declaredVariables,
+ validator: validator);
/**
* Add the constants in the given compilation [unit] to the list of constants
@@ -2590,9 +2615,10 @@
* Throws an [EvaluationException] if the operator is not appropriate for an
* object of this kind.
*/
- DartObjectImpl greaterThanOrEqual(TypeProvider typeProvider,
- DartObjectImpl rightOperand) => new DartObjectImpl(
- typeProvider.boolType, _state.greaterThanOrEqual(rightOperand._state));
+ DartObjectImpl greaterThanOrEqual(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(typeProvider.boolType,
+ _state.greaterThanOrEqual(rightOperand._state));
/**
* Return the result of invoking the '~/' operator on this object with the
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 1e5794a..ab8fe91 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -161,20 +161,20 @@
_lookUpMethod(leftHandSide, propagatedType, methodName);
node.propagatedElement = propagatedMethod;
if (_shouldReportMissingMember(staticType, staticMethod)) {
- _recordUndefinedToken(staticType.element,
- StaticTypeWarningCode.UNDEFINED_METHOD, operator, [
- methodName,
- staticType.displayName
- ]);
+ _recordUndefinedToken(
+ staticType.element,
+ StaticTypeWarningCode.UNDEFINED_METHOD,
+ operator,
+ [methodName, staticType.displayName]);
} else if (_enableHints &&
_shouldReportMissingMember(propagatedType, propagatedMethod) &&
!_memberFoundInSubclass(
propagatedType.element, methodName, true, false)) {
- _recordUndefinedToken(propagatedType.element,
- HintCode.UNDEFINED_METHOD, operator, [
- methodName,
- propagatedType.displayName
- ]);
+ _recordUndefinedToken(
+ propagatedType.element,
+ HintCode.UNDEFINED_METHOD,
+ operator,
+ [methodName, propagatedType.displayName]);
}
}
}
@@ -203,6 +203,7 @@
setMetadata(node.element, node);
return null;
}
+
@override
Object visitClassTypeAlias(ClassTypeAlias node) {
setMetadata(node.element, node);
@@ -494,8 +495,13 @@
node.staticElement = setterStaticMethod;
node.propagatedElement = setterPropagatedMethod;
// generate undefined method warning
- _checkForUndefinedIndexOperator(node, target, getterMethodName,
- setterStaticMethod, setterPropagatedMethod, staticType,
+ _checkForUndefinedIndexOperator(
+ node,
+ target,
+ getterMethodName,
+ setterStaticMethod,
+ setterPropagatedMethod,
+ staticType,
propagatedType);
// lookup getter method
MethodElement getterStaticMethod =
@@ -507,8 +513,13 @@
new AuxiliaryElements(getterStaticMethod, getterPropagatedMethod);
node.auxiliaryElements = auxiliaryElements;
// generate undefined method warning
- _checkForUndefinedIndexOperator(node, target, getterMethodName,
- getterStaticMethod, getterPropagatedMethod, staticType,
+ _checkForUndefinedIndexOperator(
+ node,
+ target,
+ getterMethodName,
+ getterStaticMethod,
+ getterPropagatedMethod,
+ staticType,
propagatedType);
} else if (isInGetterContext) {
// lookup getter method
@@ -592,7 +603,8 @@
_isDeferredPrefix(target)) {
if (node.operator.type == sc.TokenType.QUESTION_PERIOD) {
_resolver.reportErrorForNode(
- CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, target,
+ CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+ target,
[(target as SimpleIdentifier).name]);
}
LibraryElement importedLibrary = _getImportedLibrary(target);
@@ -721,10 +733,8 @@
ErrorCode proxyErrorCode = (generatedWithTypePropagation
? HintCode.UNDEFINED_METHOD
: StaticTypeWarningCode.UNDEFINED_METHOD);
- _recordUndefinedNode(targetType.element, proxyErrorCode, methodName, [
- methodName.name,
- targetTypeName
- ]);
+ _recordUndefinedNode(targetType.element, proxyErrorCode, methodName,
+ [methodName.name, targetTypeName]);
}
} else if (identical(
errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD)) {
@@ -766,17 +776,17 @@
node.propagatedElement = propagatedMethod;
if (_shouldReportMissingMember(staticType, staticMethod)) {
if (operand is SuperExpression) {
- _recordUndefinedToken(staticType.element,
- StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR, node.operator, [
- methodName,
- staticType.displayName
- ]);
+ _recordUndefinedToken(
+ staticType.element,
+ StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR,
+ node.operator,
+ [methodName, staticType.displayName]);
} else {
- _recordUndefinedToken(staticType.element,
- StaticTypeWarningCode.UNDEFINED_OPERATOR, node.operator, [
- methodName,
- staticType.displayName
- ]);
+ _recordUndefinedToken(
+ staticType.element,
+ StaticTypeWarningCode.UNDEFINED_OPERATOR,
+ node.operator,
+ [methodName, staticType.displayName]);
}
} else if (_enableHints &&
_shouldReportMissingMember(propagatedType, propagatedMethod) &&
@@ -879,27 +889,27 @@
node.propagatedElement = propagatedMethod;
if (_shouldReportMissingMember(staticType, staticMethod)) {
if (operand is SuperExpression) {
- _recordUndefinedToken(staticType.element,
- StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR, operator, [
- methodName,
- staticType.displayName
- ]);
+ _recordUndefinedToken(
+ staticType.element,
+ StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR,
+ operator,
+ [methodName, staticType.displayName]);
} else {
- _recordUndefinedToken(staticType.element,
- StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [
- methodName,
- staticType.displayName
- ]);
+ _recordUndefinedToken(
+ staticType.element,
+ StaticTypeWarningCode.UNDEFINED_OPERATOR,
+ operator,
+ [methodName, staticType.displayName]);
}
} else if (_enableHints &&
_shouldReportMissingMember(propagatedType, propagatedMethod) &&
!_memberFoundInSubclass(
propagatedType.element, methodName, true, false)) {
- _recordUndefinedToken(propagatedType.element,
- HintCode.UNDEFINED_OPERATOR, operator, [
- methodName,
- propagatedType.displayName
- ]);
+ _recordUndefinedToken(
+ propagatedType.element,
+ HintCode.UNDEFINED_OPERATOR,
+ operator,
+ [methodName, propagatedType.displayName]);
}
}
return null;
@@ -1005,7 +1015,8 @@
CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
} else if (element is PrefixElement) {
_resolver.reportErrorForNode(
- CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, node,
+ CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+ node,
[element.name]);
} else {
_recordUndefinedNode(_resolver.enclosingClass,
@@ -1052,14 +1063,14 @@
!enclosingClass.isSuperConstructorAccessible(element))) {
if (name != null) {
_resolver.reportErrorForNode(
- CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, node, [
- superType.displayName,
- name
- ]);
+ CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER,
+ node,
+ [superType.displayName, name]);
} else {
_resolver.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
- node, [superType.displayName]);
+ node,
+ [superType.displayName]);
}
return null;
} else {
@@ -1197,9 +1208,13 @@
* the target of the expression. The [methodName] is the name of the operator
* associated with the context of using of the given index expression.
*/
- bool _checkForUndefinedIndexOperator(IndexExpression expression,
- Expression target, String methodName, MethodElement staticMethod,
- MethodElement propagatedMethod, DartType staticType,
+ bool _checkForUndefinedIndexOperator(
+ IndexExpression expression,
+ Expression target,
+ String methodName,
+ MethodElement staticMethod,
+ MethodElement propagatedMethod,
+ DartType staticType,
DartType propagatedType) {
bool shouldReportMissingMember_static =
_shouldReportMissingMember(staticType, staticMethod);
@@ -1226,17 +1241,13 @@
DartType type =
shouldReportMissingMember_static ? staticType : propagatedType;
if (leftBracket == null || rightBracket == null) {
- _recordUndefinedNode(type.element, errorCode, expression, [
- methodName,
- type.displayName
- ]);
+ _recordUndefinedNode(type.element, errorCode, expression,
+ [methodName, type.displayName]);
} else {
int offset = leftBracket.offset;
int length = rightBracket.offset - offset + 1;
- _recordUndefinedOffset(type.element, errorCode, offset, length, [
- methodName,
- type.displayName
- ]);
+ _recordUndefinedOffset(type.element, errorCode, offset, length,
+ [methodName, type.displayName]);
}
return true;
}
@@ -1581,8 +1592,10 @@
* been examined, used to prevent infinite recursion and to optimize the
* search.
*/
- PropertyAccessorElement _lookUpGetterInInterfaces(InterfaceType targetType,
- bool includeTargetType, String getterName,
+ PropertyAccessorElement _lookUpGetterInInterfaces(
+ InterfaceType targetType,
+ bool includeTargetType,
+ String getterName,
HashSet<ClassElement> visitedInterfaces) {
// TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the
// specification (titled "Inheritance and Overriding" under "Interfaces")
@@ -1655,8 +1668,10 @@
* interfaces that have been examined, used to prevent infinite recursion and
* to optimize the search.
*/
- ExecutableElement _lookUpGetterOrMethodInInterfaces(InterfaceType targetType,
- bool includeTargetType, String memberName,
+ ExecutableElement _lookUpGetterOrMethodInInterfaces(
+ InterfaceType targetType,
+ bool includeTargetType,
+ String memberName,
HashSet<ClassElement> visitedInterfaces) {
// TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the
// specification (titled "Inheritance and Overriding" under "Interfaces")
@@ -1736,8 +1751,10 @@
* been examined, used to prevent infinite recursion and to optimize the
* search.
*/
- MethodElement _lookUpMethodInInterfaces(InterfaceType targetType,
- bool includeTargetType, String methodName,
+ MethodElement _lookUpMethodInInterfaces(
+ InterfaceType targetType,
+ bool includeTargetType,
+ String methodName,
HashSet<ClassElement> visitedInterfaces) {
// TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the
// specification (titled "Inheritance and Overriding" under "Interfaces")
@@ -1814,8 +1831,10 @@
* been examined, used to prevent infinite recursion and to optimize the
* search.
*/
- PropertyAccessorElement _lookUpSetterInInterfaces(InterfaceType targetType,
- bool includeTargetType, String setterName,
+ PropertyAccessorElement _lookUpSetterInInterfaces(
+ InterfaceType targetType,
+ bool includeTargetType,
+ String setterName,
HashSet<ClassElement> visitedInterfaces) {
// TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the
// specification (titled "Inheritance and Overriding" under "Interfaces")
@@ -2011,8 +2030,8 @@
// Class(args)
if (element1 is ClassElement) {
ClassElement classElement = element1;
- constructor = new InterfaceTypeImpl(classElement).lookUpConstructor(
- null, _definingLibrary);
+ constructor = new InterfaceTypeImpl(classElement)
+ .lookUpConstructor(null, _definingLibrary);
}
}
//
@@ -2040,8 +2059,8 @@
// Class.constructor(args)
if (element1 is ClassElement) {
ClassElement classElement = element1;
- constructor = new InterfaceTypeImpl(classElement).lookUpConstructor(
- nameNode2.name, _definingLibrary);
+ constructor = new InterfaceTypeImpl(classElement)
+ .lookUpConstructor(nameNode2.name, _definingLibrary);
nameNode2.staticElement = constructor;
}
}
@@ -2064,8 +2083,8 @@
return;
}
// prefix.Class.constructor(args)
- constructor = new InterfaceTypeImpl(classElement).lookUpConstructor(
- name3, _definingLibrary);
+ constructor = new InterfaceTypeImpl(classElement)
+ .lookUpConstructor(name3, _definingLibrary);
nameNode3.staticElement = constructor;
}
}
@@ -2188,19 +2207,15 @@
ErrorCode errorCode = (reportError
? CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS
: StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS);
- _resolver.reportErrorForNode(errorCode, argumentList, [
- requiredParameters.length,
- positionalArgumentCount
- ]);
+ _resolver.reportErrorForNode(errorCode, argumentList,
+ [requiredParameters.length, positionalArgumentCount]);
} else if (positionalArgumentCount > unnamedParameterCount &&
noBlankArguments) {
ErrorCode errorCode = (reportError
? CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS
: StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS);
- _resolver.reportErrorForNode(errorCode, argumentList, [
- unnamedParameterCount,
- positionalArgumentCount
- ]);
+ _resolver.reportErrorForNode(errorCode, argumentList,
+ [unnamedParameterCount, positionalArgumentCount]);
}
return resolvedParameters;
}
@@ -2218,27 +2233,27 @@
node.propagatedElement = propagatedMethod;
if (_shouldReportMissingMember(staticType, staticMethod)) {
if (leftOperand is SuperExpression) {
- _recordUndefinedToken(staticType.element,
- StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR, node.operator, [
- methodName,
- staticType.displayName
- ]);
+ _recordUndefinedToken(
+ staticType.element,
+ StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR,
+ node.operator,
+ [methodName, staticType.displayName]);
} else {
- _recordUndefinedToken(staticType.element,
- StaticTypeWarningCode.UNDEFINED_OPERATOR, node.operator, [
- methodName,
- staticType.displayName
- ]);
+ _recordUndefinedToken(
+ staticType.element,
+ StaticTypeWarningCode.UNDEFINED_OPERATOR,
+ node.operator,
+ [methodName, staticType.displayName]);
}
} else if (_enableHints &&
_shouldReportMissingMember(propagatedType, propagatedMethod) &&
!_memberFoundInSubclass(
propagatedType.element, methodName, true, false)) {
- _recordUndefinedToken(propagatedType.element,
- HintCode.UNDEFINED_OPERATOR, node.operator, [
- methodName,
- propagatedType.displayName
- ]);
+ _recordUndefinedToken(
+ propagatedType.element,
+ HintCode.UNDEFINED_OPERATOR,
+ node.operator,
+ [methodName, propagatedType.displayName]);
}
}
}
@@ -2371,7 +2386,8 @@
if (isConditional) {
_resolver.reportErrorForNode(
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
- target, [target.name]);
+ target,
+ [target.name]);
}
//
// Look to see whether the name of the method is really part of a
@@ -2480,7 +2496,8 @@
return;
} else if (classElement.isEnum && propertyName.name == "_name") {
_resolver.reportErrorForNode(
- CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD, propertyName,
+ CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD,
+ propertyName,
[propertyName.name]);
return;
}
@@ -2507,10 +2524,8 @@
} else {
errorCode = HintCode.UNDEFINED_SETTER;
}
- _recordUndefinedNode(declaringElement, errorCode, propertyName, [
- propertyName.name,
- displayType.displayName
- ]);
+ _recordUndefinedNode(declaringElement, errorCode, propertyName,
+ [propertyName.name, displayType.displayName]);
} else if (propertyName.inGetterContext()) {
ErrorCode errorCode;
if (shouldReportMissingMember_static) {
@@ -2530,13 +2545,13 @@
} else {
errorCode = HintCode.UNDEFINED_GETTER;
}
- _recordUndefinedNode(declaringElement, errorCode, propertyName, [
- propertyName.name,
- displayType.displayName
- ]);
+ _recordUndefinedNode(declaringElement, errorCode, propertyName,
+ [propertyName.name, displayType.displayName]);
} else {
- _recordUndefinedNode(declaringElement,
- StaticWarningCode.UNDEFINED_IDENTIFIER, propertyName,
+ _recordUndefinedNode(
+ declaringElement,
+ StaticWarningCode.UNDEFINED_IDENTIFIER,
+ propertyName,
[propertyName.name]);
}
}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 5eccbf7..c0e548c 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -10309,6 +10309,12 @@
* used to visit that structure.
*/
class ResolutionEraser extends GeneralizingAstVisitor<Object> {
+ /**
+ * A flag indicating whether the elements associated with declarations should
+ * be erased.
+ */
+ bool eraseDeclarations = true;
+
@override
Object visitAssignmentExpression(AssignmentExpression node) {
node.staticElement = null;
@@ -10331,13 +10337,17 @@
@override
Object visitCompilationUnit(CompilationUnit node) {
- node.element = null;
+ if (eraseDeclarations) {
+ node.element = null;
+ }
return super.visitCompilationUnit(node);
}
@override
Object visitConstructorDeclaration(ConstructorDeclaration node) {
- node.element = null;
+ if (eraseDeclarations) {
+ node.element = null;
+ }
return super.visitConstructorDeclaration(node);
}
@@ -10355,7 +10365,9 @@
@override
Object visitDirective(Directive node) {
- node.element = null;
+ if (eraseDeclarations) {
+ node.element = null;
+ }
return super.visitDirective(node);
}
@@ -10368,7 +10380,9 @@
@override
Object visitFunctionExpression(FunctionExpression node) {
- node.element = null;
+ if (eraseDeclarations) {
+ node.element = null;
+ }
return super.visitFunctionExpression(node);
}
@@ -10415,7 +10429,9 @@
@override
Object visitSimpleIdentifier(SimpleIdentifier node) {
- node.staticElement = null;
+ if (eraseDeclarations || !node.inDeclarationContext()) {
+ node.staticElement = null;
+ }
node.propagatedElement = null;
return super.visitSimpleIdentifier(node);
}
@@ -10429,8 +10445,10 @@
/**
* Remove any resolution information from the given AST structure.
*/
- static void erase(AstNode node) {
- node.accept(new ResolutionEraser());
+ static void erase(AstNode node, {bool eraseDeclarations: true}) {
+ ResolutionEraser eraser = new ResolutionEraser();
+ eraser.eraseDeclarations = eraseDeclarations;
+ node.accept(eraser);
}
}
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index 93d1ce8..b8ea0bf 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -28,14 +28,15 @@
* was found.
*/
static Comparator<AnalysisError> FILE_COMPARATOR = (AnalysisError o1,
- AnalysisError o2) => o1.source.shortName.compareTo(o2.source.shortName);
+ AnalysisError o2) =>
+ o1.source.shortName.compareTo(o2.source.shortName);
/**
* A [Comparator] that sorts error codes first by their severity (errors
* first, warnings second), and then by the the error code type.
*/
- static Comparator<AnalysisError> ERROR_CODE_COMPARATOR = (AnalysisError o1,
- AnalysisError o2) {
+ static Comparator<AnalysisError> ERROR_CODE_COMPARATOR =
+ (AnalysisError o1, AnalysisError o2) {
ErrorCode errorCode1 = o1.errorCode;
ErrorCode errorCode2 = o2.errorCode;
ErrorSeverity errorSeverity1 = errorCode1.errorSeverity;
@@ -1560,7 +1561,8 @@
* 0: the name of the constant that is missing
*/
static const CompileTimeErrorCode MISSING_ENUM_CONSTANT_IN_SWITCH =
- const CompileTimeErrorCode('MISSING_ENUM_CONSTANT_IN_SWITCH',
+ const CompileTimeErrorCode(
+ 'MISSING_ENUM_CONSTANT_IN_SWITCH',
"Missing case clause for '{0}'",
"Add a case clause for the missing constant or add a default clause.");
@@ -1596,7 +1598,8 @@
* https://code.google.com/p/dart/issues/detail?id=15101#c4
*/
static const CompileTimeErrorCode MIXIN_HAS_NO_CONSTRUCTORS =
- const CompileTimeErrorCode('MIXIN_HAS_NO_CONSTRUCTORS',
+ const CompileTimeErrorCode(
+ 'MIXIN_HAS_NO_CONSTRUCTORS',
"This mixin application is invalid because all of the constructors "
"in the base class '{0}' have optional parameters.");
@@ -2353,6 +2356,62 @@
}
/**
+ * An error listener that can be enabled or disabled while executing a function.
+ */
+class DisablableErrorListener implements AnalysisErrorListener {
+ /**
+ * The listener to which errors will be reported if this listener is enabled.
+ */
+ final AnalysisErrorListener baseListener;
+
+ /**
+ * A flag indicating whether this listener is currently enabled.
+ */
+ bool enabled = true;
+
+ /**
+ * Initialize a newly created listener to report errors to the given
+ * [baseListener].
+ */
+ DisablableErrorListener(this.baseListener);
+
+ /**
+ * Disable the processing of errors while evaluating the given [function].
+ * Return the value returned by the function.
+ */
+ dynamic disableWhile(dynamic function()) {
+ bool wasEnabled = enabled;
+ try {
+ enabled = false;
+ return function();
+ } finally {
+ enabled = wasEnabled;
+ }
+ }
+
+ /**
+ * Disable the processing of errors while evaluating the given [function].
+ * Return the value returned by the function.
+ */
+ dynamic enableWhile(dynamic function()) {
+ bool wasEnabled = enabled;
+ try {
+ enabled = true;
+ return function();
+ } finally {
+ enabled = wasEnabled;
+ }
+ }
+
+ @override
+ void onError(AnalysisError error) {
+ if (enabled) {
+ baseListener.onError(error);
+ }
+ }
+}
+
+/**
* An error code associated with an [AnalysisError].
*
* Generally, we want to provide messages that consist of three sentences. From
@@ -2885,7 +2944,8 @@
* Parameters:
* 0: the name of the declared return type
*/
- static const HintCode MISSING_RETURN = const HintCode('MISSING_RETURN',
+ static const HintCode MISSING_RETURN = const HintCode(
+ 'MISSING_RETURN',
"This function declares a return type of '{0}', but does not end with a return statement",
"Either add a return statement or change the return type to 'void'");
@@ -3728,7 +3788,8 @@
* 2: the name of the second library that the type is found
*/
static const StaticWarningCode AMBIGUOUS_IMPORT = const StaticWarningCode(
- 'AMBIGUOUS_IMPORT', "The name '{0}' is defined in the libraries {1}",
+ 'AMBIGUOUS_IMPORT',
+ "The name '{0}' is defined in the libraries {1}",
"Consider using 'as prefix' for one of the import directives "
"or hiding the name from all but one of the imports.");
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 9624115..4b47c67 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -1125,7 +1125,8 @@
}
// report problem
_errorReporter.reportErrorForNode(
- StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, typeArguments,
+ StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS,
+ typeArguments,
[num]);
return true;
}
@@ -1171,14 +1172,16 @@
if (fieldElement.isFinal || fieldElement.isConst) {
_errorReporter.reportErrorForNode(
StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR,
- formalParameter.identifier, [fieldElement.displayName]);
+ formalParameter.identifier,
+ [fieldElement.displayName]);
foundError = true;
}
} else if (state == INIT_STATE.INIT_IN_FIELD_FORMAL) {
if (fieldElement.isFinal || fieldElement.isConst) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES,
- formalParameter.identifier, [fieldElement.displayName]);
+ formalParameter.identifier,
+ [fieldElement.displayName]);
foundError = true;
}
}
@@ -1215,7 +1218,8 @@
} else if (state == INIT_STATE.INIT_IN_INITIALIZERS) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS,
- fieldName, [fieldElement.displayName]);
+ fieldName,
+ [fieldElement.displayName]);
foundError = true;
}
}
@@ -1237,7 +1241,8 @@
if (fieldElement.isConst) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_NOT_INITIALIZED,
- constructor.returnType, [fieldElement.name]);
+ constructor.returnType,
+ [fieldElement.name]);
foundError = true;
}
}
@@ -1248,14 +1253,13 @@
if (notInitFinalFields.length == 1) {
analysisError = _errorReporter.newErrorWithProperties(
StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1,
- constructor.returnType, [notInitFinalFields[0].name]);
+ constructor.returnType,
+ [notInitFinalFields[0].name]);
} else if (notInitFinalFields.length == 2) {
analysisError = _errorReporter.newErrorWithProperties(
StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2,
- constructor.returnType, [
- notInitFinalFields[0].name,
- notInitFinalFields[1].name
- ]);
+ constructor.returnType,
+ [notInitFinalFields[0].name, notInitFinalFields[1].name]);
} else {
analysisError = _errorReporter.newErrorWithProperties(
StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS,
@@ -1292,8 +1296,10 @@
*/
bool _checkForAllInvalidOverrideErrorCodes(
ExecutableElement executableElement,
- ExecutableElement overriddenExecutable, List<ParameterElement> parameters,
- List<AstNode> parameterLocations, SimpleIdentifier errorNameTarget) {
+ ExecutableElement overriddenExecutable,
+ List<ParameterElement> parameters,
+ List<AstNode> parameterLocations,
+ SimpleIdentifier errorNameTarget) {
bool isGetter = false;
bool isSetter = false;
if (executableElement is PropertyAccessorElement) {
@@ -1355,10 +1361,12 @@
// SWC.INVALID_METHOD_OVERRIDE_RETURN_TYPE
if (overriddenFTReturnType != VoidTypeImpl.instance &&
!overridingFTReturnType.isAssignableTo(overriddenFTReturnType)) {
- _errorReporter.reportTypeErrorForNode(!isGetter
+ _errorReporter.reportTypeErrorForNode(
+ !isGetter
? StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE
: StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE,
- errorNameTarget, [
+ errorNameTarget,
+ [
overridingFTReturnType,
overriddenFTReturnType,
overriddenExecutable.enclosingElement.displayName
@@ -1372,10 +1380,12 @@
int parameterIndex = 0;
for (int i = 0; i < overridingNormalPT.length; i++) {
if (!overridingNormalPT[i].isAssignableTo(overriddenNormalPT[i])) {
- _errorReporter.reportTypeErrorForNode(!isSetter
+ _errorReporter.reportTypeErrorForNode(
+ !isSetter
? StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE
: StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE,
- parameterLocations[parameterIndex], [
+ parameterLocations[parameterIndex],
+ [
overridingNormalPT[i],
overriddenNormalPT[i],
overriddenExecutable.enclosingElement.displayName
@@ -1555,8 +1565,10 @@
* to report problems on.
*/
bool _checkForAllInvalidOverrideErrorCodesForExecutable(
- ExecutableElement executableElement, List<ParameterElement> parameters,
- List<AstNode> parameterLocations, SimpleIdentifier errorNameTarget) {
+ ExecutableElement executableElement,
+ List<ParameterElement> parameters,
+ List<AstNode> parameterLocations,
+ SimpleIdentifier errorNameTarget) {
//
// Compute the overridden executable from the InheritanceManager
//
@@ -1721,10 +1733,8 @@
ErrorCode errorCode = (declaration.constKeyword != null
? CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR
: StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR);
- _errorReporter.reportErrorForNode(errorCode, redirectedConstructor, [
- constructorStrName,
- redirectedType.displayName
- ]);
+ _errorReporter.reportErrorForNode(errorCode, redirectedConstructor,
+ [constructorStrName, redirectedType.displayName]);
return true;
}
return false;
@@ -1739,7 +1749,8 @@
if (!redirectedReturnType.isAssignableTo(constructorReturnType)) {
_errorReporter.reportErrorForNode(
StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE,
- redirectedConstructor, [redirectedReturnType, constructorReturnType]);
+ redirectedConstructor,
+ [redirectedReturnType, constructorReturnType]);
return true;
}
//
@@ -1748,7 +1759,8 @@
if (!redirectedType.isSubtypeOf(constructorType)) {
_errorReporter.reportErrorForNode(
StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE,
- redirectedConstructor, [redirectedType, constructorType]);
+ redirectedConstructor,
+ [redirectedType, constructorType]);
return true;
}
return false;
@@ -1830,8 +1842,8 @@
Element element = definedNames[name];
Element prevElement = _exportedElements[name];
if (element != null && prevElement != null && prevElement != element) {
- _errorReporter.reportErrorForNode(CompileTimeErrorCode.AMBIGUOUS_EXPORT,
- directive, [
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.AMBIGUOUS_EXPORT, directive, [
name,
prevElement.library.definingCompilationUnit.displayName,
element.library.definingCompilationUnit.displayName
@@ -1861,8 +1873,10 @@
* [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
* [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
*/
- bool _checkForArgumentTypeNotAssignable(Expression expression,
- DartType expectedStaticType, DartType actualStaticType,
+ bool _checkForArgumentTypeNotAssignable(
+ Expression expression,
+ DartType expectedStaticType,
+ DartType actualStaticType,
ErrorCode errorCode) {
//
// Warning case: test static type information
@@ -1913,8 +1927,10 @@
* [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
*/
bool _checkForArgumentTypeNotAssignableWithExpectedTypes(
- Expression expression, DartType expectedStaticType,
- ErrorCode errorCode) => _checkForArgumentTypeNotAssignable(
+ Expression expression,
+ DartType expectedStaticType,
+ ErrorCode errorCode) =>
+ _checkForArgumentTypeNotAssignable(
expression, expectedStaticType, getStaticType(expression), errorCode);
/**
@@ -1999,7 +2015,8 @@
element.setter == null &&
element.isSynthetic) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER, highlightedNode,
+ StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER,
+ highlightedNode,
[element.name, element.enclosingElement.displayName]);
return true;
}
@@ -2134,10 +2151,9 @@
}
if (overriddenMember == null) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER, nameNode, [
- memberName,
- _enclosingClass.displayName
- ]);
+ StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER,
+ nameNode,
+ [memberName, _enclosingClass.displayName]);
return true;
}
}
@@ -2172,7 +2188,8 @@
CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, constructor);
} else {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME, constructor,
+ CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME,
+ constructor,
[name]);
}
return true;
@@ -2187,7 +2204,8 @@
if (field != null) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD,
- constructor, [name]);
+ constructor,
+ [name]);
return true;
}
// methods
@@ -2195,7 +2213,8 @@
if (method != null) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD,
- constructor, [name]);
+ constructor,
+ [name]);
return true;
}
}
@@ -2226,7 +2245,8 @@
// report problem
hasProblem = true;
_errorReporter.reportErrorForOffset(
- CompileTimeErrorCode.CONFLICTING_GETTER_AND_METHOD, method.nameOffset,
+ CompileTimeErrorCode.CONFLICTING_GETTER_AND_METHOD,
+ method.nameOffset,
name.length, [
_enclosingClass.displayName,
inherited.enclosingElement.displayName,
@@ -2249,7 +2269,8 @@
hasProblem = true;
_errorReporter.reportErrorForOffset(
CompileTimeErrorCode.CONFLICTING_METHOD_AND_GETTER,
- accessor.nameOffset, name.length, [
+ accessor.nameOffset,
+ name.length, [
_enclosingClass.displayName,
inherited.enclosingElement.displayName,
name
@@ -2315,11 +2336,13 @@
if (getter) {
_errorReporter.reportErrorForElement(
StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER,
- accessor, [superElementType.displayName]);
+ accessor,
+ [superElementType.displayName]);
} else {
_errorReporter.reportErrorForElement(
StaticWarningCode.CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER,
- accessor, [superElementType.displayName]);
+ accessor,
+ [superElementType.displayName]);
}
}
// done
@@ -2401,10 +2424,9 @@
!conflictingMethod.isGetter) {
// report problem
_errorReporter.reportErrorForNode(
- StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER2, name, [
- _enclosingClass.displayName,
- name.name
- ]);
+ StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER2,
+ name,
+ [_enclosingClass.displayName, name.name]);
foundError = true;
addThisMemberToTheMap = false;
}
@@ -2460,7 +2482,8 @@
// report problem
_errorReporter.reportErrorForNode(
StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER,
- nameNode, [setterType.displayName]);
+ nameNode,
+ [setterType.displayName]);
return true;
}
@@ -2508,7 +2531,8 @@
// report problem
_errorReporter.reportErrorForNode(
StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER,
- nameNode, [memberType.displayName]);
+ nameNode,
+ [memberType.displayName]);
return true;
}
@@ -2528,7 +2552,9 @@
if (_enclosingClass.name == name) {
_errorReporter.reportErrorForOffset(
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS,
- typeParameter.nameOffset, name.length, [name]);
+ typeParameter.nameOffset,
+ name.length,
+ [name]);
problemReported = true;
}
// check members
@@ -2537,7 +2563,9 @@
_enclosingClass.getSetter(name) != null) {
_errorReporter.reportErrorForOffset(
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
- typeParameter.nameOffset, name.length, [name]);
+ typeParameter.nameOffset,
+ name.length,
+ [name]);
problemReported = true;
}
}
@@ -2576,7 +2604,8 @@
}
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
- superInvocation, [element.enclosingElement.displayName]);
+ superInvocation,
+ [element.enclosingElement.displayName]);
return true;
}
}
@@ -2599,7 +2628,8 @@
// default constructor is not 'const', report problem
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
- constructor.returnType, [supertype.displayName]);
+ constructor.returnType,
+ [supertype.displayName]);
return true;
}
@@ -2640,7 +2670,8 @@
ConstructorName constructorName, TypeName typeName) {
if (typeName.isDeferred) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_DEFERRED_CLASS, constructorName,
+ CompileTimeErrorCode.CONST_DEFERRED_CLASS,
+ constructorName,
[typeName.name.name]);
return true;
}
@@ -2687,7 +2718,8 @@
* [StaticWarningCode.NEW_WITH_ABSTRACT_CLASS].
*/
bool _checkForConstOrNewWithAbstractClass(
- InstanceCreationExpression expression, TypeName typeName,
+ InstanceCreationExpression expression,
+ TypeName typeName,
InterfaceType type) {
if (type.element.isAbstract) {
ConstructorElement element = expression.staticElement;
@@ -2791,7 +2823,8 @@
* [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT].
*/
bool _checkForConstWithUndefinedConstructor(
- InstanceCreationExpression expression, ConstructorName constructorName,
+ InstanceCreationExpression expression,
+ ConstructorName constructorName,
TypeName typeName) {
// OK if resolved
if (expression.staticElement != null) {
@@ -2810,14 +2843,14 @@
SimpleIdentifier name = constructorName.name;
if (name != null) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR, name, [
- className,
- name
- ]);
+ CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR,
+ name,
+ [className, name]);
} else {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT,
- constructorName, [className]);
+ constructorName,
+ [className]);
}
return true;
}
@@ -2968,7 +3001,9 @@
// report problem
_errorReporter.reportErrorForOffset(
CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE,
- staticMember.nameOffset, name.length, [name, displayName]);
+ staticMember.nameOffset,
+ name.length,
+ [name, displayName]);
return true;
}
@@ -2987,7 +3022,8 @@
}
// report problem
_errorReporter.reportErrorForNode(
- StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, typeArguments,
+ StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS,
+ typeArguments,
[num]);
return true;
}
@@ -3053,7 +3089,8 @@
}
// report problem
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, directive,
+ CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY,
+ directive,
[directive.uri]);
return true;
}
@@ -3222,13 +3259,13 @@
// constant, not the static type. See dartbug.com/21119.
_errorReporter.reportTypeErrorForNode(
CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
- expression, [staticType, fieldType]);
+ expression,
+ [staticType, fieldType]);
}
_errorReporter.reportTypeErrorForNode(
- StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, expression, [
- staticType,
- fieldType
- ]);
+ StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE,
+ expression,
+ [staticType, fieldType]);
return true;
// TODO(brianwilkerson) Define a hint corresponding to these errors and
// report it if appropriate.
@@ -3308,11 +3345,13 @@
if (variable.initializer == null) {
if (list.isConst) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_NOT_INITIALIZED, variable.name,
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED,
+ variable.name,
[variable.name.name]);
} else if (list.isFinal) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.FINAL_NOT_INITIALIZED, variable.name,
+ StaticWarningCode.FINAL_NOT_INITIALIZED,
+ variable.name,
[variable.name.name]);
}
foundError = true;
@@ -3560,7 +3599,8 @@
}
// report problem
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY, directive,
+ CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY,
+ directive,
[directive.uri]);
return true;
}
@@ -3619,7 +3659,8 @@
}
// report problem
_errorReporter.reportErrorForNode(
- StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, name,
+ StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
+ name,
[name.name]);
return true;
}
@@ -3660,10 +3701,8 @@
if (fieldElt.isStatic) {
_errorReporter.reportErrorForNode(
StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC,
- errorNameTarget, [
- executableElementName,
- fieldElt.enclosingElement.displayName
- ]);
+ errorNameTarget,
+ [executableElementName, fieldElt.enclosingElement.displayName]);
return true;
}
}
@@ -3751,10 +3790,9 @@
DartType staticRightType = getStaticType(rhs);
if (!staticRightType.isAssignableTo(leftType)) {
_errorReporter.reportTypeErrorForNode(
- StaticTypeWarningCode.INVALID_ASSIGNMENT, rhs, [
- staticRightType,
- leftType
- ]);
+ StaticTypeWarningCode.INVALID_ASSIGNMENT,
+ rhs,
+ [staticRightType, leftType]);
return true;
}
return false;
@@ -3805,15 +3843,18 @@
if (fieldElement.isSynthetic) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD,
- initializer, [fieldName]);
+ initializer,
+ [fieldName]);
} else if (fieldElement.isStatic) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD, initializer,
+ CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD,
+ initializer,
[fieldName]);
}
} else {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD, initializer,
+ CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD,
+ initializer,
[fieldName]);
return;
}
@@ -3885,13 +3926,15 @@
if (literal.constKeyword != null) {
// TODO(paulberry): this error should be based on the actual type of the
// list element, not the static type. See dartbug.com/21119.
- if (_checkForArgumentTypeNotAssignableWithExpectedTypes(element,
+ if (_checkForArgumentTypeNotAssignableWithExpectedTypes(
+ element,
listElementType,
CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE)) {
hasProblems = true;
}
}
- if (_checkForArgumentTypeNotAssignableWithExpectedTypes(element,
+ if (_checkForArgumentTypeNotAssignableWithExpectedTypes(
+ element,
listElementType,
StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE)) {
hasProblems = true;
@@ -3932,7 +3975,8 @@
CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE)) {
hasProblems = true;
}
- if (_checkForArgumentTypeNotAssignableWithExpectedTypes(value,
+ if (_checkForArgumentTypeNotAssignableWithExpectedTypes(
+ value,
valueType,
CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE)) {
hasProblems = true;
@@ -3969,7 +4013,8 @@
for (PropertyAccessorElement accessor in _enclosingClass.accessors) {
if (className == accessor.name) {
_errorReporter.reportErrorForOffset(
- CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, accessor.nameOffset,
+ CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME,
+ accessor.nameOffset,
className.length);
problemReported = true;
}
@@ -4055,7 +4100,8 @@
if (enclosingClassForCounterpart == null) {
_errorReporter.reportTypeErrorForNode(
StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
- accessorDeclaration, [accessorTextName, setterType, getterType]);
+ accessorDeclaration,
+ [accessorTextName, setterType, getterType]);
return true;
} else {
_errorReporter.reportTypeErrorForNode(
@@ -4121,8 +4167,10 @@
int offset = statement.offset;
int end = statement.rightParenthesis.end;
_errorReporter.reportErrorForOffset(
- CompileTimeErrorCode.MISSING_ENUM_CONSTANT_IN_SWITCH, offset,
- end - offset, [constantNames[i]]);
+ CompileTimeErrorCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
+ offset,
+ end - offset,
+ [constantNames[i]]);
}
return true;
}
@@ -4165,7 +4213,8 @@
for (ConstructorElement constructor in mixinElement.constructors) {
if (!constructor.isSynthetic && !constructor.isFactory) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR, mixinName,
+ CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR,
+ mixinName,
[mixinElement.name]);
return true;
}
@@ -4199,7 +4248,8 @@
if (!mixinSupertype.isObject ||
!mixinElement.isMixinApplication && mixinElement.mixins.length != 0) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, mixinName,
+ CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT,
+ mixinName,
[mixinElement.name]);
return true;
}
@@ -4218,7 +4268,8 @@
TypeName mixinName, ClassElement mixinElement) {
if (!enableSuperMixins && mixinElement.hasReferenceToSuper) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.MIXIN_REFERENCES_SUPER, mixinName,
+ CompileTimeErrorCode.MIXIN_REFERENCES_SUPER,
+ mixinName,
[mixinElement.name]);
}
return false;
@@ -4268,7 +4319,8 @@
* See [StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR].
*/
bool _checkForNewWithUndefinedConstructor(
- InstanceCreationExpression expression, ConstructorName constructorName,
+ InstanceCreationExpression expression,
+ ConstructorName constructorName,
TypeName typeName) {
// OK if resolved
if (expression.staticElement != null) {
@@ -4288,14 +4340,14 @@
SimpleIdentifier name = constructorName.name;
if (name != null) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR, name, [
- className,
- name
- ]);
+ StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR,
+ name,
+ [className, name]);
} else {
_errorReporter.reportErrorForNode(
StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT,
- constructorName, [className]);
+ constructorName,
+ [className]);
}
return true;
}
@@ -4331,7 +4383,8 @@
if (superUnnamedConstructor != null) {
if (superUnnamedConstructor.isFactory) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, declaration.name,
+ CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
+ declaration.name,
[superUnnamedConstructor]);
return true;
}
@@ -4344,7 +4397,8 @@
// report problem
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT,
- declaration.name, [superType.displayName]);
+ declaration.name,
+ [superType.displayName]);
return true;
}
@@ -4486,11 +4540,13 @@
if (stringMembersArray.length == 1) {
analysisError = _errorReporter.newErrorWithProperties(
StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE,
- classNameNode, [stringMembersArray[0]]);
+ classNameNode,
+ [stringMembersArray[0]]);
} else if (stringMembersArray.length == 2) {
analysisError = _errorReporter.newErrorWithProperties(
StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO,
- classNameNode, [stringMembersArray[0], stringMembersArray[1]]);
+ classNameNode,
+ [stringMembersArray[0], stringMembersArray[1]]);
} else if (stringMembersArray.length == 3) {
analysisError = _errorReporter.newErrorWithProperties(
StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE,
@@ -4826,7 +4882,8 @@
}
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR,
- invocation, [constructorStrName, enclosingTypeName]);
+ invocation,
+ [constructorStrName, enclosingTypeName]);
} else {
if (redirectingElement.isFactory) {
_errorReporter.reportErrorForNode(
@@ -4974,11 +5031,9 @@
return false;
}
_errorReporter.reportTypeErrorForNode(
- StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [
- staticReturnType,
- expectedReturnType,
- _enclosingFunction.displayName
- ]);
+ StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
+ returnExpression,
+ [staticReturnType, expectedReturnType, _enclosingFunction.displayName]);
return true;
// TODO(brianwilkerson) Define a hint corresponding to the warning and
// report it if appropriate.
@@ -5053,10 +5108,9 @@
}
// report problem
_errorReporter.reportErrorForNode(
- StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE, expression, [
- expressionType,
- caseType
- ]);
+ StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE,
+ expression,
+ [expressionType, caseType]);
return true;
}
return false;
@@ -5183,7 +5237,8 @@
}
// report problem
_errorReporter.reportErrorForNode(
- StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND, parameter,
+ StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
+ parameter,
[element.displayName]);
return true;
}
@@ -5239,7 +5294,8 @@
if (superUnnamedConstructor.isFactory) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
- constructor.returnType, [superUnnamedConstructor]);
+ constructor.returnType,
+ [superUnnamedConstructor]);
return true;
}
if (!superUnnamedConstructor.isDefaultConstructor ||
@@ -5254,14 +5310,17 @@
length = (name != null ? name.end : returnType.end) - offset;
}
_errorReporter.reportErrorForOffset(
- CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT, offset,
- length, [superType.displayName]);
+ CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT,
+ offset,
+ length,
+ [superType.displayName]);
}
return false;
}
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
- constructor.returnType, [superElement.name]);
+ constructor.returnType,
+ [superElement.name]);
return true;
}
@@ -5290,7 +5349,8 @@
}
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
- name, [name.name]);
+ name,
+ [name.name]);
return true;
}
@@ -5301,7 +5361,8 @@
if (fieldElement == null || fieldElement.isSynthetic) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD,
- parameter, [parameter.identifier.name]);
+ parameter,
+ [parameter.identifier.name]);
} else {
ParameterElement parameterElement = parameter.element;
if (parameterElement is FieldFormalParameterElementImpl) {
@@ -5311,27 +5372,32 @@
if (fieldElement.isSynthetic) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD,
- parameter, [parameter.identifier.name]);
+ parameter,
+ [parameter.identifier.name]);
} else if (fieldElement.isStatic) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD,
- parameter, [parameter.identifier.name]);
+ parameter,
+ [parameter.identifier.name]);
} else if (declaredType != null &&
fieldType != null &&
!declaredType.isAssignableTo(fieldType)) {
_errorReporter.reportTypeErrorForNode(
StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE,
- parameter, [declaredType, fieldType]);
+ parameter,
+ [declaredType, fieldType]);
}
} else {
if (fieldElement.isSynthetic) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD,
- parameter, [parameter.identifier.name]);
+ parameter,
+ [parameter.identifier.name]);
} else if (fieldElement.isStatic) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD,
- parameter, [parameter.identifier.name]);
+ parameter,
+ [parameter.identifier.name]);
}
}
}
@@ -5407,14 +5473,16 @@
if (expected != -1 && numParameters != expected) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR,
- nameNode, [name, expected, numParameters]);
+ nameNode,
+ [name, expected, numParameters]);
return true;
}
// check for operator "-"
if ("-" == name && numParameters > 1) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
- nameNode, [numParameters]);
+ nameNode,
+ [numParameters]);
return true;
}
// OK
@@ -5476,10 +5544,9 @@
}
if (!impliedReturnType.isAssignableTo(declaredReturnType)) {
_errorReporter.reportTypeErrorForNode(
- StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, yieldExpression, [
- impliedReturnType,
- declaredReturnType
- ]);
+ StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
+ yieldExpression,
+ [impliedReturnType, declaredReturnType]);
return true;
}
if (isYieldEach) {
@@ -5494,10 +5561,9 @@
}
if (!impliedReturnType.isAssignableTo(requiredReturnType)) {
_errorReporter.reportTypeErrorForNode(
- StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, yieldExpression, [
- impliedReturnType,
- requiredReturnType
- ]);
+ StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
+ yieldExpression,
+ [impliedReturnType, requiredReturnType]);
return true;
}
}
@@ -5562,7 +5628,8 @@
if (interfaceNode.type == superType) {
hasProblem = true;
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, interfaceNode,
+ CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS,
+ interfaceNode,
[superType.displayName]);
}
}
@@ -5883,17 +5950,18 @@
buffer.write(element.displayName);
_errorReporter.reportErrorForOffset(
CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE,
- _enclosingClass.nameOffset, enclosingClassName.length, [
- enclosingClassName,
- buffer.toString()
- ]);
+ _enclosingClass.nameOffset,
+ enclosingClassName.length,
+ [enclosingClassName, buffer.toString()]);
return true;
} else {
// RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS or
// RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS or
// RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_WITH
- _errorReporter.reportErrorForOffset(_getBaseCaseErrorCode(element),
- _enclosingClass.nameOffset, enclosingClassName.length,
+ _errorReporter.reportErrorForOffset(
+ _getBaseCaseErrorCode(element),
+ _enclosingClass.nameOffset,
+ enclosingClassName.length,
[enclosingClassName]);
return true;
}
diff --git a/pkg/analyzer/lib/src/generated/html.dart b/pkg/analyzer/lib/src/generated/html.dart
index a72a1c8..c0012c5 100644
--- a/pkg/analyzer/lib/src/generated/html.dart
+++ b/pkg/analyzer/lib/src/generated/html.dart
@@ -401,9 +401,14 @@
new XmlAttributeNode(name, equals, value);
@override
- XmlTagNode createTagNode(Token nodeStart, Token tag,
- List<XmlAttributeNode> attributes, Token attributeEnd,
- List<XmlTagNode> tagNodes, Token contentEnd, Token closingTag,
+ XmlTagNode createTagNode(
+ Token nodeStart,
+ Token tag,
+ List<XmlAttributeNode> attributes,
+ Token attributeEnd,
+ List<XmlTagNode> tagNodes,
+ Token contentEnd,
+ Token closingTag,
Token nodeEnd) {
if (_isScriptNode(tag, attributes, tagNodes)) {
HtmlScriptTagNode tagNode = new HtmlScriptTagNode(nodeStart, tag,
@@ -529,12 +534,17 @@
* @param closingTag the name of the tag that occurs in the closing tag
* @param nodeEnd the last token in the tag
*/
- HtmlScriptTagNode(Token nodeStart, Token tag,
- List<XmlAttributeNode> attributes, Token attributeEnd,
- List<XmlTagNode> tagNodes, Token contentEnd, Token closingTag,
+ HtmlScriptTagNode(
+ Token nodeStart,
+ Token tag,
+ List<XmlAttributeNode> attributes,
+ Token attributeEnd,
+ List<XmlTagNode> tagNodes,
+ Token contentEnd,
+ Token closingTag,
Token nodeEnd)
: super(nodeStart, tag, attributes, attributeEnd, tagNodes, contentEnd,
- closingTag, nodeEnd);
+ closingTag, nodeEnd);
/**
* Return the AST structure representing the Dart code within this tag, or `null` if this
@@ -1421,11 +1431,17 @@
* @param nodeEnd the last token in the tag
* @return the node that was created
*/
- XmlTagNode createTagNode(Token nodeStart, Token tag,
- List<XmlAttributeNode> attributes, Token attributeEnd,
- List<XmlTagNode> tagNodes, Token contentEnd, Token closingTag,
- Token nodeEnd) => new XmlTagNode(nodeStart, tag, attributes, attributeEnd,
- tagNodes, contentEnd, closingTag, nodeEnd);
+ XmlTagNode createTagNode(
+ Token nodeStart,
+ Token tag,
+ List<XmlAttributeNode> attributes,
+ Token attributeEnd,
+ List<XmlTagNode> tagNodes,
+ Token contentEnd,
+ Token closingTag,
+ Token nodeEnd) =>
+ new XmlTagNode(nodeStart, tag, attributes, attributeEnd, tagNodes,
+ contentEnd, closingTag, nodeEnd);
/**
* Answer `true` if the specified tag is self closing and thus should never have content or
@@ -1736,9 +1752,15 @@
* @param nodeEnd the ending [TokenType.GT] or [TokenType.SLASH_GT] token (not
* `null`)
*/
- XmlTagNode(this.nodeStart, this._tag, List<XmlAttributeNode> attributes,
- this.attributeEnd, List<XmlTagNode> tagNodes, this.contentEnd,
- this.closingTag, this.nodeEnd) {
+ XmlTagNode(
+ this.nodeStart,
+ this._tag,
+ List<XmlAttributeNode> attributes,
+ this.attributeEnd,
+ List<XmlTagNode> tagNodes,
+ this.contentEnd,
+ this.closingTag,
+ this.nodeEnd) {
this._attributes = becomeParentOfAll(attributes, ifEmpty: NO_ATTRIBUTES);
this._tagNodes = becomeParentOfAll(tagNodes, ifEmpty: NO_TAG_NODES);
}
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 5feaaa9..0341d59 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -8,30 +8,26 @@
import 'dart:math' as math;
import 'package:analyzer/src/context/cache.dart'
- show CacheEntry, TargetedResult;
+ show CacheEntry, Delta, DeltaResult, TargetedResult;
import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/task/dart.dart'
- show
- HINTS,
- INFER_STATIC_VARIABLE_TYPES_ERRORS,
- LIBRARY_UNIT_ERRORS,
- PARSE_ERRORS,
- PARTIALLY_RESOLVE_REFERENCES_ERRORS,
- RESOLVE_FUNCTION_BODIES_ERRORS,
- RESOLVE_TYPE_NAMES_ERRORS,
- SCAN_ERRORS,
- USED_IMPORTED_ELEMENTS,
- USED_LOCAL_ELEMENTS,
- VARIABLE_REFERENCE_ERRORS,
- VERIFY_ERRORS;
-import 'package:analyzer/task/dart.dart'
- show DART_ERRORS, LibrarySpecificUnit, PARSED_UNIT, TOKEN_STREAM;
+import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/general.dart' show CONTENT, LINE_INFO;
-import 'package:analyzer/task/model.dart' show ResultDescriptor, TargetedResult;
+import 'package:analyzer/task/model.dart'
+ show AnalysisTarget, ResultDescriptor, TargetedResult, TaskDescriptor;
import 'ast.dart';
import 'element.dart';
-import 'engine.dart';
+import 'engine.dart'
+ show
+ AnalysisContext,
+ AnalysisOptions,
+ CacheState,
+ DartEntry,
+ DataDescriptor,
+ InternalAnalysisContext,
+ RecordingErrorListener,
+ SourceEntry;
import 'error.dart';
import 'error_verifier.dart';
import 'incremental_logger.dart' show logger, LoggingTimer;
@@ -830,6 +826,74 @@
}
/**
+ * The [Delta] implementation used by incremental resolver.
+ * It keeps Dart results that are either don't change or are updated.
+ */
+class IncrementalBodyDelta extends Delta {
+ /**
+ * The offset of the changed contents.
+ */
+ final int updateOffset;
+
+ /**
+ * The end of the changed contents in the old unit.
+ */
+ final int updateEndOld;
+
+ /**
+ * The end of the changed contents in the new unit.
+ */
+ final int updateEndNew;
+
+ /**
+ * The delta between [updateEndNew] and [updateEndOld].
+ */
+ final int updateDelta;
+
+ IncrementalBodyDelta(Source source, this.updateOffset, this.updateEndOld,
+ this.updateEndNew, this.updateDelta)
+ : super(source);
+
+ @override
+ DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
+ ResultDescriptor descriptor) {
+ // don't invalidate results of standard Dart tasks
+ bool isByTask(TaskDescriptor taskDescriptor) {
+ return taskDescriptor.results.contains(descriptor);
+ }
+ if (descriptor == CONTENT) {
+ return DeltaResult.KEEP_CONTINUE;
+ }
+ if (isByTask(BuildCompilationUnitElementTask.DESCRIPTOR) ||
+ isByTask(BuildDirectiveElementsTask.DESCRIPTOR) ||
+ isByTask(BuildEnumMemberElementsTask.DESCRIPTOR) ||
+ isByTask(BuildExportNamespaceTask.DESCRIPTOR) ||
+ isByTask(BuildLibraryElementTask.DESCRIPTOR) ||
+ isByTask(BuildPublicNamespaceTask.DESCRIPTOR) ||
+ isByTask(BuildSourceExportClosureTask.DESCRIPTOR) ||
+ isByTask(BuildSourceImportExportClosureTask.DESCRIPTOR) ||
+ isByTask(ComputeConstantDependenciesTask.DESCRIPTOR) ||
+ isByTask(ComputeConstantValueTask.DESCRIPTOR) ||
+ isByTask(EvaluateUnitConstantsTask.DESCRIPTOR) ||
+ isByTask(InferInstanceMembersInUnitTask.DESCRIPTOR) ||
+ isByTask(InferStaticVariableTypesInUnitTask.DESCRIPTOR) ||
+ isByTask(ParseDartTask.DESCRIPTOR) ||
+ isByTask(PartiallyResolveUnitReferencesTask.DESCRIPTOR) ||
+ isByTask(ScanDartTask.DESCRIPTOR) ||
+ isByTask(ResolveFunctionBodiesInUnitTask.DESCRIPTOR) ||
+ isByTask(ResolveLibraryReferencesTask.DESCRIPTOR) ||
+ isByTask(ResolveLibraryTypeNamesTask.DESCRIPTOR) ||
+ isByTask(ResolveUnitTypeNamesTask.DESCRIPTOR) ||
+ isByTask(ResolveVariableReferencesTask.DESCRIPTOR) ||
+ isByTask(VerifyUnitTask.DESCRIPTOR)) {
+ return DeltaResult.KEEP_CONTINUE;
+ }
+ // invalidate all the other results
+ return DeltaResult.INVALIDATE;
+ }
+}
+
+/**
* Instances of the class [IncrementalResolver] resolve the smallest portion of
* an AST structure that we currently know how to resolve.
*/
@@ -894,8 +958,16 @@
*/
final int _updateEndNew;
+ /**
+ * The delta between [_updateEndNew] and [_updateEndOld].
+ */
int _updateDelta;
+ /**
+ * The set of [AnalysisError]s that have been already shifted.
+ */
+ Set<AnalysisError> _alreadyShiftedErrors = new HashSet.identity();
+
RecordingErrorListener errorListener = new RecordingErrorListener();
ResolutionContext _resolutionContext;
@@ -935,6 +1007,7 @@
AstNode rootNode = _findResolutionRoot(node);
_prepareResolutionContext(rootNode);
// update elements
+ _updateCache();
_updateElementNameOffsets();
_buildElements(rootNode);
if (!_canBeIncrementallyResolved(rootNode)) {
@@ -1146,9 +1219,11 @@
void _shiftErrors(List<AnalysisError> errors) {
for (AnalysisError error in errors) {
- int errorOffset = error.offset;
- if (errorOffset > _updateOffset) {
- error.offset += _updateDelta;
+ if (_alreadyShiftedErrors.add(error)) {
+ int errorOffset = error.offset;
+ if (errorOffset > _updateOffset) {
+ error.offset += _updateDelta;
+ }
}
}
}
@@ -1164,6 +1239,14 @@
_shiftErrors(errors);
}
+ void _updateCache() {
+ if (newSourceEntry != null) {
+ newSourceEntry.setState(CONTENT, CacheState.INVALID,
+ delta: new IncrementalBodyDelta(_source, _updateOffset, _updateEndOld,
+ _updateEndNew, _updateDelta));
+ }
+ }
+
void _updateElementNameOffsets() {
LoggingTimer timer = logger.startTimer();
try {
@@ -1367,6 +1450,7 @@
_updateOffset,
_updateEndOld,
_updateEndNew);
+ incrementalResolver._updateCache();
incrementalResolver._updateElementNameOffsets();
incrementalResolver._shiftEntryErrors();
}
@@ -1534,6 +1618,7 @@
_updateOffset,
_updateEndOld,
_updateEndNew);
+ incrementalResolver._updateCache();
incrementalResolver._updateElementNameOffsets();
incrementalResolver._shiftEntryErrors();
_updateEntry();
@@ -1602,12 +1687,12 @@
void _updateEntry_NEW() {
_newSourceEntry.setState(DART_ERRORS, CacheState.INVALID);
// scan results
- _newSourceEntry.setState(SCAN_ERRORS, CacheState.INVALID);
List<TargetedResult> scanDeps = <TargetedResult>[
new TargetedResult(_unitSource, CONTENT)
];
- _newSourceEntry.setValue(LINE_INFO, _newLineInfo, scanDeps);
+ _newSourceEntry.setState(SCAN_ERRORS, CacheState.INVALID);
_newSourceEntry.setValue(SCAN_ERRORS, _newScanErrors, scanDeps);
+ _newSourceEntry.setValue(LINE_INFO, _newLineInfo, scanDeps);
// parse results
List<TargetedResult> parseDeps = <TargetedResult>[
new TargetedResult(_unitSource, TOKEN_STREAM)
diff --git a/pkg/analyzer/lib/src/generated/java_core.dart b/pkg/analyzer/lib/src/generated/java_core.dart
index 9a0185a..8c96357 100644
--- a/pkg/analyzer/lib/src/generated/java_core.dart
+++ b/pkg/analyzer/lib/src/generated/java_core.dart
@@ -141,24 +141,31 @@
}
return -1;
}
+
static bool isDigit(int c) {
return c >= 0x30 && c <= 0x39;
}
+
static bool isLetter(int c) {
return c >= 0x41 && c <= 0x5A || c >= 0x61 && c <= 0x7A;
}
+
static bool isLetterOrDigit(int c) {
return isLetter(c) || isDigit(c);
}
+
static bool isLowerCase(int c) {
return c >= 0x61 && c <= 0x7A;
}
+
static bool isUpperCase(int c) {
return c >= 0x41 && c <= 0x5A;
}
+
static bool isWhitespace(int c) {
return c == 0x09 || c == 0x20 || c == 0x0A || c == 0x0D;
}
+
static String toChars(int codePoint) {
if (codePoint < 0 || codePoint > MAX_CODE_POINT) {
throw new IllegalArgumentException();
@@ -171,12 +178,14 @@
int c1 = (offset & 0x3ff) + MIN_LOW_SURROGATE;
return new String.fromCharCodes([c0, c1]);
}
+
static int toLowerCase(int c) {
if (c >= 0x41 && c <= 0x5A) {
return 0x61 + (c - 0x41);
}
return c;
}
+
static int toUpperCase(int c) {
if (c >= 0x61 && c <= 0x7A) {
return 0x41 + (c - 0x61);
@@ -188,6 +197,7 @@
abstract class Enum<E extends Enum> implements Comparable<E> {
/// The name of this enum constant, as declared in the enum declaration.
final String name;
+
/// The position in the enum declaration.
final int ordinal;
const Enum(this.name, this.ordinal);
@@ -221,6 +231,7 @@
}
return true;
}
+
static int makeHashCode(List a) {
if (a == null) {
return 0;
@@ -259,6 +270,7 @@
_match = _matches.current;
return true;
}
+
String group(int i) => _match[i];
bool matches() => find();
int start() => _match.start;
@@ -270,11 +282,13 @@
if (fromIndex < 0) fromIndex = 0;
return target.indexOf(str, fromIndex);
}
+
static int lastIndexOf(String target, String str, int fromIndex) {
if (fromIndex > target.length) return -1;
if (fromIndex < 0) fromIndex = 0;
return target.lastIndexOf(str, fromIndex);
}
+
static bool startsWithBefore(String s, String other, int start) {
return s.indexOf(other, start) != -1;
}
diff --git a/pkg/analyzer/lib/src/generated/java_engine.dart b/pkg/analyzer/lib/src/generated/java_engine.dart
index 98ff8e4..d0fb62b 100644
--- a/pkg/analyzer/lib/src/generated/java_engine.dart
+++ b/pkg/analyzer/lib/src/generated/java_engine.dart
@@ -128,10 +128,12 @@
str.codeUnitAt(length - 2) == c2 &&
str.codeUnitAt(length - 1) == c3;
}
+
static endsWithChar(String str, int c) {
int length = str.length;
return length > 0 && str.codeUnitAt(length - 1) == c;
}
+
static int indexOf1(String str, int start, int c) {
int index = start;
int last = str.length;
@@ -143,6 +145,7 @@
}
return -1;
}
+
static int indexOf2(String str, int start, int c1, int c2) {
int index = start;
int last = str.length - 1;
@@ -154,6 +157,7 @@
}
return -1;
}
+
static int indexOf4(
String string, int start, int c1, int c2, int c3, int c4) {
int index = start;
@@ -169,6 +173,7 @@
}
return -1;
}
+
static int indexOf5(
String str, int start, int c1, int c2, int c3, int c4, int c5) {
int index = start;
@@ -203,10 +208,12 @@
}
return last;
}
+
static String intern(String string) => INTERNER.intern(string);
static bool isEmpty(String s) {
return s == null || s.isEmpty;
}
+
static bool isTagName(String s) {
if (s == null || s.length == 0) {
return false;
@@ -225,6 +232,7 @@
}
return true;
}
+
/**
* Produce a string containing all of the names in the given array, surrounded by single quotes,
* and separated by commas. The list must contain at least two elements.
@@ -255,17 +263,20 @@
buffer.write("'");
return buffer.toString();
}
+
static startsWith2(String str, int start, int c1, int c2) {
return str.length - start >= 2 &&
str.codeUnitAt(start) == c1 &&
str.codeUnitAt(start + 1) == c2;
}
+
static startsWith3(String str, int start, int c1, int c2, int c3) {
return str.length - start >= 3 &&
str.codeUnitAt(start) == c1 &&
str.codeUnitAt(start + 1) == c2 &&
str.codeUnitAt(start + 2) == c3;
}
+
static startsWith4(String str, int start, int c1, int c2, int c3, int c4) {
return str.length - start >= 4 &&
str.codeUnitAt(start) == c1 &&
@@ -273,6 +284,7 @@
str.codeUnitAt(start + 2) == c3 &&
str.codeUnitAt(start + 3) == c4;
}
+
static startsWith5(
String str, int start, int c1, int c2, int c3, int c4, int c5) {
return str.length - start >= 5 &&
@@ -282,6 +294,7 @@
str.codeUnitAt(start + 3) == c4 &&
str.codeUnitAt(start + 4) == c5;
}
+
static startsWith6(
String str, int start, int c1, int c2, int c3, int c4, int c5, int c6) {
return str.length - start >= 6 &&
@@ -292,6 +305,7 @@
str.codeUnitAt(start + 4) == c5 &&
str.codeUnitAt(start + 5) == c6;
}
+
static startsWithChar(String str, int c) {
return str.length != 0 && str.codeUnitAt(0) == c;
}
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 47a4bc1..113da91 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -89,11 +89,14 @@
'parseWithClause_0':
new MethodTrampoline(0, (Parser target) => target.parseWithClause()),
'advance_0': new MethodTrampoline(0, (Parser target) => target._advance()),
- 'appendScalarValue_5': new MethodTrampoline(5, (Parser target, arg0, arg1,
- arg2, arg3,
- arg4) => target._appendScalarValue(arg0, arg1, arg2, arg3, arg4)),
- 'computeStringValue_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
- arg2) => target._computeStringValue(arg0, arg1, arg2)),
+ 'appendScalarValue_5': new MethodTrampoline(
+ 5,
+ (Parser target, arg0, arg1, arg2, arg3, arg4) =>
+ target._appendScalarValue(arg0, arg1, arg2, arg3, arg4)),
+ 'computeStringValue_3': new MethodTrampoline(
+ 3,
+ (Parser target, arg0, arg1, arg2) =>
+ target._computeStringValue(arg0, arg1, arg2)),
'convertToFunctionDeclaration_1': new MethodTrampoline(
1, (Parser target, arg0) => target._convertToFunctionDeclaration(arg0)),
'couldBeStartOfCompilationUnitMember_0': new MethodTrampoline(
@@ -159,8 +162,10 @@
0, (Parser target) => target._parseAssertStatement()),
'parseAssignableExpression_1': new MethodTrampoline(
1, (Parser target, arg0) => target._parseAssignableExpression(arg0)),
- 'parseAssignableSelector_2': new MethodTrampoline(2, (Parser target, arg0,
- arg1) => target._parseAssignableSelector(arg0, arg1)),
+ 'parseAssignableSelector_2': new MethodTrampoline(
+ 2,
+ (Parser target, arg0, arg1) =>
+ target._parseAssignableSelector(arg0, arg1)),
'parseAwaitExpression_0': new MethodTrampoline(
0, (Parser target) => target._parseAwaitExpression()),
'parseBitwiseAndExpression_0': new MethodTrampoline(
@@ -175,8 +180,10 @@
(Parser target, arg0, arg1) => target._parseClassDeclaration(arg0, arg1)),
'parseClassMembers_2': new MethodTrampoline(
2, (Parser target, arg0, arg1) => target._parseClassMembers(arg0, arg1)),
- 'parseClassTypeAlias_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
- arg2) => target._parseClassTypeAlias(arg0, arg1, arg2)),
+ 'parseClassTypeAlias_3': new MethodTrampoline(
+ 3,
+ (Parser target, arg0, arg1, arg2) =>
+ target._parseClassTypeAlias(arg0, arg1, arg2)),
'parseCombinator_0':
new MethodTrampoline(0, (Parser target) => target.parseCombinator()),
'parseCombinators_0':
@@ -191,9 +198,10 @@
1, (Parser target, arg0) => target._parseCompilationUnitMember(arg0)),
'parseConstExpression_0': new MethodTrampoline(
0, (Parser target) => target._parseConstExpression()),
- 'parseConstructor_8': new MethodTrampoline(8, (Parser target, arg0, arg1,
- arg2, arg3, arg4, arg5, arg6, arg7) =>
- target._parseConstructor(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)),
+ 'parseConstructor_8': new MethodTrampoline(
+ 8,
+ (Parser target, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) => target
+ ._parseConstructor(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)),
'parseConstructorFieldInitializer_0': new MethodTrampoline(
0, (Parser target) => target._parseConstructorFieldInitializer()),
'parseContinueStatement_0': new MethodTrampoline(
@@ -224,26 +232,36 @@
1, (Parser target, arg0) => target._parseFormalParameter(arg0)),
'parseForStatement_0':
new MethodTrampoline(0, (Parser target) => target._parseForStatement()),
- 'parseFunctionBody_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
- arg2) => target._parseFunctionBody(arg0, arg1, arg2)),
- 'parseFunctionDeclaration_3': new MethodTrampoline(3, (Parser target, arg0,
- arg1, arg2) => target._parseFunctionDeclaration(arg0, arg1, arg2)),
+ 'parseFunctionBody_3': new MethodTrampoline(
+ 3,
+ (Parser target, arg0, arg1, arg2) =>
+ target._parseFunctionBody(arg0, arg1, arg2)),
+ 'parseFunctionDeclaration_3': new MethodTrampoline(
+ 3,
+ (Parser target, arg0, arg1, arg2) =>
+ target._parseFunctionDeclaration(arg0, arg1, arg2)),
'parseFunctionDeclarationStatement_0': new MethodTrampoline(
0, (Parser target) => target._parseFunctionDeclarationStatement()),
- 'parseFunctionDeclarationStatementAfterReturnType_2': new MethodTrampoline(2,
+ 'parseFunctionDeclarationStatementAfterReturnType_2': new MethodTrampoline(
+ 2,
(Parser target, arg0, arg1) =>
target._parseFunctionDeclarationStatementAfterReturnType(arg0, arg1)),
- 'parseFunctionTypeAlias_2': new MethodTrampoline(2, (Parser target, arg0,
- arg1) => target._parseFunctionTypeAlias(arg0, arg1)),
- 'parseGetter_4': new MethodTrampoline(4, (Parser target, arg0, arg1, arg2,
- arg3) => target._parseGetter(arg0, arg1, arg2, arg3)),
+ 'parseFunctionTypeAlias_2': new MethodTrampoline(
+ 2,
+ (Parser target, arg0, arg1) =>
+ target._parseFunctionTypeAlias(arg0, arg1)),
+ 'parseGetter_4': new MethodTrampoline(
+ 4,
+ (Parser target, arg0, arg1, arg2, arg3) =>
+ target._parseGetter(arg0, arg1, arg2, arg3)),
'parseIdentifierList_0':
new MethodTrampoline(0, (Parser target) => target._parseIdentifierList()),
'parseIfStatement_0':
new MethodTrampoline(0, (Parser target) => target._parseIfStatement()),
'parseImportDirective_1': new MethodTrampoline(
1, (Parser target, arg0) => target._parseImportDirective(arg0)),
- 'parseInitializedIdentifierList_4': new MethodTrampoline(4,
+ 'parseInitializedIdentifierList_4': new MethodTrampoline(
+ 4,
(Parser target, arg0, arg1, arg2, arg3) =>
target._parseInitializedIdentifierList(arg0, arg1, arg2, arg3)),
'parseInstanceCreationExpression_1': new MethodTrampoline(1,
@@ -260,11 +278,13 @@
0, (Parser target) => target._parseLogicalAndExpression()),
'parseMapLiteral_2': new MethodTrampoline(
2, (Parser target, arg0, arg1) => target._parseMapLiteral(arg0, arg1)),
- 'parseMethodDeclarationAfterParameters_7': new MethodTrampoline(7,
- (Parser target, arg0, arg1, arg2, arg3, arg4, arg5, arg6) => target
- ._parseMethodDeclarationAfterParameters(
+ 'parseMethodDeclarationAfterParameters_7': new MethodTrampoline(
+ 7,
+ (Parser target, arg0, arg1, arg2, arg3, arg4, arg5, arg6) =>
+ target._parseMethodDeclarationAfterParameters(
arg0, arg1, arg2, arg3, arg4, arg5, arg6)),
- 'parseMethodDeclarationAfterReturnType_4': new MethodTrampoline(4,
+ 'parseMethodDeclarationAfterReturnType_4': new MethodTrampoline(
+ 4,
(Parser target, arg0, arg1, arg2, arg3) => target
._parseMethodDeclarationAfterReturnType(arg0, arg1, arg2, arg3)),
'parseModifiers_0':
@@ -277,8 +297,10 @@
new MethodTrampoline(0, (Parser target) => target._parseNewExpression()),
'parseNonLabeledStatement_0': new MethodTrampoline(
0, (Parser target) => target._parseNonLabeledStatement()),
- 'parseOperator_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
- arg2) => target._parseOperator(arg0, arg1, arg2)),
+ 'parseOperator_3': new MethodTrampoline(
+ 3,
+ (Parser target, arg0, arg1, arg2) =>
+ target._parseOperator(arg0, arg1, arg2)),
'parseOptionalReturnType_0': new MethodTrampoline(
0, (Parser target) => target._parseOptionalReturnType()),
'parsePartDirective_1': new MethodTrampoline(
@@ -295,8 +317,10 @@
0, (Parser target) => target._parseRethrowExpression()),
'parseReturnStatement_0': new MethodTrampoline(
0, (Parser target) => target._parseReturnStatement()),
- 'parseSetter_4': new MethodTrampoline(4, (Parser target, arg0, arg1, arg2,
- arg3) => target._parseSetter(arg0, arg1, arg2, arg3)),
+ 'parseSetter_4': new MethodTrampoline(
+ 4,
+ (Parser target, arg0, arg1, arg2, arg3) =>
+ target._parseSetter(arg0, arg1, arg2, arg3)),
'parseShiftExpression_0': new MethodTrampoline(
0, (Parser target) => target._parseShiftExpression()),
'parseStatementList_0':
@@ -321,16 +345,20 @@
0, (Parser target) => target._parseUnaryExpression()),
'parseVariableDeclaration_0': new MethodTrampoline(
0, (Parser target) => target._parseVariableDeclaration()),
- 'parseVariableDeclarationListAfterMetadata_1': new MethodTrampoline(1,
+ 'parseVariableDeclarationListAfterMetadata_1': new MethodTrampoline(
+ 1,
(Parser target, arg0) =>
target._parseVariableDeclarationListAfterMetadata(arg0)),
- 'parseVariableDeclarationListAfterType_3': new MethodTrampoline(3,
+ 'parseVariableDeclarationListAfterType_3': new MethodTrampoline(
+ 3,
(Parser target, arg0, arg1, arg2) =>
target._parseVariableDeclarationListAfterType(arg0, arg1, arg2)),
- 'parseVariableDeclarationStatementAfterMetadata_1': new MethodTrampoline(1,
+ 'parseVariableDeclarationStatementAfterMetadata_1': new MethodTrampoline(
+ 1,
(Parser target, arg0) =>
target._parseVariableDeclarationStatementAfterMetadata(arg0)),
- 'parseVariableDeclarationStatementAfterType_3': new MethodTrampoline(3,
+ 'parseVariableDeclarationStatementAfterType_3': new MethodTrampoline(
+ 3,
(Parser target, arg0, arg1, arg2) =>
target._parseVariableDeclarationStatementAfterType(arg0, arg1, arg2)),
'parseWhileStatement_0':
@@ -342,12 +370,18 @@
new MethodTrampoline(1, (Parser target, arg0) => target._peekAt(arg0)),
'reportError_1': new MethodTrampoline(
1, (Parser target, arg0) => target._reportError(arg0)),
- 'reportErrorForCurrentToken_2': new MethodTrampoline(2, (Parser target, arg0,
- arg1) => target._reportErrorForCurrentToken(arg0, arg1)),
- 'reportErrorForNode_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
- arg2) => target._reportErrorForNode(arg0, arg1, arg2)),
- 'reportErrorForToken_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
- arg2) => target._reportErrorForToken(arg0, arg1, arg2)),
+ 'reportErrorForCurrentToken_2': new MethodTrampoline(
+ 2,
+ (Parser target, arg0, arg1) =>
+ target._reportErrorForCurrentToken(arg0, arg1)),
+ 'reportErrorForNode_3': new MethodTrampoline(
+ 3,
+ (Parser target, arg0, arg1, arg2) =>
+ target._reportErrorForNode(arg0, arg1, arg2)),
+ 'reportErrorForToken_3': new MethodTrampoline(
+ 3,
+ (Parser target, arg0, arg1, arg2) =>
+ target._reportErrorForToken(arg0, arg1, arg2)),
'skipBlock_0':
new MethodTrampoline(0, (Parser target) => target._skipBlock()),
'skipFinalConstVarOrType_1': new MethodTrampoline(
@@ -380,8 +414,10 @@
(Parser target, arg0, arg1) => target._tokenMatchesKeyword(arg0, arg1)),
'tokenMatchesString_2': new MethodTrampoline(
2, (Parser target, arg0, arg1) => target._tokenMatchesString(arg0, arg1)),
- 'translateCharacter_3': new MethodTrampoline(3, (Parser target, arg0, arg1,
- arg2) => target._translateCharacter(arg0, arg1, arg2)),
+ 'translateCharacter_3': new MethodTrampoline(
+ 3,
+ (Parser target, arg0, arg1, arg2) =>
+ target._translateCharacter(arg0, arg1, arg2)),
'unlockErrorListener_0':
new MethodTrampoline(0, (Parser target) => target._unlockErrorListener()),
'validateFormalParameterList_1': new MethodTrampoline(
@@ -394,21 +430,26 @@
1, (Parser target, arg0) => target._validateModifiersForEnum(arg0)),
'validateModifiersForField_1': new MethodTrampoline(
1, (Parser target, arg0) => target._validateModifiersForField(arg0)),
- 'validateModifiersForFunctionDeclarationStatement_1': new MethodTrampoline(1,
+ 'validateModifiersForFunctionDeclarationStatement_1': new MethodTrampoline(
+ 1,
(Parser target, arg0) =>
target._validateModifiersForFunctionDeclarationStatement(arg0)),
- 'validateModifiersForGetterOrSetterOrMethod_1': new MethodTrampoline(1,
+ 'validateModifiersForGetterOrSetterOrMethod_1': new MethodTrampoline(
+ 1,
(Parser target, arg0) =>
target._validateModifiersForGetterOrSetterOrMethod(arg0)),
'validateModifiersForOperator_1': new MethodTrampoline(
1, (Parser target, arg0) => target._validateModifiersForOperator(arg0)),
- 'validateModifiersForTopLevelDeclaration_1': new MethodTrampoline(1,
+ 'validateModifiersForTopLevelDeclaration_1': new MethodTrampoline(
+ 1,
(Parser target, arg0) =>
target._validateModifiersForTopLevelDeclaration(arg0)),
- 'validateModifiersForTopLevelFunction_1': new MethodTrampoline(1,
+ 'validateModifiersForTopLevelFunction_1': new MethodTrampoline(
+ 1,
(Parser target, arg0) =>
target._validateModifiersForTopLevelFunction(arg0)),
- 'validateModifiersForTopLevelVariable_1': new MethodTrampoline(1,
+ 'validateModifiersForTopLevelVariable_1': new MethodTrampoline(
+ 1,
(Parser target, arg0) =>
target._validateModifiersForTopLevelVariable(arg0)),
'validateModifiersForTypedef_1': new MethodTrampoline(
@@ -2328,11 +2369,11 @@
commentAndMetadata, modifiers.externalKeyword, returnType);
} else if (_matchesIdentifier() &&
_peek().matchesAny([
- TokenType.OPEN_PAREN,
- TokenType.OPEN_CURLY_BRACKET,
- TokenType.FUNCTION,
- TokenType.LT
- ])) {
+ TokenType.OPEN_PAREN,
+ TokenType.OPEN_CURLY_BRACKET,
+ TokenType.FUNCTION,
+ TokenType.LT
+ ])) {
_validateModifiersForGetterOrSetterOrMethod(modifiers);
return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
modifiers.externalKeyword, modifiers.staticKeyword, returnType);
@@ -2347,8 +2388,10 @@
// We appear to have a variable declaration with a type of "void".
//
_reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
- return _parseInitializedIdentifierList(commentAndMetadata,
- modifiers.staticKeyword, _validateModifiersForField(modifiers),
+ return _parseInitializedIdentifierList(
+ commentAndMetadata,
+ modifiers.staticKeyword,
+ _validateModifiersForField(modifiers),
returnType);
}
}
@@ -2426,8 +2469,10 @@
List<VariableDeclaration> variables = new List<VariableDeclaration>();
variables.add(
new VariableDeclaration(_createSyntheticIdentifier(), null, null));
- return new FieldDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, null,
+ return new FieldDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ null,
new VariableDeclarationList(null, null, keyword, null, variables),
_expectSemicolon());
}
@@ -2441,9 +2486,17 @@
// to loose, so we'll treat it as a method declaration with a missing
// name, parameters and empty body.
//
- return new MethodDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, null, null, null, null, null,
- _createSyntheticIdentifier(), null, new FormalParameterList(
+ return new MethodDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ null,
+ null,
+ null,
+ null,
+ null,
+ _createSyntheticIdentifier(),
+ null,
+ new FormalParameterList(
null, new List<FormalParameter>(), null, null, null),
new EmptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON)));
}
@@ -2451,9 +2504,14 @@
} else if (_tokenMatches(_peek(), TokenType.PERIOD) &&
_tokenMatchesIdentifier(_peekAt(2)) &&
_tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) {
- return _parseConstructor(commentAndMetadata, modifiers.externalKeyword,
- _validateModifiersForConstructor(modifiers), modifiers.factoryKeyword,
- parseSimpleIdentifier(), getAndAdvance(), parseSimpleIdentifier(),
+ return _parseConstructor(
+ commentAndMetadata,
+ modifiers.externalKeyword,
+ _validateModifiersForConstructor(modifiers),
+ modifiers.factoryKeyword,
+ parseSimpleIdentifier(),
+ getAndAdvance(),
+ parseSimpleIdentifier(),
parseFormalParameterList());
} else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
SimpleIdentifier methodName = parseSimpleIdentifier();
@@ -2461,15 +2519,26 @@
if (_matches(TokenType.COLON) ||
modifiers.factoryKeyword != null ||
methodName.name == className) {
- return _parseConstructor(commentAndMetadata, modifiers.externalKeyword,
+ return _parseConstructor(
+ commentAndMetadata,
+ modifiers.externalKeyword,
_validateModifiersForConstructor(modifiers),
- modifiers.factoryKeyword, methodName, null, null, parameters);
+ modifiers.factoryKeyword,
+ methodName,
+ null,
+ null,
+ parameters);
}
_validateModifiersForGetterOrSetterOrMethod(modifiers);
_validateFormalParameterList(parameters);
- return _parseMethodDeclarationAfterParameters(commentAndMetadata,
- modifiers.externalKeyword, modifiers.staticKeyword, null, methodName,
- null, parameters);
+ return _parseMethodDeclarationAfterParameters(
+ commentAndMetadata,
+ modifiers.externalKeyword,
+ modifiers.staticKeyword,
+ null,
+ methodName,
+ null,
+ parameters);
} else if (_peek()
.matchesAny([TokenType.EQ, TokenType.COMMA, TokenType.SEMICOLON])) {
if (modifiers.constKeyword == null &&
@@ -2514,8 +2583,10 @@
// class. At this point it consists of a type name, so we'll treat it as
// a field declaration with a missing field name and semicolon.
//
- return _parseInitializedIdentifierList(commentAndMetadata,
- modifiers.staticKeyword, _validateModifiersForField(modifiers),
+ return _parseInitializedIdentifierList(
+ commentAndMetadata,
+ modifiers.staticKeyword,
+ _validateModifiersForField(modifiers),
type);
}
if (_isOperator(_currentToken)) {
@@ -2536,8 +2607,10 @@
ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken);
try {
_lockErrorListener();
- return _parseInitializedIdentifierList(commentAndMetadata,
- modifiers.staticKeyword, _validateModifiersForField(modifiers),
+ return _parseInitializedIdentifierList(
+ commentAndMetadata,
+ modifiers.staticKeyword,
+ _validateModifiersForField(modifiers),
type);
} finally {
_unlockErrorListener();
@@ -2547,15 +2620,26 @@
FormalParameterList parameters = parseFormalParameterList();
if (methodName.name == className) {
_reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type);
- return _parseConstructor(commentAndMetadata, modifiers.externalKeyword,
+ return _parseConstructor(
+ commentAndMetadata,
+ modifiers.externalKeyword,
_validateModifiersForConstructor(modifiers),
- modifiers.factoryKeyword, methodName, null, null, parameters);
+ modifiers.factoryKeyword,
+ methodName,
+ null,
+ null,
+ parameters);
}
_validateModifiersForGetterOrSetterOrMethod(modifiers);
_validateFormalParameterList(parameters);
- return _parseMethodDeclarationAfterParameters(commentAndMetadata,
- modifiers.externalKeyword, modifiers.staticKeyword, type, methodName,
- null, parameters);
+ return _parseMethodDeclarationAfterParameters(
+ commentAndMetadata,
+ modifiers.externalKeyword,
+ modifiers.staticKeyword,
+ type,
+ methodName,
+ null,
+ parameters);
} else if (parseGenericMethods && _tokenMatches(_peek(), TokenType.LT)) {
return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
modifiers.externalKeyword, modifiers.staticKeyword, type);
@@ -3192,13 +3276,24 @@
_reportErrorForToken(
ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword);
}
- return new FunctionTypedFormalParameter(commentAndMetadata.comment,
- commentAndMetadata.metadata, holder.type, identifier,
- typeParameters, parameters);
+ return new FunctionTypedFormalParameter(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ holder.type,
+ identifier,
+ typeParameters,
+ parameters);
} else {
- return new FieldFormalParameter(commentAndMetadata.comment,
- commentAndMetadata.metadata, holder.keyword, holder.type,
- thisKeyword, period, identifier, typeParameters, parameters);
+ return new FieldFormalParameter(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ holder.keyword,
+ holder.type,
+ thisKeyword,
+ period,
+ identifier,
+ typeParameters,
+ parameters);
}
} else if (typeParameters != null) {
// TODO(brianwilkerson) Report an error. It looks like a function-typed
@@ -3219,9 +3314,16 @@
// TODO(brianwilkerson) If there are type parameters but no parameters,
// should we create a synthetic empty parameter list here so we can
// capture the type parameters?
- return new FieldFormalParameter(commentAndMetadata.comment,
- commentAndMetadata.metadata, holder.keyword, holder.type, thisKeyword,
- period, identifier, null, null);
+ return new FieldFormalParameter(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ holder.keyword,
+ holder.type,
+ thisKeyword,
+ period,
+ identifier,
+ null,
+ null);
}
return new SimpleFormalParameter(commentAndMetadata.comment,
commentAndMetadata.metadata, holder.keyword, holder.type, identifier);
@@ -3508,9 +3610,14 @@
* captures the components of the given method declaration).
*/
FunctionDeclaration _convertToFunctionDeclaration(MethodDeclaration method) =>
- new FunctionDeclaration(method.documentationComment, method.metadata,
- method.externalKeyword, method.returnType, method.propertyKeyword,
- method.name, new FunctionExpression(
+ new FunctionDeclaration(
+ method.documentationComment,
+ method.metadata,
+ method.externalKeyword,
+ method.returnType,
+ method.propertyKeyword,
+ method.name,
+ new FunctionExpression(
method.typeParameters, method.parameters, method.body));
/**
@@ -4212,7 +4319,8 @@
Expression _parseAssignableExpression(bool primaryAllowed) {
if (_matchesKeyword(Keyword.SUPER)) {
return _parseAssignableSelector(
- new SuperExpression(getAndAdvance()), false, allowConditional: false);
+ new SuperExpression(getAndAdvance()), false,
+ allowConditional: false);
}
//
// A primary expression can start with an identifier. We resolve the
@@ -4233,8 +4341,11 @@
expression as SimpleIdentifier, typeArguments, argumentList);
} else if (expression is PrefixedIdentifier) {
PrefixedIdentifier identifier = expression as PrefixedIdentifier;
- expression = new MethodInvocation(identifier.prefix,
- identifier.period, identifier.identifier, typeArguments,
+ expression = new MethodInvocation(
+ identifier.prefix,
+ identifier.period,
+ identifier.identifier,
+ typeArguments,
argumentList);
} else if (expression is PropertyAccess) {
PropertyAccess access = expression as PropertyAccess;
@@ -4469,9 +4580,12 @@
}
if (expression is PropertyAccess) {
PropertyAccess propertyAccess = expression as PropertyAccess;
- expression = new MethodInvocation(propertyAccess.target,
- propertyAccess.operator, propertyAccess.propertyName,
- typeArguments, parseArgumentList());
+ expression = new MethodInvocation(
+ propertyAccess.target,
+ propertyAccess.operator,
+ propertyAccess.propertyName,
+ typeArguments,
+ parseArgumentList());
} else {
expression = new FunctionExpressionInvocation(
expression, typeArguments, parseArgumentList());
@@ -4600,9 +4714,18 @@
_reportErrorForCurrentToken(ParserErrorCode.MISSING_CLASS_BODY);
}
ClassDeclaration classDeclaration = new ClassDeclaration(
- commentAndMetadata.comment, commentAndMetadata.metadata,
- abstractKeyword, keyword, name, typeParameters, extendsClause,
- withClause, implementsClause, leftBracket, members, rightBracket);
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ abstractKeyword,
+ keyword,
+ name,
+ typeParameters,
+ extendsClause,
+ withClause,
+ implementsClause,
+ leftBracket,
+ members,
+ rightBracket);
classDeclaration.nativeClause = nativeClause;
return classDeclaration;
}
@@ -4692,9 +4815,17 @@
}
semicolon = _createSyntheticToken(TokenType.SEMICOLON);
}
- return new ClassTypeAlias(commentAndMetadata.comment,
- commentAndMetadata.metadata, classKeyword, className, typeParameters,
- equals, abstractKeyword, superclass, withClause, implementsClause,
+ return new ClassTypeAlias(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ classKeyword,
+ className,
+ typeParameters,
+ equals,
+ abstractKeyword,
+ superclass,
+ withClause,
+ implementsClause,
semicolon);
}
@@ -4924,10 +5055,10 @@
commentAndMetadata, modifiers.externalKeyword, returnType));
} else if (_matchesIdentifier() &&
_peek().matchesAny([
- TokenType.OPEN_PAREN,
- TokenType.OPEN_CURLY_BRACKET,
- TokenType.FUNCTION
- ])) {
+ TokenType.OPEN_PAREN,
+ TokenType.OPEN_CURLY_BRACKET,
+ TokenType.FUNCTION
+ ])) {
_validateModifiersForTopLevelFunction(modifiers);
return _parseFunctionDeclaration(
commentAndMetadata, modifiers.externalKeyword, returnType);
@@ -4942,7 +5073,8 @@
// We appear to have a variable declaration with a type of "void".
//
_reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
- return new TopLevelVariableDeclaration(commentAndMetadata.comment,
+ return new TopLevelVariableDeclaration(
+ commentAndMetadata.comment,
commentAndMetadata.metadata,
_parseVariableDeclarationListAfterType(null,
_validateModifiersForTopLevelVariable(modifiers), null),
@@ -4978,7 +5110,8 @@
List<VariableDeclaration> variables = new List<VariableDeclaration>();
variables.add(
new VariableDeclaration(_createSyntheticIdentifier(), null, null));
- return new TopLevelVariableDeclaration(commentAndMetadata.comment,
+ return new TopLevelVariableDeclaration(
+ commentAndMetadata.comment,
commentAndMetadata.metadata,
new VariableDeclarationList(null, null, keyword, null, variables),
_expectSemicolon());
@@ -4997,8 +5130,10 @@
_reportErrorForCurrentToken(
ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
}
- return new TopLevelVariableDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, _parseVariableDeclarationListAfterType(
+ return new TopLevelVariableDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ _parseVariableDeclarationListAfterType(
null, _validateModifiersForTopLevelVariable(modifiers), null),
_expect(TokenType.SEMICOLON));
}
@@ -5013,10 +5148,12 @@
return _convertToFunctionDeclaration(_parseOperator(
commentAndMetadata, modifiers.externalKeyword, returnType));
} else if (_matches(TokenType.AT)) {
- return new TopLevelVariableDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, _parseVariableDeclarationListAfterType(
- null, _validateModifiersForTopLevelVariable(modifiers),
- returnType), _expect(TokenType.SEMICOLON));
+ return new TopLevelVariableDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ _parseVariableDeclarationListAfterType(null,
+ _validateModifiersForTopLevelVariable(modifiers), returnType),
+ _expect(TokenType.SEMICOLON));
} else if (!_matchesIdentifier()) {
// TODO(brianwilkerson) Generalize this error. We could also be parsing a
// top-level variable at this point.
@@ -5030,7 +5167,8 @@
List<VariableDeclaration> variables = new List<VariableDeclaration>();
variables.add(
new VariableDeclaration(_createSyntheticIdentifier(), null, null));
- return new TopLevelVariableDeclaration(commentAndMetadata.comment,
+ return new TopLevelVariableDeclaration(
+ commentAndMetadata.comment,
commentAndMetadata.metadata,
new VariableDeclarationList(null, null, null, returnType, variables),
semicolon);
@@ -5044,8 +5182,10 @@
return _parseFunctionDeclaration(
commentAndMetadata, modifiers.externalKeyword, returnType);
}
- return new TopLevelVariableDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, _parseVariableDeclarationListAfterType(
+ return new TopLevelVariableDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ _parseVariableDeclarationListAfterType(
null, _validateModifiersForTopLevelVariable(modifiers), returnType),
_expect(TokenType.SEMICOLON));
}
@@ -5071,9 +5211,14 @@
}
ConstructorDeclaration _parseConstructor(
- CommentAndMetadata commentAndMetadata, Token externalKeyword,
- Token constKeyword, Token factoryKeyword, SimpleIdentifier returnType,
- Token period, SimpleIdentifier name, FormalParameterList parameters) {
+ CommentAndMetadata commentAndMetadata,
+ Token externalKeyword,
+ Token constKeyword,
+ Token factoryKeyword,
+ SimpleIdentifier returnType,
+ Token period,
+ SimpleIdentifier name,
+ FormalParameterList parameters) {
bool bodyAllowed = externalKeyword == null;
Token separator = null;
List<ConstructorInitializer> initializers = null;
@@ -5141,10 +5286,20 @@
}
}
}
- return new ConstructorDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, externalKeyword, constKeyword,
- factoryKeyword, returnType, period, name, parameters, separator,
- initializers, redirectedConstructor, body);
+ return new ConstructorDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ externalKeyword,
+ constKeyword,
+ factoryKeyword,
+ returnType,
+ period,
+ name,
+ parameters,
+ separator,
+ initializers,
+ redirectedConstructor,
+ body);
}
/**
@@ -5412,8 +5567,13 @@
rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
_reportErrorForCurrentToken(ParserErrorCode.MISSING_ENUM_BODY);
}
- return new EnumDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, keyword, name, leftBracket, constants,
+ return new EnumDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ keyword,
+ name,
+ leftBracket,
+ constants,
rightBracket);
}
@@ -5459,8 +5619,12 @@
StringLiteral libraryUri = _parseUri();
List<Combinator> combinators = _parseCombinators();
Token semicolon = _expectSemicolon();
- return new ExportDirective(commentAndMetadata.comment,
- commentAndMetadata.metadata, exportKeyword, libraryUri, combinators,
+ return new ExportDirective(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ exportKeyword,
+ libraryUri,
+ combinators,
semicolon);
}
@@ -5640,13 +5804,25 @@
Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
Statement body = parseStatement2();
if (loopVariable == null) {
- return new ForEachStatement.withReference(awaitKeyword, forKeyword,
- leftParenthesis, identifier, inKeyword, iterator,
- rightParenthesis, body);
+ return new ForEachStatement.withReference(
+ awaitKeyword,
+ forKeyword,
+ leftParenthesis,
+ identifier,
+ inKeyword,
+ iterator,
+ rightParenthesis,
+ body);
}
- return new ForEachStatement.withDeclaration(awaitKeyword, forKeyword,
- leftParenthesis, loopVariable, inKeyword, iterator,
- rightParenthesis, body);
+ return new ForEachStatement.withDeclaration(
+ awaitKeyword,
+ forKeyword,
+ leftParenthesis,
+ loopVariable,
+ inKeyword,
+ iterator,
+ rightParenthesis,
+ body);
}
}
if (awaitKeyword != null) {
@@ -5665,9 +5841,17 @@
}
Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
Statement body = parseStatement2();
- return new ForStatement(forKeyword, leftParenthesis, variableList,
- initialization, leftSeparator, condition, rightSeparator, updaters,
- rightParenthesis, body);
+ return new ForStatement(
+ forKeyword,
+ leftParenthesis,
+ variableList,
+ initialization,
+ leftSeparator,
+ condition,
+ rightSeparator,
+ updaters,
+ rightParenthesis,
+ body);
} finally {
_inLoop = wasInLoop;
}
@@ -5797,7 +5981,8 @@
* | returnType? getOrSet identifier formalParameterList functionBody
*/
FunctionDeclaration _parseFunctionDeclaration(
- CommentAndMetadata commentAndMetadata, Token externalKeyword,
+ CommentAndMetadata commentAndMetadata,
+ Token externalKeyword,
TypeName returnType) {
Token keyword = null;
bool isGetter = false;
@@ -5823,7 +6008,10 @@
_reportErrorForCurrentToken(
ParserErrorCode.MISSING_FUNCTION_PARAMETERS);
parameters = new FormalParameterList(
- _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null,
+ _createSyntheticToken(TokenType.OPEN_PAREN),
+ null,
+ null,
+ null,
_createSyntheticToken(TokenType.CLOSE_PAREN));
}
} else if (_matches(TokenType.OPEN_PAREN)) {
@@ -5842,8 +6030,13 @@
// reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme());
// advance();
// }
- return new FunctionDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, externalKeyword, returnType, keyword, name,
+ return new FunctionDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ externalKeyword,
+ returnType,
+ keyword,
+ name,
new FunctionExpression(typeParameters, parameters, body));
}
@@ -5912,31 +6105,50 @@
if (_matches(TokenType.SEMICOLON) || _matches(TokenType.EOF)) {
_reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
FormalParameterList parameters = new FormalParameterList(
- _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null,
+ _createSyntheticToken(TokenType.OPEN_PAREN),
+ null,
+ null,
+ null,
_createSyntheticToken(TokenType.CLOSE_PAREN));
Token semicolon = _expect(TokenType.SEMICOLON);
- return new FunctionTypeAlias(commentAndMetadata.comment,
- commentAndMetadata.metadata, keyword, returnType, name,
- typeParameters, parameters, semicolon);
+ return new FunctionTypeAlias(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ keyword,
+ returnType,
+ name,
+ typeParameters,
+ parameters,
+ semicolon);
} else if (!_matches(TokenType.OPEN_PAREN)) {
_reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
// TODO(brianwilkerson) Recover from this error. At the very least we
// should skip to the start of the next valid compilation unit member,
// allowing for the possibility of finding the typedef parameters before
// that point.
- return new FunctionTypeAlias(commentAndMetadata.comment,
- commentAndMetadata.metadata, keyword, returnType, name,
- typeParameters, new FormalParameterList(
- _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null,
- _createSyntheticToken(TokenType.CLOSE_PAREN)),
+ return new FunctionTypeAlias(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ keyword,
+ returnType,
+ name,
+ typeParameters,
+ new FormalParameterList(_createSyntheticToken(TokenType.OPEN_PAREN),
+ null, null, null, _createSyntheticToken(TokenType.CLOSE_PAREN)),
_createSyntheticToken(TokenType.SEMICOLON));
}
FormalParameterList parameters = parseFormalParameterList();
_validateFormalParameterList(parameters);
Token semicolon = _expect(TokenType.SEMICOLON);
- return new FunctionTypeAlias(commentAndMetadata.comment,
- commentAndMetadata.metadata, keyword, returnType, name, typeParameters,
- parameters, semicolon);
+ return new FunctionTypeAlias(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ keyword,
+ returnType,
+ name,
+ typeParameters,
+ parameters,
+ semicolon);
}
/**
@@ -5965,13 +6177,23 @@
}
FunctionBody body = _parseFunctionBody(
externalKeyword != null || staticKeyword == null,
- ParserErrorCode.STATIC_GETTER_WITHOUT_BODY, false);
+ ParserErrorCode.STATIC_GETTER_WITHOUT_BODY,
+ false);
if (externalKeyword != null && body is! EmptyFunctionBody) {
_reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY);
}
- return new MethodDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType,
- propertyKeyword, null, name, null, null, body);
+ return new MethodDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ externalKeyword,
+ staticKeyword,
+ returnType,
+ propertyKeyword,
+ null,
+ name,
+ null,
+ null,
+ body);
}
/**
@@ -6053,9 +6275,16 @@
}
List<Combinator> combinators = _parseCombinators();
Token semicolon = _expectSemicolon();
- return new ImportDirective(commentAndMetadata.comment,
- commentAndMetadata.metadata, importKeyword, libraryUri, deferredToken,
- asToken, prefix, combinators, semicolon);
+ return new ImportDirective(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ importKeyword,
+ libraryUri,
+ deferredToken,
+ asToken,
+ prefix,
+ combinators,
+ semicolon);
}
/**
@@ -6078,12 +6307,17 @@
* identifier ('=' expression)?
*/
FieldDeclaration _parseInitializedIdentifierList(
- CommentAndMetadata commentAndMetadata, Token staticKeyword, Token keyword,
+ CommentAndMetadata commentAndMetadata,
+ Token staticKeyword,
+ Token keyword,
TypeName type) {
VariableDeclarationList fieldList =
_parseVariableDeclarationListAfterType(null, keyword, type);
- return new FieldDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, staticKeyword, fieldList,
+ return new FieldDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ staticKeyword,
+ fieldList,
_expect(TokenType.SEMICOLON));
}
@@ -6161,7 +6395,8 @@
// may be empty list literal
if (_matches(TokenType.INDEX)) {
BeginToken leftBracket = _createToken(
- _currentToken, TokenType.OPEN_SQUARE_BRACKET, isBegin: true);
+ _currentToken, TokenType.OPEN_SQUARE_BRACKET,
+ isBegin: true);
Token rightBracket =
new Token(TokenType.CLOSE_SQUARE_BRACKET, _currentToken.offset + 1);
leftBracket.endToken = rightBracket;
@@ -6219,8 +6454,11 @@
return _parseListLiteral(modifier, typeArguments);
}
_reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL);
- return new ListLiteral(modifier, typeArguments,
- _createSyntheticToken(TokenType.OPEN_SQUARE_BRACKET), null,
+ return new ListLiteral(
+ modifier,
+ typeArguments,
+ _createSyntheticToken(TokenType.OPEN_SQUARE_BRACKET),
+ null,
_createSyntheticToken(TokenType.CLOSE_SQUARE_BRACKET));
}
@@ -6290,12 +6528,17 @@
* | 'external'? functionSignature ';'
*/
MethodDeclaration _parseMethodDeclarationAfterParameters(
- CommentAndMetadata commentAndMetadata, Token externalKeyword,
- Token staticKeyword, TypeName returnType, SimpleIdentifier name,
- TypeParameterList typeParameters, FormalParameterList parameters) {
+ CommentAndMetadata commentAndMetadata,
+ Token externalKeyword,
+ Token staticKeyword,
+ TypeName returnType,
+ SimpleIdentifier name,
+ TypeParameterList typeParameters,
+ FormalParameterList parameters) {
FunctionBody body = _parseFunctionBody(
externalKeyword != null || staticKeyword == null,
- ParserErrorCode.MISSING_FUNCTION_BODY, false);
+ ParserErrorCode.MISSING_FUNCTION_BODY,
+ false);
if (externalKeyword != null) {
if (body is! EmptyFunctionBody) {
_reportErrorForNode(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body);
@@ -6305,9 +6548,18 @@
_reportErrorForNode(ParserErrorCode.ABSTRACT_STATIC_METHOD, body);
}
}
- return new MethodDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType,
- null, null, name, typeParameters, parameters, body);
+ return new MethodDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ externalKeyword,
+ staticKeyword,
+ returnType,
+ null,
+ null,
+ name,
+ typeParameters,
+ parameters,
+ body);
}
/**
@@ -6323,8 +6575,10 @@
* | 'external'? functionSignature ';'
*/
MethodDeclaration _parseMethodDeclarationAfterReturnType(
- CommentAndMetadata commentAndMetadata, Token externalKeyword,
- Token staticKeyword, TypeName returnType) {
+ CommentAndMetadata commentAndMetadata,
+ Token externalKeyword,
+ Token staticKeyword,
+ TypeName returnType) {
SimpleIdentifier methodName = parseSimpleIdentifier();
TypeParameterList typeParameters = null;
if (parseGenericMethods && _matches(TokenType.LT)) {
@@ -6337,14 +6591,22 @@
_reportErrorForToken(
ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous);
parameters = new FormalParameterList(
- _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null,
+ _createSyntheticToken(TokenType.OPEN_PAREN),
+ null,
+ null,
+ null,
_createSyntheticToken(TokenType.CLOSE_PAREN));
} else {
parameters = parseFormalParameterList();
}
_validateFormalParameterList(parameters);
- return _parseMethodDeclarationAfterParameters(commentAndMetadata,
- externalKeyword, staticKeyword, returnType, methodName, typeParameters,
+ return _parseMethodDeclarationAfterParameters(
+ commentAndMetadata,
+ externalKeyword,
+ staticKeyword,
+ returnType,
+ methodName,
+ typeParameters,
parameters);
}
@@ -6552,10 +6814,10 @@
TypeName returnType = parseReturnType();
if (_matchesIdentifier() &&
_peek().matchesAny([
- TokenType.OPEN_PAREN,
- TokenType.OPEN_CURLY_BRACKET,
- TokenType.FUNCTION
- ])) {
+ TokenType.OPEN_PAREN,
+ TokenType.OPEN_CURLY_BRACKET,
+ TokenType.FUNCTION
+ ])) {
return _parseFunctionDeclarationStatementAfterReturnType(
commentAndMetadata, returnType);
} else {
@@ -6699,9 +6961,18 @@
if (externalKeyword != null && body is! EmptyFunctionBody) {
_reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY);
}
- return new MethodDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, externalKeyword, null, returnType, null,
- operatorKeyword, name, null, parameters, body);
+ return new MethodDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ externalKeyword,
+ null,
+ returnType,
+ null,
+ operatorKeyword,
+ name,
+ null,
+ parameters,
+ body);
}
/**
@@ -6746,8 +7017,12 @@
LibraryIdentifier libraryName = _parseLibraryName(
ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE, ofKeyword);
Token semicolon = _expect(TokenType.SEMICOLON);
- return new PartOfDirective(commentAndMetadata.comment,
- commentAndMetadata.metadata, partKeyword, ofKeyword, libraryName,
+ return new PartOfDirective(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ partKeyword,
+ ofKeyword,
+ libraryName,
semicolon);
}
StringLiteral partUri = _parseUri();
@@ -6836,7 +7111,8 @@
// TODO(paulberry): verify with Gilad that "super" must be followed by
// unconditionalAssignableSelector in this case.
return _parseAssignableSelector(
- new SuperExpression(getAndAdvance()), false, allowConditional: false);
+ new SuperExpression(getAndAdvance()), false,
+ allowConditional: false);
} else if (_matchesKeyword(Keyword.NULL)) {
return new NullLiteral(getAndAdvance());
} else if (_matchesKeyword(Keyword.FALSE)) {
@@ -7039,13 +7315,23 @@
_validateFormalParameterList(parameters);
FunctionBody body = _parseFunctionBody(
externalKeyword != null || staticKeyword == null,
- ParserErrorCode.STATIC_SETTER_WITHOUT_BODY, false);
+ ParserErrorCode.STATIC_SETTER_WITHOUT_BODY,
+ false);
if (externalKeyword != null && body is! EmptyFunctionBody) {
_reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY);
}
- return new MethodDeclaration(commentAndMetadata.comment,
- commentAndMetadata.metadata, externalKeyword, staticKeyword, returnType,
- propertyKeyword, null, name, null, parameters, body);
+ return new MethodDeclaration(
+ commentAndMetadata.comment,
+ commentAndMetadata.metadata,
+ externalKeyword,
+ staticKeyword,
+ returnType,
+ propertyKeyword,
+ null,
+ name,
+ null,
+ parameters,
+ body);
}
/**
@@ -7195,7 +7481,8 @@
if (definedLabels.contains(label)) {
_reportErrorForToken(
ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT,
- identifier.token, [label]);
+ identifier.token,
+ [label]);
} else {
definedLabels.add(label);
}
@@ -7353,9 +7640,16 @@
rightParenthesis = _expect(TokenType.CLOSE_PAREN);
}
Block catchBody = parseBlock();
- catchClauses.add(new CatchClause(onKeyword, exceptionType, catchKeyword,
- leftParenthesis, exceptionParameter, comma, stackTraceParameter,
- rightParenthesis, catchBody));
+ catchClauses.add(new CatchClause(
+ onKeyword,
+ exceptionType,
+ catchKeyword,
+ leftParenthesis,
+ exceptionParameter,
+ comma,
+ stackTraceParameter,
+ rightParenthesis,
+ catchBody));
}
Token finallyKeyword = null;
if (_matchesKeyword(Keyword.FINALLY)) {
@@ -7468,8 +7762,10 @@
secondOperator.setNext(_currentToken);
firstOperator.setNext(secondOperator);
operator.previous.setNext(firstOperator);
- return new PrefixExpression(firstOperator, new PrefixExpression(
- secondOperator, new SuperExpression(getAndAdvance())));
+ return new PrefixExpression(
+ firstOperator,
+ new PrefixExpression(
+ secondOperator, new SuperExpression(getAndAdvance())));
} else {
// Invalid operator before 'super'
_reportErrorForCurrentToken(
@@ -7608,7 +7904,9 @@
return new VariableDeclarationList(
commentAndMetadata != null ? commentAndMetadata.comment : null,
commentAndMetadata != null ? commentAndMetadata.metadata : null,
- keyword, type, variables);
+ keyword,
+ type,
+ variables);
}
/**
@@ -7867,10 +8165,10 @@
// that should only occur at the beginning of a parameter list.
//
if (next.matchesAny([
- TokenType.AT,
- TokenType.OPEN_SQUARE_BRACKET,
- TokenType.OPEN_CURLY_BRACKET
- ]) ||
+ TokenType.AT,
+ TokenType.OPEN_SQUARE_BRACKET,
+ TokenType.OPEN_CURLY_BRACKET
+ ]) ||
_tokenMatchesKeyword(next, Keyword.VOID) ||
(_tokenMatchesIdentifier(next) &&
(next.next.matchesAny([TokenType.COMMA, TokenType.CLOSE_PAREN])))) {
@@ -8350,20 +8648,15 @@
} else {
_appendScalarValue(
buffer,
- lexeme
- .substring(
- index,
- currentIndex + 1),
+ lexeme.substring(index, currentIndex + 1),
(((((Character.digit(firstDigit, 16) << 4) +
Character.digit(secondDigit, 16)) <<
4) +
Character.digit(thirdDigit, 16)) <<
4) +
- Character
- .digit(fourthDigit, 16),
+ Character.digit(fourthDigit, 16),
index,
- currentIndex +
- 3);
+ currentIndex + 3);
}
return currentIndex + 4;
}
@@ -8705,6 +8998,7 @@
}
}
}
+
/**
* A synthetic keyword token.
*/
@@ -8933,7 +9227,8 @@
"Top-level declarations cannot be declared to be 'factory'");
static const ParserErrorCode FACTORY_WITH_INITIALIZERS =
- const ParserErrorCode('FACTORY_WITH_INITIALIZERS',
+ const ParserErrorCode(
+ 'FACTORY_WITH_INITIALIZERS',
"A 'factory' constructor cannot have initializers",
"Either remove the 'factory' keyword to make this a generative "
"constructor or remove the initializers.");
@@ -9202,7 +9497,8 @@
"The part-of directive must be the only directive in a part");
static const ParserErrorCode NON_STRING_LITERAL_AS_URI =
- const ParserErrorCode('NON_STRING_LITERAL_AS_URI',
+ const ParserErrorCode(
+ 'NON_STRING_LITERAL_AS_URI',
"The URI must be a string literal",
"Enclose the URI in either single or double quotes.");
@@ -9365,7 +9661,8 @@
@override
bool visitAnnotation(Annotation node) {
Annotation toNode = this._toNode as Annotation;
- if (_and(_isEqualTokens(node.atSign, toNode.atSign),
+ if (_and(
+ _isEqualTokens(node.atSign, toNode.atSign),
_isEqualNodes(node.name, toNode.name),
_isEqualTokens(node.period, toNode.period),
_isEqualNodes(node.constructorName, toNode.constructorName),
@@ -9379,7 +9676,8 @@
@override
bool visitArgumentList(ArgumentList node) {
ArgumentList toNode = this._toNode as ArgumentList;
- return _and(_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
+ return _and(
+ _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
_isEqualNodeLists(node.arguments, toNode.arguments),
_isEqualTokens(node.rightParenthesis, toNode.rightParenthesis));
}
@@ -9387,7 +9685,8 @@
@override
bool visitAsExpression(AsExpression node) {
AsExpression toNode = this._toNode as AsExpression;
- if (_and(_isEqualNodes(node.expression, toNode.expression),
+ if (_and(
+ _isEqualNodes(node.expression, toNode.expression),
_isEqualTokens(node.asOperator, toNode.asOperator),
_isEqualNodes(node.type, toNode.type))) {
toNode.propagatedType = node.propagatedType;
@@ -9400,7 +9699,8 @@
@override
bool visitAssertStatement(AssertStatement node) {
AssertStatement toNode = this._toNode as AssertStatement;
- return _and(_isEqualTokens(node.assertKeyword, toNode.assertKeyword),
+ return _and(
+ _isEqualTokens(node.assertKeyword, toNode.assertKeyword),
_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
_isEqualNodes(node.condition, toNode.condition),
_isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
@@ -9410,7 +9710,8 @@
@override
bool visitAssignmentExpression(AssignmentExpression node) {
AssignmentExpression toNode = this._toNode as AssignmentExpression;
- if (_and(_isEqualNodes(node.leftHandSide, toNode.leftHandSide),
+ if (_and(
+ _isEqualNodes(node.leftHandSide, toNode.leftHandSide),
_isEqualTokens(node.operator, toNode.operator),
_isEqualNodes(node.rightHandSide, toNode.rightHandSide))) {
toNode.propagatedElement = node.propagatedElement;
@@ -9437,7 +9738,8 @@
@override
bool visitBinaryExpression(BinaryExpression node) {
BinaryExpression toNode = this._toNode as BinaryExpression;
- if (_and(_isEqualNodes(node.leftOperand, toNode.leftOperand),
+ if (_and(
+ _isEqualNodes(node.leftOperand, toNode.leftOperand),
_isEqualTokens(node.operator, toNode.operator),
_isEqualNodes(node.rightOperand, toNode.rightOperand))) {
toNode.propagatedElement = node.propagatedElement;
@@ -9452,7 +9754,8 @@
@override
bool visitBlock(Block node) {
Block toNode = this._toNode as Block;
- return _and(_isEqualTokens(node.leftBracket, toNode.leftBracket),
+ return _and(
+ _isEqualTokens(node.leftBracket, toNode.leftBracket),
_isEqualNodeLists(node.statements, toNode.statements),
_isEqualTokens(node.rightBracket, toNode.rightBracket));
}
@@ -9478,7 +9781,8 @@
@override
bool visitBreakStatement(BreakStatement node) {
BreakStatement toNode = this._toNode as BreakStatement;
- if (_and(_isEqualTokens(node.breakKeyword, toNode.breakKeyword),
+ if (_and(
+ _isEqualTokens(node.breakKeyword, toNode.breakKeyword),
_isEqualNodes(node.label, toNode.label),
_isEqualTokens(node.semicolon, toNode.semicolon))) {
// TODO(paulberry): map node.target to toNode.target.
@@ -9502,7 +9806,8 @@
@override
bool visitCatchClause(CatchClause node) {
CatchClause toNode = this._toNode as CatchClause;
- return _and(_isEqualTokens(node.onKeyword, toNode.onKeyword),
+ return _and(
+ _isEqualTokens(node.onKeyword, toNode.onKeyword),
_isEqualNodes(node.exceptionType, toNode.exceptionType),
_isEqualTokens(node.catchKeyword, toNode.catchKeyword),
_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
@@ -9564,7 +9869,8 @@
@override
bool visitCompilationUnit(CompilationUnit node) {
CompilationUnit toNode = this._toNode as CompilationUnit;
- if (_and(_isEqualTokens(node.beginToken, toNode.beginToken),
+ if (_and(
+ _isEqualTokens(node.beginToken, toNode.beginToken),
_isEqualNodes(node.scriptTag, toNode.scriptTag),
_isEqualNodeLists(node.directives, toNode.directives),
_isEqualNodeLists(node.declarations, toNode.declarations),
@@ -9578,7 +9884,8 @@
@override
bool visitConditionalExpression(ConditionalExpression node) {
ConditionalExpression toNode = this._toNode as ConditionalExpression;
- if (_and(_isEqualNodes(node.condition, toNode.condition),
+ if (_and(
+ _isEqualNodes(node.condition, toNode.condition),
_isEqualTokens(node.question, toNode.question),
_isEqualNodes(node.thenExpression, toNode.thenExpression),
_isEqualTokens(node.colon, toNode.colon),
@@ -9617,7 +9924,8 @@
bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
ConstructorFieldInitializer toNode =
this._toNode as ConstructorFieldInitializer;
- return _and(_isEqualTokens(node.thisKeyword, toNode.thisKeyword),
+ return _and(
+ _isEqualTokens(node.thisKeyword, toNode.thisKeyword),
_isEqualTokens(node.period, toNode.period),
_isEqualNodes(node.fieldName, toNode.fieldName),
_isEqualTokens(node.equals, toNode.equals),
@@ -9627,7 +9935,8 @@
@override
bool visitConstructorName(ConstructorName node) {
ConstructorName toNode = this._toNode as ConstructorName;
- if (_and(_isEqualNodes(node.type, toNode.type),
+ if (_and(
+ _isEqualNodes(node.type, toNode.type),
_isEqualTokens(node.period, toNode.period),
_isEqualNodes(node.name, toNode.name))) {
toNode.staticElement = node.staticElement;
@@ -9639,7 +9948,8 @@
@override
bool visitContinueStatement(ContinueStatement node) {
ContinueStatement toNode = this._toNode as ContinueStatement;
- if (_and(_isEqualTokens(node.continueKeyword, toNode.continueKeyword),
+ if (_and(
+ _isEqualTokens(node.continueKeyword, toNode.continueKeyword),
_isEqualNodes(node.label, toNode.label),
_isEqualTokens(node.semicolon, toNode.semicolon))) {
// TODO(paulberry): map node.target to toNode.target.
@@ -9662,7 +9972,8 @@
@override
bool visitDefaultFormalParameter(DefaultFormalParameter node) {
DefaultFormalParameter toNode = this._toNode as DefaultFormalParameter;
- return _and(_isEqualNodes(node.parameter, toNode.parameter),
+ return _and(
+ _isEqualNodes(node.parameter, toNode.parameter),
node.kind == toNode.kind,
_isEqualTokens(node.separator, toNode.separator),
_isEqualNodes(node.defaultValue, toNode.defaultValue));
@@ -9671,7 +9982,8 @@
@override
bool visitDoStatement(DoStatement node) {
DoStatement toNode = this._toNode as DoStatement;
- return _and(_isEqualTokens(node.doKeyword, toNode.doKeyword),
+ return _and(
+ _isEqualTokens(node.doKeyword, toNode.doKeyword),
_isEqualNodes(node.body, toNode.body),
_isEqualTokens(node.whileKeyword, toNode.whileKeyword),
_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
@@ -9792,7 +10104,8 @@
@override
bool visitForEachStatement(ForEachStatement node) {
ForEachStatement toNode = this._toNode as ForEachStatement;
- return _and(_isEqualTokens(node.forKeyword, toNode.forKeyword),
+ return _and(
+ _isEqualTokens(node.forKeyword, toNode.forKeyword),
_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
_isEqualNodes(node.loopVariable, toNode.loopVariable),
_isEqualTokens(node.inKeyword, toNode.inKeyword),
@@ -9804,7 +10117,8 @@
@override
bool visitFormalParameterList(FormalParameterList node) {
FormalParameterList toNode = this._toNode as FormalParameterList;
- return _and(_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
+ return _and(
+ _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
_isEqualNodeLists(node.parameters, toNode.parameters),
_isEqualTokens(node.leftDelimiter, toNode.leftDelimiter),
_isEqualTokens(node.rightDelimiter, toNode.rightDelimiter),
@@ -9814,7 +10128,8 @@
@override
bool visitForStatement(ForStatement node) {
ForStatement toNode = this._toNode as ForStatement;
- return _and(_isEqualTokens(node.forKeyword, toNode.forKeyword),
+ return _and(
+ _isEqualTokens(node.forKeyword, toNode.forKeyword),
_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
_isEqualNodes(node.variables, toNode.variables),
_isEqualNodes(node.initialization, toNode.initialization),
@@ -9910,7 +10225,8 @@
@override
bool visitIfStatement(IfStatement node) {
IfStatement toNode = this._toNode as IfStatement;
- return _and(_isEqualTokens(node.ifKeyword, toNode.ifKeyword),
+ return _and(
+ _isEqualTokens(node.ifKeyword, toNode.ifKeyword),
_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
_isEqualNodes(node.condition, toNode.condition),
_isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
@@ -9948,7 +10264,8 @@
@override
bool visitIndexExpression(IndexExpression node) {
IndexExpression toNode = this._toNode as IndexExpression;
- if (_and(_isEqualNodes(node.target, toNode.target),
+ if (_and(
+ _isEqualNodes(node.target, toNode.target),
_isEqualTokens(node.leftBracket, toNode.leftBracket),
_isEqualNodes(node.index, toNode.index),
_isEqualTokens(node.rightBracket, toNode.rightBracket))) {
@@ -9966,7 +10283,8 @@
bool visitInstanceCreationExpression(InstanceCreationExpression node) {
InstanceCreationExpression toNode =
this._toNode as InstanceCreationExpression;
- if (_and(_isEqualTokens(node.keyword, toNode.keyword),
+ if (_and(
+ _isEqualTokens(node.keyword, toNode.keyword),
_isEqualNodes(node.constructorName, toNode.constructorName),
_isEqualNodes(node.argumentList, toNode.argumentList))) {
toNode.propagatedType = node.propagatedType;
@@ -9992,7 +10310,8 @@
@override
bool visitInterpolationExpression(InterpolationExpression node) {
InterpolationExpression toNode = this._toNode as InterpolationExpression;
- return _and(_isEqualTokens(node.leftBracket, toNode.leftBracket),
+ return _and(
+ _isEqualTokens(node.leftBracket, toNode.leftBracket),
_isEqualNodes(node.expression, toNode.expression),
_isEqualTokens(node.rightBracket, toNode.rightBracket));
}
@@ -10007,7 +10326,8 @@
@override
bool visitIsExpression(IsExpression node) {
IsExpression toNode = this._toNode as IsExpression;
- if (_and(_isEqualNodes(node.expression, toNode.expression),
+ if (_and(
+ _isEqualNodes(node.expression, toNode.expression),
_isEqualTokens(node.isOperator, toNode.isOperator),
_isEqualTokens(node.notOperator, toNode.notOperator),
_isEqualNodes(node.type, toNode.type))) {
@@ -10061,7 +10381,8 @@
@override
bool visitListLiteral(ListLiteral node) {
ListLiteral toNode = this._toNode as ListLiteral;
- if (_and(_isEqualTokens(node.constKeyword, toNode.constKeyword),
+ if (_and(
+ _isEqualTokens(node.constKeyword, toNode.constKeyword),
_isEqualNodes(node.typeArguments, toNode.typeArguments),
_isEqualTokens(node.leftBracket, toNode.leftBracket),
_isEqualNodeLists(node.elements, toNode.elements),
@@ -10076,7 +10397,8 @@
@override
bool visitMapLiteral(MapLiteral node) {
MapLiteral toNode = this._toNode as MapLiteral;
- if (_and(_isEqualTokens(node.constKeyword, toNode.constKeyword),
+ if (_and(
+ _isEqualTokens(node.constKeyword, toNode.constKeyword),
_isEqualNodes(node.typeArguments, toNode.typeArguments),
_isEqualTokens(node.leftBracket, toNode.leftBracket),
_isEqualNodeLists(node.entries, toNode.entries),
@@ -10091,7 +10413,8 @@
@override
bool visitMapLiteralEntry(MapLiteralEntry node) {
MapLiteralEntry toNode = this._toNode as MapLiteralEntry;
- return _and(_isEqualNodes(node.key, toNode.key),
+ return _and(
+ _isEqualNodes(node.key, toNode.key),
_isEqualTokens(node.separator, toNode.separator),
_isEqualNodes(node.value, toNode.value));
}
@@ -10115,7 +10438,8 @@
@override
bool visitMethodInvocation(MethodInvocation node) {
MethodInvocation toNode = this._toNode as MethodInvocation;
- if (_and(_isEqualNodes(node.target, toNode.target),
+ if (_and(
+ _isEqualNodes(node.target, toNode.target),
_isEqualTokens(node.operator, toNode.operator),
_isEqualNodes(node.methodName, toNode.methodName),
_isEqualNodes(node.argumentList, toNode.argumentList))) {
@@ -10148,7 +10472,8 @@
@override
bool visitNativeFunctionBody(NativeFunctionBody node) {
NativeFunctionBody toNode = this._toNode as NativeFunctionBody;
- return _and(_isEqualTokens(node.nativeKeyword, toNode.nativeKeyword),
+ return _and(
+ _isEqualTokens(node.nativeKeyword, toNode.nativeKeyword),
_isEqualNodes(node.stringLiteral, toNode.stringLiteral),
_isEqualTokens(node.semicolon, toNode.semicolon));
}
@@ -10167,7 +10492,8 @@
@override
bool visitParenthesizedExpression(ParenthesizedExpression node) {
ParenthesizedExpression toNode = this._toNode as ParenthesizedExpression;
- if (_and(_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
+ if (_and(
+ _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
_isEqualNodes(node.expression, toNode.expression),
_isEqualTokens(node.rightParenthesis, toNode.rightParenthesis))) {
toNode.propagatedType = node.propagatedType;
@@ -10225,7 +10551,8 @@
@override
bool visitPrefixedIdentifier(PrefixedIdentifier node) {
PrefixedIdentifier toNode = this._toNode as PrefixedIdentifier;
- if (_and(_isEqualNodes(node.prefix, toNode.prefix),
+ if (_and(
+ _isEqualNodes(node.prefix, toNode.prefix),
_isEqualTokens(node.period, toNode.period),
_isEqualNodes(node.identifier, toNode.identifier))) {
toNode.propagatedType = node.propagatedType;
@@ -10252,7 +10579,8 @@
@override
bool visitPropertyAccess(PropertyAccess node) {
PropertyAccess toNode = this._toNode as PropertyAccess;
- if (_and(_isEqualNodes(node.target, toNode.target),
+ if (_and(
+ _isEqualNodes(node.target, toNode.target),
_isEqualTokens(node.operator, toNode.operator),
_isEqualNodes(node.propertyName, toNode.propertyName))) {
toNode.propagatedType = node.propagatedType;
@@ -10267,7 +10595,8 @@
RedirectingConstructorInvocation node) {
RedirectingConstructorInvocation toNode =
this._toNode as RedirectingConstructorInvocation;
- if (_and(_isEqualTokens(node.thisKeyword, toNode.thisKeyword),
+ if (_and(
+ _isEqualTokens(node.thisKeyword, toNode.thisKeyword),
_isEqualTokens(node.period, toNode.period),
_isEqualNodes(node.constructorName, toNode.constructorName),
_isEqualNodes(node.argumentList, toNode.argumentList))) {
@@ -10291,7 +10620,8 @@
@override
bool visitReturnStatement(ReturnStatement node) {
ReturnStatement toNode = this._toNode as ReturnStatement;
- return _and(_isEqualTokens(node.returnKeyword, toNode.returnKeyword),
+ return _and(
+ _isEqualTokens(node.returnKeyword, toNode.returnKeyword),
_isEqualNodes(node.expression, toNode.expression),
_isEqualTokens(node.semicolon, toNode.semicolon));
}
@@ -10361,7 +10691,8 @@
bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
SuperConstructorInvocation toNode =
this._toNode as SuperConstructorInvocation;
- if (_and(_isEqualTokens(node.superKeyword, toNode.superKeyword),
+ if (_and(
+ _isEqualTokens(node.superKeyword, toNode.superKeyword),
_isEqualTokens(node.period, toNode.period),
_isEqualNodes(node.constructorName, toNode.constructorName),
_isEqualNodes(node.argumentList, toNode.argumentList))) {
@@ -10385,7 +10716,8 @@
@override
bool visitSwitchCase(SwitchCase node) {
SwitchCase toNode = this._toNode as SwitchCase;
- return _and(_isEqualNodeLists(node.labels, toNode.labels),
+ return _and(
+ _isEqualNodeLists(node.labels, toNode.labels),
_isEqualTokens(node.keyword, toNode.keyword),
_isEqualNodes(node.expression, toNode.expression),
_isEqualTokens(node.colon, toNode.colon),
@@ -10395,7 +10727,8 @@
@override
bool visitSwitchDefault(SwitchDefault node) {
SwitchDefault toNode = this._toNode as SwitchDefault;
- return _and(_isEqualNodeLists(node.labels, toNode.labels),
+ return _and(
+ _isEqualNodeLists(node.labels, toNode.labels),
_isEqualTokens(node.keyword, toNode.keyword),
_isEqualTokens(node.colon, toNode.colon),
_isEqualNodeLists(node.statements, toNode.statements));
@@ -10404,7 +10737,8 @@
@override
bool visitSwitchStatement(SwitchStatement node) {
SwitchStatement toNode = this._toNode as SwitchStatement;
- return _and(_isEqualTokens(node.switchKeyword, toNode.switchKeyword),
+ return _and(
+ _isEqualTokens(node.switchKeyword, toNode.switchKeyword),
_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
_isEqualNodes(node.expression, toNode.expression),
_isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
@@ -10462,7 +10796,8 @@
@override
bool visitTryStatement(TryStatement node) {
TryStatement toNode = this._toNode as TryStatement;
- return _and(_isEqualTokens(node.tryKeyword, toNode.tryKeyword),
+ return _and(
+ _isEqualTokens(node.tryKeyword, toNode.tryKeyword),
_isEqualNodes(node.body, toNode.body),
_isEqualNodeLists(node.catchClauses, toNode.catchClauses),
_isEqualTokens(node.finallyKeyword, toNode.finallyKeyword),
@@ -10472,7 +10807,8 @@
@override
bool visitTypeArgumentList(TypeArgumentList node) {
TypeArgumentList toNode = this._toNode as TypeArgumentList;
- return _and(_isEqualTokens(node.leftBracket, toNode.leftBracket),
+ return _and(
+ _isEqualTokens(node.leftBracket, toNode.leftBracket),
_isEqualNodeLists(node.arguments, toNode.arguments),
_isEqualTokens(node.rightBracket, toNode.rightBracket));
}
@@ -10502,7 +10838,8 @@
@override
bool visitTypeParameterList(TypeParameterList node) {
TypeParameterList toNode = this._toNode as TypeParameterList;
- return _and(_isEqualTokens(node.leftBracket, toNode.leftBracket),
+ return _and(
+ _isEqualTokens(node.leftBracket, toNode.leftBracket),
_isEqualNodeLists(node.typeParameters, toNode.typeParameters),
_isEqualTokens(node.rightBracket, toNode.rightBracket));
}
@@ -10540,7 +10877,8 @@
@override
bool visitWhileStatement(WhileStatement node) {
WhileStatement toNode = this._toNode as WhileStatement;
- return _and(_isEqualTokens(node.whileKeyword, toNode.whileKeyword),
+ return _and(
+ _isEqualTokens(node.whileKeyword, toNode.whileKeyword),
_isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
_isEqualNodes(node.condition, toNode.condition),
_isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
@@ -10557,7 +10895,8 @@
@override
bool visitYieldStatement(YieldStatement node) {
YieldStatement toNode = this._toNode as YieldStatement;
- return _and(_isEqualTokens(node.yieldKeyword, toNode.yieldKeyword),
+ return _and(
+ _isEqualTokens(node.yieldKeyword, toNode.yieldKeyword),
_isEqualNodes(node.expression, toNode.expression),
_isEqualTokens(node.semicolon, toNode.semicolon));
}
@@ -10565,9 +10904,18 @@
/**
* Return `true` if all of the parameters are `true`.
*/
- bool _and(bool b1, bool b2, [bool b3 = true, bool b4 = true, bool b5 = true,
- bool b6 = true, bool b7 = true, bool b8 = true, bool b9 = true,
- bool b10 = true, bool b11 = true, bool b12 = true, bool b13 = true]) {
+ bool _and(bool b1, bool b2,
+ [bool b3 = true,
+ bool b4 = true,
+ bool b5 = true,
+ bool b6 = true,
+ bool b7 = true,
+ bool b8 = true,
+ bool b9 = true,
+ bool b10 = true,
+ bool b11 = true,
+ bool b12 = true,
+ bool b13 = true]) {
// TODO(brianwilkerson) Inline this method.
return b1 &&
b2 &&
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 4a17411..36d68f9 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -9547,6 +9547,154 @@
}
/**
+ * An AST visitor that is used to resolve the some of the nodes within a single
+ * compilation unit. The nodes that are skipped are those that are within
+ * function bodies.
+ */
+class PartialResolverVisitor extends ResolverVisitor {
+ /**
+ * A flag indicating whether the resolver is being run in strong mode.
+ */
+ final bool strongMode;
+
+ /**
+ * The static variables that have an initializer. These are the variables that
+ * need to be re-resolved after static variables have their types inferred. A
+ * subset of these variables are those whose types should be inferred. The
+ * list will be empty unless the resolver is being run in strong mode.
+ */
+ final List<VariableElement> staticVariables = <VariableElement>[];
+
+ /**
+ * A flag indicating whether we should discard errors while resolving the
+ * initializer for variable declarations. We do this for top-level variables
+ * and fields because their initializer will be re-resolved at a later time.
+ */
+ bool discardErrorsInInitializer = false;
+
+ /**
+ * Initialize a newly created visitor to resolve the nodes in an AST node.
+ *
+ * The [definingLibrary] is the element for the library containing the node
+ * being visited. The [source] is the source representing the compilation unit
+ * containing the node being visited. The [typeProvider] is the object used to
+ * access the types from the core library. The [errorListener] is the error
+ * listener that will be informed of any errors that are found during
+ * resolution. The [nameScope] is the scope used to resolve identifiers in the
+ * node that will first be visited. If `null` or unspecified, a new
+ * [LibraryScope] will be created based on [definingLibrary] and
+ * [typeProvider]. The [inheritanceManager] is used to perform inheritance
+ * lookups. If `null` or unspecified, a new [InheritanceManager] will be
+ * created based on [definingLibrary]. The [typeAnalyzerFactory] is used to
+ * create the type analyzer. If `null` or unspecified, a type analyzer of
+ * type [StaticTypeAnalyzer] will be created.
+ */
+ PartialResolverVisitor(LibraryElement definingLibrary, Source source,
+ TypeProvider typeProvider, AnalysisErrorListener errorListener,
+ {Scope nameScope,
+ InheritanceManager inheritanceManager,
+ StaticTypeAnalyzerFactory typeAnalyzerFactory})
+ : strongMode = definingLibrary.context.analysisOptions.strongMode,
+ super(definingLibrary, source, typeProvider,
+ new DisablableErrorListener(errorListener));
+
+ @override
+ Object visitBlockFunctionBody(BlockFunctionBody node) {
+ if (_shouldBeSkipped(node)) {
+ return null;
+ }
+ return super.visitBlockFunctionBody(node);
+ }
+
+ @override
+ Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ if (_shouldBeSkipped(node)) {
+ return null;
+ }
+ return super.visitExpressionFunctionBody(node);
+ }
+
+ @override
+ Object visitFieldDeclaration(FieldDeclaration node) {
+ if (strongMode && node.isStatic) {
+ _addStaticVariables(node.fields.variables);
+ bool wasDiscarding = discardErrorsInInitializer;
+ discardErrorsInInitializer = true;
+ try {
+ return super.visitFieldDeclaration(node);
+ } finally {
+ discardErrorsInInitializer = wasDiscarding;
+ }
+ }
+ return super.visitFieldDeclaration(node);
+ }
+
+ @override
+ Object visitNode(AstNode node) {
+ if (discardErrorsInInitializer) {
+ AstNode parent = node.parent;
+ if (parent is VariableDeclaration && parent.initializer == node) {
+ DisablableErrorListener listener = errorListener;
+ return listener.disableWhile(() => super.visitNode(node));
+ }
+ }
+ return super.visitNode(node);
+ }
+
+ @override
+ Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ if (strongMode) {
+ _addStaticVariables(node.variables.variables);
+ bool wasDiscarding = discardErrorsInInitializer;
+ discardErrorsInInitializer = true;
+ try {
+ return super.visitTopLevelVariableDeclaration(node);
+ } finally {
+ discardErrorsInInitializer = wasDiscarding;
+ }
+ }
+ return super.visitTopLevelVariableDeclaration(node);
+ }
+
+ /**
+ * Add all of the [variables] with initializers to the list of variables whose
+ * type can be inferred. Technically, we only infer the types of variables
+ * that do not have a static type, but all variables with initializers
+ * potentially need to be re-resolved after inference because they might
+ * refer to a field whose type was inferred.
+ */
+ void _addStaticVariables(NodeList<VariableDeclaration> variables) {
+ for (VariableDeclaration variable in variables) {
+ if (variable.initializer != null) {
+ staticVariables.add(variable.element);
+ }
+ }
+ }
+
+ /**
+ * Return `true` if the given function body should be skipped because it is
+ * the body of a top-level function, method or constructor.
+ */
+ bool _shouldBeSkipped(FunctionBody body) {
+ AstNode parent = body.parent;
+ if (parent is MethodDeclaration) {
+ return parent.body == body;
+ }
+ if (parent is ConstructorDeclaration) {
+ return parent.body == body;
+ }
+ if (parent is FunctionExpression) {
+ AstNode parent2 = parent.parent;
+ if (parent2 is FunctionDeclaration &&
+ parent2.parent is! FunctionDeclarationStatement) {
+ return parent.body == body;
+ }
+ }
+ return false;
+ }
+}
+
+/**
* Instances of the class `PubVerifier` traverse an AST structure looking for deviations from
* pub best practices.
*/
@@ -10132,21 +10280,19 @@
/**
* Initialize a newly created visitor to resolve the nodes in an AST node.
*
- * [definingLibrary] is the element for the library containing the node being
- * visited.
- * [source] is the source representing the compilation unit containing the
- * node being visited.
- * [typeProvider] the object used to access the types from the core library.
- * [errorListener] the error listener that will be informed of any errors
- * that are found during resolution.
- * [nameScope] is the scope used to resolve identifiers in the node that will
- * first be visited. If `null` or unspecified, a new [LibraryScope] will be
- * created based on [definingLibrary] and [typeProvider].
- * [inheritanceManager] is used to perform inheritance lookups. If `null` or
- * unspecified, a new [InheritanceManager] will be created based on
- * [definingLibrary].
- * [typeAnalyzerFactory] is used to create the type analyzer. If `null` or
- * unspecified, a type analyzer of type [StaticTypeAnalyzer] will be created.
+ * The [definingLibrary] is the element for the library containing the node
+ * being visited. The [source] is the source representing the compilation unit
+ * containing the node being visited. The [typeProvider] is the object used to
+ * access the types from the core library. The [errorListener] is the error
+ * listener that will be informed of any errors that are found during
+ * resolution. The [nameScope] is the scope used to resolve identifiers in the
+ * node that will first be visited. If `null` or unspecified, a new
+ * [LibraryScope] will be created based on [definingLibrary] and
+ * [typeProvider]. The [inheritanceManager] is used to perform inheritance
+ * lookups. If `null` or unspecified, a new [InheritanceManager] will be
+ * created based on [definingLibrary]. The [typeAnalyzerFactory] is used to
+ * create the type analyzer. If `null` or unspecified, a type analyzer of
+ * type [StaticTypeAnalyzer] will be created.
*/
ResolverVisitor(LibraryElement definingLibrary, Source source,
TypeProvider typeProvider, AnalysisErrorListener errorListener,
@@ -10285,7 +10431,14 @@
/**
* Prepares this [ResolverVisitor] to using it for incremental resolution.
*/
- void initForIncrementalResolution() {
+ void initForIncrementalResolution([Declaration declaration = null]) {
+ if (declaration != null) {
+ Element element = declaration.element;
+ if (element is ExecutableElement) {
+ _enclosingFunction = element;
+ }
+ _commentBeforeFunction = declaration.documentationComment;
+ }
_overrideManager.enterScope();
}
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index e6d7a54..31bd28a 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -602,8 +602,8 @@
SourceFactory(this._resolvers,
[this._packages, ResourceProvider resourceProvider])
: _resourceProvider = resourceProvider != null
- ? resourceProvider
- : PhysicalResourceProvider.INSTANCE;
+ ? resourceProvider
+ : PhysicalResourceProvider.INSTANCE;
/**
* Return the [DartSdk] associated with this [SourceFactory], or `null` if there
@@ -639,16 +639,17 @@
Map<String, List<Folder>> packageMap = <String, List<Folder>>{};
_packages.asMap().forEach((String name, Uri uri) {
if (uri.scheme == 'file' || uri.scheme == '' /* unspecified */) {
- packageMap[name] =
- <Folder>[_resourceProvider.getFolder(uri.toFilePath())];
+ packageMap[name] = <Folder>[
+ _resourceProvider.getFolder(uri.toFilePath())
+ ];
}
});
return packageMap;
}
// Default to the PackageMapUriResolver.
- PackageMapUriResolver resolver = _resolvers.firstWhere(
- (r) => r is PackageMapUriResolver, orElse: () => null);
+ PackageMapUriResolver resolver = _resolvers
+ .firstWhere((r) => r is PackageMapUriResolver, orElse: () => null);
return resolver != null ? resolver.packageMap : null;
}
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index 76d3396..4708aa0 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -415,8 +415,10 @@
new CaughtException(exception, stackTrace));
}
}
- return new JavaFile.relative(pkgDir, relPath.replaceAll(
- '/', new String.fromCharCode(JavaFile.separatorChar)));
+ return new JavaFile.relative(
+ pkgDir,
+ relPath.replaceAll(
+ '/', new String.fromCharCode(JavaFile.separatorChar)));
}
@override
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index bffeaad..3da6e37 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -328,7 +328,9 @@
node.element as ExecutableElementImpl;
functionElement.returnType =
_computeStaticReturnTypeOfFunctionDeclaration(node);
- _recordPropagatedTypeOfFunction(functionElement, function.body);
+ if (node.parent is FunctionDeclarationStatement) {
+ _recordPropagatedTypeOfFunction(functionElement, function.body);
+ }
_recordStaticType(function, functionElement.type);
return null;
}
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index d0d9c00..5b5204a 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -337,13 +337,13 @@
@override
List<InterfaceType> get nonSubtypableTypes => <InterfaceType>[
- nullType,
- numType,
- intType,
- doubleType,
- boolType,
- stringType
- ];
+ nullType,
+ numType,
+ intType,
+ doubleType,
+ boolType,
+ stringType
+ ];
@override
DartObjectImpl get nullObject {
diff --git a/pkg/analyzer/lib/src/generated/visitors.dart b/pkg/analyzer/lib/src/generated/visitors.dart
index defb317..59e644f 100644
--- a/pkg/analyzer/lib/src/generated/visitors.dart
+++ b/pkg/analyzer/lib/src/generated/visitors.dart
@@ -303,6 +303,7 @@
node.visitChildren(this);
return null;
}
+
@override
T visitFunctionDeclaration(FunctionDeclaration node) {
_delegates.forEach((delegate) => delegate.visitFunctionDeclaration(node));
@@ -475,6 +476,7 @@
node.visitChildren(this);
return null;
}
+
@override
T visitMethodInvocation(MethodInvocation node) {
_delegates.forEach((delegate) => delegate.visitMethodInvocation(node));
@@ -545,6 +547,7 @@
node.visitChildren(this);
return null;
}
+
@override
T visitPrefixedIdentifier(PrefixedIdentifier node) {
_delegates.forEach((delegate) => delegate.visitPrefixedIdentifier(node));
diff --git a/pkg/analyzer/lib/src/plugin/engine_plugin.dart b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
index 65ead96..75debaa 100644
--- a/pkg/analyzer/lib/src/plugin/engine_plugin.dart
+++ b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
@@ -7,6 +7,7 @@
import 'package:analyzer/plugin/task.dart';
import 'package:analyzer/src/generated/engine.dart'
show InternalAnalysisContext;
+import 'package:analyzer/src/generated/error.dart' show AnalysisError;
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/src/task/dart_work_manager.dart';
import 'package:analyzer/src/task/general.dart';
@@ -22,6 +23,27 @@
class EnginePlugin implements Plugin {
/**
* The simple identifier of the extension point that allows plugins to
+ * register new analysis error results to compute for a Dart source.
+ */
+ static const String DART_ERRORS_FOR_SOURCE_EXTENSION_POINT =
+ 'dartErrorsForSource';
+
+ /**
+ * The simple identifier of the extension point that allows plugins to
+ * register new analysis error results to compute for a Dart library
+ * specific unit.
+ */
+ static const String DART_ERRORS_FOR_UNIT_EXTENSION_POINT =
+ 'dartErrorsForUnit';
+
+ /**
+ * The simple identifier of the extension point that allows plugins to
+ * register new analysis error results to compute for an HTML source.
+ */
+ static const String HTML_ERRORS_EXTENSION_POINT = 'htmlErrors';
+
+ /**
+ * The simple identifier of the extension point that allows plugins to
* register new analysis tasks with the analysis engine.
*/
static const String TASK_EXTENSION_POINT = 'task';
@@ -39,6 +61,24 @@
static const String UNIQUE_IDENTIFIER = 'analysis_engine.core';
/**
+ * The extension point that allows plugins to register new analysis error
+ * results for a Dart source.
+ */
+ ExtensionPoint dartErrorsForSourceExtensionPoint;
+
+ /**
+ * The extension point that allows plugins to register new analysis error
+ * results for a Dart library specific unit.
+ */
+ ExtensionPoint dartErrorsForUnitExtensionPoint;
+
+ /**
+ * The extension point that allows plugins to register new analysis error
+ * results for an HTML source.
+ */
+ ExtensionPoint htmlErrorsExtensionPoint;
+
+ /**
* The extension point that allows plugins to register new analysis tasks with
* the analysis engine.
*/
@@ -56,6 +96,26 @@
EnginePlugin();
/**
+ * Return a list containing all of the contributed analysis error result
+ * descriptors for Dart sources.
+ */
+ List<TaskDescriptor> get dartErrorsForSource =>
+ dartErrorsForSourceExtensionPoint.extensions;
+
+ /**
+ * Return a list containing all of the contributed analysis error result
+ * descriptors for Dart library specific units.
+ */
+ List<TaskDescriptor> get dartErrorsForUnit =>
+ dartErrorsForUnitExtensionPoint.extensions;
+
+ /**
+ * Return a list containing all of the contributed analysis error result
+ * descriptors for HTML sources.
+ */
+ List<TaskDescriptor> get htmlErrors => htmlErrorsExtensionPoint.extensions;
+
+ /**
* Return a list containing all of the task descriptors that were contributed.
*/
List<TaskDescriptor> get taskDescriptors => taskExtensionPoint.extensions;
@@ -72,6 +132,15 @@
@override
void registerExtensionPoints(RegisterExtensionPoint registerExtensionPoint) {
+ dartErrorsForSourceExtensionPoint = registerExtensionPoint(
+ DART_ERRORS_FOR_SOURCE_EXTENSION_POINT,
+ _validateAnalysisErrorListResultDescriptor);
+ dartErrorsForUnitExtensionPoint = registerExtensionPoint(
+ DART_ERRORS_FOR_UNIT_EXTENSION_POINT,
+ _validateAnalysisErrorListResultDescriptor);
+ htmlErrorsExtensionPoint = registerExtensionPoint(
+ HTML_ERRORS_EXTENSION_POINT,
+ _validateAnalysisErrorListResultDescriptor);
taskExtensionPoint =
registerExtensionPoint(TASK_EXTENSION_POINT, _validateTaskExtension);
workManagerFactoryExtensionPoint = registerExtensionPoint(
@@ -83,6 +152,27 @@
void registerExtensions(RegisterExtension registerExtension) {
_registerTaskExtensions(registerExtension);
_registerWorkManagerFactoryExtensions(registerExtension);
+ _registerDartErrorsForSource(registerExtension);
+ _registerDartErrorsForUnit(registerExtension);
+ _registerHtmlErrors(registerExtension);
+ }
+
+ void _registerDartErrorsForSource(RegisterExtension registerExtension) {
+ String id = DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID;
+ registerExtension(id, BUILD_DIRECTIVES_ERRORS);
+ registerExtension(id, BUILD_LIBRARY_ERRORS);
+ registerExtension(id, PARSE_ERRORS);
+ registerExtension(id, SCAN_ERRORS);
+ }
+
+ void _registerDartErrorsForUnit(RegisterExtension registerExtension) {
+ String id = DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID;
+ registerExtension(id, LIBRARY_UNIT_ERRORS);
+ }
+
+ void _registerHtmlErrors(RegisterExtension registerExtension) {
+ String id = HTML_ERRORS_EXTENSION_POINT_ID;
+ registerExtension(id, HTML_DOCUMENT_ERRORS);
}
void _registerTaskExtensions(RegisterExtension registerExtension) {
@@ -145,8 +235,20 @@
}
/**
- * Validate the given extension by throwing an [ExtensionError] if it is not a
- * valid domain.
+ * Validate the given extension by throwing an [ExtensionError] if it is not
+ * a [ListResultDescriptor] of [AnalysisError]s.
+ */
+ void _validateAnalysisErrorListResultDescriptor(Object extension) {
+ if (extension is! ListResultDescriptor<AnalysisError>) {
+ String id = taskExtensionPoint.uniqueIdentifier;
+ throw new ExtensionError(
+ 'Extensions to $id must be a ListResultDescriptor<AnalysisError>');
+ }
+ }
+
+ /**
+ * Validate the given extension by throwing an [ExtensionError] if it is not
+ * a [TaskDescriptor].
*/
void _validateTaskExtension(Object extension) {
if (extension is! TaskDescriptor) {
@@ -156,8 +258,8 @@
}
/**
- * Validate the given extension by throwing an [ExtensionError] if it is not a
- * valid domain.
+ * Validate the given extension by throwing an [ExtensionError] if it is not
+ * a [WorkManagerFactory].
*/
void _validateWorkManagerFactoryExtension(Object extension) {
if (extension is! WorkManagerFactory) {
diff --git a/pkg/analyzer/lib/src/plugin/options_plugin.dart b/pkg/analyzer/lib/src/plugin/options_plugin.dart
index 1dea284..fc82910 100644
--- a/pkg/analyzer/lib/src/plugin/options_plugin.dart
+++ b/pkg/analyzer/lib/src/plugin/options_plugin.dart
@@ -11,7 +11,6 @@
/// by applications that want to consume options defined in the analysis
/// options file.
class OptionsPlugin implements Plugin {
-
/// The simple identifier of the extension point that allows plugins to
/// register new options processors.
static const String OPTIONS_PROCESSOR_EXTENSION_POINT = 'optionsProcessor';
diff --git a/pkg/analyzer/lib/src/services/lint.dart b/pkg/analyzer/lib/src/services/lint.dart
index 9dd51a0..5601c4a 100644
--- a/pkg/analyzer/lib/src/services/lint.dart
+++ b/pkg/analyzer/lib/src/services/lint.dart
@@ -27,7 +27,6 @@
///
/// See [LintCode].
class LintGenerator {
-
/// A global container for contributed linters.
static final List<Linter> LINTERS = <Linter>[];
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index e81545c..88a5637 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -21,6 +21,7 @@
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/plugin/engine_plugin.dart';
import 'package:analyzer/src/task/driver.dart';
import 'package:analyzer/src/task/general.dart';
import 'package:analyzer/src/task/html.dart';
@@ -72,16 +73,6 @@
'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS);
/**
- * A list of the [ClassElement]s representing the classes defined in a
- * compilation unit.
- *
- * The result is only available for [LibrarySpecificUnit]s, and only when strong
- * mode is enabled.
- */
-final ListResultDescriptor<ClassElement> CLASSES_IN_UNIT =
- new ListResultDescriptor<ClassElement>('CLASSES_IN_UNIT', null);
-
-/**
* A list of the [ConstantEvaluationTarget]s defined in a unit. This includes
* constants defined at top level, statically inside classes, and local to
* functions, as well as constant constructors, annotations, and default values
@@ -1932,31 +1923,6 @@
*/
class DartErrorsTask extends SourceBasedAnalysisTask {
/**
- * The name of the [BUILD_DIRECTIVES_ERRORS] input.
- */
- static const String BUILD_DIRECTIVES_ERRORS_INPUT = 'BUILD_DIRECTIVES_ERRORS';
-
- /**
- * The name of the [BUILD_LIBRARY_ERRORS] input.
- */
- static const String BUILD_LIBRARY_ERRORS_INPUT = 'BUILD_LIBRARY_ERRORS';
-
- /**
- * The name of the [LIBRARY_UNIT_ERRORS] input.
- */
- static const String LIBRARY_UNIT_ERRORS_INPUT = 'LIBRARY_UNIT_ERRORS';
-
- /**
- * The name of the [PARSE_ERRORS] input.
- */
- static const String PARSE_ERRORS_INPUT = 'PARSE_ERRORS';
-
- /**
- * The name of the [SCAN_ERRORS] input.
- */
- static const String SCAN_ERRORS_INPUT = 'SCAN_ERRORS';
-
- /**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask',
@@ -1970,18 +1936,21 @@
@override
void internalPerform() {
+ List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
//
// Prepare inputs.
//
- List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
- errorLists.add(getRequiredInput(BUILD_DIRECTIVES_ERRORS_INPUT));
- errorLists.add(getRequiredInput(BUILD_LIBRARY_ERRORS_INPUT));
- errorLists.add(getRequiredInput(PARSE_ERRORS_INPUT));
- errorLists.add(getRequiredInput(SCAN_ERRORS_INPUT));
- Map<Source, List<AnalysisError>> unitErrors =
- getRequiredInput(LIBRARY_UNIT_ERRORS_INPUT);
- for (List<AnalysisError> errors in unitErrors.values) {
- errorLists.add(errors);
+ EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
+ for (ResultDescriptor result in enginePlugin.dartErrorsForSource) {
+ String inputName = result.name + '_input';
+ errorLists.add(getRequiredInput(inputName));
+ }
+ for (ResultDescriptor result in enginePlugin.dartErrorsForUnit) {
+ String inputName = result.name + '_input';
+ Map<Source, List<AnalysisError>> errorMap = getRequiredInput(inputName);
+ for (List<AnalysisError> errors in errorMap.values) {
+ errorLists.add(errors);
+ }
}
//
// Record outputs.
@@ -1996,17 +1965,23 @@
*/
static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
Source source = target;
- return <String, TaskInput>{
- BUILD_DIRECTIVES_ERRORS_INPUT: BUILD_DIRECTIVES_ERRORS.of(source),
- BUILD_LIBRARY_ERRORS_INPUT: BUILD_LIBRARY_ERRORS.of(source),
- PARSE_ERRORS_INPUT: PARSE_ERRORS.of(source),
- SCAN_ERRORS_INPUT: SCAN_ERRORS.of(source),
- LIBRARY_UNIT_ERRORS_INPUT:
+ Map<String, TaskInput> inputs = <String, TaskInput>{};
+ EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
+ // for Source
+ for (ResultDescriptor result in enginePlugin.dartErrorsForSource) {
+ String inputName = result.name + '_input';
+ inputs[inputName] = result.of(source);
+ }
+ // for LibrarySpecificUnit
+ for (ResultDescriptor result in enginePlugin.dartErrorsForUnit) {
+ String inputName = result.name + '_input';
+ inputs[inputName] =
CONTAINING_LIBRARIES.of(source).toMap((Source library) {
LibrarySpecificUnit unit = new LibrarySpecificUnit(library, source);
- return LIBRARY_UNIT_ERRORS.of(unit);
- })
- };
+ return result.of(unit);
+ });
+ }
+ return inputs;
}
/**
@@ -2703,6 +2678,7 @@
"NodeLocator failed to find a variable's declaration");
}
Expression initializer = declaration.initializer;
+ ResolutionEraser.erase(initializer, eraseDeclarations: false);
ResolutionContext resolutionContext =
ResolutionContextBuilder.contextFor(initializer, errorListener);
ResolverVisitor visitor = new ResolverVisitor(
@@ -2725,7 +2701,9 @@
(variable.initializer as ExecutableElementImpl).returnType = newType;
if (variable is PropertyInducingElementImpl) {
setReturnType(variable.getter, newType);
- setParameterType(variable.setter, newType);
+ if (!variable.isFinal && !variable.isConst) {
+ setParameterType(variable.setter, newType);
+ }
}
} else {
// TODO(brianwilkerson) For now we simply don't infer any type for
@@ -3141,7 +3119,6 @@
'PartiallyResolveUnitReferencesTask',
createTask,
buildInputs, <ResultDescriptor>[
- CLASSES_IN_UNIT,
INFERABLE_STATIC_VARIABLES_IN_UNIT,
PARTIALLY_RESOLVE_REFERENCES_ERRORS,
RESOLVED_UNIT5
@@ -3169,29 +3146,14 @@
//
InheritanceManager inheritanceManager =
new InheritanceManager(libraryElement);
- // TODO(brianwilkerson) Improve performance by not resolving anything inside
- // function bodies. Function bodies will be resolved later so this is wasted
- // effort.
- AstVisitor visitor = new ResolverVisitor(
+ PartialResolverVisitor visitor = new PartialResolverVisitor(
libraryElement, unitElement.source, typeProvider, errorListener,
inheritanceManager: inheritanceManager);
unit.accept(visitor);
//
- // Prepare targets for inference.
- //
- List<VariableElement> staticVariables = <VariableElement>[];
- List<ClassElement> classes = <ClassElement>[];
- if (context.analysisOptions.strongMode) {
- InferrenceFinder inferrenceFinder = new InferrenceFinder();
- unit.accept(inferrenceFinder);
- staticVariables = inferrenceFinder.staticVariables;
- classes = inferrenceFinder.classes;
- }
- //
// Record outputs.
//
- outputs[CLASSES_IN_UNIT] = classes;
- outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT] = staticVariables;
+ outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT] = visitor.staticVariables;
outputs[PARTIALLY_RESOLVE_REFERENCES_ERRORS] =
removeDuplicateErrors(errorListener.errors);
outputs[RESOLVED_UNIT5] = unit;
@@ -3438,8 +3400,18 @@
visitor.prepareToResolveMembersInClass(
resolutionContext.enclosingClassDeclaration);
}
- visitor.initForIncrementalResolution();
+ Declaration declaration = functionBody.getAncestor((AstNode node) =>
+ node is ConstructorDeclaration ||
+ node is FunctionDeclaration ||
+ node is MethodDeclaration);
+ visitor.initForIncrementalResolution(declaration);
functionBody.accept(visitor);
+ if (declaration is FunctionDeclaration) {
+ // This is in the wrong place. The propagated return type is stored
+ // locally in the resolver, not in the declaration (or element). Hence,
+ // this needs to happen later.
+ declaration.accept(visitor.typeAnalyzer);
+ }
}
/**
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index e4210d5..8daa5cf 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -102,7 +102,12 @@
WorkOrder workOrder = createWorkOrderForResult(target, result);
if (workOrder != null) {
while (workOrder.moveNext()) {
+// AnalysisTask previousTask = task;
+// String message = workOrder.current.toString();
task = performWorkItem(workOrder.current);
+// if (task == null) {
+// throw new AnalysisException(message, previousTask.caughtException);
+// }
}
}
return task;
diff --git a/pkg/analyzer/lib/src/task/html.dart b/pkg/analyzer/lib/src/task/html.dart
index 0722ed4..d169560 100644
--- a/pkg/analyzer/lib/src/task/html.dart
+++ b/pkg/analyzer/lib/src/task/html.dart
@@ -6,9 +6,13 @@
import 'dart:collection';
+import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/plugin/engine_plugin.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/src/task/general.dart';
import 'package:analyzer/task/dart.dart';
@@ -18,9 +22,6 @@
import 'package:html/dom.dart';
import 'package:html/parser.dart';
import 'package:source_span/source_span.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
/**
* The Dart scripts that are embedded in an HTML file.
@@ -107,11 +108,11 @@
/**
* The task descriptor describing this kind of task.
*/
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartScriptsTask',
- createTask, buildInputs, <ResultDescriptor>[
- DART_SCRIPTS,
- REFERENCED_LIBRARIES
- ]);
+ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+ 'DartScriptsTask',
+ createTask,
+ buildInputs,
+ <ResultDescriptor>[DART_SCRIPTS, REFERENCED_LIBRARIES]);
DartScriptsTask(InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@@ -190,17 +191,17 @@
*/
class HtmlErrorsTask extends SourceBasedAnalysisTask {
/**
+ * The suffix to add to the names of contributed error results.
+ */
+ static const String INPUT_SUFFIX = '_input';
+
+ /**
* The name of the input that is a list of errors from each of the embedded
* Dart scripts.
*/
static const String DART_ERRORS_INPUT = 'DART_ERRORS';
/**
- * The name of the [HTML_DOCUMENT_ERRORS] input.
- */
- static const String DOCUMENT_ERRORS_INPUT = 'DOCUMENT_ERRORS';
-
- /**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('HtmlErrorsTask',
@@ -214,24 +215,26 @@
@override
void internalPerform() {
+ EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
//
// Prepare inputs.
//
List<List<AnalysisError>> dartErrors = getRequiredInput(DART_ERRORS_INPUT);
- List<AnalysisError> documentErrors =
- getRequiredInput(DOCUMENT_ERRORS_INPUT);
+ List<List<AnalysisError>> htmlErrors = <List<AnalysisError>>[];
+ for (ResultDescriptor result in enginePlugin.htmlErrors) {
+ String inputName = result.name + INPUT_SUFFIX;
+ htmlErrors.add(getRequiredInput(inputName));
+ }
//
// Compute the error list.
//
- List<AnalysisError> errors = <AnalysisError>[];
- errors.addAll(documentErrors);
- for (List<AnalysisError> scriptErrors in dartErrors) {
- errors.addAll(scriptErrors);
- }
+ List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
+ errorLists.addAll(dartErrors);
+ errorLists.addAll(htmlErrors);
//
// Record outputs.
//
- outputs[HTML_ERRORS] = removeDuplicateErrors(errors);
+ outputs[HTML_ERRORS] = AnalysisError.mergeLists(errorLists);
}
/**
@@ -240,10 +243,15 @@
* given [target].
*/
static Map<String, TaskInput> buildInputs(Source target) {
- return <String, TaskInput>{
- DOCUMENT_ERRORS_INPUT: HTML_DOCUMENT_ERRORS.of(target),
+ EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
+ Map<String, TaskInput> inputs = <String, TaskInput>{
DART_ERRORS_INPUT: DART_SCRIPTS.of(target).toListOf(DART_ERRORS)
};
+ for (ResultDescriptor result in enginePlugin.htmlErrors) {
+ String inputName = result.name + INPUT_SUFFIX;
+ inputs[inputName] = result.of(target);
+ }
+ return inputs;
}
/**
@@ -268,11 +276,11 @@
/**
* The task descriptor describing this kind of task.
*/
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('ParseHtmlTask',
- createTask, buildInputs, <ResultDescriptor>[
- HTML_DOCUMENT,
- HTML_DOCUMENT_ERRORS
- ]);
+ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+ 'ParseHtmlTask',
+ createTask,
+ buildInputs,
+ <ResultDescriptor>[HTML_DOCUMENT, HTML_DOCUMENT_ERRORS]);
/**
* Initialize a newly created task to access the content of the source
@@ -291,7 +299,8 @@
if (context.getModificationStamp(target.source) < 0) {
String message = 'Content could not be read';
if (context is InternalAnalysisContext) {
- CacheEntry entry = (context as InternalAnalysisContext).getCacheEntry(target);
+ CacheEntry entry =
+ (context as InternalAnalysisContext).getCacheEntry(target);
CaughtException exception = entry.exception;
if (exception != null) {
message = exception.toString();
@@ -299,8 +308,10 @@
}
outputs[HTML_DOCUMENT] = new Document();
- outputs[HTML_DOCUMENT_ERRORS] = <AnalysisError>[new AnalysisError(
- target.source, 0, 0, ScannerErrorCode.UNABLE_GET_CONTENT, [message])];
+ outputs[HTML_DOCUMENT_ERRORS] = <AnalysisError>[
+ new AnalysisError(
+ target.source, 0, 0, ScannerErrorCode.UNABLE_GET_CONTENT, [message])
+ ];
} else {
HtmlParser parser = new HtmlParser(content, generateSpans: true);
parser.compatMode = 'quirks';
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index bc562a7..d6a0c14 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -69,8 +69,8 @@
* Fills [unitDelta] with added/remove elements.
*/
void build() {
- new CompilationUnitBuilder().buildCompilationUnit(
- unitSource, newUnit, librarySource);
+ new CompilationUnitBuilder()
+ .buildCompilationUnit(unitSource, newUnit, librarySource);
_processDirectives();
_processUnitMembers();
newUnit.element = unitElement;
diff --git a/pkg/analyzer/lib/src/task/inputs.dart b/pkg/analyzer/lib/src/task/inputs.dart
index 308b06a..c93a127 100644
--- a/pkg/analyzer/lib/src/task/inputs.dart
+++ b/pkg/analyzer/lib/src/task/inputs.dart
@@ -25,7 +25,8 @@
* defined on a single target.
*/
class ListTaskInputImpl<E> extends SimpleTaskInput<List<E>>
- with ListTaskInputMixin<E> implements ListTaskInput<E> {
+ with ListTaskInputMixin<E>
+ implements ListTaskInput<E> {
/**
* Initialize a newly created task input that computes the input by accessing
* the given [result] associated with the given [target].
@@ -168,7 +169,8 @@
abstract class MapTaskInputMixin<K, V> implements MapTaskInput<K, V> {
TaskInput<List /*<E>*/ > toFlattenList(
BinaryFunction<K, dynamic /*element of V*/, dynamic /*<E>*/ > mapper) {
- return new MapToFlattenListTaskInput<K, dynamic /*element of V*/, dynamic /*E*/ >(
+ return new MapToFlattenListTaskInput<K, dynamic /*element of V*/,
+ dynamic /*E*/ >(
this as MapTaskInput<K, List /*<element of V>*/ >, mapper);
}
}
@@ -301,7 +303,8 @@
* An input to an [AnalysisTask] that is computed by mapping the value of
* another task input to a list of values.
*/
-class ObjectToListTaskInput<E> extends TaskInputImpl<List<E>> with ListTaskInputMixin<E>
+class ObjectToListTaskInput<E> extends TaskInputImpl<List<E>>
+ with ListTaskInputMixin<E>
implements ListTaskInput<E> {
/**
* The input used to compute the value to be mapped.
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index 3d13146..a78d590 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -83,83 +83,6 @@
typedef bool VariableFilter(VariableElement element);
/**
- * An object used to find static variables whose types should be inferred and
- * classes whose members should have types inferred. Clients are expected to
- * visit a [CompilationUnit].
- */
-class InferrenceFinder extends SimpleAstVisitor {
- /**
- * The static variables that should have types inferred for them.
- */
- final List<VariableElement> staticVariables = <VariableElement>[];
-
- /**
- * The classes defined in the unit.
- *
- * TODO(brianwilkerson) We don't currently remove classes whose members do not
- * need to be processed, but we potentially could.
- */
- final List<ClassElement> classes = <ClassElement>[];
-
- /**
- * Initialize a newly created finder.
- */
- InferrenceFinder();
-
- @override
- void visitClassDeclaration(ClassDeclaration node) {
- classes.add(node.element);
- for (ClassMember member in node.members) {
- member.accept(this);
- }
- }
-
- @override
- void visitClassTypeAlias(ClassTypeAlias node) {
- classes.add(node.element);
- }
-
- @override
- void visitCompilationUnit(CompilationUnit node) {
- for (CompilationUnitMember declaration in node.declarations) {
- declaration.accept(this);
- }
- }
-
- @override
- void visitFieldDeclaration(FieldDeclaration node) {
- if (node.isStatic && node.fields.type == null) {
- _addVariables(node.fields.variables);
- }
- }
-
- @override
- void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- if (node.variables.type == null) {
- _addVariables(node.variables.variables);
- }
- }
-
- /**
- * Add all of the [variables] with initializers to the list of variables whose
- * type can be inferred. Technically, we only infer the types of variables
- * that do not have a static type, but all variables with initializers
- * potentially need to be re-resolved after inference because they might
- * refer to fields whose type was inferred.
- */
- void _addVariables(NodeList<VariableDeclaration> variables) {
- for (VariableDeclaration variable in variables) {
- if (variable.initializer != null) {
- VariableElement element = variable.element;
- if (element.hasImplicitType) {
- staticVariables.add(element);
- }
- }
- }
- }
-}
-
-/**
* An object used to infer the type of instance fields and the return types of
* instance methods within a single compilation unit.
*/
@@ -416,7 +339,7 @@
(fieldElement as FieldElementImpl).type = newType;
setReturnType(fieldElement.getter, newType);
if (!fieldElement.isFinal && !fieldElement.isConst) {
- setParameterType(fieldElement.setter, newType);
+ setParameterType(fieldElement.setter, newType);
}
}
}
diff --git a/pkg/analyzer/lib/task/dart.dart b/pkg/analyzer/lib/task/dart.dart
index a0e309e..644ab24 100644
--- a/pkg/analyzer/lib/task/dart.dart
+++ b/pkg/analyzer/lib/task/dart.dart
@@ -128,7 +128,8 @@
* The result is only available for [Source]s representing a compilation unit.
*/
final ResultDescriptor<Token> TOKEN_STREAM = new ResultDescriptor<Token>(
- 'TOKEN_STREAM', null, cachingPolicy: TOKEN_STREAM_CACHING_POLICY);
+ 'TOKEN_STREAM', null,
+ cachingPolicy: TOKEN_STREAM_CACHING_POLICY);
/**
* The sources of the Dart files that a library consists of.
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index 9375576..833a6d3 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -198,8 +198,8 @@
_safelyPerform();
} on AnalysisException catch (exception, stackTrace) {
caughtException = new CaughtException(exception, stackTrace);
- AnalysisEngine.instance.logger.logInformation(
- "Task failed: ${description}", caughtException);
+ AnalysisEngine.instance.logger
+ .logInformation("Task failed: ${description}", caughtException);
}
}
@@ -221,8 +221,8 @@
if (contextName == null) {
contextName = 'unnamed';
}
- AnalysisEngine.instance.instrumentationService.logAnalysisTask(
- contextName, this);
+ AnalysisEngine.instance.instrumentationService
+ .logAnalysisTask(contextName, this);
//
// Gather statistics on the performance of the task.
//
@@ -268,7 +268,8 @@
* values associated with this result will remain in the cache.
*/
factory ListResultDescriptor(String name, List<E> defaultValue,
- {ResultCachingPolicy<List<E>> cachingPolicy}) = ListResultDescriptorImpl<E>;
+ {ResultCachingPolicy<List<E>> cachingPolicy}) = ListResultDescriptorImpl<
+ E>;
@override
ListTaskInput<E> of(AnalysisTarget target);
@@ -443,7 +444,9 @@
* and produces the given [results]. The [buildTask] will be used to create
* the instance of [AnalysisTask] thusly described.
*/
- factory TaskDescriptor(String name, BuildTask buildTask,
+ factory TaskDescriptor(
+ String name,
+ BuildTask buildTask,
CreateTaskInputs inputBuilder,
List<ResultDescriptor> results) = TaskDescriptorImpl;
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index a08ede7..a60941b 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -38,11 +38,64 @@
void initializeTestEnvironment() {}
void _assertEqualError(AnalysisError incrError, AnalysisError fullError) {
- expect(incrError.errorCode, same(fullError.errorCode));
- expect(incrError.source, fullError.source);
- expect(incrError.offset, fullError.offset);
- expect(incrError.length, fullError.length);
- expect(incrError.message, fullError.message);
+ if (incrError.errorCode != fullError.errorCode ||
+ incrError.source != fullError.source ||
+ incrError.offset != fullError.offset ||
+ incrError.length != fullError.length ||
+ incrError.message != fullError.message) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.writeln('Found error does not match expected error:');
+ if (incrError.errorCode == fullError.errorCode) {
+ buffer.write(' errorCode = ');
+ buffer.write(fullError.errorCode.uniqueName);
+ } else {
+ buffer.write(' Expected errorCode = ');
+ buffer.write(fullError.errorCode.uniqueName);
+ buffer.write(' found ');
+ buffer.write(incrError.errorCode.uniqueName);
+ }
+ buffer.writeln();
+ if (incrError.source == fullError.source) {
+ buffer.write(' source = ');
+ buffer.write(fullError.source);
+ } else {
+ buffer.write(' Expected source = ');
+ buffer.write(fullError.source);
+ buffer.write(' found ');
+ buffer.write(incrError.source);
+ }
+ buffer.writeln();
+ if (incrError.offset == fullError.offset) {
+ buffer.write(' offset = ');
+ buffer.write(fullError.offset);
+ } else {
+ buffer.write(' Expected offset = ');
+ buffer.write(fullError.offset);
+ buffer.write(' found ');
+ buffer.write(incrError.offset);
+ }
+ buffer.writeln();
+ if (incrError.length == fullError.length) {
+ buffer.write(' length = ');
+ buffer.write(fullError.length);
+ } else {
+ buffer.write(' Expected length = ');
+ buffer.write(fullError.length);
+ buffer.write(' found ');
+ buffer.write(incrError.length);
+ }
+ buffer.writeln();
+ if (incrError.message == fullError.message) {
+ buffer.write(' message = ');
+ buffer.write(fullError.message);
+ } else {
+ buffer.write(' Expected message = ');
+ buffer.write(fullError.message);
+ buffer.write(' found ');
+ buffer.write(incrError.message);
+ }
+ fail(buffer.toString());
+ }
}
void _assertEqualErrors(
@@ -4425,8 +4478,7 @@
// Resolve "newCode" from scratch.
if (compareWithFull) {
_resetWithIncremental(false);
- source = addSource(newCode + ' ');
- source = addSource(newCode);
+ changeSource(source, newCode);
_runTasks();
LibraryElement library = resolve2(source);
CompilationUnit fullNewUnit = resolveCompilationUnit(source, library);
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 6463a7b..f5153cf 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -7974,6 +7974,16 @@
}
/**
+ * Change the contents of the given [source] to the given [contents].
+ */
+ void changeSource(Source source, String contents) {
+ analysisContext2.setContents(source, contents);
+ ChangeSet changeSet = new ChangeSet();
+ changeSet.changedSource(source);
+ analysisContext2.applyChanges(changeSet);
+ }
+
+ /**
* Computes errors for the given [librarySource].
* This assumes that the given [librarySource] and its parts have already
* been added to the content provider using the method [addNamedSource].
@@ -8054,75 +8064,6 @@
}
/**
- * @param code the code that iterates using variable "v". We check that
- * "v" has expected static and propagated type.
- */
- void _assertPropagatedIterationType(String code, DartType expectedStaticType,
- DartType expectedPropagatedType) {
- SimpleIdentifier identifier = _findMarkedIdentifier(code, "v in ");
- expect(identifier.staticType, same(expectedStaticType));
- expect(identifier.propagatedType, same(expectedPropagatedType));
- }
-
- /**
- * @param code the code that assigns the value to the variable "v", no matter how. We check that
- * "v" has expected static and propagated type.
- */
- void _assertPropagatedAssignedType(String code, DartType expectedStaticType,
- DartType expectedPropagatedType) {
- SimpleIdentifier identifier = _findMarkedIdentifier(code, "v = ");
- expect(identifier.staticType, same(expectedStaticType));
- expect(identifier.propagatedType, same(expectedPropagatedType));
- }
-
- /**
- * Check the static and propagated types of the expression marked with "; // marker" comment.
- *
- * @param code source code to analyze, with the expression to check marked with "// marker".
- * @param expectedStaticType if non-null, check actual static type is equal to this.
- * @param expectedPropagatedType if non-null, check actual static type is equal to this.
- * @throws Exception
- */
- void _assertTypeOfMarkedExpression(String code, DartType expectedStaticType,
- DartType expectedPropagatedType) {
- SimpleIdentifier identifier = _findMarkedIdentifier(code, "; // marker");
- if (expectedStaticType != null) {
- expect(identifier.staticType, expectedStaticType);
- }
- expect(identifier.propagatedType, expectedPropagatedType);
- }
-
- /**
- * Return the `SimpleIdentifier` marked by `marker`. The source code must have no
- * errors and be verifiable.
- *
- * @param code source code to analyze.
- * @param marker marker identifying sought after expression in source code.
- * @return expression marked by the marker.
- * @throws Exception
- */
- SimpleIdentifier _findMarkedIdentifier(String code, String marker) {
- try {
- Source source = addSource(code);
- LibraryElement library = resolve2(source);
- assertNoErrors(source);
- verify([source]);
- CompilationUnit unit = resolveCompilationUnit(source, library);
- // Could generalize this further by making [SimpleIdentifier.class] a
- // parameter.
- return EngineTestCase.findNode(
- unit, code, marker, (node) => node is SimpleIdentifier);
- } catch (exception) {
- // Is there a better exception to throw here? The point is that an
- // assertion failure here should be a failure, in both "test_*" and
- // "fail_*" tests. However, an assertion failure is success for the
- // purpose of "fail_*" tests, so without catching them here "fail_*" tests
- // can succeed by failing for the wrong reason.
- throw new JavaException("Unexexpected assertion failure: $exception");
- }
- }
-
- /**
* In the rare cases we want to group several tests into single "test_" method, so need a way to
* reset test instance to reuse it.
*/
@@ -8241,6 +8182,45 @@
}
/**
+ * @param code the code that assigns the value to the variable "v", no matter how. We check that
+ * "v" has expected static and propagated type.
+ */
+ void _assertPropagatedAssignedType(String code, DartType expectedStaticType,
+ DartType expectedPropagatedType) {
+ SimpleIdentifier identifier = _findMarkedIdentifier(code, "v = ");
+ expect(identifier.staticType, same(expectedStaticType));
+ expect(identifier.propagatedType, same(expectedPropagatedType));
+ }
+
+ /**
+ * @param code the code that iterates using variable "v". We check that
+ * "v" has expected static and propagated type.
+ */
+ void _assertPropagatedIterationType(String code, DartType expectedStaticType,
+ DartType expectedPropagatedType) {
+ SimpleIdentifier identifier = _findMarkedIdentifier(code, "v in ");
+ expect(identifier.staticType, same(expectedStaticType));
+ expect(identifier.propagatedType, same(expectedPropagatedType));
+ }
+
+ /**
+ * Check the static and propagated types of the expression marked with "; // marker" comment.
+ *
+ * @param code source code to analyze, with the expression to check marked with "// marker".
+ * @param expectedStaticType if non-null, check actual static type is equal to this.
+ * @param expectedPropagatedType if non-null, check actual static type is equal to this.
+ * @throws Exception
+ */
+ void _assertTypeOfMarkedExpression(String code, DartType expectedStaticType,
+ DartType expectedPropagatedType) {
+ SimpleIdentifier identifier = _findMarkedIdentifier(code, "; // marker");
+ if (expectedStaticType != null) {
+ expect(identifier.staticType, expectedStaticType);
+ }
+ expect(identifier.propagatedType, expectedPropagatedType);
+ }
+
+ /**
* Create a source object representing a file with the given [fileName] and
* give it an empty content. Return the source that was created.
*/
@@ -8250,6 +8230,36 @@
analysisContext2.setContents(source, "");
return source;
}
+
+ /**
+ * Return the `SimpleIdentifier` marked by `marker`. The source code must have no
+ * errors and be verifiable.
+ *
+ * @param code source code to analyze.
+ * @param marker marker identifying sought after expression in source code.
+ * @return expression marked by the marker.
+ * @throws Exception
+ */
+ SimpleIdentifier _findMarkedIdentifier(String code, String marker) {
+ try {
+ Source source = addSource(code);
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = resolveCompilationUnit(source, library);
+ // Could generalize this further by making [SimpleIdentifier.class] a
+ // parameter.
+ return EngineTestCase.findNode(
+ unit, code, marker, (node) => node is SimpleIdentifier);
+ } catch (exception) {
+ // Is there a better exception to throw here? The point is that an
+ // assertion failure here should be a failure, in both "test_*" and
+ // "fail_*" tests. However, an assertion failure is success for the
+ // purpose of "fail_*" tests, so without catching them here "fail_*" tests
+ // can succeed by failing for the wrong reason.
+ throw new JavaException("Unexexpected assertion failure: $exception");
+ }
+ }
}
class Scope_EnclosedScopeTest_test_define_duplicate extends Scope {
@@ -11870,6 +11880,273 @@
}
@reflectiveTest
+class StrongModeTypePropagationTest extends ResolverTestCase {
+ @override
+ void setUp() {
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ options.strongMode = true;
+ resetWithOptions(options);
+ }
+
+ void test_foreachInference_dynamic_disabled() {
+ String code = r'''
+main() {
+ var list = <int>[];
+ for (dynamic v in list) {
+ v; // marker
+ }
+}''';
+ _assertPropagatedIterationType(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ _assertTypeOfMarkedExpression(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ }
+
+ void test_foreachInference_reusedVar_disabled() {
+ String code = r'''
+main() {
+ var list = <int>[];
+ var v;
+ for (v in list) {
+ v; // marker
+ }
+}''';
+ _assertPropagatedIterationType(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ _assertTypeOfMarkedExpression(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ }
+
+ void test_foreachInference_var() {
+ String code = r'''
+main() {
+ var list = <int>[];
+ for (var v in list) {
+ v; // marker
+ }
+}''';
+ _assertPropagatedIterationType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_foreachInference_var_iterable() {
+ String code = r'''
+main() {
+ Iterable<int> list = <int>[];
+ for (var v in list) {
+ v; // marker
+ }
+}''';
+ _assertPropagatedIterationType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_foreachInference_var_stream() {
+ String code = r'''
+import 'dart:async';
+main() async {
+ Stream<int> stream = null;
+ await for (var v in stream) {
+ v; // marker
+ }
+}''';
+ _assertPropagatedIterationType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_bottom_disabled() {
+ String code = r'''
+main() {
+ var v = null;
+ return v; // marker
+}''';
+ _assertPropagatedAssignedType(code, typeProvider.dynamicType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.dynamicType, null);
+ }
+
+ void test_localVariableInference_constant() {
+ String code = r'''
+main() {
+ var v = 3;
+ return v; // marker
+}''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_declaredType_disabled() {
+ String code = r'''
+main() {
+ dynamic v = 3;
+ return v; // marker
+}''';
+ _assertPropagatedAssignedType(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ _assertTypeOfMarkedExpression(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ }
+
+ void test_localVariableInference_noInitializer_disabled() {
+ String code = r'''
+main() {
+ var v;
+ v = 3;
+ return v; // marker
+}''';
+ _assertPropagatedAssignedType(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ _assertTypeOfMarkedExpression(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ }
+
+ void test_localVariableInference_transitive_field_inferred_lexical() {
+ if (!AnalysisEngine.instance.useTaskModel) {
+ return;
+ }
+ String code = r'''
+class A {
+ final x = 3;
+ f() {
+ var v = x;
+ return v; // marker
+ }
+}
+main() {
+}
+''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_transitive_field_inferred_reversed() {
+ if (!AnalysisEngine.instance.useTaskModel) {
+ return;
+ }
+ String code = r'''
+class A {
+ f() {
+ var v = x;
+ return v; // marker
+ }
+ final x = 3;
+}
+main() {
+}
+''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_transitive_field_lexical() {
+ String code = r'''
+class A {
+ int x = 3;
+ f() {
+ var v = x;
+ return v; // marker
+ }
+}
+main() {
+}
+''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_transitive_field_reversed() {
+ String code = r'''
+class A {
+ f() {
+ var v = x;
+ return v; // marker
+ }
+ int x = 3;
+}
+main() {
+}
+''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_transitive_list_local() {
+ String code = r'''
+main() {
+ var x = <int>[3];
+ var v = x[0];
+ return v; // marker
+}''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_transitive_local() {
+ String code = r'''
+main() {
+ var x = 3;
+ var v = x;
+ return v; // marker
+}''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_transitive_toplevel_inferred_lexical() {
+ if (!AnalysisEngine.instance.useTaskModel) {
+ return;
+ }
+ String code = r'''
+final x = 3;
+main() {
+ var v = x;
+ return v; // marker
+}
+''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_transitive_toplevel_inferred_reversed() {
+ if (!AnalysisEngine.instance.useTaskModel) {
+ return;
+ }
+ String code = r'''
+main() {
+ var v = x;
+ return v; // marker
+}
+final x = 3;
+''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_transitive_toplevel_lexical() {
+ String code = r'''
+int x = 3;
+main() {
+ var v = x;
+ return v; // marker
+}
+''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_localVariableInference_transitive_toplevel_reversed() {
+ String code = r'''
+main() {
+ var v = x;
+ return v; // marker
+}
+int x = 3;
+''';
+ _assertPropagatedAssignedType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+}
+
+@reflectiveTest
class SubtypeManagerTest extends EngineTestCase {
/**
* The inheritance manager being tested.
@@ -13443,72 +13720,6 @@
typeProvider.stringType);
}
- void test_propagatedReturnType_function_hasReturnType_returnsNull() {
- String code = r'''
-String f() => null;
-main() {
- var v = f();
-}''';
- _assertPropagatedAssignedType(
- code, typeProvider.dynamicType, typeProvider.stringType);
- }
-
- void test_propagatedReturnType_function_lessSpecificStaticReturnType() {
- String code = r'''
-Object f() => 42;
-main() {
- var v = f();
-}''';
- _assertPropagatedAssignedType(
- code, typeProvider.dynamicType, typeProvider.intType);
- }
-
- void test_propagatedReturnType_function_moreSpecificStaticReturnType() {
- String code = r'''
-int f(v) => (v as num);
-main() {
- var v = f(3);
-}''';
- _assertPropagatedAssignedType(
- code, typeProvider.dynamicType, typeProvider.intType);
- }
-
- void test_propagatedReturnType_function_noReturnTypeName_blockBody_multipleReturns() {
- String code = r'''
-f() {
- if (true) return 0;
- return 1.0;
-}
-main() {
- var v = f();
-}''';
- _assertPropagatedAssignedType(
- code, typeProvider.dynamicType, typeProvider.numType);
- }
-
- void test_propagatedReturnType_function_noReturnTypeName_blockBody_oneReturn() {
- String code = r'''
-f() {
- var z = 42;
- return z;
-}
-main() {
- var v = f();
-}''';
- _assertPropagatedAssignedType(
- code, typeProvider.dynamicType, typeProvider.intType);
- }
-
- void test_propagatedReturnType_function_noReturnTypeName_expressionBody() {
- String code = r'''
-f() => 42;
-main() {
- var v = f();
-}''';
- _assertPropagatedAssignedType(
- code, typeProvider.dynamicType, typeProvider.intType);
- }
-
void test_propagatedReturnType_localFunction() {
String code = r'''
main() {
@@ -13563,261 +13774,6 @@
}
@reflectiveTest
-class StrongModeTypePropagationTest extends ResolverTestCase {
- @override
- void setUp() {
- AnalysisOptionsImpl options = new AnalysisOptionsImpl();
- options.strongMode = true;
- resetWithOptions(options);
- }
-
- void test_localVariableInference_constant() {
- String code = r'''
-main() {
- var v = 3;
- return v; // marker
-}''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void test_localVariableInference_transitive_local() {
- String code = r'''
-main() {
- var x = 3;
- var v = x;
- return v; // marker
-}''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void test_localVariableInference_transitive_list_local() {
- String code = r'''
-main() {
- var x = <int>[3];
- var v = x[0];
- return v; // marker
-}''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void test_localVariableInference_transitive_toplevel_lexical() {
- String code = r'''
-int x = 3;
-main() {
- var v = x;
- return v; // marker
-}
-''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void test_localVariableInference_transitive_toplevel_reversed() {
- String code = r'''
-main() {
- var v = x;
- return v; // marker
-}
-int x = 3;
-''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void fail_localVariableInference_transitive_toplevel_inferred_lexical() {
- String code = r'''
-final x = 3;
-main() {
- var v = x;
- return v; // marker
-}
-''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void fail_localVariableInference_transitive_toplevel_inferred_reversed() {
- String code = r'''
-main() {
- var v = x;
- return v; // marker
-}
-final x = 3;
-''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void test_localVariableInference_transitive_field_lexical() {
- String code = r'''
-class A {
- int x = 3;
- f() {
- var v = x;
- return v; // marker
- }
-}
-main() {
-}
-''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void test_localVariableInference_transitive_field_reversed() {
- String code = r'''
-class A {
- f() {
- var v = x;
- return v; // marker
- }
- int x = 3;
-}
-main() {
-}
-''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void fail_localVariableInference_transitive_field_inferred_lexical() {
- String code = r'''
-class A {
- final x = 3;
- f() {
- var v = x;
- return v; // marker
- }
-}
-main() {
-}
-''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void fail_localVariableInference_transitive_field_inferred_reversed() {
- String code = r'''
-class A {
- f() {
- var v = x;
- return v; // marker
- }
- final x = 3;
-}
-main() {
-}
-''';
- _assertPropagatedAssignedType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void test_localVariableInference_declaredType_disabled() {
- String code = r'''
-main() {
- dynamic v = 3;
- return v; // marker
-}''';
- _assertPropagatedAssignedType(
- code, typeProvider.dynamicType, typeProvider.intType);
- _assertTypeOfMarkedExpression(
- code, typeProvider.dynamicType, typeProvider.intType);
- }
-
- void test_localVariableInference_bottom_disabled() {
- String code = r'''
-main() {
- var v = null;
- return v; // marker
-}''';
- _assertPropagatedAssignedType(code, typeProvider.dynamicType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.dynamicType, null);
- }
-
- void test_localVariableInference_noInitializer_disabled() {
- String code = r'''
-main() {
- var v;
- v = 3;
- return v; // marker
-}''';
- _assertPropagatedAssignedType(
- code, typeProvider.dynamicType, typeProvider.intType);
- _assertTypeOfMarkedExpression(
- code, typeProvider.dynamicType, typeProvider.intType);
- }
-
- void test_foreachInference_var() {
- String code = r'''
-main() {
- var list = <int>[];
- for (var v in list) {
- v; // marker
- }
-}''';
- _assertPropagatedIterationType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void test_foreachInference_var_iterable() {
- String code = r'''
-main() {
- Iterable<int> list = <int>[];
- for (var v in list) {
- v; // marker
- }
-}''';
- _assertPropagatedIterationType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void test_foreachInference_var_stream() {
- String code = r'''
-import 'dart:async';
-main() async {
- Stream<int> stream = null;
- await for (var v in stream) {
- v; // marker
- }
-}''';
- _assertPropagatedIterationType(code, typeProvider.intType, null);
- _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
- }
-
- void test_foreachInference_dynamic_disabled() {
- String code = r'''
-main() {
- var list = <int>[];
- for (dynamic v in list) {
- v; // marker
- }
-}''';
- _assertPropagatedIterationType(
- code, typeProvider.dynamicType, typeProvider.intType);
- _assertTypeOfMarkedExpression(
- code, typeProvider.dynamicType, typeProvider.intType);
- }
-
- void test_foreachInference_reusedVar_disabled() {
- String code = r'''
-main() {
- var list = <int>[];
- var v;
- for (v in list) {
- v; // marker
- }
-}''';
- _assertPropagatedIterationType(
- code, typeProvider.dynamicType, typeProvider.intType);
- _assertTypeOfMarkedExpression(
- code, typeProvider.dynamicType, typeProvider.intType);
- }
-}
-
-@reflectiveTest
class TypeProviderImplTest extends EngineTestCase {
void test_creation() {
//
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 6c1b066..20cc0e2 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -558,7 +558,8 @@
bool generateExceptionOnRead = false;
@override
- int get modificationStamp => generateExceptionOnRead ? -1 : _modificationStamp;
+ int get modificationStamp =>
+ generateExceptionOnRead ? -1 : _modificationStamp;
/**
* The number of times that the contents of this source have been requested.
@@ -575,46 +576,58 @@
}
return new TimestampedData<String>(0, _contents);
}
+
String get encoding {
throw new UnsupportedOperationException();
}
+
String get fullName {
return _name;
}
+
int get hashCode => 0;
bool get isInSystemLibrary {
return false;
}
+
String get shortName {
return _name;
}
+
Uri get uri {
throw new UnsupportedOperationException();
}
+
UriKind get uriKind {
throw new UnsupportedOperationException();
}
+
bool operator ==(Object other) {
if (other is TestSource) {
return other._name == _name;
}
return false;
}
+
bool exists() => exists2;
void getContentsToReceiver(Source_ContentReceiver receiver) {
throw new UnsupportedOperationException();
}
+
Source resolve(String uri) {
throw new UnsupportedOperationException();
}
+
Uri resolveRelativeUri(Uri uri) {
return new Uri(scheme: 'file', path: _name).resolveUri(uri);
}
+
void setContents(String value) {
generateExceptionOnRead = false;
_modificationStamp = new DateTime.now().millisecondsSinceEpoch;
_contents = value;
}
+
@override
String toString() => '$_name';
}
diff --git a/pkg/analyzer/test/instrumentation/instrumentation_test.dart b/pkg/analyzer/test/instrumentation/instrumentation_test.dart
index e23fd9a..290b71a 100644
--- a/pkg/analyzer/test/instrumentation/instrumentation_test.dart
+++ b/pkg/analyzer/test/instrumentation/instrumentation_test.dart
@@ -111,8 +111,10 @@
service.logVersion('myUuid', 'someClientId', 'someClientVersion',
'aServerVersion', 'anSdkVersion');
expect(server.normalChannel.toString(), '');
- expect(server.priorityChannel.toString(), endsWith(
- ':myUuid:someClientId:someClientVersion:aServerVersion:anSdkVersion\n'));
+ expect(
+ server.priorityChannel.toString(),
+ endsWith(
+ ':myUuid:someClientId:someClientVersion:aServerVersion:anSdkVersion\n'));
}
}
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart
index b9f3608..21432ed 100644
--- a/pkg/analyzer/test/src/context/cache_test.dart
+++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -622,6 +622,38 @@
expect(cache.get(target2), isNull);
}
+ test_setState_invalid_withDelta_keepDependency() {
+ Source target = new TestSource('/test.dart');
+ CacheEntry entry = new CacheEntry(target);
+ cache.put(entry);
+ ResultDescriptor result1 = new ResultDescriptor('result1', -1);
+ ResultDescriptor result2 = new ResultDescriptor('result2', -2);
+ ResultDescriptor result3 = new ResultDescriptor('result3', -3);
+ // set results, all of them are VALID
+ entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+ entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
+ entry.setValue(result3, 333, [new TargetedResult(target, result2)]);
+ expect(entry.getState(result1), CacheState.VALID);
+ expect(entry.getState(result2), CacheState.VALID);
+ expect(entry.getState(result3), CacheState.VALID);
+ // result2 depends on result1
+ expect(entry.getResultData(result1).dependentResults,
+ unorderedEquals([new TargetedResult(target, result2)]));
+ expect(entry.getResultData(result2).dependedOnResults,
+ unorderedEquals([new TargetedResult(target, result1)]));
+ // invalidate result2 with Delta: keep result2, invalidate result3
+ entry.setState(result2, CacheState.INVALID,
+ delta: new _KeepContinueDelta(target, result2));
+ expect(entry.getState(result1), CacheState.VALID);
+ expect(entry.getState(result2), CacheState.VALID);
+ expect(entry.getState(result3), CacheState.INVALID);
+ // result2 still depends on result1
+ expect(entry.getResultData(result1).dependentResults,
+ unorderedEquals([new TargetedResult(target, result2)]));
+ expect(entry.getResultData(result2).dependedOnResults,
+ unorderedEquals([new TargetedResult(target, result1)]));
+ }
+
test_setState_valid() {
AnalysisTarget target = new TestSource();
ResultDescriptor result = new ResultDescriptor('test', null);
@@ -713,6 +745,8 @@
expect(entry.getValue(result1), 111);
expect(entry.getValue(result2), 2222);
expect(entry.getValue(result3), -3);
+ expect(entry.getResultData(result1).dependentResults,
+ unorderedEquals([new TargetedResult(target, result2)]));
expect(entry.getResultData(result2).dependedOnResults,
unorderedEquals([new TargetedResult(target, result1)]));
}
@@ -1057,6 +1091,25 @@
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
+/**
+ * Keep the given [keepDescriptor], invalidate all the other results.
+ */
+class _KeepContinueDelta implements Delta {
+ final Source source;
+ final ResultDescriptor keepDescriptor;
+
+ _KeepContinueDelta(this.source, this.keepDescriptor);
+
+ @override
+ DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
+ ResultDescriptor descriptor) {
+ if (descriptor == keepDescriptor) {
+ return DeltaResult.KEEP_CONTINUE;
+ }
+ return DeltaResult.INVALIDATE;
+ }
+}
+
class _TestAnalysisTarget implements AnalysisTarget {
@override
Source get source => null;
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index bad2cc6..acfb596 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -2239,7 +2239,7 @@
}
''');
_assertInvalid(sourceA, LIBRARY_ERRORS_READY);
- _assertValid(sourceB, LIBRARY_ERRORS_READY);
+ _assertValid(sourceB, LIBRARY_ELEMENT);
// The a.dart's unit and element are updated incrementally.
// They are the same instances as initially.
// So, all the references from other units are still valid.
@@ -2275,7 +2275,7 @@
}
''');
_assertInvalid(sourceA, LIBRARY_ERRORS_READY);
- _assertInvalid(sourceB, LIBRARY_ERRORS_READY);
+ _assertInvalid(sourceB, LIBRARY_ELEMENT);
// The a.dart's unit and element are the same.
{
LibrarySpecificUnit target = new LibrarySpecificUnit(sourceA, sourceA);
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index e5b7bcb..25de8b3 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -14,8 +14,10 @@
import 'package:analyzer/src/generated/source.dart';
class MockSdk implements DartSdk {
- static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary('dart:core',
- '/lib/core/core.dart', '''
+ static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary(
+ 'dart:core',
+ '/lib/core/core.dart',
+ '''
library dart.core;
import 'dart:async';
@@ -108,8 +110,10 @@
const Object override = const _Override();
''');
- static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary('dart:async',
- '/lib/async/async.dart', '''
+ static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary(
+ 'dart:async',
+ '/lib/async/async.dart',
+ '''
library dart.async;
import 'dart:math';
@@ -125,14 +129,18 @@
''');
static const _MockSdkLibrary LIB_COLLECTION = const _MockSdkLibrary(
- 'dart:collection', '/lib/collection/collection.dart', '''
+ 'dart:collection',
+ '/lib/collection/collection.dart',
+ '''
library dart.collection;
abstract class HashMap<K, V> implements Map<K, V> {}
''');
static const _MockSdkLibrary LIB_CONVERT = const _MockSdkLibrary(
- 'dart:convert', '/lib/convert/convert.dart', '''
+ 'dart:convert',
+ '/lib/convert/convert.dart',
+ '''
library dart.convert;
import 'dart:async';
@@ -141,8 +149,10 @@
class JsonDecoder extends Converter<String, Object> {}
''');
- static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary('dart:math',
- '/lib/math/math.dart', '''
+ static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary(
+ 'dart:math',
+ '/lib/math/math.dart',
+ '''
library dart.math;
const double E = 2.718281828459045;
const double PI = 3.1415926535897932;
@@ -159,8 +169,10 @@
}
''');
- static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary('dart:html',
- '/lib/html/dartium/html_dartium.dart', '''
+ static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary(
+ 'dart:html',
+ '/lib/html/dartium/html_dartium.dart',
+ '''
library dart.html;
class HtmlElement {}
''');
diff --git a/pkg/analyzer/test/src/mock_sdk.dart b/pkg/analyzer/test/src/mock_sdk.dart
index 1487f4a..d4f6ac1 100644
--- a/pkg/analyzer/test/src/mock_sdk.dart
+++ b/pkg/analyzer/test/src/mock_sdk.dart
@@ -12,8 +12,10 @@
import 'package:analyzer/src/generated/source.dart';
class MockSdk implements DartSdk {
- static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary('dart:core',
- '/lib/core/core.dart', '''
+ static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary(
+ 'dart:core',
+ '/lib/core/core.dart',
+ '''
library dart.core;
import 'dart:async';
@@ -106,8 +108,10 @@
const Object override = const _Override();
''');
- static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary('dart:async',
- '/lib/async/async.dart', '''
+ static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary(
+ 'dart:async',
+ '/lib/async/async.dart',
+ '''
library dart.async;
import 'dart:math';
@@ -123,14 +127,18 @@
''');
static const _MockSdkLibrary LIB_COLLECTION = const _MockSdkLibrary(
- 'dart:collection', '/lib/collection/collection.dart', '''
+ 'dart:collection',
+ '/lib/collection/collection.dart',
+ '''
library dart.collection;
abstract class HashMap<K, V> implements Map<K, V> {}
''');
static const _MockSdkLibrary LIB_CONVERT = const _MockSdkLibrary(
- 'dart:convert', '/lib/convert/convert.dart', '''
+ 'dart:convert',
+ '/lib/convert/convert.dart',
+ '''
library dart.convert;
import 'dart:async';
@@ -139,8 +147,10 @@
class JsonDecoder extends Converter<String, Object> {}
''');
- static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary('dart:math',
- '/lib/math/math.dart', '''
+ static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary(
+ 'dart:math',
+ '/lib/math/math.dart',
+ '''
library dart.math;
const double E = 2.718281828459045;
const double PI = 3.1415926535897932;
@@ -157,8 +167,10 @@
}
''');
- static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary('dart:html',
- '/lib/html/dartium/html_dartium.dart', '''
+ static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary(
+ 'dart:html',
+ '/lib/html/dartium/html_dartium.dart',
+ '''
library dart.html;
class HtmlElement {}
''');
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 95a9ff5..3667038 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -57,7 +57,6 @@
runReflectiveTests(PartiallyResolveUnitReferencesTaskTest);
runReflectiveTests(ResolveFunctionBodiesInUnitTaskTest);
runReflectiveTests(ResolveLibraryTypeNamesTaskTest);
-// runReflectiveTests(ResolveUnitReferencesTaskTest);
runReflectiveTests(ResolveUnitTypeNamesTaskTest);
runReflectiveTests(ResolveVariableReferencesTaskTest);
runReflectiveTests(ScanDartTaskTest);
@@ -1911,7 +1910,22 @@
@reflectiveTest
class InferStaticVariableTypesInUnitTaskTest extends _AbstractDartTaskTest {
- void test_perform() {
+ void test_perform_nestedDeclarations() {
+ enableStrongMode();
+ AnalysisTarget source = newSource(
+ '/test.dart',
+ '''
+var f = (int x) {
+ int squared(int value) => value * value;
+ var xSquared = squared(x);
+ return xSquared;
+};
+''');
+ computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6,
+ matcher: isInferStaticVariableTypesInUnitTask);
+ }
+
+ void test_perform_recursive() {
enableStrongMode();
AnalysisTarget firstSource = newSource(
'/first.dart',
@@ -1949,6 +1963,30 @@
expect(variableC.element.type, typeM);
expect(variableC.initializer.staticType, typeM);
}
+
+ void test_perform_simple() {
+ enableStrongMode();
+ AnalysisTarget source = newSource(
+ '/test.dart',
+ '''
+var X = 1;
+
+var Y = () {
+ return 1 + X;
+};
+''');
+ computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6,
+ matcher: isInferStaticVariableTypesInUnitTask);
+ CompilationUnit unit = outputs[RESOLVED_UNIT6];
+ TopLevelVariableDeclaration declaration = unit.declarations[1];
+ FunctionExpression function =
+ declaration.variables.variables[0].initializer;
+ BlockFunctionBody body = function.body;
+ ReturnStatement statement = body.block.statements[0];
+ Expression expression = statement.expression;
+ InterfaceType intType = context.typeProvider.intType;
+ expect(expression.staticType, intType);
+ }
}
@reflectiveTest
@@ -2269,8 +2307,7 @@
computeResult(target, RESOLVED_UNIT5,
matcher: isPartiallyResolveUnitReferencesTask);
// Test the outputs
- expect(outputs[CLASSES_IN_UNIT], hasLength(2));
- expect(outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT], hasLength(2));
+ expect(outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT], hasLength(4));
CompilationUnit unit = outputs[RESOLVED_UNIT5];
expect(unit, same(outputs[RESOLVED_UNIT5]));
// Test the state of the AST
@@ -2280,8 +2317,7 @@
expect(initializer.staticElement, isNotNull);
// Test the error generation
_fillErrorListener(PARTIALLY_RESOLVE_REFERENCES_ERRORS);
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[StaticWarningCode.UNDEFINED_IDENTIFIER]);
+ errorListener.assertNoErrors();
}
test_perform_importExport() {
@@ -2311,20 +2347,83 @@
computeResult(new LibrarySpecificUnit(sourceC, sourceC), RESOLVED_UNIT5,
matcher: isPartiallyResolveUnitReferencesTask);
// validate
- expect(outputs[CLASSES_IN_UNIT], hasLength(0));
expect(outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT], hasLength(0));
CompilationUnit unit = outputs[RESOLVED_UNIT5];
expect(unit, isNotNull);
- FunctionDeclaration functionDeclaration = unit.declarations[0];
- BlockFunctionBody body = functionDeclaration.functionExpression.body;
+ FunctionDeclaration mainFunction = unit.declarations[0];
+ expect(mainFunction.element, isNotNull);
+ BlockFunctionBody body = mainFunction.functionExpression.body;
List<Statement> statements = body.block.statements;
ExpressionStatement statement = statements[0];
MethodInvocation invocation = statement.expression;
MethodElement methodElement = invocation.methodName.staticElement;
- expect(methodElement, isNotNull);
- expect(methodElement.type, isNotNull);
- expect(methodElement.returnType.toString(), 'int');
+ expect(methodElement, isNull);
+ }
+
+ test_perform_notResolved() {
+ enableStrongMode();
+ Source source = newSource(
+ '/test.dart',
+ '''
+int A;
+f1() {
+ A;
+}
+var f2 = () {
+ A;
+ void f3() {
+ A;
+ }
+}
+class C {
+ C() {
+ A;
+ }
+ m() {
+ A;
+ }
+}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT5,
+ matcher: isPartiallyResolveUnitReferencesTask);
+ CompilationUnit unit = outputs[RESOLVED_UNIT5];
+ NodeList<CompilationUnitMember> declarations = unit.declarations;
+
+ void expectReference(BlockFunctionBody body, bool isResolved) {
+ ExpressionStatement statement = body.block.statements[0];
+ SimpleIdentifier reference = statement.expression;
+ expect(reference.staticElement, isResolved ? isNotNull : isNull);
+ }
+ //
+ // The reference to 'A' in 'f1' should not be resolved.
+ //
+ FunctionDeclaration f1 = declarations[1];
+ expectReference(f1.functionExpression.body, false);
+ //
+ // The references to 'A' in 'f2' should be resolved.
+ //
+ TopLevelVariableDeclaration f2 = declarations[2];
+ FunctionExpression expression2 = f2.variables.variables[0].initializer;
+ BlockFunctionBody body2 = expression2.body;
+ expectReference(body2, true);
+
+ FunctionDeclarationStatement statement2 = body2.block.statements[1];
+ BlockFunctionBody innerBody =
+ statement2.functionDeclaration.functionExpression.body;
+ expectReference(innerBody, true);
+ //
+ // The references to 'A' in 'C' should not be resolved.
+ //
+ ClassDeclaration c = declarations[3];
+ NodeList<ClassMember> members = c.members;
+
+ ConstructorDeclaration constructor = members[0];
+ expectReference(constructor.body, false);
+
+ MethodDeclaration method = members[1];
+ expectReference(method.body, false);
}
}
diff --git a/pkg/analyzer/test/src/task/html_test.dart b/pkg/analyzer/test/src/task/html_test.dart
index ec78be1..a07dc75 100644
--- a/pkg/analyzer/test/src/task/html_test.dart
+++ b/pkg/analyzer/test/src/task/html_test.dart
@@ -175,18 +175,6 @@
@reflectiveTest
class HtmlErrorsTaskTest extends AbstractContextTest {
- test_buildInputs() {
- Source source = newSource('/test.html');
- Map<String, TaskInput> inputs = HtmlErrorsTask.buildInputs(source);
- expect(inputs, isNotNull);
- expect(
- inputs.keys,
- unorderedEquals([
- HtmlErrorsTask.DART_ERRORS_INPUT,
- HtmlErrorsTask.DOCUMENT_ERRORS_INPUT
- ]));
- }
-
test_constructor() {
Source source = newSource('/test.html');
HtmlErrorsTask task = new HtmlErrorsTask(context, source);
diff --git a/pkg/analyzer/test/src/task/strong_mode_test.dart b/pkg/analyzer/test/src/task/strong_mode_test.dart
index 6d9b3f9..7b719ab 100644
--- a/pkg/analyzer/test/src/task/strong_mode_test.dart
+++ b/pkg/analyzer/test/src/task/strong_mode_test.dart
@@ -18,55 +18,11 @@
main() {
initializeTestEnvironment();
- runReflectiveTests(InferrenceFinderTest);
runReflectiveTests(InstanceMemberInferrerTest);
runReflectiveTests(VariableGathererTest);
}
@reflectiveTest
-class InferrenceFinderTest extends AbstractContextTest {
- void test_creation() {
- InferrenceFinder finder = new InferrenceFinder();
- expect(finder, isNotNull);
- expect(finder.classes, isEmpty);
- expect(finder.staticVariables, isEmpty);
- }
-
- void test_visit() {
- Source source = addSource(
- '/test.dart',
- r'''
-const c = 1;
-final f = '';
-var v = const A();
-int i;
-class A {
- static final fa = 0;
- static int fi;
- const A();
-}
-class B extends A {
- static const cb = 1;
- static vb = 0;
- const ci = 2;
- final fi = '';
- var vi;
-}
-class C = Object with A;
-typedef int F(int x);
-''');
- LibrarySpecificUnit librarySpecificUnit =
- new LibrarySpecificUnit(source, source);
- computeResult(librarySpecificUnit, RESOLVED_UNIT5);
- CompilationUnit unit = outputs[RESOLVED_UNIT5];
- InferrenceFinder finder = new InferrenceFinder();
- unit.accept(finder);
- expect(finder.classes, hasLength(3));
- expect(finder.staticVariables, hasLength(6));
- }
-}
-
-@reflectiveTest
class InstanceMemberInferrerTest extends AbstractContextTest {
InstanceMemberInferrer get createInferrer =>
new InstanceMemberInferrer(context.typeProvider);
diff --git a/pkg/analyzer/test/src/task/test_support.dart b/pkg/analyzer/test/src/task/test_support.dart
index 2173ba2..e68952b 100644
--- a/pkg/analyzer/test/src/task/test_support.dart
+++ b/pkg/analyzer/test/src/task/test_support.dart
@@ -36,8 +36,11 @@
final bool handlesDependencyCycles;
TestAnalysisTask(AnalysisContext context, AnalysisTarget target,
- {this.descriptor, this.exception, this.handlesDependencyCycles: false,
- this.results, this.value: 1})
+ {this.descriptor,
+ this.exception,
+ this.handlesDependencyCycles: false,
+ this.results,
+ this.value: 1})
: super(context, target);
@override
diff --git a/pkg/analyzer/tool/task_dependency_graph.dart b/pkg/analyzer/tool/task_dependency_graph.dart
index 4625b42..5da2976 100644
--- a/pkg/analyzer/tool/task_dependency_graph.dart
+++ b/pkg/analyzer/tool/task_dependency_graph.dart
@@ -94,7 +94,9 @@
CompilationUnitElement modelElement = getUnit(modelSource).element;
InterfaceType analysisTaskType = modelElement.getType('AnalysisTask').type;
DartType dynamicType = context.typeProvider.dynamicType;
- resultDescriptorType = modelElement.getType('ResultDescriptor').type
+ resultDescriptorType = modelElement
+ .getType('ResultDescriptor')
+ .type
.substitute4([dynamicType]);
CompilationUnit taskUnit = getUnit(taskSource);
CompilationUnitElement taskUnitElement = taskUnit.element;
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index d2849d2..b9e48ed 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -19,6 +19,7 @@
LIBRARIES;
import '../compiler_new.dart' as api;
+import 'commandline_options.dart';
import 'common/tasks.dart' show
GenericTask;
import 'compiler.dart' as leg;
@@ -66,59 +67,60 @@
this.allowedLibraryCategories = getAllowedLibraryCategories(options),
super(
outputProvider: outputProvider,
- enableTypeAssertions: hasOption(options, '--enable-checked-mode'),
- enableUserAssertions: hasOption(options, '--enable-checked-mode'),
+ enableTypeAssertions: hasOption(options, Flags.enableCheckedMode),
+ enableUserAssertions: hasOption(options, Flags.enableCheckedMode),
trustTypeAnnotations:
- hasOption(options, '--trust-type-annotations'),
+ hasOption(options, Flags.trustTypeAnnotations),
trustPrimitives:
- hasOption(options, '--trust-primitives'),
- enableMinification: hasOption(options, '--minify'),
+ hasOption(options, Flags.trustPrimitives),
+ enableMinification: hasOption(options, Flags.minify),
useFrequencyNamer:
- !hasOption(options, "--no-frequency-based-minification"),
- preserveUris: hasOption(options, '--preserve-uris'),
+ !hasOption(options, Flags.noFrequencyBasedMinification),
+ preserveUris: hasOption(options, Flags.preserveUris),
enableNativeLiveTypeAnalysis:
- !hasOption(options, '--disable-native-live-type-analysis'),
+ !hasOption(options, Flags.disableNativeLiveTypeAnalysis),
emitJavaScript: !(hasOption(options, '--output-type=dart') ||
hasOption(options, '--output-type=dart-multi')),
dart2dartMultiFile: hasOption(options, '--output-type=dart-multi'),
- generateSourceMap: !hasOption(options, '--no-source-maps'),
- analyzeAllFlag: hasOption(options, '--analyze-all'),
- analyzeOnly: hasOption(options, '--analyze-only'),
- analyzeMain: hasOption(options, '--analyze-main'),
+ generateSourceMap: !hasOption(options, Flags.noSourceMaps),
+ analyzeAllFlag: hasOption(options, Flags.analyzeAll),
+ analyzeOnly: hasOption(options, Flags.analyzeOnly),
+ analyzeMain: hasOption(options, Flags.analyzeMain),
analyzeSignaturesOnly:
- hasOption(options, '--analyze-signatures-only'),
+ hasOption(options, Flags.analyzeSignaturesOnly),
strips: extractCsvOption(options, '--force-strip='),
enableConcreteTypeInference:
- hasOption(options, '--enable-concrete-type-inference'),
+ hasOption(options, Flags.enableConcreteTypeInference),
disableTypeInferenceFlag:
- hasOption(options, '--disable-type-inference'),
- preserveComments: hasOption(options, '--preserve-comments'),
- useCpsIr: hasOption(options, '--use-cps-ir'),
- verbose: hasOption(options, '--verbose'),
+ hasOption(options, Flags.disableTypeInference),
+ preserveComments: hasOption(options, Flags.preserveComments),
+ useCpsIr: hasOption(options, Flags.useCpsIr),
+ verbose: hasOption(options, Flags.verbose),
sourceMapUri: extractUriOption(options, '--source-map='),
outputUri: extractUriOption(options, '--out='),
- terseDiagnostics: hasOption(options, '--terse'),
+ terseDiagnostics: hasOption(options, Flags.terse),
deferredMapUri: extractUriOption(options, '--deferred-map='),
- dumpInfo: hasOption(options, '--dump-info'),
+ dumpInfo: hasOption(options, Flags.dumpInfo),
buildId: extractStringOption(
options, '--build-id=',
"build number could not be determined"),
showPackageWarnings:
- hasOption(options, '--show-package-warnings'),
- useContentSecurityPolicy: hasOption(options, '--csp'),
- useStartupEmitter: hasOption(options, '--fast-startup'),
+ hasOption(options, Flags.showPackageWarnings),
+ useContentSecurityPolicy:
+ hasOption(options, Flags.useContentSecurityPolicy),
+ useStartupEmitter: hasOption(options, Flags.fastStartup),
hasIncrementalSupport:
forceIncrementalSupport ||
- hasOption(options, '--incremental-support'),
- suppressWarnings: hasOption(options, '--suppress-warnings'),
- fatalWarnings: hasOption(options, '--fatal-warnings'),
+ hasOption(options, Flags.incrementalSupport),
+ suppressWarnings: hasOption(options, Flags.suppressWarnings),
+ fatalWarnings: hasOption(options, Flags.fatalWarnings),
enableExperimentalMirrors:
- hasOption(options, '--enable-experimental-mirrors'),
+ hasOption(options, Flags.enableExperimentalMirrors),
generateCodeWithCompileTimeErrors:
- hasOption(options, '--generate-code-with-compile-time-errors'),
- testMode: hasOption(options, '--test-mode'),
+ hasOption(options, Flags.generateCodeWithCompileTimeErrors),
+ testMode: hasOption(options, Flags.testMode),
allowNativeExtensions:
- hasOption(options, '--allow-native-extensions')) {
+ hasOption(options, Flags.allowNativeExtensions)) {
tasks.addAll([
userHandlerTask = new GenericTask('Diagnostic handler', this),
userProviderTask = new GenericTask('Input provider', this),
@@ -141,8 +143,8 @@
if (!analyzeOnly) {
if (allowNativeExtensions) {
throw new ArgumentError(
- "--allow-native-extensions is only supported in combination with "
- "--analyze-only");
+ "${Flags.allowNativeExtensions} is only supported in combination "
+ "with ${Flags.analyzeOnly}");
}
}
}
@@ -189,10 +191,13 @@
// TODO(johnniwinther): Merge better with [translateDartUri] when
// [scanBuiltinLibrary] is removed.
- String lookupLibraryPath(LibraryInfo info) {
+ String lookupLibraryPath(Uri uri, LibraryInfo info) {
if (info == null) return null;
if (!info.isDart2jsLibrary) return null;
- if (!allowedLibraryCategories.contains(info.category)) return null;
+ if (!allowedLibraryCategories.contains(info.category)) {
+ registerDisallowedLibraryUse(uri);
+ return null;
+ }
String path = info.dart2jsPath;
if (path == null) {
path = info.path;
@@ -216,9 +221,9 @@
/// See [leg.Compiler.translateResolvedUri].
Uri translateResolvedUri(elements.LibraryElement importingLibrary,
- Uri resolvedUri, tree.Node node) {
+ Uri resolvedUri, Spannable spannable) {
if (resolvedUri.scheme == 'dart') {
- return translateDartUri(importingLibrary, resolvedUri, node);
+ return translateDartUri(importingLibrary, resolvedUri, spannable);
}
return resolvedUri;
}
@@ -312,9 +317,9 @@
}
Uri translateDartUri(elements.LibraryElement importingLibrary,
- Uri resolvedUri, tree.Node node) {
+ Uri resolvedUri, Spannable spannable) {
LibraryInfo libraryInfo = lookupLibraryInfo(resolvedUri.path);
- String path = lookupLibraryPath(libraryInfo);
+ String path = lookupLibraryPath(resolvedUri, libraryInfo);
if (libraryInfo != null &&
libraryInfo.category == "Internal") {
bool allowInternalLibraryAccess = false;
@@ -329,21 +334,28 @@
if (!allowInternalLibraryAccess) {
if (importingLibrary != null) {
reportError(
- node,
+ spannable,
MessageKind.INTERNAL_LIBRARY_FROM,
{'resolvedUri': resolvedUri,
'importingUri': importingLibrary.canonicalUri});
} else {
reportError(
- node,
+ spannable,
MessageKind.INTERNAL_LIBRARY,
{'resolvedUri': resolvedUri});
}
}
}
if (path == null) {
- reportError(node, MessageKind.LIBRARY_NOT_FOUND,
- {'resolvedUri': resolvedUri});
+ if (libraryInfo == null) {
+ reportError(spannable, MessageKind.LIBRARY_NOT_FOUND,
+ {'resolvedUri': resolvedUri});
+ } else {
+ reportError(spannable, MessageKind.LIBRARY_NOT_SUPPORTED,
+ {'resolvedUri': resolvedUri});
+ }
+ // TODO(johnniwinther): Support signaling the error through the returned
+ // value.
return null;
}
if (resolvedUri.path == 'html' ||
@@ -472,7 +484,7 @@
bool get isMockCompilation {
return mockableLibraryUsed
- && (options.indexOf('--allow-mock-compilation') != -1);
+ && (options.indexOf(Flags.allowMockCompilation) != -1);
}
void callUserHandler(Message message, Uri uri, int begin, int end,
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
new file mode 100644
index 0000000..4cd99ed
--- /dev/null
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.cmdline.options;
+
+/// Commandline flags used in `dart2js.dart` and/or `apiimpl.dart`.
+class Flags {
+ static const String allowMockCompilation = '--allow-mock-compilation';
+ static const String allowNativeExtensions = '--allow-native-extensions';
+ static const String analyzeAll = '--analyze-all';
+ static const String analyzeMain = '--analyze-main';
+ static const String analyzeOnly = '--analyze-only';
+ static const String analyzeSignaturesOnly = '--analyze-signatures-only';
+ static const String disableDiagnosticColors = '--disable-diagnostic-colors';
+ static const String disableNativeLiveTypeAnalysis =
+ '--disable-native-live-type-analysis';
+ static const String disableTypeInference = '--disable-type-inference';
+ static const String dumpInfo = '--dump-info';
+ static const String enableCheckedMode = '--enable-checked-mode';
+ static const String enableConcreteTypeInference =
+ '--enable-concrete-type-inference';
+ static const String enableDiagnosticColors = '--enable-diagnostic-colors';
+ static const String enableExperimentalMirrors =
+ '--enable-experimental-mirrors';
+ static const String fastStartup = '--fast-startup';
+ static const String fatalWarnings = '--fatal-warnings';
+ static const String generateCodeWithCompileTimeErrors =
+ '--generate-code-with-compile-time-errors';
+ static const String incrementalSupport = '--incremental-support';
+ static const String minify = '--minify';
+ static const String noFrequencyBasedMinification =
+ '--no-frequency-based-minification';
+ static const String noSourceMaps = '--no-source-maps';
+ static const String preserveComments = '--preserve-comments';
+ static const String preserveUris = '--preserve-uris';
+ static const String showPackageWarnings = '--show-package-warnings';
+ static const String suppressHints = '--suppress-hints';
+ static const String suppressWarnings = '--suppress-warnings';
+ static const String terse = '--terse';
+ static const String testMode = '--test-mode';
+ static const String trustPrimitives = '--trust-primitives';
+ static const String trustTypeAnnotations = '--trust-type-annotations';
+ static const String useContentSecurityPolicy = '--csp';
+ static const String useCpsIr = '--use-cps-ir';
+ static const String verbose = '--verbose';
+ static const String version = '--version';
+}
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index 42ad090..7af8750 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -212,7 +212,6 @@
void enableIsolateSupport(Enqueuer enqueuer) {}
void registerRequiredType(DartType type, Element enclosingElement) {}
- void registerClassUsingVariableExpression(ClassElement cls) {}
void registerConstSymbol(String name, Registry registry) {}
void registerNewSymbol(Registry registry) {}
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 7051ffe..5d104ef 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -18,10 +18,17 @@
/// The name of the call operator.
static const String call = 'call';
+ /// The name of the current element property used on iterators in for-each
+ /// loops.
+ static const String current = 'current';
+
/// The name of the from environment constructors on 'int', 'bool' and
/// 'String'.
static const String fromEnvironment = 'fromEnvironment';
+ /// The name of the iterator property used in for-each loops.
+ static const String iterator = 'iterator';
+
/// The name of the main method.
static const String main = 'main';
@@ -39,13 +46,13 @@
/// The name of the current element property used on iterators in for-each
/// loops.
- static const Name current = const PublicName('current');
+ static const Name current = const PublicName(Identifiers.current);
/// The name of the dynamic type.
static const Name dynamic_ = const PublicName('dynamic');
/// The name of the iterator property used in for-each loops.
- static const Name iterator = const PublicName('iterator');
+ static const Name iterator = const PublicName(Identifiers.iterator);
/// The name of the move next method used on iterators in for-each loops.
static const Name moveNext = const PublicName('moveNext');
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
index 2f9b828..e43cf14 100644
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ b/pkg/compiler/lib/src/common/resolution.dart
@@ -10,7 +10,8 @@
DartType;
import '../elements/elements.dart' show
AstElement,
- ErroneousElement;
+ ErroneousElement,
+ TypeVariableElement;
import '../enqueue.dart' show
ResolutionEnqueuer,
WorldImpact;
@@ -66,7 +67,8 @@
/// Called during resolution to notify to the backend that the
/// program uses a type variable as an expression.
- void onTypeVariableExpression(Registry registry) {}
+ void onTypeVariableExpression(Registry registry,
+ TypeVariableElement variable) {}
/// Called during resolution to notify to the backend that the
/// program uses a type literal.
@@ -114,4 +116,7 @@
/// Called when resolving the `Symbol` constructor.
void onSymbolConstructor(Registry registry) {}
+
+ /// Called when resolving a prefix or postfix expression.
+ void onIncDecOperation(Registry registry) {}
}
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index db180aa..747dc38 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -133,7 +133,8 @@
Selector,
Universe;
import 'util/util.dart' show
- Link;
+ Link,
+ Setlet;
import 'world.dart' show
World;
@@ -275,6 +276,11 @@
List<Uri> librariesToAnalyzeWhenRun;
+ /// The set of platform libraries reported as unsupported.
+ ///
+ /// For instance when importing 'dart:io' without '--categories=Server'.
+ Set<Uri> disallowedLibraryUris = new Setlet<Uri>();
+
Tracer tracer;
CompilerTask measuredTask;
@@ -770,6 +776,72 @@
return backend.onLibraryScanned(library, loader);
}
+ /// Compute the set of distinct import chains to the library at [uri] within
+ /// [loadedLibraries].
+ ///
+ /// The chains are strings of the form
+ ///
+ /// <main-uri> => <intermediate-uri1> => <intermediate-uri2> => <uri>
+ ///
+ Set<String> computeImportChainsFor(LoadedLibraries loadedLibraries, Uri uri) {
+ // TODO(johnniwinther): Move computation of dependencies to the library
+ // loader.
+ Uri rootUri = loadedLibraries.rootUri;
+ Set<String> importChains = new Set<String>();
+ // The maximum number of full imports chains to process.
+ final int chainLimit = 10000;
+ // The maximum number of imports chains to show.
+ final int compactChainLimit = verbose ? 20 : 10;
+ int chainCount = 0;
+ loadedLibraries.forEachImportChain(uri,
+ callback: (Link<Uri> importChainReversed) {
+ Link<CodeLocation> compactImportChain = const Link<CodeLocation>();
+ CodeLocation currentCodeLocation =
+ new UriLocation(importChainReversed.head);
+ compactImportChain = compactImportChain.prepend(currentCodeLocation);
+ for (Link<Uri> link = importChainReversed.tail;
+ !link.isEmpty;
+ link = link.tail) {
+ Uri uri = link.head;
+ if (!currentCodeLocation.inSameLocation(uri)) {
+ currentCodeLocation =
+ verbose ? new UriLocation(uri) : new CodeLocation(uri);
+ compactImportChain =
+ compactImportChain.prepend(currentCodeLocation);
+ }
+ }
+ String importChain =
+ compactImportChain.map((CodeLocation codeLocation) {
+ return codeLocation.relativize(rootUri);
+ }).join(' => ');
+
+ if (!importChains.contains(importChain)) {
+ if (importChains.length > compactChainLimit) {
+ importChains.add('...');
+ return false;
+ } else {
+ importChains.add(importChain);
+ }
+ }
+
+ chainCount++;
+ if (chainCount > chainLimit) {
+ // Assume there are more import chains.
+ importChains.add('...');
+ return false;
+ }
+ return true;
+ });
+ return importChains;
+ }
+
+ /// Register that [uri] was recognized but disallowed as a dependency.
+ ///
+ /// For instance import of 'dart:io' without '--categories=Server'.
+ void registerDisallowedLibraryUse(Uri uri) {
+ disallowedLibraryUris.add(uri);
+ }
+
/// This method is called when all new libraries loaded through
/// [LibraryLoader.loadLibrary] has been loaded and their imports/exports
/// have been computed.
@@ -780,60 +852,26 @@
/// libraries.
Future onLibrariesLoaded(LoadedLibraries loadedLibraries) {
return new Future.sync(() {
+ for (Uri uri in disallowedLibraryUris) {
+ if (loadedLibraries.containsLibrary(uri)) {
+ Set<String> importChains =
+ computeImportChainsFor(loadedLibraries, Uri.parse('dart:io'));
+ reportInfo(NO_LOCATION_SPANNABLE,
+ MessageKind.DISALLOWED_LIBRARY_IMPORT,
+ {'uri': uri,
+ 'importChain': importChains.join(
+ MessageTemplate.DISALLOWED_LIBRARY_IMPORT_PADDING)});
+ }
+ }
+
if (!loadedLibraries.containsLibrary(Uris.dart_core)) {
return null;
}
+
if (!enableExperimentalMirrors &&
loadedLibraries.containsLibrary(Uris.dart_mirrors)) {
- // TODO(johnniwinther): Move computation of dependencies to the library
- // loader.
- Uri rootUri = loadedLibraries.rootUri;
- Set<String> importChains = new Set<String>();
- // The maximum number of full imports chains to process.
- final int chainLimit = 10000;
- // The maximum number of imports chains to show.
- final int compactChainLimit = verbose ? 20 : 10;
- int chainCount = 0;
- loadedLibraries.forEachImportChain(Uris.dart_mirrors,
- callback: (Link<Uri> importChainReversed) {
- Link<CodeLocation> compactImportChain = const Link<CodeLocation>();
- CodeLocation currentCodeLocation =
- new UriLocation(importChainReversed.head);
- compactImportChain = compactImportChain.prepend(currentCodeLocation);
- for (Link<Uri> link = importChainReversed.tail;
- !link.isEmpty;
- link = link.tail) {
- Uri uri = link.head;
- if (!currentCodeLocation.inSameLocation(uri)) {
- currentCodeLocation =
- verbose ? new UriLocation(uri) : new CodeLocation(uri);
- compactImportChain =
- compactImportChain.prepend(currentCodeLocation);
- }
- }
- String importChain =
- compactImportChain.map((CodeLocation codeLocation) {
- return codeLocation.relativize(rootUri);
- }).join(' => ');
-
- if (!importChains.contains(importChain)) {
- if (importChains.length > compactChainLimit) {
- importChains.add('...');
- return false;
- } else {
- importChains.add(importChain);
- }
- }
-
- chainCount++;
- if (chainCount > chainLimit) {
- // Assume there are more import chains.
- importChains.add('...');
- return false;
- }
- return true;
- });
-
+ Set<String> importChains =
+ computeImportChainsFor(loadedLibraries, Uris.dart_mirrors);
if (!backend.supportsReflection) {
reportError(NO_LOCATION_SPANNABLE,
MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND);
@@ -848,11 +886,6 @@
functionClass.ensureResolved(this);
functionApplyMethod = functionClass.lookupLocalMember('apply');
- proxyConstant =
- constants.getConstantValue(
- resolver.constantCompiler.compileConstant(
- coreLibrary.find('proxy')));
-
if (preserveComments) {
return libraryLoader.loadLibrary(Uris.dart_mirrors)
.then((LibraryElement libraryElement) {
@@ -862,6 +895,18 @@
}).then((_) => backend.onLibrariesLoaded(loadedLibraries));
}
+ bool isProxyConstant(ConstantValue value) {
+ FieldElement field = coreLibrary.find('proxy');
+ if (field == null) return false;
+ if (!enqueuer.resolution.hasBeenResolved(field)) return false;
+ if (proxyConstant == null) {
+ proxyConstant =
+ constants.getConstantValue(
+ resolver.constantCompiler.compileConstant(field));
+ }
+ return proxyConstant == value;
+ }
+
Element findRequiredElement(LibraryElement library, String name) {
var element = library.find(name);
if (element == null) {
@@ -1492,7 +1537,7 @@
* See [LibraryLoader] for terminology on URIs.
*/
Uri translateResolvedUri(LibraryElement importingLibrary,
- Uri resolvedUri, Node node) {
+ Uri resolvedUri, Spannable spannable) {
unimplemented(importingLibrary, 'Compiler.translateResolvedUri');
return null;
}
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 7311912..fd0f68a 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -1563,7 +1563,7 @@
@override
void visitDeferred(DeferredConstantExpression exp, context) {
- sb.write(exp.prefix.deferredImport.prefix.source);
+ sb.write(exp.prefix.name);
sb.write('.');
write(exp, exp.expression);
}
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
index d93de7b..070aa60 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -161,7 +161,7 @@
/// The subclass describes how to compute the value.
///
/// All primitives except [Parameter] must be bound by a [LetPrim].
-abstract class Primitive extends Definition<Primitive> {
+abstract class Primitive extends Variable<Primitive> {
/// The [VariableElement] or [ParameterElement] from which the primitive
/// binding originated.
Entity hint;
@@ -405,6 +405,17 @@
final Reference<Continuation> continuation;
final SourceInformation sourceInformation;
+ /// If true, the [receiver] is intercepted and the actual receiver is in
+ /// the first argument. Otherwise, the [receiver] is the actual receiver.
+ ///
+ /// This flag is always false for non-intercepted selectors, but it may also
+ /// be false for intercepted selectors after dummy receiver optimization
+ /// (in this case the first argument is a dummy value).
+ ///
+ /// It is always false before the unsugaring pass, where interceptors have
+ /// not yet been introduced.
+ bool receiverIsIntercepted = false;
+
/// If true, it is known that the receiver cannot be `null`.
bool receiverIsNotNull = false;
@@ -484,14 +495,14 @@
/// Note that [InvokeConstructor] does it itself allocate an object.
/// The invoked constructor will do that using [CreateInstance].
class InvokeConstructor extends CallExpression {
- final DartType type;
+ final DartType dartType;
final ConstructorElement target;
final List<Reference<Primitive>> arguments;
final Reference<Continuation> continuation;
final Selector selector;
final SourceInformation sourceInformation;
- InvokeConstructor(this.type,
+ InvokeConstructor(this.dartType,
this.target,
this.selector,
List<Primitive> args,
@@ -512,9 +523,9 @@
/// to the same primitive).
class Refinement extends Primitive {
Reference<Primitive> value;
- final TypeMask type;
+ final TypeMask refineType;
- Refinement(Primitive value, this.type)
+ Refinement(Primitive value, this.refineType)
: value = new Reference<Primitive>(value);
bool get isSafeForElimination => true;
@@ -534,7 +545,7 @@
/// to simplify code generation for type tests.
class TypeTest extends Primitive {
Reference<Primitive> value;
- final DartType type;
+ final DartType dartType;
/// If [type] is an [InterfaceType], this holds the internal representation of
/// the type arguments to [type]. Since these may reference type variables
@@ -550,7 +561,7 @@
final List<Reference<Primitive>> typeArguments;
TypeTest(Primitive value,
- this.type,
+ this.dartType,
List<Primitive> typeArguments)
: this.value = new Reference<Primitive>(value),
this.typeArguments = _referenceList(typeArguments);
@@ -573,14 +584,14 @@
/// continuation parameter without needing flow-sensitive analysis.
class TypeCast extends CallExpression {
Reference<Primitive> value;
- final DartType type;
+ final DartType dartType;
/// See the corresponding field on [TypeTest].
final List<Reference<Primitive>> typeArguments;
final Reference<Continuation> continuation;
TypeCast(Primitive value,
- this.type,
+ this.dartType,
List<Primitive> typeArguments,
Continuation cont)
: this.value = new Reference<Primitive>(value),
@@ -1036,10 +1047,10 @@
class LiteralList extends Primitive {
/// The List type being created; this is not the type argument.
- final InterfaceType type;
+ final InterfaceType dartType;
final List<Reference<Primitive>> values;
- LiteralList(this.type, List<Primitive> values)
+ LiteralList(this.dartType, List<Primitive> values)
: this.values = _referenceList(values);
accept(Visitor visitor) => visitor.visitLiteralList(this);
@@ -1058,10 +1069,10 @@
}
class LiteralMap extends Primitive {
- final InterfaceType type;
+ final InterfaceType dartType;
final List<LiteralMapEntry> entries;
- LiteralMap(this.type, this.entries);
+ LiteralMap(this.dartType, this.entries);
accept(Visitor visitor) => visitor.visitLiteralMap(this);
@@ -1135,8 +1146,16 @@
accept(Visitor visitor) => visitor.visitContinuation(this);
}
+/// Common interface for [Primitive] and [MutableVariable].
+abstract class Variable<T extends Variable<T>> extends Definition<T> {
+ /// Type of value held in the variable.
+ ///
+ /// Is `null` until initialized by type propagation.
+ TypeMask type;
+}
+
/// Identifies a mutable variable.
-class MutableVariable extends Definition {
+class MutableVariable extends Variable<MutableVariable> {
Entity hint;
MutableVariable(this.hint);
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
index 1131ce8..631e909 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
@@ -159,8 +159,8 @@
// constructor calls in the DartBackend, we get an element with no enclosing
// class. Clean this up by introducing a name field to the node and
// removing [ErroneousElement]s from the IR.
- if (node.type != null) {
- className = node.type.toString();
+ if (node.dartType != null) {
+ className = node.dartType.toString();
} else {
className = node.target.enclosingClass.name;
}
@@ -232,13 +232,14 @@
String value = access(node.value);
String cont = access(node.continuation);
String typeArguments = node.typeArguments.map(access).join(' ');
- return '$indentation(TypeCast $value ${node.type} ($typeArguments) $cont)';
+ return '$indentation(TypeCast $value ${node.dartType}'
+ ' ($typeArguments) $cont)';
}
String visitTypeTest(TypeTest node) {
String value = access(node.value);
String typeArguments = node.typeArguments.map(access).join(' ');
- return '(TypeTest $value ${node.type} ($typeArguments))';
+ return '(TypeTest $value ${node.dartType} ($typeArguments))';
}
String visitLiteralList(LiteralList node) {
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
index 6b56330..5240db9 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -82,7 +82,10 @@
});
tag("HIR", () {
if (entryPointParameters != null) {
- String params = entryPointParameters.map(names.name).join(', ');
+ String formatParameter(cps_ir.Parameter param) {
+ return '${names.name(param)} ${param.type}';
+ }
+ String params = entryPointParameters.map(formatParameter).join(', ');
printStmt('x0', 'Entry ($params)');
}
for (cps_ir.Parameter param in block.parameters) {
@@ -103,7 +106,8 @@
visitLetPrim(cps_ir.LetPrim node) {
String id = names.name(node.primitive);
- printStmt(id, "LetPrim $id = ${formatPrimitive(node.primitive)}");
+ String primitive = visit(node.primitive);
+ printStmt(id, "LetPrim $id = $primitive [type=${node.primitive.type}]");
visit(node.body);
}
@@ -215,7 +219,7 @@
String value = formatReference(node.value);
String args = node.typeArguments.map(formatReference).join(', ');
String kont = formatReference(node.continuation);
- printStmt(dummy, "TypeCast ($value ${node.type} ($args)) $kont");
+ printStmt(dummy, "TypeCast ($value ${node.dartType} ($args)) $kont");
}
visitInvokeContinuation(cps_ir.InvokeContinuation node) {
@@ -249,8 +253,6 @@
}
}
- String formatPrimitive(cps_ir.Primitive p) => visit(p);
-
visitConstant(cps_ir.Constant node) {
return "Constant ${node.value.toStructuredString()}";
}
@@ -344,7 +346,7 @@
visitTypeTest(cps_ir.TypeTest node) {
String value = formatReference(node.value);
String args = node.typeArguments.map(formatReference).join(', ');
- return "TypeTest ($value ${node.type} ($args))";
+ return "TypeTest ($value ${node.dartType} ($args))";
}
visitApplyBuiltinOperator(cps_ir.ApplyBuiltinOperator node) {
diff --git a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
index 03cafdf..ec12543 100644
--- a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
+++ b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
@@ -7,13 +7,13 @@
import 'optimizers.dart' show Pass;
import 'shrinking_reductions.dart' show ParentVisitor;
import 'cps_ir_nodes.dart';
-import '../types/types.dart';
import '../types/constants.dart';
import '../constants/values.dart';
-import '../world.dart';
import '../common/names.dart';
import '../universe/universe.dart';
import '../elements/elements.dart';
+import '../types/types.dart' show TypeMask;
+import 'type_mask_system.dart';
/// Inserts [Refinement] nodes in the IR to allow for sparse path-sensitive
/// type analysis in the [TypePropagator] pass.
@@ -26,18 +26,12 @@
class InsertRefinements extends RecursiveVisitor implements Pass {
String get passName => 'Insert refinement nodes';
- final TypesTask types;
- final World world;
- final TypeMask nonNullType;
- final TypeMask nullType;
+ final TypeMaskSystem types;
/// Maps unrefined primitives to its refinement currently in scope (if any).
final Map<Primitive, Refinement> refinementFor = <Primitive, Refinement>{};
- InsertRefinements(this.types, World world)
- : this.world = world,
- nonNullType = new TypeMask.nonNullSubtype(world.objectClass, world),
- nullType = new TypeMask.empty();
+ InsertRefinements(this.types);
void rewrite(FunctionDefinition node) {
new ParentVisitor().visit(node);
@@ -134,7 +128,7 @@
push(cont);
} else {
// Filter away receivers that throw on this selector.
- TypeMask type = world.allFunctions.receiverType(node.selector, node.mask);
+ TypeMask type = types.receiverTypeFor(node.selector, node.mask);
pushRefinement(cont, new Refinement(receiver, type));
}
}
@@ -153,10 +147,6 @@
return prim is Constant && prim.value.isTrue;
}
- TypeMask getTypeOf(ConstantValue constant) {
- return computeTypeMask(types.compiler, constant);
- }
-
void visitBranch(Branch node) {
processReference(node.condition);
Primitive condition = node.condition.definition;
@@ -171,10 +161,9 @@
sinkContinuationToUse(falseCont, node);
// If the condition is an 'is' check, promote the checked value.
- if (condition is TypeTest && condition.type.element is ClassElement) {
+ if (condition is TypeTest) {
Primitive value = condition.value.definition;
- ClassElement classElement = condition.type.element;
- TypeMask type = new TypeMask.nonNullSubtype(classElement, world);
+ TypeMask type = types.subtypesOf(condition.dartType);
Primitive refinedValue = new Refinement(value, type);
pushRefinement(trueCont, refinedValue);
push(falseCont);
@@ -190,13 +179,13 @@
Continuation trueCont,
Continuation falseCont) {
if (second is Constant && second.value.isNull) {
- Refinement refinedTrue = new Refinement(first, nullType);
- Refinement refinedFalse = new Refinement(first, nonNullType);
+ Refinement refinedTrue = new Refinement(first, types.nullType);
+ Refinement refinedFalse = new Refinement(first, types.nonNullType);
pushRefinement(trueCont, refinedTrue);
pushRefinement(falseCont, refinedFalse);
} else if (first is Constant && first.value.isNull) {
- Refinement refinedTrue = new Refinement(second, nullType);
- Refinement refinedFalse = new Refinement(second, nonNullType);
+ Refinement refinedTrue = new Refinement(second, types.nullType);
+ Refinement refinedFalse = new Refinement(second, types.nonNullType);
pushRefinement(trueCont, refinedTrue);
pushRefinement(falseCont, refinedFalse);
} else {
diff --git a/pkg/compiler/lib/src/cps_ir/loop_invariant_code_motion.dart b/pkg/compiler/lib/src/cps_ir/loop_invariant_code_motion.dart
index 4471019..877f4ac 100644
--- a/pkg/compiler/lib/src/cps_ir/loop_invariant_code_motion.dart
+++ b/pkg/compiler/lib/src/cps_ir/loop_invariant_code_motion.dart
@@ -126,9 +126,15 @@
}
bool shouldLift(Primitive prim) {
- // Interceptors are safe and almost always profitable for lifting
+ // Interceptors are generally safe and almost always profitable for lifting
// out of loops. Several other primitive could be lifted too, but it's not
// always profitable to do so.
+
+ // Note that the type of the interceptor is technically not sound after
+ // lifting because its current type might have been computed based on a
+ // refinement node (which has since been removed). As a whole, it still
+ // works out because all uses of the interceptor must occur in a context
+ // where it indeed has the type it claims to have.
return prim is Interceptor;
}
}
diff --git a/pkg/compiler/lib/src/cps_ir/mutable_ssa.dart b/pkg/compiler/lib/src/cps_ir/mutable_ssa.dart
index d01c3f5..3dea17c 100644
--- a/pkg/compiler/lib/src/cps_ir/mutable_ssa.dart
+++ b/pkg/compiler/lib/src/cps_ir/mutable_ssa.dart
@@ -191,6 +191,7 @@
<MutableVariable, Primitive>{};
for (MutableVariable variable in mutableVariables) {
Parameter phi = new Parameter(variable.hint);
+ phi.type = variable.type;
cont.parameters.add(phi);
phi.parent = cont;
environment[variable] = phi;
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index d10823a..1ffe526 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -37,3 +37,11 @@
value.isNaN ||
value is StringConstantValue && value.primitiveValue.isEmpty;
}
+
+/// Returns true if [value] satisfies a branching condition with the
+/// given strictness.
+///
+/// For non-strict, this is the opposite of [isFalsyConstant].
+bool isTruthyConstant(ConstantValue value, {bool strict: false}) {
+ return strict ? value.isTrue : !isFalsyConstant(value);
+}
diff --git a/pkg/compiler/lib/src/cps_ir/redundant_join.dart b/pkg/compiler/lib/src/cps_ir/redundant_join.dart
index 4acb2ef..747e701 100644
--- a/pkg/compiler/lib/src/cps_ir/redundant_join.dart
+++ b/pkg/compiler/lib/src/cps_ir/redundant_join.dart
@@ -109,12 +109,12 @@
Primitive argument = invoke.arguments[parameterIndex].definition;
if (argument is! Constant) return; // Branching condition is unknown.
Constant constant = argument;
- if (isFalsyConstant(constant.value)) {
- ++falseHits;
- falseCall = invoke;
- } else {
+ if (isTruthyConstant(constant.value, strict: branch.isStrictCheck)) {
++trueHits;
trueCall = invoke;
+ } else {
+ ++falseHits;
+ falseCall = invoke;
}
}
@@ -182,10 +182,10 @@
Reference reference = branchCont.firstRef;
InvokeContinuation invoke = branchCont.firstRef.parent;
Constant condition = invoke.arguments[parameterIndex].definition;
- if (isFalsyConstant(condition.value)) {
- invoke.continuation.changeTo(falseCont);
- } else {
+ if (isTruthyConstant(condition.value, strict: branch.isStrictCheck)) {
invoke.continuation.changeTo(trueCont);
+ } else {
+ invoke.continuation.changeTo(falseCont);
}
assert(branchCont.firstRef != reference);
}
@@ -248,6 +248,7 @@
// create a new parameter object for this continuation.
if (param.parent != cont) {
Parameter newParam = new Parameter(param.hint);
+ newParam.type = param.type;
renaming[param] = newParam;
cont.parameters[i] = newParam;
newParam.parent = cont;
diff --git a/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart b/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
index 81df956..fb6b539 100644
--- a/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
+++ b/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
@@ -40,16 +40,18 @@
String get passName => 'Scalar replacement';
final dart2js.InternalErrorFunction _internalError;
+ final World _classWorld;
ScalarReplacer(dart2js.Compiler compiler)
- : _internalError = compiler.internalError;
+ : _internalError = compiler.internalError,
+ _classWorld = compiler.world;
@override
void rewrite(FunctionDefinition root) {
// Set all parent pointers.
new ParentVisitor().visit(root);
ScalarReplacementVisitor analyzer =
- new ScalarReplacementVisitor(_internalError);
+ new ScalarReplacementVisitor(_internalError, _classWorld);
analyzer.analyze(root);
analyzer.process();
}
@@ -62,13 +64,14 @@
class ScalarReplacementVisitor extends RecursiveVisitor {
final dart2js.InternalErrorFunction internalError;
+ final World classWorld;
ScalarReplacementRemovalVisitor removalVisitor;
Primitive _current = null;
Set<Primitive> _allocations = new Set<Primitive>();
Queue<Primitive> _queue = new Queue<Primitive>();
- ScalarReplacementVisitor(this.internalError) {
+ ScalarReplacementVisitor(this.internalError, this.classWorld) {
removalVisitor = new ScalarReplacementRemovalVisitor(this);
}
@@ -130,6 +133,7 @@
InteriorNode insertionPoint = allocation.parent; // LetPrim
for (FieldElement field in writes) {
MutableVariable variable = new MutableVariable(field);
+ variable.type = new TypeMask.nonNullEmpty();
cells[field] = variable;
Primitive initialValue = fieldInitialValues[field];
if (initialValue == null) {
@@ -153,6 +157,7 @@
MutableVariable variable = cells[getField.field];
if (variable != null) {
GetMutable getter = new GetMutable(variable);
+ getter.type = getField.type;
getter.variable.parent = getter;
getter.substituteFor(getField);
replacePrimitive(getField, getter);
@@ -166,6 +171,7 @@
SetField setField = use;
MutableVariable variable = cells[setField.field];
Primitive value = setField.value.definition;
+ variable.type = variable.type.union(value.type, classWorld);
SetMutable setter = new SetMutable(variable, value);
setter.variable.parent = setter;
setter.value.parent = setter;
diff --git a/pkg/compiler/lib/src/cps_ir/share_interceptors.dart b/pkg/compiler/lib/src/cps_ir/share_interceptors.dart
index 27afeb5..67aa417 100644
--- a/pkg/compiler/lib/src/cps_ir/share_interceptors.dart
+++ b/pkg/compiler/lib/src/cps_ir/share_interceptors.dart
@@ -6,9 +6,15 @@
import 'cps_ir_nodes.dart';
import 'optimizers.dart';
+import 'type_mask_system.dart';
+import '../elements/elements.dart';
import '../constants/values.dart';
-/// Merges calls to `getInterceptor` when one call dominates the other.
+/// Merges calls to `getInterceptor` when one call is in scope of the other.
+///
+/// Also replaces `getInterceptor` calls with an interceptor constant when
+/// the result is known statically, and there is no interceptor already in
+/// scope.
///
/// Should run after [LoopInvariantCodeMotion] so interceptors lifted out from
/// loops can be merged.
diff --git a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
new file mode 100644
index 0000000..e05db65
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
@@ -0,0 +1,336 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.type_mask_system;
+
+import '../closure.dart' show ClosureClassElement, Identifiers;
+import '../common/names.dart' show Selectors, Identifiers;
+import '../compiler.dart' as dart2js show Compiler;
+import '../constants/constant_system.dart';
+import '../constants/values.dart';
+import '../dart_types.dart' as types;
+import '../elements/elements.dart';
+import '../io/source_information.dart' show SourceInformation;
+import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import '../types/types.dart';
+import '../types/constants.dart' show computeTypeMask;
+import '../universe/universe.dart';
+import '../world.dart' show World;
+
+enum AbstractBool {
+ True, False, Maybe, Nothing
+}
+
+class TypeMaskSystem {
+ final TypesTask inferrer;
+ final World classWorld;
+ final JavaScriptBackend backend;
+
+ TypeMask get dynamicType => inferrer.dynamicType;
+ TypeMask get typeType => inferrer.typeType;
+ TypeMask get functionType => inferrer.functionType;
+ TypeMask get boolType => inferrer.boolType;
+ TypeMask get intType => inferrer.intType;
+ TypeMask get doubleType => inferrer.doubleType;
+ TypeMask get numType => inferrer.numType;
+ TypeMask get stringType => inferrer.stringType;
+ TypeMask get listType => inferrer.listType;
+ TypeMask get mapType => inferrer.mapType;
+ TypeMask get nonNullType => inferrer.nonNullType;
+ TypeMask get nullType => inferrer.nullType;
+ TypeMask get extendableNativeListType => backend.extendableArrayType;
+
+ TypeMask numStringBoolType;
+
+ ClassElement get jsNullClass => backend.jsNullClass;
+
+ // TODO(karlklose): remove compiler here.
+ TypeMaskSystem(dart2js.Compiler compiler)
+ : inferrer = compiler.typesTask,
+ classWorld = compiler.world,
+ backend = compiler.backend {
+
+ // Build the number+string+bool type. To make containment tests more
+ // inclusive, we use the num, String, bool types for this, not
+ // the JSNumber, JSString, JSBool subclasses.
+ TypeMask anyNum =
+ new TypeMask.nonNullSubtype(classWorld.numClass, classWorld);
+ TypeMask anyString =
+ new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld);
+ TypeMask anyBool =
+ new TypeMask.nonNullSubtype(classWorld.boolClass, classWorld);
+ numStringBoolType =
+ new TypeMask.unionOf(<TypeMask>[anyNum, anyString, anyBool],
+ classWorld);
+ }
+
+ bool methodUsesReceiverArgument(FunctionElement function) {
+ assert(backend.isInterceptedMethod(function));
+ ClassElement clazz = function.enclosingClass.declaration;
+ return clazz.isSubclassOf(backend.jsInterceptorClass) ||
+ classWorld.isUsedAsMixin(clazz);
+ }
+
+ Element locateSingleElement(TypeMask mask, Selector selector) {
+ return mask.locateSingleElement(selector, mask, classWorld.compiler);
+ }
+
+ ClassElement singleClass(TypeMask mask) {
+ return mask.singleClass(classWorld);
+ }
+
+ bool needsNoSuchMethodHandling(TypeMask mask, Selector selector) {
+ return mask.needsNoSuchMethodHandling(selector, classWorld);
+ }
+
+ TypeMask getReceiverType(MethodElement method) {
+ assert(method.isInstanceMember);
+ if (classWorld.isUsedAsMixin(method.enclosingClass.declaration)) {
+ // If used as a mixin, the receiver could be any of the classes that mix
+ // in the class, and these are not considered subclasses.
+ // TODO(asgerf): Exclude the subtypes that only `implement` the class.
+ return nonNullSubtype(method.enclosingClass);
+ } else {
+ return nonNullSubclass(method.enclosingClass);
+ }
+ }
+
+ TypeMask getParameterType(ParameterElement parameter) {
+ return inferrer.getGuaranteedTypeOfElement(parameter);
+ }
+
+ TypeMask getReturnType(FunctionElement function) {
+ return inferrer.getGuaranteedReturnTypeOfElement(function);
+ }
+
+ TypeMask getInvokeReturnType(Selector selector, TypeMask mask) {
+ TypeMask result = inferrer.getGuaranteedTypeOfSelector(selector, mask);
+ // Tearing off .call from a function returns the function itself.
+ if (selector.isGetter &&
+ selector.name == Identifiers.call &&
+ !areDisjoint(functionType, mask)) {
+ result = join(result, functionType);
+ }
+ return result;
+ }
+
+ TypeMask getFieldType(FieldElement field) {
+ return inferrer.getGuaranteedTypeOfElement(field);
+ }
+
+ TypeMask join(TypeMask a, TypeMask b) {
+ return a.union(b, classWorld);
+ }
+
+ TypeMask getTypeOf(ConstantValue constant) {
+ return computeTypeMask(inferrer.compiler, constant);
+ }
+
+ TypeMask nonNullExact(ClassElement element) {
+ // The class world does not know about classes created by
+ // closure conversion, so just treat those as a subtypes of Function.
+ // TODO(asgerf): Maybe closure conversion should create a new ClassWorld?
+ if (element.isClosure) return functionType;
+ return new TypeMask.nonNullExact(element.declaration, classWorld);
+ }
+
+ TypeMask nonNullSubclass(ClassElement element) {
+ if (element.isClosure) return functionType;
+ return new TypeMask.nonNullSubclass(element.declaration, classWorld);
+ }
+
+ TypeMask nonNullSubtype(ClassElement element) {
+ if (element.isClosure) return functionType;
+ return new TypeMask.nonNullSubtype(element.declaration, classWorld);
+ }
+
+ bool isDefinitelyBool(TypeMask t, {bool allowNull: false}) {
+ if (!allowNull && t.isNullable) return false;
+ return t.nonNullable().containsOnlyBool(classWorld);
+ }
+
+ bool isDefinitelyNum(TypeMask t, {bool allowNull: false}) {
+ if (!allowNull && t.isNullable) return false;
+ return t.nonNullable().containsOnlyNum(classWorld);
+ }
+
+ bool isDefinitelyString(TypeMask t, {bool allowNull: false}) {
+ if (!allowNull && t.isNullable) return false;
+ return t.nonNullable().containsOnlyString(classWorld);
+ }
+
+ bool isDefinitelyNumStringBool(TypeMask t, {bool allowNull: false}) {
+ if (!allowNull && t.isNullable) return false;
+ return numStringBoolType.containsMask(t.nonNullable(), classWorld);
+ }
+
+ bool isDefinitelyNotNumStringBool(TypeMask t) {
+ return areDisjoint(t, numStringBoolType);
+ }
+
+ /// True if all values of [t] are either integers or not numbers at all.
+ ///
+ /// This does not imply that the value is an integer, since most other values
+ /// such as null are also not a non-integer double.
+ bool isDefinitelyNotNonIntegerDouble(TypeMask t) {
+ // Even though int is a subclass of double in the JS type system, we can
+ // still check this with disjointness, because [doubleType] is the *exact*
+ // double class, so this excludes things that are known to be instances of a
+ // more specific class.
+ // We currently exploit that there are no subclasses of double that are
+ // not integers (e.g. there is no UnsignedDouble class or whatever).
+ return areDisjoint(t, doubleType);
+ }
+
+ bool isDefinitelyInt(TypeMask t, {bool allowNull: false}) {
+ if (!allowNull && t.isNullable) return false;
+ return t.satisfies(backend.jsIntClass, classWorld);
+ }
+
+ bool isDefinitelyNativeList(TypeMask t, {bool allowNull: false}) {
+ if (!allowNull && t.isNullable) return false;
+ return t.nonNullable().satisfies(backend.jsArrayClass, classWorld);
+ }
+
+ bool isDefinitelyMutableNativeList(TypeMask t, {bool allowNull: false}) {
+ if (!allowNull && t.isNullable) return false;
+ return t.nonNullable().satisfies(backend.jsMutableArrayClass, classWorld);
+ }
+
+ bool isDefinitelyFixedNativeList(TypeMask t, {bool allowNull: false}) {
+ if (!allowNull && t.isNullable) return false;
+ return t.nonNullable().satisfies(backend.jsFixedArrayClass, classWorld);
+ }
+
+ bool isDefinitelyExtendableNativeList(TypeMask t, {bool allowNull: false}) {
+ if (!allowNull && t.isNullable) return false;
+ return t.nonNullable().satisfies(backend.jsExtendableArrayClass,
+ classWorld);
+ }
+
+ bool isDefinitelyIndexable(TypeMask t, {bool allowNull: false}) {
+ if (!allowNull && t.isNullable) return false;
+ return t.nonNullable().satisfies(backend.jsIndexableClass, classWorld);
+ }
+
+ bool areDisjoint(TypeMask leftType, TypeMask rightType) {
+ TypeMask intersection = leftType.intersection(rightType, classWorld);
+ return intersection.isEmpty && !intersection.isNullable;
+ }
+
+ AbstractBool isSubtypeOf(TypeMask value,
+ types.DartType type,
+ {bool allowNull}) {
+ assert(allowNull != null);
+ if (type is types.DynamicType) {
+ return AbstractBool.True;
+ }
+ if (type is types.InterfaceType) {
+ TypeMask typeAsMask = allowNull
+ ? new TypeMask.subtype(type.element, classWorld)
+ : new TypeMask.nonNullSubtype(type.element, classWorld);
+ if (areDisjoint(value, typeAsMask)) {
+ // Disprove the subtype relation based on the class alone.
+ return AbstractBool.False;
+ }
+ if (!type.treatAsRaw) {
+ // If there are type arguments, we cannot prove the subtype relation,
+ // because the type arguments are unknown on both the value and type.
+ return AbstractBool.Maybe;
+ }
+ if (typeAsMask.containsMask(value, classWorld)) {
+ // All possible values are contained in the set of allowed values.
+ // Note that we exploit the fact that [typeAsMask] is an exact
+ // representation of [type], not an approximation.
+ return AbstractBool.True;
+ }
+ // The value is neither contained in the type, nor disjoint from the type.
+ return AbstractBool.Maybe;
+ }
+ // TODO(asgerf): Support function types, and what else might be missing.
+ return AbstractBool.Maybe;
+ }
+
+ /// Returns whether [type] is one of the falsy values: false, 0, -0, NaN,
+ /// the empty string, or null.
+ AbstractBool boolify(TypeMask type) {
+ if (isDefinitelyNotNumStringBool(type) && !type.isNullable) {
+ return AbstractBool.True;
+ }
+ return AbstractBool.Maybe;
+ }
+
+ AbstractBool strictBoolify(TypeMask type) {
+ if (areDisjoint(type, boolType)) return AbstractBool.False;
+ return AbstractBool.Maybe;
+ }
+
+ /// Create a type mask containing at least all subtypes of [type].
+ TypeMask subtypesOf(types.DartType type) {
+ if (type is types.InterfaceType) {
+ ClassElement element = type.element;
+ if (element.isObject) {
+ return dynamicType;
+ }
+ if (element == classWorld.nullClass) {
+ return nullType;
+ }
+ if (element == classWorld.stringClass) {
+ return stringType;
+ }
+ if (element == classWorld.numClass ||
+ element == classWorld.doubleClass) {
+ return numType;
+ }
+ if (element == classWorld.intClass) {
+ return intType;
+ }
+ if (element == classWorld.boolClass) {
+ return boolType;
+ }
+ return new TypeMask.nonNullSubtype(element, classWorld);
+ }
+ if (type is types.FunctionType) {
+ return functionType;
+ }
+ return dynamicType;
+ }
+
+ /// Returns a subset of [mask] containing at least the types
+ /// that can respond to [selector] without throwing.
+ TypeMask receiverTypeFor(Selector selector, TypeMask mask) {
+ return classWorld.allFunctions.receiverType(selector, mask);
+ }
+
+ /// The result of an index operation on something of [type], or the dynamic
+ /// type if unknown.
+ TypeMask elementTypeOfIndexable(TypeMask type) {
+ if (type is UnionTypeMask) {
+ return new TypeMask.unionOf(
+ type.disjointMasks.map(elementTypeOfIndexable), classWorld);
+ }
+ if (type is ContainerTypeMask) {
+ return type.elementType;
+ }
+ if (isDefinitelyString(type)) {
+ return stringType;
+ }
+ if (type.satisfies(backend.typedArrayClass, classWorld)) {
+ if (type.satisfies(backend.typedArrayOfIntClass, classWorld)) {
+ return intType;
+ }
+ return numType;
+ }
+ return dynamicType;
+ }
+
+ /// The length of something of [type], or `null` if unknown.
+ int getContainerLength(TypeMask type) {
+ if (type is ContainerTypeMask) {
+ return type.length;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 5ef491b..631aaf2 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -30,248 +30,7 @@
import '../world.dart' show World;
import 'cps_fragment.dart';
import 'cps_ir_nodes.dart';
-import 'cps_ir_nodes_sexpr.dart' show SExpressionStringifier;
-
-enum AbstractBool {
- True, False, Maybe, Nothing
-}
-
-class TypeMaskSystem {
- final TypesTask inferrer;
- final World classWorld;
- final JavaScriptBackend backend;
-
- TypeMask get dynamicType => inferrer.dynamicType;
- TypeMask get typeType => inferrer.typeType;
- TypeMask get functionType => inferrer.functionType;
- TypeMask get boolType => inferrer.boolType;
- TypeMask get intType => inferrer.intType;
- TypeMask get doubleType => inferrer.doubleType;
- TypeMask get numType => inferrer.numType;
- TypeMask get stringType => inferrer.stringType;
- TypeMask get listType => inferrer.listType;
- TypeMask get mapType => inferrer.mapType;
- TypeMask get nonNullType => inferrer.nonNullType;
- TypeMask get extendableNativeListType => backend.extendableArrayType;
-
- TypeMask numStringBoolType;
-
- ClassElement get jsNullClass => backend.jsNullClass;
-
- // TODO(karlklose): remove compiler here.
- TypeMaskSystem(dart2js.Compiler compiler)
- : inferrer = compiler.typesTask,
- classWorld = compiler.world,
- backend = compiler.backend {
-
- // Build the number+string+bool type. To make containment tests more
- // inclusive, we use the num, String, bool types for this, not
- // the JSNumber, JSString, JSBool subclasses.
- TypeMask anyNum =
- new TypeMask.nonNullSubtype(classWorld.numClass, classWorld);
- TypeMask anyString =
- new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld);
- TypeMask anyBool =
- new TypeMask.nonNullSubtype(classWorld.boolClass, classWorld);
- numStringBoolType =
- new TypeMask.unionOf(<TypeMask>[anyNum, anyString, anyBool],
- classWorld);
- }
-
- bool methodUsesReceiverArgument(FunctionElement function) {
- assert(backend.isInterceptedMethod(function));
- ClassElement clazz = function.enclosingClass.declaration;
- return clazz.isSubclassOf(backend.jsInterceptorClass) ||
- classWorld.isUsedAsMixin(clazz);
- }
-
- Element locateSingleElement(TypeMask mask, Selector selector) {
- return mask.locateSingleElement(selector, mask, classWorld.compiler);
- }
-
- ClassElement singleClass(TypeMask mask) {
- return mask.singleClass(classWorld);
- }
-
- bool needsNoSuchMethodHandling(TypeMask mask, Selector selector) {
- return mask.needsNoSuchMethodHandling(selector, classWorld);
- }
-
- TypeMask getReceiverType(MethodElement method) {
- assert(method.isInstanceMember);
- if (classWorld.isUsedAsMixin(method.enclosingClass.declaration)) {
- // If used as a mixin, the receiver could be any of the classes that mix
- // in the class, and these are not considered subclasses.
- // TODO(asgerf): Exclude the subtypes that only `implement` the class.
- return nonNullSubtype(method.enclosingClass);
- } else {
- return nonNullSubclass(method.enclosingClass);
- }
- }
-
- TypeMask getParameterType(ParameterElement parameter) {
- return inferrer.getGuaranteedTypeOfElement(parameter);
- }
-
- TypeMask getReturnType(FunctionElement function) {
- return inferrer.getGuaranteedReturnTypeOfElement(function);
- }
-
- TypeMask getInvokeReturnType(Selector selector, TypeMask mask) {
- return inferrer.getGuaranteedTypeOfSelector(selector, mask);
- }
-
- TypeMask getFieldType(FieldElement field) {
- return inferrer.getGuaranteedTypeOfElement(field);
- }
-
- TypeMask join(TypeMask a, TypeMask b) {
- return a.union(b, classWorld);
- }
-
- TypeMask getTypeOf(ConstantValue constant) {
- return computeTypeMask(inferrer.compiler, constant);
- }
-
- TypeMask nonNullExact(ClassElement element) {
- // The class world does not know about classes created by
- // closure conversion, so just treat those as a subtypes of Function.
- // TODO(asgerf): Maybe closure conversion should create a new ClassWorld?
- if (element.isClosure) return functionType;
- return new TypeMask.nonNullExact(element.declaration, classWorld);
- }
-
- TypeMask nonNullSubclass(ClassElement element) {
- if (element.isClosure) return functionType;
- return new TypeMask.nonNullSubclass(element.declaration, classWorld);
- }
-
- TypeMask nonNullSubtype(ClassElement element) {
- if (element.isClosure) return functionType;
- return new TypeMask.nonNullSubtype(element.declaration, classWorld);
- }
-
- bool isDefinitelyBool(TypeMask t, {bool allowNull: false}) {
- if (!allowNull && t.isNullable) return false;
- return t.nonNullable().containsOnlyBool(classWorld);
- }
-
- bool isDefinitelyNum(TypeMask t, {bool allowNull: false}) {
- if (!allowNull && t.isNullable) return false;
- return t.nonNullable().containsOnlyNum(classWorld);
- }
-
- bool isDefinitelyString(TypeMask t, {bool allowNull: false}) {
- if (!allowNull && t.isNullable) return false;
- return t.nonNullable().containsOnlyString(classWorld);
- }
-
- bool isDefinitelyNumStringBool(TypeMask t, {bool allowNull: false}) {
- if (!allowNull && t.isNullable) return false;
- return numStringBoolType.containsMask(t.nonNullable(), classWorld);
- }
-
- bool isDefinitelyNotNumStringBool(TypeMask t) {
- return areDisjoint(t, numStringBoolType);
- }
-
- /// True if all values of [t] are either integers or not numbers at all.
- ///
- /// This does not imply that the value is an integer, since most other values
- /// such as null are also not a non-integer double.
- bool isDefinitelyNotNonIntegerDouble(TypeMask t) {
- // Even though int is a subclass of double in the JS type system, we can
- // still check this with disjointness, because [doubleType] is the *exact*
- // double class, so this excludes things that are known to be instances of a
- // more specific class.
- // We currently exploit that there are no subclasses of double that are
- // not integers (e.g. there is no UnsignedDouble class or whatever).
- return areDisjoint(t, doubleType);
- }
-
- bool isDefinitelyInt(TypeMask t, {bool allowNull: false}) {
- if (!allowNull && t.isNullable) return false;
- return t.satisfies(backend.jsIntClass, classWorld);
- }
-
- bool isDefinitelyNativeList(TypeMask t, {bool allowNull: false}) {
- if (!allowNull && t.isNullable) return false;
- return t.nonNullable().satisfies(backend.jsArrayClass, classWorld);
- }
-
- bool isDefinitelyMutableNativeList(TypeMask t, {bool allowNull: false}) {
- if (!allowNull && t.isNullable) return false;
- return t.nonNullable().satisfies(backend.jsMutableArrayClass, classWorld);
- }
-
- bool isDefinitelyFixedNativeList(TypeMask t, {bool allowNull: false}) {
- if (!allowNull && t.isNullable) return false;
- return t.nonNullable().satisfies(backend.jsFixedArrayClass, classWorld);
- }
-
- bool isDefinitelyExtendableNativeList(TypeMask t, {bool allowNull: false}) {
- if (!allowNull && t.isNullable) return false;
- return t.nonNullable().satisfies(backend.jsExtendableArrayClass,
- classWorld);
- }
-
- bool isDefinitelyIndexable(TypeMask t, {bool allowNull: false}) {
- if (!allowNull && t.isNullable) return false;
- return t.nonNullable().satisfies(backend.jsIndexableClass, classWorld);
- }
-
- bool areDisjoint(TypeMask leftType, TypeMask rightType) {
- TypeMask intersection = leftType.intersection(rightType, classWorld);
- return intersection.isEmpty && !intersection.isNullable;
- }
-
- AbstractBool isSubtypeOf(TypeMask value,
- types.DartType type,
- {bool allowNull}) {
- assert(allowNull != null);
- if (type is types.DynamicType) {
- return AbstractBool.True;
- }
- if (type is types.InterfaceType) {
- TypeMask typeAsMask = allowNull
- ? new TypeMask.subtype(type.element, classWorld)
- : new TypeMask.nonNullSubtype(type.element, classWorld);
- if (areDisjoint(value, typeAsMask)) {
- // Disprove the subtype relation based on the class alone.
- return AbstractBool.False;
- }
- if (!type.treatAsRaw) {
- // If there are type arguments, we cannot prove the subtype relation,
- // because the type arguments are unknown on both the value and type.
- return AbstractBool.Maybe;
- }
- if (typeAsMask.containsMask(value, classWorld)) {
- // All possible values are contained in the set of allowed values.
- // Note that we exploit the fact that [typeAsMask] is an exact
- // representation of [type], not an approximation.
- return AbstractBool.True;
- }
- // The value is neither contained in the type, nor disjoint from the type.
- return AbstractBool.Maybe;
- }
- // TODO(asgerf): Support function types, and what else might be missing.
- return AbstractBool.Maybe;
- }
-
- /// Returns whether [type] is one of the falsy values: false, 0, -0, NaN,
- /// the empty string, or null.
- AbstractBool boolify(TypeMask type) {
- if (isDefinitelyNotNumStringBool(type) && !type.isNullable) {
- return AbstractBool.True;
- }
- return AbstractBool.Maybe;
- }
-
- AbstractBool strictBoolify(TypeMask type) {
- if (areDisjoint(type, boolType)) return AbstractBool.False;
- return AbstractBool.Maybe;
- }
-}
+import 'type_mask_system.dart';
class ConstantPropagationLattice {
final TypeMaskSystem typeSystem;
@@ -575,17 +334,19 @@
final dart2js.Compiler _compiler;
final CpsFunctionCompiler _functionCompiler;
- // The constant system is used for evaluation of expressions with constant
- // arguments.
final ConstantPropagationLattice _lattice;
final dart2js.InternalErrorFunction _internalError;
- final Map<Definition, AbstractValue> _values = <Definition, AbstractValue>{};
+ final Map<Variable, ConstantValue> _values = <Variable, ConstantValue>{};
+ final TypeMaskSystem _typeSystem;
- TypePropagator(dart2js.Compiler compiler, this._functionCompiler)
+ TypePropagator(dart2js.Compiler compiler,
+ TypeMaskSystem typeSystem,
+ this._functionCompiler)
: _compiler = compiler,
_internalError = compiler.internalError,
+ _typeSystem = typeSystem,
_lattice = new ConstantPropagationLattice(
- new TypeMaskSystem(compiler),
+ typeSystem,
compiler.backend.constantSystem,
compiler.types);
@@ -650,7 +411,7 @@
JavaScriptBackend get backend => compiler.backend;
TypeMaskSystem get typeSystem => lattice.typeSystem;
types.DartTypes get dartTypes => lattice.dartTypes;
- Map<Node, AbstractValue> get values => analyzer.values;
+ Map<Variable, ConstantValue> get values => analyzer.values;
final dart2js.InternalErrorFunction internalError;
@@ -734,6 +495,9 @@
void visitContinuation(Continuation node) {
if (node.isReturnContinuation) return;
+ if (!analyzer.reachableContinuations.contains(node)) {
+ replaceSubtree(node.body, new Unreachable());
+ }
// Process the continuation body.
// Note that the continuation body may have changed since the continuation
// was put on the stack (e.g. [visitInvokeContinuation] may do this).
@@ -809,8 +573,8 @@
/// Make a constant primitive for [constant] and set its entry in [values].
Constant makeConstantPrimitive(ConstantValue constant) {
Constant primitive = new Constant(constant);
- values[primitive] = new AbstractValue.constantValue(constant,
- typeSystem.getTypeOf(constant));
+ primitive.type = typeSystem.getTypeOf(constant);
+ values[primitive] = constant;
return primitive;
}
@@ -960,10 +724,8 @@
}
if (node.selector.isOperator && node.arguments.length == 2) {
- // The operators we specialize are are intercepted calls, so the operands
- // are in the argument list.
- Primitive leftArg = node.arguments[0].definition;
- Primitive rightArg = node.arguments[1].definition;
+ Primitive leftArg = getDartReceiver(node);
+ Primitive rightArg = getDartArgument(node, 0);
AbstractValue left = getValue(leftArg);
AbstractValue right = getValue(rightArg);
@@ -1035,7 +797,7 @@
}
Primitive getDartReceiver(InvokeMethod node) {
- if (isInterceptedSelector(node.selector)) {
+ if (node.receiverIsIntercepted) {
return node.arguments[0].definition;
} else {
return node.receiver.definition;
@@ -1230,6 +992,14 @@
}
if (!isExtendable) return false;
CpsFragment cps = new CpsFragment(sourceInfo);
+ Primitive length = cps.letPrim(new GetLength(list));
+ Primitive isEmpty = cps.applyBuiltin(
+ BuiltinOperator.StrictEq,
+ [length, cps.makeZero()]);
+ CpsFragment fail = cps.ifTruthy(isEmpty);
+ fail.invokeStaticThrower(
+ backend.getThrowIndexOutOfBoundsError(),
+ [list, fail.makeConstant(new IntConstantValue(-1))]);
Primitive removedItem = cps.invokeBuiltin(BuiltinMethod.Pop,
list,
<Primitive>[],
@@ -1708,7 +1478,7 @@
AbstractValue receiver = getValue(node.receiver.definition);
node.receiverIsNotNull = receiver.isDefinitelyNotNull;
- if (isInterceptedSelector(node.selector) &&
+ if (node.receiverIsIntercepted &&
node.receiver.definition.sameValue(node.arguments[0].definition)) {
// The receiver and first argument are the same; that means we already
// determined in visitInterceptor that we are targeting a non-interceptor.
@@ -1731,6 +1501,7 @@
insertLetPrim(node, dummy);
node.arguments[0].unlink();
node.arguments[0] = new Reference<Primitive>(dummy);
+ node.receiverIsIntercepted = false;
}
}
}
@@ -1739,7 +1510,7 @@
Continuation cont = node.continuation.definition;
AbstractValue value = getValue(node.value.definition);
- switch (lattice.isSubtypeOf(value, node.type, allowNull: true)) {
+ switch (lattice.isSubtypeOf(value, node.dartType, allowNull: true)) {
case AbstractBool.Maybe:
case AbstractBool.Nothing:
break;
@@ -1892,9 +1663,15 @@
if (inlineInvokeStatic(node)) return;
}
- AbstractValue getValue(Primitive primitive) {
- AbstractValue value = values[primitive];
- return value == null ? new AbstractValue.nothing() : value;
+ AbstractValue getValue(Variable node) {
+ ConstantValue constant = values[node];
+ if (constant != null) {
+ return new AbstractValue.constantValue(constant, node.type);
+ }
+ if (node.type != null) {
+ return new AbstractValue.nonConstant(node.type);
+ }
+ return lattice.nothing;
}
@@ -2024,7 +1801,7 @@
Primitive visitTypeTest(TypeTest node) {
Primitive prim = node.value.definition;
AbstractValue value = getValue(prim);
- if (node.type == dartTypes.coreTypes.intType) {
+ if (node.dartType == dartTypes.coreTypes.intType) {
// Compile as typeof x === 'number' && Math.floor(x) === x
if (lattice.isDefinitelyNum(value, allowNull: true)) {
// If value is null or a number, we can skip the typeof test.
@@ -2046,8 +1823,8 @@
<Primitive>[prim, prim, prim],
node.sourceInformation);
}
- if (node.type == dartTypes.coreTypes.numType ||
- node.type == dartTypes.coreTypes.doubleType) {
+ if (node.dartType == dartTypes.coreTypes.numType ||
+ node.dartType == dartTypes.coreTypes.doubleType) {
return new ApplyBuiltinOperator(
BuiltinOperator.IsNumber,
<Primitive>[prim],
@@ -2141,7 +1918,7 @@
// Stores the current lattice value for primitives and mutable variables.
// Access through [getValue] and [setValue].
- final Map<Definition, AbstractValue> values;
+ final Map<Variable, ConstantValue> values;
/// Expressions that invoke their call continuation with a constant value
/// and without any side effects. These can be replaced by the constant.
@@ -2205,17 +1982,24 @@
/// Returns the lattice value corresponding to [node], defaulting to nothing.
///
/// Never returns null.
- AbstractValue getValue(Definition node) {
- AbstractValue value = values[node];
- return (value == null) ? nothing : value;
+ AbstractValue getValue(Variable node) {
+ ConstantValue constant = values[node];
+ if (constant != null) {
+ return new AbstractValue.constantValue(constant, node.type);
+ }
+ if (node.type != null) {
+ return new AbstractValue.nonConstant(node.type);
+ }
+ return lattice.nothing;
}
/// Joins the passed lattice [updateValue] to the current value of [node],
/// and adds it to the definition work set if it has changed and [node] is
/// a definition.
- void setValue(Definition node, AbstractValue updateValue) {
+ void setValue(Variable node, AbstractValue updateValue) {
AbstractValue oldValue = getValue(node);
AbstractValue newValue = lattice.join(oldValue, updateValue);
+ node.type = newValue.type; // Ensure type is initialized even if bottom.
if (oldValue == newValue) {
return;
}
@@ -2223,10 +2007,48 @@
// Values may only move in the direction NOTHING -> CONSTANT -> NONCONST.
assert(newValue.kind >= oldValue.kind);
- values[node] = newValue;
+ values[node] = newValue.isConstant ? newValue.constant : null;
defWorklist.add(node);
}
+ /// Updates the value of a [CallExpression]'s continuation parameter.
+ void setResult(CallExpression call,
+ AbstractValue updateValue,
+ {bool canReplace: false}) {
+ Continuation cont = call.continuation.definition;
+ setValue(cont.parameters.single, updateValue);
+ if (!updateValue.isNothing) {
+ setReachable(cont);
+
+ if (updateValue.isConstant && canReplace) {
+ replacements[call] = updateValue.constant;
+ } else {
+ // A replacement might have been set in a previous iteration.
+ replacements.remove(call);
+ }
+ }
+ }
+
+ bool isInterceptedSelector(Selector selector) {
+ return backend.isInterceptedSelector(selector);
+ }
+
+ Primitive getDartReceiver(InvokeMethod node) {
+ if (node.receiverIsIntercepted) {
+ return node.arguments[0].definition;
+ } else {
+ return node.receiver.definition;
+ }
+ }
+
+ Primitive getDartArgument(InvokeMethod node, int n) {
+ if (isInterceptedSelector(node.selector)) {
+ return node.arguments[n+1].definition;
+ } else {
+ return node.arguments[n].definition;
+ }
+ }
+
// -------------------------- Visitor overrides ------------------------------
void visit(Node node) { node.accept(this); }
@@ -2289,35 +2111,17 @@
}
void visitInvokeStatic(InvokeStatic node) {
- Continuation cont = node.continuation.definition;
- setReachable(cont);
-
- assert(cont.parameters.length == 1);
- Parameter returnValue = cont.parameters[0];
-
- /// Sets the value of the target continuation parameter, and possibly
- /// try to replace the whole invocation with a constant.
- void setResult(AbstractValue updateValue, {bool canReplace: false}) {
- setValue(returnValue, updateValue);
- if (canReplace && updateValue.isConstant) {
- replacements[node] = updateValue.constant;
- } else {
- // A previous iteration might have tried to replace this.
- replacements.remove(node);
- }
- }
-
if (node.target.library.isInternalLibrary) {
switch (node.target.name) {
case InternalMethod.Stringify:
AbstractValue argValue = getValue(node.arguments[0].definition);
- setResult(lattice.stringify(argValue), canReplace: true);
+ setResult(node, lattice.stringify(argValue), canReplace: true);
return;
}
}
TypeMask returnType = typeSystem.getReturnType(node.target);
- setResult(nonConstant(returnType));
+ setResult(node, nonConstant(returnType));
}
void visitInvokeContinuation(InvokeContinuation node) {
@@ -2327,45 +2131,28 @@
// Forward the constant status of all continuation invokes to the
// continuation. Note that this is effectively a phi node in SSA terms.
for (int i = 0; i < node.arguments.length; i++) {
- Definition def = node.arguments[i].definition;
+ Primitive def = node.arguments[i].definition;
AbstractValue cell = getValue(def);
setValue(cont.parameters[i], cell);
}
}
void visitInvokeMethod(InvokeMethod node) {
- Continuation cont = node.continuation.definition;
- setReachable(cont);
-
- /// Sets the value of the target continuation parameter, and possibly
- /// try to replace the whole invocation with a constant.
- void setResult(AbstractValue updateValue, {bool canReplace: false}) {
- Parameter returnValue = cont.parameters[0];
- setValue(returnValue, updateValue);
- if (canReplace && updateValue.isConstant) {
- replacements[node] = updateValue.constant;
- } else {
- // A previous iteration might have tried to replace this.
- replacements.remove(node);
- }
- }
-
AbstractValue receiver = getValue(node.receiver.definition);
if (receiver.isNothing) {
return; // And come back later.
}
if (!node.selector.isOperator) {
// TODO(jgruber): Handle known methods on constants such as String.length.
- setResult(lattice.getInvokeReturnType(node.selector, node.mask));
+ setResult(node, lattice.getInvokeReturnType(node.selector, node.mask));
return;
}
// Calculate the resulting constant if possible.
- // Operators are intercepted, so the operands are in the argument list.
AbstractValue result;
String opname = node.selector.name;
if (node.arguments.length == 1) {
- AbstractValue argument = getValue(node.arguments[0].definition);
+ AbstractValue argument = getValue(getDartReceiver(node));
// Unary operator.
if (opname == "unary-") {
opname = "-";
@@ -2374,8 +2161,8 @@
result = lattice.unaryOp(operator, argument);
} else if (node.arguments.length == 2) {
// Binary operator.
- AbstractValue left = getValue(node.arguments[0].definition);
- AbstractValue right = getValue(node.arguments[1].definition);
+ AbstractValue left = getValue(getDartReceiver(node));
+ AbstractValue right = getValue(getDartArgument(node, 0));
BinaryOperator operator = BinaryOperator.parse(opname);
result = lattice.binaryOp(operator, left, right);
}
@@ -2383,9 +2170,9 @@
// Update value of the continuation parameter. Again, this is effectively
// a phi.
if (result == null) {
- setResult(lattice.getInvokeReturnType(node.selector, node.mask));
+ setResult(node, lattice.getInvokeReturnType(node.selector, node.mask));
} else {
- setResult(result, canReplace: true);
+ setResult(node, result, canReplace: true);
}
}
@@ -2481,27 +2268,22 @@
}
void visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
- // TODO(asgerf): For pop(), use the container type from the TypeMask.
- setValue(node, nonConstant());
+ AbstractValue receiver = getValue(node.receiver.definition);
+ if (node.method == BuiltinMethod.Pop) {
+ setValue(node, nonConstant(
+ typeSystem.elementTypeOfIndexable(receiver.type)));
+ } else {
+ setValue(node, nonConstant());
+ }
}
void visitInvokeMethodDirectly(InvokeMethodDirectly node) {
- Continuation cont = node.continuation.definition;
- setReachable(cont);
-
- assert(cont.parameters.length == 1);
- Parameter returnValue = cont.parameters[0];
// TODO(karlklose): lookup the function and get ites return type.
- setValue(returnValue, nonConstant());
+ setResult(node, nonConstant());
}
void visitInvokeConstructor(InvokeConstructor node) {
- Continuation cont = node.continuation.definition;
- setReachable(cont);
-
- assert(cont.parameters.length == 1);
- Parameter returnValue = cont.parameters[0];
- setValue(returnValue, nonConstant(typeSystem.getReturnType(node.target)));
+ setResult(node, nonConstant(typeSystem.getReturnType(node.target)));
}
void visitThrow(Throw node) {
@@ -2537,7 +2319,7 @@
void visitTypeTest(TypeTest node) {
AbstractValue input = getValue(node.value.definition);
TypeMask boolType = typeSystem.boolType;
- switch(lattice.isSubtypeOf(input, node.type, allowNull: false)) {
+ switch(lattice.isSubtypeOf(input, node.dartType, allowNull: false)) {
case AbstractBool.Nothing:
break; // And come back later.
@@ -2558,7 +2340,7 @@
void visitTypeCast(TypeCast node) {
Continuation cont = node.continuation.definition;
AbstractValue input = getValue(node.value.definition);
- switch (lattice.isSubtypeOf(input, node.type, allowNull: true)) {
+ switch (lattice.isSubtypeOf(input, node.dartType, allowNull: true)) {
case AbstractBool.Nothing:
break; // And come back later.
@@ -2572,13 +2354,10 @@
case AbstractBool.Maybe:
setReachable(cont);
- TypeMask type = input.type;
- if (node.type.element is ClassElement) {
- // Narrow type of output to those that survive the cast.
- type = type.intersection(
- new TypeMask.subtype(node.type.element, classWorld),
- classWorld);
- }
+ // Narrow type of output to those that survive the cast.
+ TypeMask type = input.type.intersection(
+ typeSystem.subtypesOf(node.dartType),
+ classWorld);
setValue(cont.parameters.single, nonConstant(type));
break;
}
@@ -2643,12 +2422,7 @@
void visitSetStatic(SetStatic node) {}
void visitGetLazyStatic(GetLazyStatic node) {
- Continuation cont = node.continuation.definition;
- setReachable(cont);
-
- assert(cont.parameters.length == 1);
- Parameter returnValue = cont.parameters[0];
- setValue(returnValue, nonConstant(typeSystem.getFieldType(node.element)));
+ setResult(node, nonConstant(typeSystem.getFieldType(node.element)));
}
void visitInterceptor(Interceptor node) {
@@ -2707,23 +2481,27 @@
@override
void visitForeignCode(ForeignCode node) {
if (node.continuation != null) {
- Continuation continuation = node.continuation.definition;
- setReachable(continuation);
-
- assert(continuation.parameters.length == 1);
- Parameter returnValue = continuation.parameters.first;
- setValue(returnValue, nonConstant(node.type));
+ setResult(node, nonConstant(node.type));
}
}
@override
void visitGetLength(GetLength node) {
- setValue(node, nonConstant(typeSystem.intType));
+ AbstractValue input = getValue(node.object.definition);
+ int length = typeSystem.getContainerLength(input.type);
+ if (length != null) {
+ // TODO(asgerf): Constant-folding the length might degrade the VM's
+ // own bounds-check elimination?
+ setValue(node, constantValue(new IntConstantValue(length)));
+ } else {
+ setValue(node, nonConstant(typeSystem.intType));
+ }
}
@override
void visitGetIndex(GetIndex node) {
- setValue(node, nonConstant());
+ AbstractValue input = getValue(node.object.definition);
+ setValue(node, nonConstant(typeSystem.elementTypeOfIndexable(input.type)));
}
@override
@@ -2740,13 +2518,14 @@
@override
void visitRefinement(Refinement node) {
AbstractValue value = getValue(node.value.definition);
- if (value.isNothing || typeSystem.areDisjoint(value.type, node.type)) {
+ if (value.isNothing ||
+ typeSystem.areDisjoint(value.type, node.refineType)) {
setValue(node, nothing);
} else if (value.isConstant) {
setValue(node, value);
} else {
setValue(node,
- nonConstant(value.type.intersection(node.type, classWorld)));
+ nonConstant(value.type.intersection(node.refineType, classWorld)));
}
}
}
@@ -2850,7 +2629,7 @@
class ResetAnalysisInfo extends RecursiveVisitor {
Set<Continuation> reachableContinuations;
- Map<Definition, AbstractValue> values;
+ Map<Variable, ConstantValue> values;
ResetAnalysisInfo(this.reachableContinuations, this.values);
@@ -2860,10 +2639,12 @@
}
processLetPrim(LetPrim node) {
- values.remove(node.primitive);
+ node.primitive.type = null;
+ values[node.primitive] = null;
}
processLetMutable(LetMutable node) {
- values.remove(node.variable);
+ node.variable.type = null;
+ values[node.variable] = null;
}
}
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index a2f98b7..31c62c7 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -12,6 +12,7 @@
stdin, stderr;
import '../compiler.dart' as api;
+import 'commandline_options.dart';
import 'io/source_file.dart';
import 'source_file_provider.dart';
import 'filenames.dart';
@@ -286,10 +287,10 @@
wantHelp = true;
break;
case 'c':
- setCheckedMode('--enable-checked-mode');
+ setCheckedMode(Flags.enableCheckedMode);
break;
case 'm':
- implyCompilation('--minify');
+ implyCompilation(Flags.minify);
break;
default:
throw 'Internal error: "$shortOption" did not match';
@@ -301,60 +302,60 @@
List<OptionHandler> handlers = <OptionHandler>[
new OptionHandler('-[chvm?]+', handleShortOptions),
new OptionHandler('--throw-on-error(?:=[0-9]+)?', handleThrowOnError),
- new OptionHandler('--suppress-warnings', (_) {
+ new OptionHandler(Flags.suppressWarnings, (_) {
diagnosticHandler.showWarnings = false;
- passThrough('--suppress-warnings');
+ passThrough(Flags.suppressWarnings);
}),
- new OptionHandler('--fatal-warnings', passThrough),
- new OptionHandler('--suppress-hints',
+ new OptionHandler(Flags.fatalWarnings, passThrough),
+ new OptionHandler(Flags.suppressHints,
(_) => diagnosticHandler.showHints = false),
new OptionHandler(
'--output-type=dart|--output-type=dart-multi|--output-type=js',
setOutputType),
- new OptionHandler('--use-cps-ir', passThrough),
- new OptionHandler('--no-frequency-based-minification', passThrough),
- new OptionHandler('--verbose', setVerbose),
- new OptionHandler('--version', (_) => wantVersion = true),
+ new OptionHandler(Flags.useCpsIr, passThrough),
+ new OptionHandler(Flags.noFrequencyBasedMinification, passThrough),
+ new OptionHandler(Flags.verbose, setVerbose),
+ new OptionHandler(Flags.version, (_) => wantVersion = true),
new OptionHandler('--library-root=.+', setLibraryRoot),
new OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
- new OptionHandler('--allow-mock-compilation', passThrough),
- new OptionHandler('--fast-startup', passThrough),
- new OptionHandler('--minify|-m', implyCompilation),
- new OptionHandler('--preserve-uris', passThrough),
+ new OptionHandler(Flags.allowMockCompilation, passThrough),
+ new OptionHandler(Flags.fastStartup, passThrough),
+ new OptionHandler('${Flags.minify}|-m', implyCompilation),
+ new OptionHandler(Flags.preserveUris, passThrough),
new OptionHandler('--force-strip=.*', setStrip),
- new OptionHandler('--disable-diagnostic-colors',
+ new OptionHandler(Flags.disableDiagnosticColors,
(_) => diagnosticHandler.enableColors = false),
- new OptionHandler('--enable-diagnostic-colors',
+ new OptionHandler(Flags.enableDiagnosticColors,
(_) => diagnosticHandler.enableColors = true),
new OptionHandler('--enable[_-]checked[_-]mode|--checked',
- (_) => setCheckedMode('--enable-checked-mode')),
- new OptionHandler('--enable-concrete-type-inference',
+ (_) => setCheckedMode(Flags.enableCheckedMode)),
+ new OptionHandler(Flags.enableConcreteTypeInference,
(_) => implyCompilation(
- '--enable-concrete-type-inference')),
- new OptionHandler('--trust-type-annotations',
+ Flags.enableConcreteTypeInference)),
+ new OptionHandler(Flags.trustTypeAnnotations,
(_) => setTrustTypeAnnotations(
- '--trust-type-annotations')),
- new OptionHandler('--trust-primitives',
+ Flags.trustTypeAnnotations)),
+ new OptionHandler(Flags.trustPrimitives,
(_) => setTrustPrimitives(
- '--trust-primitives')),
+ Flags.trustPrimitives)),
new OptionHandler(r'--help|/\?|/h', (_) => wantHelp = true),
new OptionHandler('--packages=.+', setPackageConfig),
new OptionHandler('--package-root=.+|-p.+', setPackageRoot),
- new OptionHandler('--analyze-all', setAnalyzeAll),
- new OptionHandler('--analyze-only', setAnalyzeOnly),
- new OptionHandler('--no-source-maps', passThrough),
- new OptionHandler('--analyze-signatures-only', setAnalyzeOnly),
- new OptionHandler('--disable-native-live-type-analysis', passThrough),
+ new OptionHandler(Flags.analyzeAll, setAnalyzeAll),
+ new OptionHandler(Flags.analyzeOnly, setAnalyzeOnly),
+ new OptionHandler(Flags.noSourceMaps, passThrough),
+ new OptionHandler(Flags.analyzeSignaturesOnly, setAnalyzeOnly),
+ new OptionHandler(Flags.disableNativeLiveTypeAnalysis, passThrough),
new OptionHandler('--categories=.*', setCategories),
- new OptionHandler('--disable-type-inference', implyCompilation),
- new OptionHandler('--terse', passThrough),
+ new OptionHandler(Flags.disableTypeInference, implyCompilation),
+ new OptionHandler(Flags.terse, passThrough),
new OptionHandler('--deferred-map=.+', implyCompilation),
- new OptionHandler('--dump-info', setDumpInfo),
+ new OptionHandler(Flags.dumpInfo, setDumpInfo),
new OptionHandler('--disallow-unsafe-eval',
(_) => hasDisallowUnsafeEval = true),
- new OptionHandler('--show-package-warnings', passThrough),
- new OptionHandler('--csp', passThrough),
- new OptionHandler('--enable-experimental-mirrors', passThrough),
+ new OptionHandler(Flags.showPackageWarnings, passThrough),
+ new OptionHandler(Flags.useContentSecurityPolicy, passThrough),
+ new OptionHandler(Flags.enableExperimentalMirrors, passThrough),
new OptionHandler('--enable-async', (_) {
diagnosticHandler.info(
"Option '--enable-async' is no longer needed. "
@@ -373,9 +374,9 @@
"Enums are supported by default.",
api.Diagnostic.HINT);
}),
- new OptionHandler('--allow-native-extensions', setAllowNativeExtensions),
- new OptionHandler('--generate-code-with-compile-time-errors', passThrough),
- new OptionHandler('--test-mode', passThrough),
+ new OptionHandler(Flags.allowNativeExtensions, setAllowNativeExtensions),
+ new OptionHandler(Flags.generateCodeWithCompileTimeErrors, passThrough),
+ new OptionHandler(Flags.testMode, passThrough),
// The following three options must come last.
new OptionHandler('-D.+=.*', addInEnvironment),
@@ -415,7 +416,7 @@
}
if (checkedMode && trustTypeAnnotations) {
- helpAndFail("Option '--trust-type-annotations' may not be used in "
+ helpAndFail("Option '${Flags.trustTypeAnnotations}' may not be used in "
"checked mode.");
}
@@ -426,23 +427,23 @@
if ((analyzeOnly || analyzeAll) && !optionsImplyCompilation.isEmpty) {
if (!analyzeOnly) {
diagnosticHandler.info(
- "Option '--analyze-all' implies '--analyze-only'.",
+ "Option '${Flags.analyzeAll}' implies '${Flags.analyzeOnly}'.",
api.Diagnostic.INFO);
}
diagnosticHandler.info(
"Options $optionsImplyCompilation indicate that output is expected, "
- "but compilation is turned off by the option '--analyze-only'.",
+ "but compilation is turned off by the option '${Flags.analyzeOnly}'.",
api.Diagnostic.INFO);
}
if (analyzeAll) analyzeOnly = true;
if (!analyzeOnly) {
if (allowNativeExtensions) {
- helpAndFail("Option '--allow-native-extensions' is only supported in "
- "combination with the '--analyze-only' option.");
+ helpAndFail("Option '${Flags.allowNativeExtensions}' is only supported "
+ "in combination with the '${Flags.analyzeOnly}' option.");
}
}
if (dumpInfo && outputLanguage == OUTPUT_LANGUAGE_DART) {
- helpAndFail("Option '--dump-info' is not supported in "
+ helpAndFail("Option '${Flags.dumpInfo}' is not supported in "
"combination with the '--output-type=dart' option.");
}
diff --git a/pkg/compiler/lib/src/dart_backend/outputter.dart b/pkg/compiler/lib/src/dart_backend/outputter.dart
index 07d5a4e..82e5170 100644
--- a/pkg/compiler/lib/src/dart_backend/outputter.dart
+++ b/pkg/compiler/lib/src/dart_backend/outputter.dart
@@ -267,7 +267,7 @@
fixedStaticNames.add(element.name);
});
- for (Element export in library.exports) {
+ library.forEachExport((Element export) {
if (!library.isInternalLibrary &&
export.library.isInternalLibrary) {
// If an element of an internal library is reexported by a platform
@@ -276,7 +276,7 @@
// implementation detail of dart2js.
reexportingLibraries[export] = library;
}
- }
+ });
}
// Map to keep track of names of enum classes. Since these cannot be renamed
@@ -526,23 +526,22 @@
stripTypes: forceStripTypes,
minify: enableMinification);
unparsers[outputLibrary] = unparser;
- LibraryName libraryName = outputLibrary.libraryTag;
- if (libraryName != null) {
- unparser.visitLibraryName(libraryName);
+ if (outputLibrary.hasLibraryName) {
+ unparser.unparseLibraryName(outputLibrary.libraryName);
}
- for (LibraryTag tag in outputLibrary.tags) {
- if (tag is! LibraryDependency) continue;
- LibraryDependency dependency = tag;
- LibraryElement libraryElement =
- outputLibrary.getLibraryFromTag(dependency);
+ for (ImportElement import in outputLibrary.imports) {
+ LibraryElement libraryElement = import.importedLibrary;
String uri = outputPaths.containsKey(libraryElement)
? "${outputPaths[libraryElement]}.dart"
: libraryElement.canonicalUri.toString();
- if (dependency is Import) {
- unparser.unparseImportTag(uri);
- } else {
- unparser.unparseExportTag(uri);
- }
+ unparser.unparseImportTag(uri);
+ }
+ for (ExportElement export in outputLibrary.exports) {
+ LibraryElement libraryElement = export.exportedLibrary;
+ String uri = outputPaths.containsKey(libraryElement)
+ ? "${outputPaths[libraryElement]}.dart"
+ : libraryElement.canonicalUri.toString();
+ unparser.unparseExportTag(uri);
}
}
} else {
diff --git a/pkg/compiler/lib/src/dart_types.dart b/pkg/compiler/lib/src/dart_types.dart
index 23e87a8..1686c5a 100644
--- a/pkg/compiler/lib/src/dart_types.dart
+++ b/pkg/compiler/lib/src/dart_types.dart
@@ -12,7 +12,8 @@
import 'diagnostics/invariant.dart' show
invariant;
import 'diagnostics/spannable.dart' show
- CURRENT_ELEMENT_SPANNABLE;
+ CURRENT_ELEMENT_SPANNABLE,
+ NO_LOCATION_SPANNABLE;
import 'elements/modelx.dart' show
LibraryElementX,
TypeDeclarationElementX,
@@ -1663,6 +1664,88 @@
}
return const DynamicType();
}
+
+ /// Computes the unaliased type of the first non type variable bound of
+ /// [type].
+ ///
+ /// This is used to normalize malformed types, type variables and typedef
+ /// before use in typechecking.
+ ///
+ /// Malformed types are normalized to `dynamic`. Typedefs are normalized to
+ /// their alias, or `dynamic` if cyclic. Type variables are normalized to the
+ /// normalized type of their bound, or `Object` if cyclic.
+ ///
+ /// For instance for these types:
+ ///
+ /// class Foo<T extends Bar, S extends T, U extends Baz> {}
+ /// class Bar<X extends Y, Y extends X> {}
+ /// typedef Baz();
+ ///
+ /// the unaliased bounds types are:
+ ///
+ /// unaliasedBound(Foo) = Foo
+ /// unaliasedBound(Bar) = Bar
+ /// unaliasedBound(Unresolved) = `dynamic`
+ /// unaliasedBound(Baz) = ()->dynamic
+ /// unaliasedBound(T) = Bar
+ /// unaliasedBound(S) = unaliasedBound(T) = Bar
+ /// unaliasedBound(U) = unaliasedBound(Baz) = ()->dynamic
+ /// unaliasedBound(X) = unaliasedBound(Y) = `Object`
+ ///
+ static DartType computeUnaliasedBound(Compiler compiler, DartType type) {
+ DartType originalType = type;
+ while (type.isTypeVariable) {
+ TypeVariableType variable = type;
+ type = variable.element.bound;
+ if (type == originalType) {
+ type = compiler.objectClass.rawType;
+ }
+ }
+ if (type.isMalformed) {
+ return const DynamicType();
+ }
+ return type.unalias(compiler);
+ }
+
+ /// Computes the interface type of [type], which is the type that defines
+ /// the property of [type].
+ ///
+ /// For an interface type it is the type itself, for a type variable it is the
+ /// interface type of the bound, for function types and typedefs it is the
+ /// `Function` type. For other types, like `dynamic`, `void` and malformed
+ /// types, there is no interface type and `null` is returned.
+ ///
+ /// For instance for these types:
+ ///
+ /// class Foo<T extends Bar, S extends T, U extends Baz> {}
+ /// class Bar {}
+ /// typedef Baz();
+ ///
+ /// the interface types are:
+ ///
+ /// interfaceType(Foo) = Foo
+ /// interfaceType(Bar) = Bar
+ /// interfaceType(Baz) = interfaceType(()->dynamic) = Function
+ /// interfaceType(T) = interfaceType(Bar) = Bar
+ /// interfaceType(S) = interfaceType(T) = interfaceType(Bar) = Bar
+ /// interfaceType(U) = interfaceType(Baz)
+ /// = intefaceType(()->dynamic) = Function
+ ///
+ /// When typechecking `o.foo` the interface type of the static type of `o` is
+ /// used to lookup the existence and type of `foo`.
+ ///
+ static InterfaceType computeInterfaceType(Compiler compiler, DartType type) {
+ type = computeUnaliasedBound(compiler, type);
+ if (type.treatAsDynamic) {
+ return null;
+ }
+ if (type.isFunctionType) {
+ type = compiler.functionClass.rawType;
+ }
+ assert(invariant(NO_LOCATION_SPANNABLE, type.isInterfaceType,
+ message: "unexpected type kind ${type.kind}."));
+ return type;
+ }
}
/**
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 378710d8..949a37b 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -18,6 +18,8 @@
import 'dart_types.dart';
import 'diagnostics/messages.dart' show
MessageKind;
+import 'diagnostics/spannable.dart' show
+ Spannable;
import 'elements/elements.dart' show
AccessorElement,
AstElement,
@@ -25,7 +27,9 @@
Element,
ElementKind,
Elements,
+ ExportElement,
FunctionElement,
+ ImportElement,
LibraryElement,
MetadataAnnotation,
PrefixElement,
@@ -66,7 +70,7 @@
class OutputUnit {
/// The deferred imports that will load this output unit when one of them is
/// loaded.
- final Setlet<Import> imports = new Setlet<Import>();
+ final Setlet<_DeferredImport> imports = new Setlet<_DeferredImport>();
/// `true` if this output unit is for the main output file.
final bool isMainOutput;
@@ -86,7 +90,7 @@
int get hashCode {
int sum = 0;
- for (Import import in imports) {
+ for (_DeferredImport import in imports) {
sum = (sum + import.hashCode) & 0x3FFFFFFF; // Stay in 30 bit range.
}
return sum;
@@ -105,8 +109,7 @@
/// A synthetic [Import] representing the loading of the main
/// program.
- final Import _fakeMainImport = new Import(null, new LiteralString(null,
- new LiteralDartString("main")), null, null, null);
+ final _DeferredImport _fakeMainImport = const _DeferredImport();
/// The OutputUnit that will be loaded when the program starts.
final OutputUnit mainOutputUnit = new OutputUnit(isMainOutput: true);
@@ -127,7 +130,8 @@
/// can be loaded in parallel. And finally lib1 can be loaded.
final Map<String, List<OutputUnit>> hunksToLoad =
new Map<String, List<OutputUnit>>();
- final Map<Import, String> importDeferName = new Map<Import, String>();
+ final Map<_DeferredImport, String> _importDeferName =
+ <_DeferredImport, String>{};
/// A mapping from elements and constants to their output unit. Query this via
/// [outputUnitForElement]
@@ -142,17 +146,18 @@
/// All the imports with a [DeferredLibrary] annotation, mapped to the
/// [LibraryElement] they import.
/// The main library is included in this set for convenience.
- final Map<Import, LibraryElement> _allDeferredImports =
- new Map<Import, LibraryElement>();
+ final Map<_DeferredImport, LibraryElement> _allDeferredImports =
+ new Map<_DeferredImport, LibraryElement>();
/// Because the token-stream is forgotten later in the program, we cache a
/// description of each deferred import.
- final _deferredImportDescriptions = new Map<Import, ImportDescription>();
+ final Map<_DeferredImport, ImportDescription>_deferredImportDescriptions =
+ <_DeferredImport, ImportDescription>{};
// For each deferred import we want to know exactly what elements have to
// be loaded.
- Map<Import, Set<Element>> _importedDeferredBy = null;
- Map<Import, Set<ConstantValue>> _constantsDeferredBy = null;
+ Map<_DeferredImport, Set<Element>> _importedDeferredBy = null;
+ Map<_DeferredImport, Set<ConstantValue>> _constantsDeferredBy = null;
Set<Element> _mainElements = new Set<Element>();
@@ -192,6 +197,16 @@
return outputUnitForElement(element) != mainOutputUnit;
}
+ /// Returns the unique name for the deferred import of [prefix].
+ String getImportDeferName(Spannable node, PrefixElement prefix) {
+ String name =
+ _importDeferName[new _DeclaredDeferredImport(prefix.deferredImport)];
+ if (name == null) {
+ compiler.internalError(node, "No deferred name for $prefix.");
+ }
+ return name;
+ }
+
/// Returns `true` if element [to] is reachable from element [from] without
/// crossing a deferred import.
///
@@ -207,14 +222,14 @@
void registerConstantDeferredUse(DeferredConstantValue constant,
PrefixElement prefix) {
OutputUnit outputUnit = new OutputUnit();
- outputUnit.imports.add(prefix.deferredImport);
+ outputUnit.imports.add(new _DeclaredDeferredImport(prefix.deferredImport));
_constantToOutputUnit[constant] = outputUnit;
}
/// Answers whether [element] is explicitly deferred when referred to from
/// [library].
bool _isExplicitlyDeferred(Element element, LibraryElement library) {
- Link<Import> imports = _getImports(element, library);
+ Iterable<ImportElement> imports = _getImports(element, library);
// If the element is not imported explicitly, it is implicitly imported
// not deferred.
if (imports.isEmpty) return false;
@@ -222,11 +237,11 @@
// is explicitly deferred, we say the element is explicitly deferred.
// TODO(sigurdm): We might want to give a warning if the imports do not
// agree.
- return imports.every((Import import) => import.isDeferred);
+ return imports.every((ImportElement import) => import.isDeferred);
}
/// Returns a [Link] of every [Import] that imports [element] into [library].
- Link<Import> _getImports(Element element, LibraryElement library) {
+ Iterable<ImportElement> _getImports(Element element, LibraryElement library) {
if (element.isClassMember) {
element = element.enclosingClass;
}
@@ -246,6 +261,11 @@
Set<ConstantValue> constants,
isMirrorUsage) {
+ if (element.isErroneous) {
+ // Erroneous elements are ignored.
+ return;
+ }
+
/// Recursively collects all the dependencies of [type].
void collectTypeDependencies(DartType type) {
if (type is GenericType) {
@@ -379,14 +399,16 @@
iterateTags(LibraryElement library) {
// TODO(sigurdm): Make helper getLibraryDependencyTags when tags is
// changed to be a List instead of a Link.
- for (LibraryTag tag in library.tags) {
- if (tag is! LibraryDependency) continue;
- LibraryDependency libraryDependency = tag;
- if (!(libraryDependency is Import && libraryDependency.isDeferred)) {
- LibraryElement importedLibrary = library.getLibraryFromTag(tag);
+ for (ImportElement import in library.imports) {
+ if (!import.isDeferred) {
+ LibraryElement importedLibrary = import.importedLibrary;
traverseLibrary(importedLibrary);
}
}
+ for (ExportElement export in library.exports) {
+ LibraryElement exportedLibrary = export.exportedLibrary;
+ traverseLibrary(exportedLibrary);
+ }
}
iterateTags(library);
@@ -400,7 +422,8 @@
}
/// Add all dependencies of [constant] to the mapping of [import].
- void _mapConstantDependencies(ConstantValue constant, Import import) {
+ void _mapConstantDependencies(ConstantValue constant,
+ _DeferredImport import) {
Set<ConstantValue> constants = _constantsDeferredBy.putIfAbsent(import,
() => new Set<ConstantValue>());
if (constants.contains(constant)) return;
@@ -418,7 +441,7 @@
/// sets [_importedDeferredBy] and [_constantsDeferredBy].
/// Only one of [element] and [constant] should be given.
void _mapDependencies({Element element,
- Import import,
+ _DeferredImport import,
isMirrorUsage: false}) {
Set<Element> elements = _importedDeferredBy.putIfAbsent(import,
@@ -449,8 +472,9 @@
for (Element dependency in dependentElements) {
if (_isExplicitlyDeferred(dependency, library)) {
- for (Import deferredImport in _getImports(dependency, library)) {
- _mapDependencies(element: dependency, import: deferredImport);
+ for (ImportElement deferredImport in _getImports(dependency, library)) {
+ _mapDependencies(element: dependency,
+ import: new _DeclaredDeferredImport(deferredImport));
}
} else {
_mapDependencies(element: dependency, import: import);
@@ -460,7 +484,7 @@
for (ConstantValue dependency in dependentConstants) {
if (dependency is DeferredConstantValue) {
_mapConstantDependencies(dependency,
- dependency.prefix.deferredImport);
+ new _DeclaredDeferredImport(dependency.prefix.deferredImport));
} else {
_mapConstantDependencies(dependency, import);
}
@@ -471,7 +495,8 @@
///
/// The elements are added with [_mapDependencies].
void _addMirrorElements() {
- void mapDependenciesIfResolved(Element element, Import deferredImport) {
+ void mapDependenciesIfResolved(Element element,
+ _DeferredImport deferredImport) {
// If an element is the target of a MirrorsUsed annotation but never used
// It will not be resolved, and we should not call isNeededForReflection.
// TODO(sigurdm): Unresolved elements should just answer false when
@@ -479,27 +504,20 @@
// So we have to filter them out here.
if (element is AnalyzableElementX && !element.hasTreeElements) return;
if (compiler.backend.isAccessibleByReflection(element)) {
- _mapDependencies(element: element, import: deferredImport,
- isMirrorUsage: true);
+ _mapDependencies(
+ element: element, import: deferredImport, isMirrorUsage: true);
}
}
// For each deferred import we analyze all elements reachable from the
// imported library through non-deferred imports.
- handleLibrary(LibraryElement library, Import deferredImport) {
+ void handleLibrary(LibraryElement library, _DeferredImport deferredImport) {
library.implementation.forEachLocalMember((Element element) {
mapDependenciesIfResolved(element, deferredImport);
});
- for (MetadataAnnotation metadata in library.metadata) {
- ConstantValue constant =
- backend.constants.getConstantValueForMetadata(metadata);
- if (constant != null) {
- _mapConstantDependencies(constant, deferredImport);
- }
- }
- for (LibraryTag tag in library.tags) {
- for (MetadataAnnotation metadata in tag.metadata) {
+ void processMetadata(Element element) {
+ for (MetadataAnnotation metadata in element.metadata) {
ConstantValue constant =
backend.constants.getConstantValueForMetadata(metadata);
if (constant != null) {
@@ -507,9 +525,13 @@
}
}
}
+
+ processMetadata(library);
+ library.imports.forEach(processMetadata);
+ library.exports.forEach(processMetadata);
}
- for (Import deferredImport in _allDeferredImports.keys) {
+ for (_DeferredImport deferredImport in _allDeferredImports.keys) {
LibraryElement deferredLibrary = _allDeferredImports[deferredImport];
for (LibraryElement library in
_nonDeferredReachableLibraries(deferredLibrary)) {
@@ -524,36 +546,15 @@
void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) {
Set<String> usedImportNames = new Set<String>();
- // Finds the first argument to the [DeferredLibrary] annotation
- void computeImportDeferName(Import import) {
- String result;
- if (import == _fakeMainImport) {
- result = "main";
- } else if (import.isDeferred) {
- result = import.prefix.toString();
- } else {
- Link<MetadataAnnotation> metadatas = import.metadata;
- assert(metadatas != null);
- for (MetadataAnnotation metadata in metadatas) {
- metadata.ensureResolved(compiler);
- ConstantValue value =
- compiler.constants.getConstantValue(metadata.constant);
- Element element = value.getType(compiler.coreTypes).element;
- if (element == deferredLibraryClass) {
- ConstructedConstantValue constant = value;
- StringConstantValue s = constant.fields.values.single;
- result = s.primitiveValue.slowToString();
- break;
- }
- }
- }
+ void computeImportDeferName(_DeferredImport import) {
+ String result = import.computeImportDeferName(compiler);
assert(result != null);
- importDeferName[import] = makeUnique(result, usedImportNames);;
+ _importDeferName[import] = makeUnique(result, usedImportNames);
}
int counter = 1;
- for (Import import in _allDeferredImports.keys) {
+ for (_DeferredImport import in _allDeferredImports.keys) {
computeImportDeferName(import);
}
@@ -582,13 +583,13 @@
sortedOutputUnits.sort((a, b) => b.imports.length - a.imports.length);
// For each deferred import we find out which outputUnits to load.
- for (Import import in _allDeferredImports.keys) {
+ for (_DeferredImport import in _allDeferredImports.keys) {
if (import == _fakeMainImport) continue;
- hunksToLoad[importDeferName[import]] = new List<OutputUnit>();
+ hunksToLoad[_importDeferName[import]] = new List<OutputUnit>();
for (OutputUnit outputUnit in sortedOutputUnits) {
if (outputUnit == mainOutputUnit) continue;
if (outputUnit.imports.contains(import)) {
- hunksToLoad[importDeferName[import]].add(outputUnit);
+ hunksToLoad[_importDeferName[import]].add(outputUnit);
}
}
}
@@ -601,8 +602,8 @@
}
if (main == null) return;
LibraryElement mainLibrary = main.library;
- _importedDeferredBy = new Map<Import, Set<Element>>();
- _constantsDeferredBy = new Map<Import, Set<ConstantValue>>();
+ _importedDeferredBy = new Map<_DeferredImport, Set<Element>>();
+ _constantsDeferredBy = new Map<_DeferredImport, Set<ConstantValue>>();
_importedDeferredBy[_fakeMainImport] = _mainElements;
measureElement(mainLibrary, () {
@@ -631,7 +632,7 @@
// Reverse the mappings. For each element record an OutputUnit collecting
// all deferred imports mapped to this element. Same for constants.
- for (Import import in _importedDeferredBy.keys) {
+ for (_DeferredImport import in _importedDeferredBy.keys) {
for (Element element in _importedDeferredBy[import]) {
// Only one file should be loaded when the program starts, so make
// sure that only one OutputUnit is created for [fakeMainImport].
@@ -644,7 +645,7 @@
}
}
}
- for (Import import in _constantsDeferredBy.keys) {
+ for (_DeferredImport import in _constantsDeferredBy.keys) {
for (ConstantValue constant in _constantsDeferredBy[import]) {
// Only one file should be loaded when the program starts, so make
// sure that only one OutputUnit is created for [fakeMainImport].
@@ -711,19 +712,17 @@
// The prefixes that have been used by any imports in this library.
Setlet<String> usedPrefixes = new Setlet<String>();
// The last deferred import we saw with a given prefix (if any).
- Map<String, Import> prefixDeferredImport = new Map<String, Import>();
+ Map<String, ImportElement> prefixDeferredImport =
+ new Map<String, ImportElement>();
for (LibraryElement library in compiler.libraryLoader.libraries) {
compiler.withCurrentElement(library, () {
prefixDeferredImport.clear();
usedPrefixes.clear();
// TODO(sigurdm): Make helper getLibraryImportTags when tags is a List
// instead of a Link.
- for (LibraryTag tag in library.tags) {
- if (tag is! Import) continue;
- Import import = tag;
-
+ for (ImportElement import in library.imports) {
/// Give an error if the old annotation-based syntax has been used.
- Link<MetadataAnnotation> metadataList = import.metadata;
+ List<MetadataAnnotation> metadataList = import.metadata;
if (metadataList != null) {
for (MetadataAnnotation metadata in metadataList) {
metadata.ensureResolved(compiler);
@@ -738,20 +737,21 @@
}
String prefix = (import.prefix != null)
- ? import.prefix.toString()
+ ? import.prefix.name
: null;
// The last import we saw with the same prefix.
- Import previousDeferredImport = prefixDeferredImport[prefix];
+ ImportElement previousDeferredImport = prefixDeferredImport[prefix];
if (import.isDeferred) {
- LibraryElement importedLibrary = library.getLibraryFromTag(import);
- _allDeferredImports[import] = importedLibrary;
+ _DeferredImport key = new _DeclaredDeferredImport(import);
+ LibraryElement importedLibrary = import.importedLibrary;
+ _allDeferredImports[key] = importedLibrary;
if (prefix == null) {
compiler.reportError(import,
MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX);
} else {
prefixDeferredImport[prefix] = import;
- _deferredImportDescriptions[import] =
+ _deferredImportDescriptions[key] =
new ImportDescription(import, library, compiler);
}
isProgramSplit = true;
@@ -760,7 +760,7 @@
if (prefix != null) {
if (previousDeferredImport != null ||
(import.isDeferred && usedPrefixes.contains(prefix))) {
- Import failingImport = (previousDeferredImport != null)
+ ImportElement failingImport = (previousDeferredImport != null)
? previousDeferredImport
: import;
compiler.reportError(failingImport.prefix,
@@ -850,8 +850,8 @@
JavaScriptBackend backend = compiler.backend;
Map<String, Map<String, dynamic>> mapping =
new Map<String, Map<String, dynamic>>();
- _deferredImportDescriptions.keys.forEach((ast.Import import) {
- List<OutputUnit> outputUnits = hunksToLoad[importDeferName[import]];
+ _deferredImportDescriptions.keys.forEach((_DeferredImport import) {
+ List<OutputUnit> outputUnits = hunksToLoad[_importDeferName[import]];
ImportDescription description = _deferredImportDescriptions[import];
Map<String, dynamic> libraryMap =
mapping.putIfAbsent(description.importingUri,
@@ -874,20 +874,73 @@
final String prefix;
final LibraryElement _importingLibrary;
- ImportDescription(Import import,
+ ImportDescription(ImportElement import,
LibraryElement importingLibrary,
Compiler compiler)
: importingUri = uri_extras.relativize(
compiler.mainApp.canonicalUri,
importingLibrary.canonicalUri, false),
- prefix = import.prefix.source,
+ prefix = import.prefix.name,
_importingLibrary = importingLibrary;
String get importingLibraryName {
- String libraryName = _importingLibrary.getLibraryName();
- return libraryName == ""
- ? "<unnamed>"
- : libraryName;
+ return _importingLibrary.hasLibraryName
+ ? _importingLibrary.libraryName : "<unnamed>";
+ }
+}
+
+/// A node in the deferred import graph.
+///
+/// This class serves as the root node; the 'import' of the main library.
+class _DeferredImport {
+ const _DeferredImport();
+
+ /// Computes a suggestive name for this import.
+ String computeImportDeferName(Compiler compiler) => 'main';
+}
+
+/// A node in the deferred import graph defined by a deferred import directive.
+class _DeclaredDeferredImport implements _DeferredImport {
+ final ImportElement declaration;
+
+ _DeclaredDeferredImport(this.declaration);
+
+ @override
+ String computeImportDeferName(Compiler compiler) {
+ String result;
+ if (declaration.isDeferred) {
+ if (declaration.prefix != null) {
+ result = declaration.prefix.name;
+ } else {
+ // This happens when the deferred import isn't declared with a prefix.
+ assert(compiler.compilationFailed);
+ result = '';
+ }
+ } else {
+ // Finds the first argument to the [DeferredLibrary] annotation
+ List<MetadataAnnotation> metadatas = declaration.metadata;
+ assert(metadatas != null);
+ for (MetadataAnnotation metadata in metadatas) {
+ metadata.ensureResolved(compiler);
+ ConstantValue value =
+ compiler.constants.getConstantValue(metadata.constant);
+ Element element = value.getType(compiler.coreTypes).element;
+ if (element == compiler.deferredLibraryClass) {
+ ConstructedConstantValue constant = value;
+ StringConstantValue s = constant.fields.values.single;
+ result = s.primitiveValue.slowToString();
+ break;
+ }
+ }
+ }
+ assert(result != null);
+ return result;
}
+ bool operator ==(other) {
+ if (other is! _DeclaredDeferredImport) return false;
+ return declaration == other.declaration;
+ }
+
+ int get hashCode => declaration.hashCode * 17;
}
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index b812fd3..8fabdf8 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -166,6 +166,7 @@
DEFERRED_TYPE_ANNOTATION,
DEPRECATED_TYPEDEF_MIXIN_SYNTAX,
DIRECTLY_THROWING_NSM,
+ DISALLOWED_LIBRARY_IMPORT,
DUPLICATE_DEFINITION,
DUPLICATE_EXPORT,
DUPLICATE_EXPORT_CONT,
@@ -197,6 +198,7 @@
FACTORY_REDIRECTION_IN_NON_FACTORY,
FINAL_FUNCTION_TYPE_PARAMETER,
FINAL_WITHOUT_INITIALIZER,
+ FORIN_NOT_ASSIGNABLE,
FORMAL_DECLARED_CONST,
FORMAL_DECLARED_STATIC,
FUNCTION_TYPE_FORMAL_WITH_DEFAULT,
@@ -272,6 +274,7 @@
INVALID_USE_OF_SUPER,
LIBRARY_NAME_MISMATCH,
LIBRARY_NOT_FOUND,
+ LIBRARY_NOT_SUPPORTED,
LIBRARY_TAG_MUST_BE_FIRST,
MAIN_NOT_A_FUNCTION,
MAIN_WITH_EXTRA_PARAMETER,
@@ -309,6 +312,7 @@
NATIVE_NOT_SUPPORTED,
NO_BREAK_TARGET,
NO_CATCH_NOR_FINALLY,
+ NO_COMMON_SUBTYPES,
NO_CONTINUE_TARGET,
NO_INSTANCE_AVAILABLE,
NO_MATCHING_CONSTRUCTOR,
@@ -492,6 +496,11 @@
const MessageTemplate(MessageKind.NOT_ASSIGNABLE,
"'#{fromType}' is not assignable to '#{toType}'."),
+ MessageKind.FORIN_NOT_ASSIGNABLE:
+ const MessageTemplate(MessageKind.FORIN_NOT_ASSIGNABLE,
+ "The element type '#{currentType}' of '#{expressionType}' "
+ "is not assignable to '#{elementType}'."),
+
MessageKind.VOID_EXPRESSION:
const MessageTemplate(MessageKind.VOID_EXPRESSION,
"Expression does not yield a value."),
@@ -2088,6 +2097,20 @@
const MessageTemplate(MessageKind.LIBRARY_NOT_FOUND,
"Library not found '#{resolvedUri}'."),
+ MessageKind.LIBRARY_NOT_SUPPORTED:
+ const MessageTemplate(MessageKind.LIBRARY_NOT_SUPPORTED,
+ "Library not supported '#{resolvedUri}'.",
+ howToFix: "Try removing the dependency or enabling support using "
+ "the '--categories' option.",
+ examples: const [/*
+ """
+ import 'dart:io';
+ main() {}
+ """
+ */]),
+ // TODO(johnniwinther): Enable example when message_kind_test.dart
+ // supports library loader callbacks.
+
MessageKind.UNSUPPORTED_EQ_EQ_EQ:
const MessageTemplate(MessageKind.UNSUPPORTED_EQ_EQ_EQ,
"'===' is not an operator. "
@@ -2894,6 +2917,10 @@
howToFix:
"Try replacing '#{shownType}' with '#{shownTypeSuggestion}'."),
+ MessageKind.NO_COMMON_SUBTYPES:
+ const MessageTemplate(MessageKind.NO_COMMON_SUBTYPES,
+ "Types '#{left}' and '#{right}' have no common subtypes."),
+
MessageKind.HIDDEN_WARNINGS_HINTS:
const MessageTemplate(MessageKind.HIDDEN_WARNINGS_HINTS,
"#{warnings} warning(s) and #{hints} hint(s) suppressed in #{uri}."),
@@ -3263,6 +3290,14 @@
****************************************************************
'''),
+ MessageKind.DISALLOWED_LIBRARY_IMPORT:
+ const MessageTemplate(MessageKind.DISALLOWED_LIBRARY_IMPORT, '''
+Your app imports the unsupported library '#{uri}' via:
+''''''
+$DISALLOWED_LIBRARY_IMPORT_PADDING#{importChain}
+
+Use the --categories option to support import of '#{uri}'.
+'''),
MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND:
const MessageTemplate(
@@ -3303,8 +3338,14 @@
}; // End of TEMPLATES.
+ /// Padding used before and between import chains in the message for
+ /// [MessageKind.IMPORT_EXPERIMENTAL_MIRRORS].
static const String IMPORT_EXPERIMENTAL_MIRRORS_PADDING = '\n* ';
+ /// Padding used before and between import chains in the message for
+ /// [MessageKind.DISALLOWED_LIBRARY_IMPORT].
+ static const String DISALLOWED_LIBRARY_IMPORT_PADDING = '\n ';
+
toString() => template;
Message message([Map arguments = const {}, bool terse = false]) {
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 4ba2073..adf558d 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -82,8 +82,7 @@
}
LibraryInfo visitLibraryElement(LibraryElement element, _) {
- String libname = element.getLibraryName();
- libname = libname == "" ? "<unnamed>" : libname;
+ String libname = element.hasLibraryName ? element.libraryName : "<unnamed>";
int size = compiler.dumpInfoTask.sizeOf(element);
LibraryInfo info =
new LibraryInfo(libname, element.canonicalUri, null, size);
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index 5320fcb..6c4352a 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -133,9 +133,9 @@
bool get isInternalLibrary =>
isPlatformLibrary && canonicalUri.path.startsWith('_');
- String getLibraryOrScriptName() {
- if (hasLibraryName()) {
- return getLibraryName();
+ String get libraryOrScriptName {
+ if (hasLibraryName) {
+ return libraryName;
} else {
// Use the file name as script name.
String path = canonicalUri.path;
@@ -145,7 +145,7 @@
int compareTo(LibraryElement other) {
if (this == other) return 0;
- return getLibraryOrScriptName().compareTo(other.getLibraryOrScriptName());
+ return libraryOrScriptName.compareTo(other.libraryOrScriptName);
}
}
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index 219349b..7c538b5 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -106,6 +106,10 @@
const ElementKind('abstract_field', ElementCategory.VARIABLE);
static const ElementKind LIBRARY =
const ElementKind('library', ElementCategory.NONE);
+ static const ElementKind IMPORT =
+ const ElementKind('import', ElementCategory.NONE);
+ static const ElementKind EXPORT =
+ const ElementKind('export', ElementCategory.NONE);
static const ElementKind PREFIX =
const ElementKind('prefix', ElementCategory.PREFIX);
static const ElementKind TYPEDEF =
@@ -182,11 +186,17 @@
String get name;
ElementKind get kind;
Element get enclosingElement;
- Link<MetadataAnnotation> get metadata;
+ Iterable<MetadataAnnotation> get metadata;
/// `true` if this element is a library.
bool get isLibrary;
+ /// `true` if this element is an import declaration.
+ bool get isImport => kind == ElementKind.IMPORT;
+
+ /// `true` if this element is an export declaration.
+ bool get isExport => kind == ElementKind.EXPORT;
+
/// `true` if this element is a compilation unit.
bool get isCompilationUnit;
@@ -832,6 +842,22 @@
int compareTo(CompilationUnitElement other);
}
+abstract class ImportElement extends Element {
+ Uri get uri;
+ LibraryElement get importedLibrary;
+ bool get isDeferred;
+ PrefixElement get prefix;
+ // TODO(johnniwinther): Remove this when no longer needed in source mirrors.
+ Import get node;
+}
+
+abstract class ExportElement extends Element {
+ Uri get uri;
+ LibraryElement get exportedLibrary;
+ // TODO(johnniwinther): Remove this when no longer needed in source mirrors.
+ Export get node;
+}
+
abstract class LibraryElement extends Element
implements ScopeContainerElement, AnalyzableElement {
/**
@@ -847,9 +873,13 @@
CompilationUnitElement get entryCompilationUnit;
Link<CompilationUnitElement> get compilationUnits;
- Iterable<LibraryTag> get tags;
- LibraryName get libraryTag;
- Link<Element> get exports;
+
+ /// The import declarations in this library, including the implicit import of
+ /// 'dart:core', if present.
+ Iterable<ImportElement> get imports;
+
+ /// The export declarations in this library.
+ Iterable<ExportElement> get exports;
/**
* [:true:] if this library is part of the platform, that is, its canonical
@@ -874,9 +904,6 @@
LibraryElement get implementation;
- /// Return the library element corresponding to an import or export.
- LibraryElement getLibraryFromTag(LibraryDependency tag);
-
Element find(String elementName);
Element findLocal(String elementName);
Element findExported(String elementName);
@@ -886,32 +913,35 @@
void forEachImport(f(Element element));
/// Returns the imports that import element into this library.
- Link<Import> getImportsFor(Element element);
+ Iterable<ImportElement> getImportsFor(Element element);
- bool hasLibraryName();
- String getLibraryName();
+ /// `true` if this library has name as given through a library tag.
+ bool get hasLibraryName;
- /**
- * Returns the library name (as defined by the library tag) or for script
- * (which have no library tag) the script file name. The latter case is used
- * to provide a 'library name' for scripts to use for instance in dartdoc.
- *
- * Note: the returned filename is still escaped ("a%20b.dart" instead of
- * "a b.dart").
- */
- String getLibraryOrScriptName();
+ /// The library name, which is either the name given in the library tag
+ /// or the empty string if there is no library tag.
+ String get libraryName;
+
+ /// Returns the library name (as defined by the library tag) or for script
+ /// (which have no library tag) the script file name. The latter case is used
+ /// to provide a 'library name' for scripts to use for instance in dartdoc.
+ ///
+ /// Note: the returned filename is still escaped ("a%20b.dart" instead of
+ /// "a b.dart").
+ String get libraryOrScriptName;
int compareTo(LibraryElement other);
}
/// The implicit scope defined by a import declaration with a prefix clause.
abstract class PrefixElement extends Element {
- void addImport(Element element, Import import, DiagnosticListener listener);
Element lookupLocalMember(String memberName);
+
/// Is true if this prefix belongs to a deferred import.
bool get isDeferred;
- void markAsDeferred(Import import);
- Import get deferredImport;
+
+ /// Import that declared this deferred prefix.
+ ImportElement get deferredImport;
}
/// A type alias definition.
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 6574231..de3c11f 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -59,7 +59,7 @@
final ElementKind kind;
final Element enclosingElement;
final int hashCode = ++elementHashCode;
- Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();
+ List<MetadataAnnotation> metadataInternal;
ElementX(this.name, this.kind, this.enclosingElement) {
assert(isErroneous || implementationLibrary != null);
@@ -73,14 +73,27 @@
return null;
}
- void addMetadata(MetadataAnnotationX annotation) {
- assert(annotation.annotatedElement == null);
- annotation.annotatedElement = this;
- addMetadataInternal(annotation);
+ void set metadata(List<MetadataAnnotation> metadata) {
+ assert(metadataInternal == null);
+ for (MetadataAnnotationX annotation in metadata) {
+ assert(annotation.annotatedElement == null);
+ annotation.annotatedElement = this;
+ }
+ metadataInternal = metadata;
}
- void addMetadataInternal(MetadataAnnotation annotation) {
- metadata = metadata.prepend(annotation);
+ Iterable<MetadataAnnotation> get metadata {
+ if (isPatch && metadataInternal != null) {
+ if (origin.metadata.isEmpty) {
+ return metadataInternal;
+ } else {
+ return <MetadataAnnotation>[]
+ ..addAll(origin.metadata)
+ ..addAll(metadataInternal);
+ }
+ }
+ return metadataInternal != null
+ ? metadataInternal : const <MetadataAnnotation>[];
}
bool get isClosure => false;
@@ -280,7 +293,7 @@
}
get asyncMarker => AsyncMarker.SYNC;
- Link<MetadataAnnotation> get metadata => unsupported();
+ Iterable<MetadataAnnotation> get metadata => unsupported();
bool get hasNode => false;
get node => unsupported();
get hasResolvedAst => false;
@@ -547,11 +560,10 @@
for (Element element in ambiguousElements) {
var arguments = {'name': element.name};
listener.reportInfo(element, code, arguments);
- Link<Import> importers = importer.importers.getImports(element);
listener.withCurrentElement(importer, () {
- for (; !importers.isEmpty; importers = importers.tail) {
+ for (ImportElement import in importer.importers.getImports(element)) {
listener.reportInfo(
- importers.head, MessageKind.IMPORTED_HERE, arguments);
+ import, MessageKind.IMPORTED_HERE, arguments);
}
});
}
@@ -678,6 +690,19 @@
@override
LibraryElementX get library => enclosingElement.declaration;
+ void set metadata(List<MetadataAnnotation> metadata) {
+ for (MetadataAnnotationX annotation in metadata) {
+ assert(annotation.annotatedElement == null);
+ annotation.annotatedElement = this;
+ }
+ // TODO(johnniwinther): Remove this work-around when import, export,
+ // part, and part-of declarations are elements.
+ if (metadataInternal == null) {
+ metadataInternal = <MetadataAnnotation>[];
+ }
+ metadataInternal.addAll(metadata);
+ }
+
void forEachLocalMember(f(Element element)) {
localMembers.forEach(f);
}
@@ -736,22 +761,26 @@
}
}
+/// Map from [Element] to the [ImportElement]s throught which it was imported.
+///
+/// This is used for error reporting and deferred loading.
class Importers {
- Map<Element, Link<Import>> importers = new Map<Element, Link<Import>>();
+ Map<Element, List<ImportElement>> importers =
+ new Map<Element, List<ImportElement>>();
- Link<Import> getImports(Element element) {
- Link<Import> imports = importers[element];
- return imports != null ? imports : const Link<Import>();
+ /// Returns the the list of [ImportElement]s through which [element] was
+ /// imported.
+ List<ImportElement> getImports(Element element) {
+ List<ImportElement> imports = importers[element];
+ return imports != null ? imports : const <ImportElement>[];
}
- Import getImport(Element element) => getImports(element).head;
+ /// Returns the first [ImportElement] through which [element] was imported.
+ ImportElement getImport(Element element) => getImports(element).first;
- void registerImport(Element element, Import import) {
- if (import == null) return;
-
- importers[element] =
- importers.putIfAbsent(element, () => const Link<Import>())
- .prepend(import);
+ /// Register [element] as imported through [import];
+ void registerImport(Element element, ImportElement import) {
+ importers.putIfAbsent(element, () => <ImportElement>[]).add(import);
}
}
@@ -774,7 +803,7 @@
*/
void addImport(Element enclosingElement,
Element element,
- Import import,
+ ImportElement import,
DiagnosticListener listener) {
LibraryElementX library = enclosingElement.library;
Importers importers = library.importers;
@@ -789,7 +818,7 @@
Element existing = importScope.putIfAbsent(name, () => element);
importers.registerImport(element, import);
- void registerWarnOnUseElement(Import import,
+ void registerWarnOnUseElement(ImportElement import,
MessageKind messageKind,
Element hidingElement,
Element hiddenElement) {
@@ -810,7 +839,7 @@
}
if (existing != element) {
- Import existingImport = importers.getImport(existing);
+ ImportElement existingImport = importers.getImport(existing);
if (existing.library.isPlatformLibrary &&
!element.library.isPlatformLibrary) {
// [existing] is implicitly hidden.
@@ -819,7 +848,7 @@
} else if (!existing.library.isPlatformLibrary &&
element.library.isPlatformLibrary) {
// [element] is implicitly hidden.
- if (import == null) {
+ if (import.isSynthesized) {
// [element] is imported implicitly (probably through dart:core).
registerWarnOnUseElement(
existingImport, MessageKind.HIDDEN_IMPLICIT_IMPORT,
@@ -840,6 +869,94 @@
}
Element operator [](String name) => importScope[name];
+
+ void forEach(f(Element element)) => importScope.values.forEach(f);
+}
+
+abstract class LibraryDependencyElementX extends ElementX {
+ final LibraryDependency node;
+ final Uri uri;
+ LibraryElement libraryDependency;
+
+ LibraryDependencyElementX(CompilationUnitElement enclosingElement,
+ ElementKind kind,
+ this.node,
+ this.uri)
+ : super('', kind, enclosingElement);
+
+ @override
+ List<MetadataAnnotation> get metadata => node.metadata;
+
+ void set metadata(value) {
+ // The metadata is stored on [libraryDependency].
+ throw new SpannableAssertionFailure(
+ this, 'Cannot set metadata on a import/export.');
+ }
+
+ @override
+ Token get position => node.getBeginToken();
+
+ SourceSpan get sourcePosition {
+ return new SourceSpan.fromNode(compilationUnit.script.resourceUri, node);
+ }
+
+ String toString() => '$kind($uri)';
+}
+
+class ImportElementX extends LibraryDependencyElementX
+ implements ImportElement {
+ PrefixElementX prefix;
+
+ ImportElementX(CompilationUnitElement enclosingElement, Import node, Uri uri)
+ : super(enclosingElement, ElementKind.IMPORT, node, uri);
+
+ @override
+ Import get node => super.node;
+
+ @override
+ LibraryElement get importedLibrary => libraryDependency;
+
+ @override
+ accept(ElementVisitor visitor, arg) => visitor.visitImportElement(this, arg);
+
+ @override
+ bool get isDeferred => node.isDeferred;
+}
+
+class SyntheticImportElement extends ImportElementX {
+ SyntheticImportElement(CompilationUnitElement enclosingElement, Uri uri)
+ : super(enclosingElement, null, uri);
+
+ @override
+ Token get position => library.position;
+
+ @override
+ bool get isSynthesized => true;
+
+ @override
+ bool get isDeferred => false;
+
+ @override
+ List<MetadataAnnotation> get metadata => const <MetadataAnnotation>[];
+
+ @override
+ SourceSpan get sourcePosition => library.sourcePosition;
+}
+
+
+class ExportElementX extends LibraryDependencyElementX
+ implements ExportElement {
+
+ ExportElementX(CompilationUnitElement enclosingElement, Export node, Uri uri)
+ : super(enclosingElement, ElementKind.EXPORT, node, uri);
+
+ Export get node => super.node;
+
+ @override
+ LibraryElement get exportedLibrary => libraryDependency;
+
+ @override
+ accept(ElementVisitor visitor, arg) => visitor.visitExportElement(this, arg);
}
class LibraryElementX
@@ -877,6 +994,9 @@
*/
Link<Element> slotForExports;
+ List<ImportElement> _imports = <ImportElement>[];
+ List<ExportElement> _exports = <ExportElement>[];
+
final Map<LibraryDependency, LibraryElement> tagMapping =
new Map<LibraryDependency, LibraryElement>();
@@ -892,11 +1012,14 @@
}
}
- Link<MetadataAnnotation> get metadata {
- return (libraryTag == null) ? super.metadata : libraryTag.metadata;
+ Iterable<MetadataAnnotation> get metadata {
+ if (libraryTag != null) {
+ return libraryTag.metadata;
+ }
+ return const <MetadataAnnotation>[];
}
- set metadata(value) {
+ void set metadata(value) {
// The metadata is stored on [libraryTag].
throw new SpannableAssertionFailure(this, 'Cannot set metadata on Library');
}
@@ -925,13 +1048,17 @@
return tagsCache;
}
- /// Record which element an import or export tag resolved to.
- void recordResolvedTag(LibraryDependency tag, LibraryElement library) {
- assert(tagMapping[tag] == null);
- tagMapping[tag] = library;
+ void addImportDeclaration(ImportElement import) {
+ _imports.add(import);
}
- LibraryElement getLibraryFromTag(LibraryDependency tag) => tagMapping[tag];
+ Iterable<ImportElement> get imports => _imports;
+
+ void addExportDeclaration(ExportElement export) {
+ _exports.add(export);
+ }
+
+ Iterable<ExportElement> get exports => _exports;
/**
* Adds [element] to the import scope of this library.
@@ -940,7 +1067,9 @@
* [ErroneousElement] will be put in the imported scope, allowing for
* detection of ambiguous uses of imported names.
*/
- void addImport(Element element, Import import, DiagnosticListener listener) {
+ void addImport(Element element,
+ ImportElement import,
+ DiagnosticListener listener) {
importScope.addImport(this, element, import, listener);
}
@@ -967,12 +1096,6 @@
*/
bool get exportsHandled => slotForExports != null;
- Link<Element> get exports {
- assert(invariant(this, exportsHandled,
- message: 'Exports not handled on $this'));
- return slotForExports;
- }
-
/**
* Sets the export scope of this library. This method can only be called once.
*/
@@ -1024,7 +1147,9 @@
}
Element findExported(String elementName) {
- for (Link link = exports; !link.isEmpty; link = link.tail) {
+ assert(invariant(this, exportsHandled,
+ message: 'Exports not handled on $this'));
+ for (Link link = slotForExports; !link.isEmpty; link = link.tail) {
Element element = link.head;
if (element.name == elementName) return element;
}
@@ -1032,16 +1157,17 @@
}
void forEachExport(f(Element element)) {
- exports.forEach((Element e) => f(e));
+ assert(invariant(this, exportsHandled,
+ message: 'Exports not handled on $this'));
+ slotForExports.forEach((Element e) => f(e));
}
- Link<Import> getImportsFor(Element element) => importers.getImports(element);
-
- @override
- void forEachImport(f(Element element)) {
- importScope.importScope.values.forEach(f);
+ Iterable<ImportElement> getImportsFor(Element element) {
+ return importers.getImports(element);
}
+ void forEachImport(f(Element element)) => importScope.forEach(f);
+
void forEachLocalMember(f(Element element)) {
if (isPatch) {
// Patch libraries traverse both origin and injected members.
@@ -1067,17 +1193,23 @@
});
}
- bool hasLibraryName() => libraryTag != null;
+ bool get hasLibraryName => libraryTag != null;
- /**
- * Returns the library name, which is either the name given in the library tag
- * or the empty string if there is no library tag.
- */
- String getLibraryName() {
+ String get libraryName {
if (libraryTag == null) return '';
return libraryTag.name.toString();
}
+ String get libraryOrScriptName {
+ if (libraryTag != null) {
+ return libraryTag.name.toString();
+ } else {
+ // Use the file name as script name.
+ String path = canonicalUri.path;
+ return path.substring(path.lastIndexOf('/') + 1);
+ }
+ }
+
Scope buildScope() => new LibraryScope(this);
String toString() {
@@ -1104,13 +1236,15 @@
final ImportScope importScope = new ImportScope();
- bool get isDeferred => _deferredImport != null;
+ bool get isDeferred => deferredImport != null;
// Only needed for deferred imports.
- Import _deferredImport;
- Import get deferredImport => _deferredImport;
+ final ImportElement deferredImport;
- PrefixElementX(String prefix, Element enclosing, this.firstPosition)
+ PrefixElementX(String prefix,
+ Element enclosing,
+ this.firstPosition,
+ this.deferredImport)
: super(prefix, ElementKind.PREFIX, enclosing);
bool get isTopLevel => false;
@@ -1121,7 +1255,9 @@
Token get position => firstPosition;
- void addImport(Element element, Import import, DiagnosticListener listener) {
+ void addImport(Element element,
+ ImportElement import,
+ DiagnosticListener listener) {
importScope.addImport(this, element, import, listener);
}
@@ -1129,10 +1265,6 @@
return visitor.visitPrefixElement(this, arg);
}
- void markAsDeferred(Import deferredImport) {
- _deferredImport = deferredImport;
- }
-
String toString() => '$kind($name)';
}
@@ -1218,7 +1350,7 @@
VariableDefinitions definitions;
DartType type;
final Modifiers modifiers;
- Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();
+ List<MetadataAnnotation> metadataInternal;
VariableList(Modifiers this.modifiers);
@@ -1228,6 +1360,25 @@
assert(modifiers != null);
}
+ Iterable<MetadataAnnotation> get metadata {
+ return metadataInternal != null
+ ? metadataInternal : const <MetadataAnnotation>[];
+ }
+
+ void set metadata(List<MetadataAnnotation> metadata) {
+ if (metadata.isEmpty) {
+ // For a multi declaration like:
+ //
+ // @foo @bar var a, b, c
+ //
+ // the metadata list is reported through the declaration of `a`, and `b`
+ // and `c` report an empty list of metadata.
+ return;
+ }
+ assert(metadataInternal == null);
+ metadataInternal = metadata;
+ }
+
VariableDefinitions parseNode(Element element, DiagnosticListener listener) {
return definitions;
}
@@ -1284,10 +1435,14 @@
// TODO(johnniwinther): Ensure that the [TreeElements] for this variable hold
// the mappings for all its metadata.
- Link<MetadataAnnotation> get metadata => variables.metadata;
+ Iterable<MetadataAnnotation> get metadata => variables.metadata;
- void addMetadataInternal(MetadataAnnotation annotation) {
- variables.metadata = variables.metadata.prepend(annotation);
+ void set metadata(List<MetadataAnnotation> metadata) {
+ for (MetadataAnnotationX annotation in metadata) {
+ assert(annotation.annotatedElement == null);
+ annotation.annotatedElement = this;
+ }
+ variables.metadata = metadata;
}
// A variable cannot be patched therefore defines itself.
@@ -2097,7 +2252,7 @@
FunctionExpression get node => constructor.node;
- Link<MetadataAnnotation> get metadata => constructor.metadata;
+ List<MetadataAnnotation> get metadata => constructor.metadata;
bool get isInstanceMember => true;
@@ -2363,6 +2518,7 @@
void ensureResolved(Compiler compiler) {
if (resolutionState == STATE_NOT_STARTED) {
compiler.resolver.resolveClass(this);
+ compiler.world.registerClass(this);
}
}
@@ -2617,7 +2773,7 @@
final Node node;
final Modifiers modifiers;
- Link<FunctionElement> constructors = new Link<FunctionElement>();
+ Link<ConstructorElement> constructors = new Link<ConstructorElement>();
InterfaceType mixinType;
diff --git a/pkg/compiler/lib/src/elements/names.dart b/pkg/compiler/lib/src/elements/names.dart
index 514729c..314a94b 100644
--- a/pkg/compiler/lib/src/elements/names.dart
+++ b/pkg/compiler/lib/src/elements/names.dart
@@ -110,5 +110,5 @@
return super==(other) && library == other.library;
}
- String toString() => '${library.getLibraryName()}#${super.toString()}';
+ String toString() => '${library.libraryName}#${super.toString()}';
}
diff --git a/pkg/compiler/lib/src/elements/visitor.dart b/pkg/compiler/lib/src/elements/visitor.dart
index 7769226..23d5263 100644
--- a/pkg/compiler/lib/src/elements/visitor.dart
+++ b/pkg/compiler/lib/src/elements/visitor.dart
@@ -20,6 +20,8 @@
R visitAmbiguousElement(AmbiguousElement e, A arg) => null;
R visitCompilationUnitElement(CompilationUnitElement e, A arg) => null;
R visitLibraryElement(LibraryElement e, A arg) => null;
+ R visitImportElement(ImportElement e, A arg) => null;
+ R visitExportElement(ExportElement e, A arg) => null;
R visitPrefixElement(PrefixElement e, A arg) => null;
R visitTypedefElement(TypedefElement e, A arg) => null;
R visitVariableElement(VariableElement e, A arg) => null;
@@ -76,6 +78,16 @@
}
@override
+ R visitImportElement(ImportElement e, A arg) {
+ return visitElement(e, arg);
+ }
+
+ @override
+ R visitExportElement(ExportElement e, A arg) {
+ return visitElement(e, arg);
+ }
+
+ @override
R visitPrefixElement(PrefixElement e, A arg) {
return visitElement(e, arg);
}
diff --git a/pkg/compiler/lib/src/helpers/stats.dart b/pkg/compiler/lib/src/helpers/stats.dart
index 13897c7..d7f6b5d 100644
--- a/pkg/compiler/lib/src/helpers/stats.dart
+++ b/pkg/compiler/lib/src/helpers/stats.dart
@@ -458,7 +458,7 @@
indentation = ''.padLeft(countText.length, ' ');
if (commonPrefix != null) {
int index = 0;
- for (String line in commonPrefix) {
+ for (StackTraceLine line in commonPrefix) {
sb.write(indentation);
if (index > 1) {
sb.write('...\n');
diff --git a/pkg/compiler/lib/src/helpers/trace.dart b/pkg/compiler/lib/src/helpers/trace.dart
index f19b0d0..b928bb6 100644
--- a/pkg/compiler/lib/src/helpers/trace.dart
+++ b/pkg/compiler/lib/src/helpers/trace.dart
@@ -131,8 +131,9 @@
// Dart VM are:
// #n <method-name> (<uri>:<line-no>:<column-no>)
// #n <method-name> (<uri>:<line-no>)
+ // #n <method-name> (<uri>)
// in which '<anonymous closure>' is the name used for an (unnamed) function
- // expression.
+ // expression. The last case is used for async bodies.
for (String line in stackTrace.split('\n')) {
try {
index++;
@@ -154,16 +155,33 @@
lineNo = line.substring(nextToLastColon+1, lastColon);
columnNo = line.substring(lastColon+1, rightParenPos);
try {
- int.parse(lineNo);
+ int.parse(columnNo);
+ try {
+ int.parse(lineNo);
+ } on FormatException {
+ // Only line number.
+ lineNo = columnNo;
+ columnNo = '';
+ nextToLastColon = lastColon;
+ }
} on FormatException {
- lineNo = columnNo;
+ // No column number nor line number.
+ lineNo = '';
columnNo = '';
- nextToLastColon = lastColon;
+ nextToLastColon = rightParenPos;
}
} else {
lineNo = line.substring(lastColon+1, rightParenPos);
columnNo = '';
- nextToLastColon = lastColon;
+ try {
+ int.parse(lineNo);
+ nextToLastColon = lastColon;
+ } on FormatException {
+ // No column number nor line number.
+ lineNo = columnNo;
+ columnNo = '';
+ nextToLastColon = rightParenPos;
+ }
}
if (lineNo.length > maxLineNoLength) {
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index e031100..bb88478 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -332,6 +332,9 @@
ClassElement jsInvocationMirrorClass;
+ ClassElement typedArrayClass;
+ ClassElement typedArrayOfIntClass;
+
/// If [true], the compiler will emit code that logs whenever a method is
/// called. When TRACE_METHOD is 'console' this will be logged
/// directly in the JavaScript console. When TRACE_METHOD is 'post' the
@@ -1369,10 +1372,6 @@
}
}
- void registerClassUsingVariableExpression(ClassElement cls) {
- rti.classesUsingTypeVariableExpression.add(cls);
- }
-
bool classNeedsRti(ClassElement cls) {
return rti.classesNeedingRti.contains(cls.declaration) ||
compiler.enabledRuntimeType;
@@ -1501,16 +1500,8 @@
*
* Invariant: [element] must be a declaration element.
*/
- String assembleCode(Element element) {
+ String getGeneratedCode(Element element) {
assert(invariant(element, element.isDeclaration));
- var code = generatedCode[element];
- if (namer is jsAst.TokenFinalizer) {
- jsAst.TokenCounter counter = new jsAst.TokenCounter();
- counter.countTokens(code);
- // Avoid a warning.
- var finalizer = namer;
- finalizer.finalizeTokens();
- }
return jsAst.prettyPrint(generatedCode[element], compiler).getText();
}
@@ -1528,17 +1519,15 @@
'percentage': percentage.round()});
for (LibraryElement library in compiler.libraryLoader.libraries) {
if (library.isInternalLibrary) continue;
- for (LibraryTag tag in library.tags) {
- Import importTag = tag.asImport();
- if (importTag == null) continue;
- LibraryElement importedLibrary = library.getLibraryFromTag(tag);
+ for (ImportElement import in library.imports) {
+ LibraryElement importedLibrary = import.importedLibrary;
if (importedLibrary != compiler.mirrorsLibrary) continue;
MessageKind kind =
compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(library)
? MessageKind.MIRROR_IMPORT
: MessageKind.MIRROR_IMPORT_NO_USAGE;
compiler.withCurrentElement(library, () {
- compiler.reportInfo(importTag, kind);
+ compiler.reportInfo(import, kind);
});
}
}
@@ -2085,7 +2074,10 @@
Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
return super.onLibraryScanned(library, loader).then((_) {
- if (library.isPlatformLibrary && !library.isPatched) {
+ if (library.isPlatformLibrary &&
+ // Don't patch library currently disallowed.
+ !library.isSynthesized &&
+ !library.isPatched) {
// Apply patch, if any.
Uri patchUri = compiler.resolvePatchUri(library.canonicalUri.path);
if (patchUri != null) {
@@ -2160,6 +2152,9 @@
htmlLibraryIsLoaded = true;
} else if (uri == PACKAGE_LOOKUP_MAP) {
lookupMapAnalysis.init(library);
+ } else if (uri == Uris.dart__native_typed_data) {
+ typedArrayClass = findClass('NativeTypedArray');
+ typedArrayOfIntClass = findClass('NativeTypedArrayOfInt');
}
annotations.onLibraryScanned(library);
});
@@ -2313,8 +2308,7 @@
*/
bool matchesMirrorsMetaTarget(Element element) {
if (metaTargetsUsed.isEmpty) return false;
- for (Link link = element.metadata; !link.isEmpty; link = link.tail) {
- MetadataAnnotation metadata = link.head;
+ for (MetadataAnnotation metadata in element.metadata) {
// TODO(kasperl): It would be nice if we didn't have to resolve
// all metadata but only stuff that potentially would match one
// of the used meta targets.
@@ -2625,7 +2619,7 @@
bool hasForceInline = false;
bool hasNoThrows = false;
bool hasNoSideEffects = false;
- for (MetadataAnnotation metadata in element.metadata) {
+ for (MetadataAnnotation metadata in element.implementation.metadata) {
metadata.ensureResolved(compiler);
ConstantValue constantValue =
compiler.constants.getConstantValue(metadata.constant);
@@ -2894,19 +2888,21 @@
/// Returns `true` if [element] is annotated with [annotationClass].
bool _hasAnnotation(Element element, ClassElement annotationClass) {
if (annotationClass == null) return false;
- for (Link<MetadataAnnotation> link = element.metadata;
- !link.isEmpty;
- link = link.tail) {
- ConstantValue value =
- compiler.constants.getConstantValue(link.head.constant);
- if (value.isConstructedObject) {
- ConstructedConstantValue constructedConstant = value;
- if (constructedConstant.type.element == annotationClass) {
- return true;
+ return compiler.withCurrentElement(element, () {
+ for (MetadataAnnotation metadata in element.metadata) {
+ assert(invariant(metadata, metadata.constant != null,
+ message: "Unevaluated metadata constant."));
+ ConstantValue value =
+ compiler.constants.getConstantValue(metadata.constant);
+ if (value.isConstructedObject) {
+ ConstructedConstantValue constructedConstant = value;
+ if (constructedConstant.type.element == annotationClass) {
+ return true;
+ }
}
}
- }
- return false;
+ return false;
+ });
}
}
@@ -2990,7 +2986,8 @@
backend.getCheckConcurrentModificationError(), registry);
}
- void onTypeVariableExpression(Registry registry) {
+ void onTypeVariableExpression(Registry registry,
+ TypeVariableElement variable) {
assert(registry.isForResolution);
registerBackendStaticInvocation(backend.getSetRuntimeTypeInfo(), registry);
registerBackendStaticInvocation(backend.getGetRuntimeTypeInfo(), registry);
@@ -2998,6 +2995,9 @@
registerBackendInstantiation(backend.compiler.listClass, registry);
registerBackendStaticInvocation(backend.getRuntimeTypeToString(), registry);
registerBackendStaticInvocation(backend.getCreateRuntimeType(), registry);
+ needsInt(registry, 'Needed for accessing a type variable literal on this.');
+ ClassElement cls = variable.enclosingClass;
+ backend.rti.classesUsingTypeVariableExpression.add(cls);
}
// TODO(johnniwinther): Maybe split this into [onAssertType] and [onTestType].
@@ -3058,7 +3058,7 @@
registerBackendStaticInvocation(
backend.getThrowAbstractClassInstantiationError(), registry);
// Also register the types of the arguments passed to this method.
- registerBackendInstantiation(backend.compiler.stringClass, registry);
+ needsString(registry, '// Needed to encode the message.');
}
void onFallThroughError(Registry registry) {
@@ -3075,8 +3075,10 @@
assert(registry.isForResolution);
registerBackendStaticInvocation(backend.getThrowNoSuchMethod(), registry);
// Also register the types of the arguments passed to this method.
- registerBackendInstantiation(backend.compiler.listClass, registry);
- registerBackendInstantiation(backend.compiler.stringClass, registry);
+ needsList(registry,
+ 'Needed to encode the arguments for throw NoSuchMethodError.');
+ needsString(registry,
+ 'Needed to encode the name for throw NoSuchMethodError.');
}
void onThrowRuntimeError(Registry registry) {
@@ -3101,8 +3103,12 @@
backend.compiler.objectClass.lookupLocalMember(
Identifiers.noSuchMethod_),
registry);
- registerBackendInstantiation(backend.compiler.listClass, registry);
- registerBackendInstantiation(backend.compiler.stringClass, registry);
+ needsInt(registry,
+ 'Needed to encode the invocation kind of super.noSuchMethod.');
+ needsList(registry,
+ 'Needed to encode the arguments of super.noSuchMethod.');
+ needsString(registry,
+ 'Needed to encode the name of super.noSuchMethod.');
}
void onMapLiteral(ResolutionRegistry registry,
@@ -3132,6 +3138,29 @@
registerBackendStaticInvocation(
backend.compiler.symbolValidatedConstructor, registry);
}
+
+ /// Called when resolving a prefix or postfix expression.
+ void onIncDecOperation(Registry registry) {
+ needsInt(registry, 'Needed for the `+ 1` or `- 1` operation of ++/--.');
+ }
+
+ /// Helper for registering that `int` is needed.
+ void needsInt(Registry registry, String reason) {
+ // TODO(johnniwinther): Register [reason] for use in dump-info.
+ registerBackendInstantiation(backend.compiler.intClass, registry);
+ }
+
+ /// Helper for registering that `List` is needed.
+ void needsList(Registry registry, String reason) {
+ // TODO(johnniwinther): Register [reason] for use in dump-info.
+ registerBackendInstantiation(backend.compiler.listClass, registry);
+ }
+
+ /// Helper for registering that `String` is needed.
+ void needsString(Registry registry, String reason) {
+ // TODO(johnniwinther): Register [reason] for use in dump-info.
+ registerBackendInstantiation(backend.compiler.stringClass, registry);
+ }
}
/// Records that [constant] is used by the element behind [registry].
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 93a2320..16093d3 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -38,6 +38,7 @@
import '../../tree_ir/optimization/optimization.dart' as tree_opt;
import '../../tree_ir/tree_ir_integrity.dart';
import '../../cps_ir/cps_ir_nodes_sexpr.dart';
+import '../../cps_ir/type_mask_system.dart';
class CpsFunctionCompiler implements FunctionCompiler {
final ConstantSystem constantSystem;
@@ -48,6 +49,7 @@
// TODO(karlklose,sigurdm): remove and update dart-doc of [compile].
final FunctionCompiler fallbackCompiler;
+ TypeMaskSystem typeSystem;
Tracer get tracer => compiler.tracer;
@@ -69,8 +71,8 @@
/// Generates JavaScript code for `work.element`.
js.Fun compile(CodegenWorkItem work) {
AstElement element = work.element;
- JavaScriptBackend backend = compiler.backend;
return compiler.withCurrentElement(element, () {
+ typeSystem = new TypeMaskSystem(compiler);
try {
// TODO(karlklose): remove this fallback when we do not need it for
// testing anymore.
@@ -170,10 +172,13 @@
assert(checkCpsIntegrity(cpsNode));
}
+ TypeMaskSystem typeSystem = new TypeMaskSystem(compiler);
+
applyCpsPass(new RedundantJoinEliminator());
applyCpsPass(new RedundantPhiEliminator());
- applyCpsPass(new InsertRefinements(compiler.typesTask, compiler.world));
- TypePropagator typePropagator = new TypePropagator(compiler, this);
+ applyCpsPass(new InsertRefinements(typeSystem));
+ TypePropagator typePropagator =
+ new TypePropagator(compiler, typeSystem, this);
applyCpsPass(typePropagator);
dumpTypedIR(cpsNode, typePropagator);
applyCpsPass(new RemoveRefinements());
diff --git a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
index 4fa59bb..6209cda 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
@@ -250,6 +250,7 @@
}
node.arguments.insert(0, node.receiver);
node.receiver = new Reference<Primitive>(newReceiver);
+ node.receiverIsIntercepted = true;
}
processInvokeMethodDirectly(InvokeMethodDirectly node) {
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
index 9bc3a86..5d0183a 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -261,7 +261,7 @@
const ForgetConstantElementVisitor();
void visitElement(Element e, JavaScriptConstantCompiler constants) {
- for (MetadataAnnotation data in e.metadata) {
+ for (MetadataAnnotation data in e.implementation.metadata) {
constants.metadataConstantMap.remove(data);
if (data.hasNode) {
data.node.accept(new ForgetConstantNodeVisitor(constants));
diff --git a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
index 7be572b..4f372c3 100644
--- a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
@@ -28,6 +28,7 @@
import '../enqueue.dart' show Enqueuer;
import 'js_backend.dart' show JavaScriptBackend;
import '../dart_types.dart' show DynamicType, InterfaceType;
+import 'package:pub_semver/pub_semver.dart';
/// An analysis and optimization to remove unused entries from a `LookupMap`.
///
@@ -162,8 +163,12 @@
// TODO(sigmund): add proper version resolution using the pub_semver package
// when we introduce the next version.
- String version = value.primitiveValue.slowToString();
- if (version != '0.0.1') {
+ Version version;
+ try {
+ version = new Version.parse(value.primitiveValue.slowToString());
+ } catch (e) {}
+
+ if (version == null || !_validLookupMapVersionConstraint.allows(version)) {
backend.compiler.reportInfo(lookupMapVersionVariable,
MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP);
return;
@@ -430,3 +435,6 @@
}
}
}
+
+final _validLookupMapVersionConstraint =
+ new VersionConstraint.parse('^0.0.1');
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 6156b27..541aa7b 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -1144,12 +1144,12 @@
LibraryElement library = element;
name = libraryLongNames[library];
if (name != null) return name;
- name = library.getLibraryOrScriptName();
+ name = library.libraryOrScriptName;
if (name.contains('.')) {
// For libraries that have a library tag, we use the last part
// of the fully qualified name as their base name. For all other
// libraries, we use the first part of their filename.
- name = library.hasLibraryName()
+ name = library.hasLibraryName
? name.substring(name.lastIndexOf('.') + 1)
: name.substring(0, name.indexOf('.'));
}
@@ -1346,7 +1346,7 @@
return 'P';
}
return userGlobalObjects[
- library.getLibraryOrScriptName().hashCode % userGlobalObjects.length];
+ library.libraryOrScriptName.hashCode % userGlobalObjects.length];
}
jsAst.Name deriveLazyInitializerName(jsAst.Name name) {
@@ -1988,4 +1988,4 @@
global,
instance,
constant
-}
\ No newline at end of file
+}
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index 5d6eae3..60e1597 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -193,7 +193,8 @@
int get hashCode => super.hashCode;
finalize() {
- assert(!isFinalized);
+ assert(invariant(NO_LOCATION_SPANNABLE, !isFinalized,
+ message: "TokenName($key)=$_name has already been finalized."));
_name = _scope.getNextName();
}
}
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index 6a5716b..d6748b9 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -1089,7 +1089,7 @@
String libraryName =
(!compiler.enableMinification || backend.mustRetainLibraryNames) ?
- library.getLibraryName() :
+ library.libraryName :
"";
jsAst.Fun metadata = task.metadataCollector.buildMetadataFunction(library);
@@ -1982,10 +1982,6 @@
..add(js.statement('${typesAccess}.push.apply(${typesAccess}, '
'${namer.deferredTypesName});'));
- // Sets the static state variable to the state of the current isolate
- // (which is provided as second argument).
- body.add(js.statement("${namer.staticStateHolder} = arguments[1];"));
-
body.add(buildCompileTimeConstants(fragment.constants,
isMainFragment: false));
body.add(buildStaticNonFinalFieldInitializations(outputUnit));
@@ -1995,7 +1991,7 @@
statements
..add(buildGeneratedBy())
..add(js.statement('${deferredInitializers}.current = '
- """function (#) {
+ """function (#, ${namer.staticStateHolder}) {
#
}
""", [globalsHolder, body]));
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index 8ffda24..af55455 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -161,18 +161,13 @@
if (!_mustEmitMetadataFor(element)) return null;
return _compiler.withCurrentElement(element, () {
List<jsAst.Expression> metadata = <jsAst.Expression>[];
- Link link = element.metadata;
- // TODO(ahe): Why is metadata sometimes null?
- if (link != null) {
- for (; !link.isEmpty; link = link.tail) {
- MetadataAnnotation annotation = link.head;
- ConstantValue constant =
- _backend.constants.getConstantValueForMetadata(annotation);
- if (constant == null) {
- _compiler.internalError(annotation, 'Annotation value is null.');
- } else {
- metadata.add(_emitter.constantReference(constant));
- }
+ for (MetadataAnnotation annotation in element.metadata) {
+ ConstantValue constant =
+ _backend.constants.getConstantValueForMetadata(annotation);
+ if (constant == null) {
+ _compiler.internalError(annotation, 'Annotation value is null.');
+ } else {
+ metadata.add(_emitter.constantReference(constant));
}
}
if (metadata.isEmpty) return null;
@@ -289,12 +284,8 @@
return _compiler.withCurrentElement(element, () {
if (!_mustEmitMetadataFor(element)) return const <jsAst.DeferredNumber>[];
List<jsAst.DeferredNumber> metadata = <jsAst.DeferredNumber>[];
- Link link = element.metadata;
- // TODO(ahe): Why is metadata sometimes null?
- if (link != null) {
- for (; !link.isEmpty; link = link.tail) {
- metadata.add(reifyMetadata(link.head));
- }
+ for (MetadataAnnotation annotation in element.metadata) {
+ metadata.add(reifyMetadata(annotation));
}
return metadata;
});
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index 62ad6c6..9984f05d 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -17,17 +17,26 @@
invariant;
import 'diagnostics/messages.dart' show
MessageKind;
+import 'diagnostics/spannable.dart' show
+ Spannable;
import 'elements/elements.dart' show
CompilationUnitElement,
Element,
+ ImportElement,
+ ExportElement,
LibraryElement,
PrefixElement;
import 'elements/modelx.dart' show
CompilationUnitElementX,
DeferredLoaderGetterElementX,
ErroneousElementX,
+ ExportElementX,
+ ImportElementX,
LibraryElementX,
- PrefixElementX;
+ LibraryDependencyElementX,
+ PrefixElementX,
+ SyntheticImportElement;
+
import 'native/native.dart' as native;
import 'script.dart';
import 'tree/tree.dart';
@@ -337,7 +346,7 @@
Uri resourceUri = library.entryCompilationUnit.script.resourceUri;
libraryResourceUriMap[resourceUri] = library;
- String name = library.getLibraryOrScriptName();
+ String name = library.libraryOrScriptName;
libraryNames[name] = library;
}
@@ -374,21 +383,52 @@
TagState tagState = new TagState();
bool importsDartCore = false;
- var libraryDependencies = new LinkBuilder<LibraryDependency>();
+ LinkBuilder<LibraryDependencyElementX> libraryDependencies =
+ new LinkBuilder<LibraryDependencyElementX>();
Uri base = library.entryCompilationUnit.script.readableUri;
return Future.forEach(library.tags, (LibraryTag tag) {
return compiler.withCurrentElement(library, () {
+
+ Uri computeUri(LibraryDependency node) {
+ String tagUriString = node.uri.dartString.slowToString();
+ try {
+ return Uri.parse(tagUriString);
+ } on FormatException {
+ compiler.reportError(
+ node.uri,
+ MessageKind.INVALID_URI, {'uri': tagUriString});
+ return null;
+ }
+ }
+
if (tag.isImport) {
- Import import = tag;
- tagState.checkTag(TagState.IMPORT_OR_EXPORT, import, compiler);
- if (import.uri.dartString.slowToString() == 'dart:core') {
+ Uri uri = computeUri(tag);
+ if (uri == null) {
+ // Skip this erroneous import.
+ return new Future.value();
+ }
+ // TODO(johnniwinther): Create imports during parsing.
+ ImportElementX import =
+ new ImportElementX(library.entryCompilationUnit, tag, uri);
+ tagState.checkTag(TagState.IMPORT_OR_EXPORT, import.node, compiler);
+ if (import.uri == Uris.dart_core) {
importsDartCore = true;
}
+ library.addImportDeclaration(import);
libraryDependencies.addLast(import);
} else if (tag.isExport) {
- tagState.checkTag(TagState.IMPORT_OR_EXPORT, tag, compiler);
- libraryDependencies.addLast(tag);
+ Uri uri = computeUri(tag);
+ if (uri == null) {
+ // Skip this erroneous export.
+ return new Future.value();
+ }
+ // TODO(johnniwinther): Create exports during parsing.
+ ExportElementX export =
+ new ExportElementX(library.entryCompilationUnit, tag, uri);
+ tagState.checkTag(TagState.IMPORT_OR_EXPORT, export.node, compiler);
+ library.addExportDeclaration(export);
+ libraryDependencies.addLast(export);
} else if (tag.isLibraryName) {
tagState.checkTag(TagState.LIBRARY, tag, compiler);
if (library.libraryTag == null) {
@@ -416,14 +456,19 @@
if (!importsDartCore && library.canonicalUri != Uris.dart_core) {
return createLibrary(handler, null, Uris.dart_core)
.then((LibraryElement coreLibrary) {
- handler.registerDependency(library, null, coreLibrary);
+ handler.registerDependency(library,
+ new SyntheticImportElement(
+ library.entryCompilationUnit, Uris.dart_core),
+ coreLibrary);
});
}
});
}).then((_) {
- return Future.forEach(libraryDependencies.toList(), (tag) {
+ return Future.forEach(libraryDependencies.toList(),
+ (LibraryDependencyElementX libraryDependency) {
return compiler.withCurrentElement(library, () {
- return registerLibraryFromTag(handler, library, tag);
+ return registerLibraryFromImportExport(
+ handler, library, libraryDependency);
});
});
});
@@ -432,15 +477,14 @@
void checkDuplicatedLibraryName(LibraryElement library) {
if (library.isInternalLibrary) return;
Uri resourceUri = library.entryCompilationUnit.script.resourceUri;
- LibraryName tag = library.libraryTag;
LibraryElement existing =
libraryResourceUriMap.putIfAbsent(resourceUri, () => library);
if (!identical(existing, library)) {
- if (tag != null) {
+ if (library.hasLibraryName) {
compiler.withCurrentElement(library, () {
- compiler.reportWarning(tag.name,
+ compiler.reportWarning(library,
MessageKind.DUPLICATED_LIBRARY_RESOURCE,
- {'libraryName': tag.name,
+ {'libraryName': library.libraryName,
'resourceUri': resourceUri,
'canonicalUri1': library.canonicalUri,
'canonicalUri2': existing.canonicalUri});
@@ -452,17 +496,17 @@
'canonicalUri1': library.canonicalUri,
'canonicalUri2': existing.canonicalUri});
}
- } else if (tag != null) {
- String name = library.getLibraryOrScriptName();
+ } else if (library.hasLibraryName) {
+ String name = library.libraryOrScriptName;
existing = libraryNames.putIfAbsent(name, () => library);
if (!identical(existing, library)) {
compiler.withCurrentElement(library, () {
- compiler.reportWarning(tag.name,
+ compiler.reportWarning(library,
MessageKind.DUPLICATED_LIBRARY_NAME,
{'libraryName': name});
});
compiler.withCurrentElement(existing, () {
- compiler.reportWarning(existing.libraryTag.name,
+ compiler.reportWarning(existing,
MessageKind.DUPLICATED_LIBRARY_NAME,
{'libraryName': name});
});
@@ -501,25 +545,19 @@
* export scope. If the tag does not contain a valid URI, then its dependency
* is not registered in [handler].
*/
- Future<Null> registerLibraryFromTag(LibraryDependencyHandler handler,
- LibraryElement library,
- LibraryDependency tag) {
+ Future<Null> registerLibraryFromImportExport(
+ LibraryDependencyHandler handler,
+ LibraryElement library,
+ LibraryDependencyElementX libraryDependency) {
Uri base = library.canonicalUri;
- String tagUriString = tag.uri.dartString.slowToString();
- Uri resolvedUri;
- try {
- resolvedUri = base.resolve(tagUriString);
- } on FormatException {
- compiler.reportError(
- tag.uri, MessageKind.INVALID_URI, {'uri': tagUriString});
- // 'reportError' does not stop necessarily stop compilation
- return new Future.value();
- }
- return createLibrary(handler, library, resolvedUri, tag.uri)
+ Uri resolvedUri = base.resolveUri(libraryDependency.uri);
+ return createLibrary(handler, library, resolvedUri, libraryDependency)
.then((LibraryElement loadedLibrary) {
if (loadedLibrary == null) return;
compiler.withCurrentElement(library, () {
- handler.registerDependency(library, tag, loadedLibrary);
+ libraryDependency.libraryDependency = loadedLibrary;
+ handler.registerDependency(
+ library, libraryDependency, loadedLibrary);
});
});
}
@@ -534,10 +572,13 @@
compiler.onLibraryCreated(library);
libraryCanonicalUriMap[library.canonicalUri] = library;
return compiler.onLibraryScanned(library, handler).then((_) {
- return Future.forEach(library.tags, (LibraryTag tag) {
- LibraryElement dependency = library.getLibraryFromTag(tag);
- return createLibrary(handler, library, dependency.canonicalUri);
- }).then((_) => library);
+ return Future.forEach(library.imports, (ImportElement import) {
+ return createLibrary(handler, library, import.uri);
+ }).then((_) {
+ return Future.forEach(library.exports, (ExportElement export) {
+ return createLibrary(handler, library, export.uri);
+ }).then((_) => library);
+ });
});
}
@@ -550,7 +591,7 @@
Future<LibraryElement> createLibrary(LibraryDependencyHandler handler,
LibraryElement importingLibrary,
Uri resolvedUri,
- [Node node]) {
+ [Spannable node]) {
Uri readableUri =
compiler.translateResolvedUri(importingLibrary, resolvedUri, node);
LibraryElement library = libraryCanonicalUriMap[resolvedUri];
@@ -671,7 +712,7 @@
* An [import] tag and the [importedLibrary] imported through [import].
*/
class ImportLink {
- final Import import;
+ final ImportElementX import;
final LibraryElement importedLibrary;
ImportLink(this.import, this.importedLibrary);
@@ -683,14 +724,19 @@
assert(invariant(importingLibrary,
importedLibrary.exportsHandled,
message: 'Exports not handled on $importedLibrary'));
- var combinatorFilter = new CombinatorFilter.fromTag(import);
- if (import != null && import.prefix != null) {
- String prefix = import.prefix.source;
+ Import tag = import.node;
+ CombinatorFilter combinatorFilter =
+ new CombinatorFilter.fromTag(tag);
+ if (tag != null && tag.prefix != null) {
+ String prefix = tag.prefix.source;
Element existingElement = importingLibrary.find(prefix);
- PrefixElement prefixElement;
+ PrefixElementX prefixElement;
if (existingElement == null || !existingElement.isPrefix) {
- prefixElement = new PrefixElementX(prefix,
- importingLibrary.entryCompilationUnit, import.getBeginToken());
+ prefixElement = new PrefixElementX(
+ prefix,
+ importingLibrary.entryCompilationUnit,
+ tag.getBeginToken(),
+ tag.isDeferred ? import : null);
} else {
prefixElement = existingElement;
}
@@ -699,14 +745,11 @@
if (combinatorFilter.exclude(element)) return;
prefixElement.addImport(element, import, compiler);
});
- if (import.isDeferred) {
+ import.prefix = prefixElement;
+ if (prefixElement.isDeferred) {
prefixElement.addImport(
new DeferredLoaderGetterElementX(prefixElement),
import, compiler);
- // TODO(sigurdm): When we remove support for the annotation based
- // syntax the [PrefixElement] constructor should receive this
- // information.
- prefixElement.markAsDeferred(import);
}
} else {
importedLibrary.forEachExport((Element element) {
@@ -725,13 +768,13 @@
* the library dependency graph.
*/
class ExportLink {
- final Export export;
+ final ExportElementX export;
final CombinatorFilter combinatorFilter;
final LibraryDependencyNode exportNode;
- ExportLink(Export export, LibraryDependencyNode this.exportNode)
+ ExportLink(ExportElementX export, LibraryDependencyNode this.exportNode)
: this.export = export,
- this.combinatorFilter = new CombinatorFilter.fromTag(export);
+ this.combinatorFilter = new CombinatorFilter.fromTag(export.node);
/**
* Exports [element] to the dependent library unless [element] is filtered by
@@ -780,11 +823,11 @@
* The export scope for [library] which is gradually computed by the work-list
* computation in [LibraryDependencyHandler.computeExports].
*/
- Map<String, Element> exportScope =
- new Map<String, Element>();
+ Map<String, Element> exportScope = <String, Element>{};
/// Map from exported elements to the export directives that exported them.
- Map<Element, Link<Export>> exporters = new Map<Element, Link<Export>>();
+ Map<Element, Link<ExportElement>> exporters =
+ <Element, Link<ExportElement>>{};
/**
* The set of exported elements that need to be propageted to dependent
@@ -792,8 +835,8 @@
* [LibraryDependencyHandler.computeExports]. Each export element is mapped
* to a list of exports directives that export it.
*/
- Map<Element, Link<Export>> pendingExportMap =
- new Map<Element, Link<Export>>();
+ Map<Element, Link<ExportElement>> pendingExportMap =
+ <Element, Link<ExportElement>>{};
LibraryDependencyNode(this.library);
@@ -801,7 +844,7 @@
* Registers that the library of this node imports [importLibrary] through the
* [import] tag.
*/
- void registerImportDependency(Import import,
+ void registerImportDependency(ImportElementX import,
LibraryElement importedLibrary) {
imports = imports.prepend(new ImportLink(import, importedLibrary));
}
@@ -810,7 +853,7 @@
* Registers that the library of this node is exported by
* [exportingLibraryNode] through the [export] tag.
*/
- void registerExportDependency(Export export,
+ void registerExportDependency(ExportElementX export,
LibraryDependencyNode exportingLibraryNode) {
// Register the exported library in the exporting library node.
exportingLibraryNode.exports =
@@ -827,22 +870,22 @@
*/
void registerInitialExports() {
for (Element element in library.getNonPrivateElementsInScope()) {
- pendingExportMap[element] = const Link<Export>();
+ pendingExportMap[element] = const Link<ExportElement>();
}
}
void registerHandledExports(LibraryElement exportedLibraryElement,
- Export export,
+ ExportElementX export,
CombinatorFilter filter) {
assert(invariant(library, exportedLibraryElement.exportsHandled));
- for (Element exportedElement in exportedLibraryElement.exports) {
+ exportedLibraryElement.forEachExport((Element exportedElement) {
if (!filter.exclude(exportedElement)) {
- Link<Export> exports =
+ Link<ExportElement> exports =
pendingExportMap.putIfAbsent(exportedElement,
- () => const Link<Export>());
+ () => const Link<ExportElement>());
pendingExportMap[exportedElement] = exports.prepend(export);
}
- }
+ });
}
/**
@@ -864,9 +907,9 @@
/**
* Copies and clears pending export set for this node.
*/
- Map<Element, Link<Export>> pullPendingExports() {
- Map<Element, Link<Export>> pendingExports =
- new Map<Element, Link<Export>>.from(pendingExportMap);
+ Map<Element, Link<ExportElement>> pullPendingExports() {
+ Map<Element, Link<ExportElement>> pendingExports =
+ new Map<Element, Link<ExportElement>>.from(pendingExportMap);
pendingExportMap.clear();
return pendingExports;
}
@@ -876,17 +919,17 @@
* is a duplicate, an error element is inserted into the export scope.
*/
Element addElementToExportScope(Compiler compiler, Element element,
- Link<Export> exports) {
+ Link<ExportElement> exports) {
String name = element.name;
void reportDuplicateExport(Element duplicate,
- Link<Export> duplicateExports,
+ Link<ExportElement> duplicateExports,
{bool reportError: true}) {
assert(invariant(library, !duplicateExports.isEmpty,
message: "No export for $duplicate from ${duplicate.library} "
"in $library."));
compiler.withCurrentElement(library, () {
- for (Export export in duplicateExports) {
+ for (ExportElement export in duplicateExports) {
if (reportError) {
compiler.reportError(export,
MessageKind.DUPLICATE_EXPORT, {'name': name});
@@ -900,7 +943,7 @@
}
void reportDuplicateExportDecl(Element duplicate,
- Link<Export> duplicateExports) {
+ Link<ExportElement> duplicateExports) {
assert(invariant(library, !duplicateExports.isEmpty,
message: "No export for $duplicate from ${duplicate.library} "
"in $library."));
@@ -922,7 +965,7 @@
exporters[element] = exports;
} else {
// Declared elements hide exported elements.
- Link<Export> existingExports = exporters[existingElement];
+ Link<ExportElement> existingExports = exporters[existingElement];
reportDuplicateExport(existingElement, existingExports);
reportDuplicateExport(element, exports, reportError: false);
reportDuplicateExportDecl(existingElement, existingExports);
@@ -957,12 +1000,12 @@
* the pending export set was modified. The combinators of [export] are used
* to filter the element.
*/
- bool addElementToPendingExports(Element element, Export export) {
+ bool addElementToPendingExports(Element element, ExportElement export) {
bool changed = false;
if (!identical(exportScope[element.name], element)) {
- Link<Export> exports = pendingExportMap.putIfAbsent(element, () {
+ Link<ExportElement> exports = pendingExportMap.putIfAbsent(element, () {
changed = true;
- return const Link<Export>();
+ return const Link<ExportElement>();
});
pendingExportMap[element] = exports.prepend(export);
}
@@ -1006,8 +1049,8 @@
bool changed = true;
while (changed) {
changed = false;
- Map<LibraryDependencyNode, Map<Element, Link<Export>>> tasks =
- new Map<LibraryDependencyNode, Map<Element, Link<Export>>>();
+ Map<LibraryDependencyNode, Map<Element, Link<ExportElement>>> tasks =
+ new Map<LibraryDependencyNode, Map<Element, Link<ExportElement>>>();
// Locally defined elements take precedence over exported
// elements. So we must propagate local elements first. We
@@ -1015,12 +1058,13 @@
// propagating. This enforces that we handle exports
// breadth-first, with locally defined elements being level 0.
nodeMap.forEach((_, LibraryDependencyNode node) {
- Map<Element, Link<Export>> pendingExports = node.pullPendingExports();
+ Map<Element, Link<ExportElement>> pendingExports =
+ node.pullPendingExports();
tasks[node] = pendingExports;
});
tasks.forEach((LibraryDependencyNode node,
- Map<Element, Link<Export>> pendingExports) {
- pendingExports.forEach((Element element, Link<Export> exports) {
+ Map<Element, Link<ExportElement>> pendingExports) {
+ pendingExports.forEach((Element element, Link<ExportElement> exports) {
element = node.addElementToExportScope(compiler, element, exports);
if (node.propagateElement(element)) {
changed = true;
@@ -1042,23 +1086,20 @@
});
}
- /**
- * Registers that [library] depends on [loadedLibrary] through [tag].
- */
+ /// Registers that [library] depends on [loadedLibrary] through
+ /// [libraryDependency].
void registerDependency(LibraryElementX library,
- LibraryDependency tag,
+ LibraryDependencyElementX libraryDependency,
LibraryElement loadedLibrary) {
- if (tag != null) {
- library.recordResolvedTag(tag, loadedLibrary);
- }
- if (tag is Export) {
+ if (libraryDependency.isExport) {
// [loadedLibrary] is exported by [library].
LibraryDependencyNode exportingNode = nodeMap[library];
if (loadedLibrary.exportsHandled) {
// Export scope already computed on [loadedLibrary].
- var combinatorFilter = new CombinatorFilter.fromTag(tag);
+ CombinatorFilter combinatorFilter =
+ new CombinatorFilter.fromTag(libraryDependency.node);
exportingNode.registerHandledExports(
- loadedLibrary, tag, combinatorFilter);
+ loadedLibrary, libraryDependency, combinatorFilter);
return;
}
LibraryDependencyNode exportedNode = nodeMap[loadedLibrary];
@@ -1066,13 +1107,13 @@
message: "$loadedLibrary has not been registered"));
assert(invariant(library, exportingNode != null,
message: "$library has not been registered"));
- exportedNode.registerExportDependency(tag, exportingNode);
- } else if (tag == null || tag is Import) {
+ exportedNode.registerExportDependency(libraryDependency, exportingNode);
+ } else if (libraryDependency == null || libraryDependency.isImport) {
// [loadedLibrary] is imported by [library].
LibraryDependencyNode importingNode = nodeMap[library];
assert(invariant(library, importingNode != null,
message: "$library has not been registered"));
- importingNode.registerImportDependency(tag, loadedLibrary);
+ importingNode.registerImportDependency(libraryDependency, loadedLibrary);
}
}
diff --git a/pkg/compiler/lib/src/mirrors/dart2js_library_mirror.dart b/pkg/compiler/lib/src/mirrors/dart2js_library_mirror.dart
index 38925b5..2d43e7d 100644
--- a/pkg/compiler/lib/src/mirrors/dart2js_library_mirror.dart
+++ b/pkg/compiler/lib/src/mirrors/dart2js_library_mirror.dart
@@ -4,7 +4,6 @@
part of dart2js.mirrors;
-
class Dart2JsLibraryMirror
extends Dart2JsElementMirror
with ObjectMirrorMixin, ContainerMixin
@@ -18,7 +17,8 @@
throw new UnsupportedError('LibraryMirror.operator [] unsupported.');
}
- LibraryElement get _element => super._element;
+ // TODO(johnniwinther): Avoid the need for [LibraryElementX].
+ LibraryElementX get _element => super._element;
Uri get uri => _element.canonicalUri;
@@ -33,7 +33,7 @@
* file name (for scripts without a library tag). The latter case is used to
* provide a 'library name' for scripts, to use for instance in dartdoc.
*/
- String get _simpleNameString => _element.getLibraryOrScriptName();
+ String get _simpleNameString => _element.libraryOrScriptName;
Symbol get qualifiedName => simpleName;
@@ -75,17 +75,33 @@
void _ensureLibraryDependenciesAnalyzed() {
if (_libraryDependencies == null) {
+ // TODO(johnniwinther): Support order of declarations on [LibraryElement].
+ Map<LibraryDependency, Dart2JsLibraryDependencyMirror> mirrorMap =
+ <LibraryDependency, Dart2JsLibraryDependencyMirror>{};
+
+ void addLibraryDependency(LibraryDependency libraryDependency,
+ LibraryElement targetLibraryElement) {
+ assert(targetLibraryElement != null);
+ LibraryMirror targetLibrary =
+ mirrorSystem._getLibrary(targetLibraryElement);
+ mirrorMap[libraryDependency] = new Dart2JsLibraryDependencyMirror(
+ libraryDependency, this, targetLibrary);
+ }
+ for (ImportElement import in _element.imports) {
+ addLibraryDependency(import.node, import.importedLibrary);
+ }
+ for (ExportElement export in _element.exports) {
+ addLibraryDependency(export.node, export.exportedLibrary);
+ }
+
_libraryDependencies = <LibraryDependencySourceMirror>[];
+
for (LibraryTag node in _element.tags) {
LibraryDependency libraryDependency = node.asLibraryDependency();
if (libraryDependency != null) {
- LibraryElement targetLibraryElement =
- _element.getLibraryFromTag(libraryDependency);
- assert(targetLibraryElement != null);
- LibraryMirror targetLibrary =
- mirrorSystem._getLibrary(targetLibraryElement);
- _libraryDependencies.add(new Dart2JsLibraryDependencyMirror(
- libraryDependency, this, targetLibrary));
+ Dart2JsLibraryDependencyMirror mirror = mirrorMap[libraryDependency];
+ assert(mirror != null);
+ _libraryDependencies.add(mirror);
}
}
}
diff --git a/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart b/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
index c35fd8b..3834728 100644
--- a/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
+++ b/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
@@ -18,6 +18,8 @@
import '../diagnostics/spannable.dart' show
NO_LOCATION_SPANNABLE;
import '../elements/elements.dart';
+import '../elements/modelx.dart' show
+ LibraryElementX;
import '../resolution/scope.dart' show
Scope;
import '../script.dart';
diff --git a/pkg/compiler/lib/src/mirrors_used.dart b/pkg/compiler/lib/src/mirrors_used.dart
index fac0234..553f9cc 100644
--- a/pkg/compiler/lib/src/mirrors_used.dart
+++ b/pkg/compiler/lib/src/mirrors_used.dart
@@ -28,6 +28,7 @@
import 'elements/elements.dart' show
ClassElement,
Element,
+ ImportElement,
LibraryElement,
MetadataAnnotation,
ScopeContainerElement,
@@ -199,12 +200,10 @@
new Map<LibraryElement, List<MirrorUsage>>();
for (LibraryElement library in compiler.libraryLoader.libraries) {
if (library.isInternalLibrary) continue;
- for (LibraryTag tag in library.tags) {
- Import importTag = tag.asImport();
- if (importTag == null) continue;
+ for (ImportElement import in library.imports) {
compiler.withCurrentElement(library, () {
List<MirrorUsage> usages =
- mirrorsUsedOnLibraryTag(library, importTag);
+ mirrorsUsedOnLibraryTag(library, import);
if (usages != null) {
List<MirrorUsage> existing = result[library];
if (existing != null) {
@@ -255,13 +254,13 @@
/// Find @MirrorsUsed annotations on the given import [tag] in [library]. The
/// annotations are represented as [MirrorUsage].
List<MirrorUsage> mirrorsUsedOnLibraryTag(LibraryElement library,
- Import tag) {
- LibraryElement importedLibrary = library.getLibraryFromTag(tag);
+ ImportElement import) {
+ LibraryElement importedLibrary = import.importedLibrary;
if (importedLibrary != compiler.mirrorsLibrary) {
return null;
}
List<MirrorUsage> result = <MirrorUsage>[];
- for (MetadataAnnotation metadata in tag.metadata) {
+ for (MetadataAnnotation metadata in import.metadata) {
metadata.ensureResolved(compiler);
ConstantValue value =
compiler.constants.getConstantValue(metadata.constant);
@@ -476,8 +475,8 @@
LibraryElement libraryCandiate;
String libraryNameCandiate;
for (LibraryElement l in compiler.libraryLoader.libraries) {
- if (l.hasLibraryName()) {
- String libraryName = l.getLibraryOrScriptName();
+ if (l.hasLibraryName) {
+ String libraryName = l.libraryOrScriptName;
if (string == libraryName) {
// Found an exact match.
libraryCandiate = l;
@@ -535,7 +534,7 @@
compiler.reportHint(
spannable, MessageKind.MIRRORS_CANNOT_RESOLVE_IN_LIBRARY,
{'name': identifiers[0],
- 'library': library.getLibraryOrScriptName()});
+ 'library': library.libraryOrScriptName});
} else {
compiler.reportHint(
spannable, MessageKind.MIRRORS_CANNOT_FIND_IN_ELEMENT,
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index edbefd1..23bf702 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -652,7 +652,7 @@
}
void _overrideWithAnnotations(Element element, Compiler compiler) {
- if (element.metadata.isEmpty) return;
+ if (element.implementation.metadata.isEmpty) return;
DartType lookup(String name) {
Element e = element.buildScope().lookup(name);
@@ -685,10 +685,8 @@
static _collect(Element element, Compiler compiler, Element annotationClass,
lookup(str)) {
var types = null;
- for (Link<MetadataAnnotation> link = element.metadata;
- !link.isEmpty;
- link = link.tail) {
- MetadataAnnotation annotation = link.head.ensureResolved(compiler);
+ for (MetadataAnnotation annotation in element.implementation.metadata) {
+ annotation.ensureResolved(compiler);
ConstantValue value =
compiler.constants.getConstantValue(annotation.constant);
if (!value.isConstructedObject) continue;
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 1f9b47b..3de82e0 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -314,10 +314,8 @@
String findJsNameFromAnnotation(Element element) {
String name = null;
ClassElement annotationClass = annotationJsNameClass;
- for (Link<MetadataAnnotation> link = element.metadata;
- !link.isEmpty;
- link = link.tail) {
- MetadataAnnotation annotation = link.head.ensureResolved(compiler);
+ for (MetadataAnnotation annotation in element.implementation.metadata) {
+ annotation.ensureResolved(compiler);
ConstantValue value =
compiler.constants.getConstantValue(annotation.constant);
if (!value.isConstructedObject) continue;
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
index 00ec535..8473d03 100644
--- a/pkg/compiler/lib/src/parser/element_listener.dart
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -37,7 +37,8 @@
EOF_TOKEN;
import '../tree/tree.dart';
import '../util/util.dart' show
- Link;
+ Link,
+ LinkBuilder;
import 'partial_elements.dart' show
PartialClassElement,
@@ -69,7 +70,8 @@
Link<Node> nodes = const Link<Node>();
- Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();
+ LinkBuilder<MetadataAnnotation> metadata =
+ new LinkBuilder<MetadataAnnotation>();
/// Records a stack of booleans for each member parsed (a stack is used to
/// support nested members which isn't currently possible, but it also serves
@@ -212,9 +214,9 @@
void endTopLevelDeclaration(Token token) {
if (!metadata.isEmpty) {
- recoverableError(metadata.head.beginToken,
+ recoverableError(metadata.first.beginToken,
'Metadata not supported here.');
- metadata = const Link<MetadataAnnotation>();
+ metadata.clear();
}
}
@@ -595,19 +597,15 @@
compilationUnitElement.addMember(element, listener);
}
- Link<MetadataAnnotation> popMetadata(ElementX element) {
- var result = const Link<MetadataAnnotation>();
- for (Link link = metadata; !link.isEmpty; link = link.tail) {
- element.addMetadata(link.head);
- // Reverse the list as is implicitly done by addMetadata.
- result = result.prepend(link.head);
- }
- metadata = const Link<MetadataAnnotation>();
+ List<MetadataAnnotation> popMetadata(ElementX element) {
+ List<MetadataAnnotation> result = metadata.toList();
+ element.metadata = result;
+ metadata.clear();
return result;
}
void pushMetadata(MetadataAnnotation annotation) {
- metadata = metadata.prepend(annotation);
+ metadata.addLast(annotation);
}
void addLibraryTag(LibraryTag tag) {
diff --git a/pkg/compiler/lib/src/parser/member_listener.dart b/pkg/compiler/lib/src/parser/member_listener.dart
index 08656d3..c9cbd48 100644
--- a/pkg/compiler/lib/src/parser/member_listener.dart
+++ b/pkg/compiler/lib/src/parser/member_listener.dart
@@ -153,10 +153,7 @@
}
void addMetadata(ElementX memberElement) {
- for (Link link = metadata; !link.isEmpty; link = link.tail) {
- memberElement.addMetadata(link.head);
- }
- metadata = const Link<MetadataAnnotation>();
+ memberElement.metadata = metadata.toList();
}
void addMember(ElementX memberElement) {
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index 0f30084..ee2995f 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -386,10 +386,7 @@
static checkAnnotation(Compiler compiler,
Element element,
EagerAnnotationHandler handler) {
- for (Link<MetadataAnnotation> link = element.metadata;
- !link.isEmpty;
- link = link.tail) {
- MetadataAnnotation annotation = link.head;
+ for (MetadataAnnotation annotation in element.implementation.metadata) {
var result = handler.apply(compiler, element, annotation);
if (result != null) {
// TODO(johnniwinther): Perform this check in
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index dbfdd13..9d8b71e 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -1846,7 +1846,7 @@
registry.registerThrowNoSuchMethod();
ErroneousElement error = reportAndCreateErroneousElement(
node, name.text, MessageKind.PRIVATE_ACCESS,
- {'libraryName': member.library.getLibraryOrScriptName(),
+ {'libraryName': member.library.libraryOrScriptName,
'name': name});
// TODO(johnniwinther): Add an [AccessSemantics] for unresolved static
// member access.
@@ -1862,7 +1862,7 @@
registry.registerThrowNoSuchMethod();
ErroneousElement error = reportAndCreateErroneousElement(
node, name.text, MessageKind.PRIVATE_ACCESS,
- {'libraryName': member.library.getLibraryOrScriptName(),
+ {'libraryName': member.library.libraryOrScriptName,
'name': name});
// TODO(johnniwinther): Add an [AccessSemantics] for unresolved static
// member access.
@@ -1953,8 +1953,7 @@
} else {
semantics = new StaticAccess.typeParameterTypeLiteral(element);
}
- registry.registerClassUsingVariableExpression(element.enclosingClass);
- registry.registerTypeVariableExpression();
+ registry.registerTypeVariableExpression(element);
registry.useElement(node, element);
registry.registerTypeLiteral(node, element.type);
@@ -2007,6 +2006,11 @@
MessageKind.ASSIGNING_TYPE, const {});
}
+ if (node.isComplex) {
+ // We read the type variable before trying write to it.
+ registry.registerTypeVariableExpression(element);
+ }
+
// TODO(23998): Remove this when all information goes through
// the [SendStructure].
registry.useElement(node, error);
@@ -3422,6 +3426,7 @@
? new PrefixStructure(semantics, operator)
: new PostfixStructure(semantics, operator);
registry.registerSendStructure(node, sendStructure);
+ registry.registerIncDecOperation();
} else {
Node rhs = node.arguments.head;
visitExpression(rhs);
@@ -3783,7 +3788,7 @@
}
}
if (node.metadata != null) {
- variables.metadata =
+ variables.metadataInternal =
compiler.resolver.resolveMetadata(enclosingElement, node);
}
visitor.visit(node.definitions);
@@ -3892,6 +3897,21 @@
}
if (node.isConst) {
analyzeConstantDeferred(node);
+
+ // TODO(johnniwinther): Compute this in the [ConstructorResolver].
+ // Check that the constructor is not deferred.
+ Send send = node.send.selector.asSend();
+ if (send != null) {
+ // Of the form `const a.b(...)`.
+ if (compiler.deferredLoadTask.deferredPrefixElement(
+ send, registry.mapping) != null) {
+ // `a` is a deferred prefix.
+ isValidAsConstant = false;
+ // TODO(johnniwinther): Create an [ErroneousConstantExpression] here
+ // when constants are only created during resolution.
+ }
+ }
+
if (isValidAsConstant &&
constructor.isConst &&
argumentsResult.isValidAsConstant) {
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 6a40754..625f8f0 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -455,12 +455,8 @@
backend.resolutionCallbacks.onSuperNoSuchMethod(this);
}
- void registerClassUsingVariableExpression(ClassElement element) {
- backend.registerClassUsingVariableExpression(element);
- }
-
- void registerTypeVariableExpression() {
- backend.resolutionCallbacks.onTypeVariableExpression(this);
+ void registerTypeVariableExpression(TypeVariableElement element) {
+ backend.resolutionCallbacks.onTypeVariableExpression(this, element);
}
void registerTypeLiteral(Send node, DartType type) {
@@ -610,6 +606,10 @@
backend.resolutionCallbacks.onAsyncForIn(node, this);
}
+ void registerIncDecOperation() {
+ backend.resolutionCallbacks.onIncDecOperation(this);
+ }
+
void registerTryStatement() {
mapping.containsTryStatement = true;
}
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index 5874251..a137493 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -78,7 +78,7 @@
}
WorldImpact processMetadata([WorldImpact result]) {
- for (MetadataAnnotation metadata in element.metadata) {
+ for (MetadataAnnotation metadata in element.implementation.metadata) {
metadata.ensureResolved(compiler);
}
return result;
@@ -594,11 +594,11 @@
}
void _postProcessClassElement(BaseClassElementX element) {
- for (MetadataAnnotation metadata in element.metadata) {
+ for (MetadataAnnotation metadata in element.implementation.metadata) {
metadata.ensureResolved(compiler);
ConstantValue value =
compiler.constants.getConstantValue(metadata.constant);
- if (!element.isProxy && value == compiler.proxyConstant) {
+ if (!element.isProxy && compiler.isProxyConstant(value)) {
element.isProxy = true;
}
}
@@ -611,7 +611,7 @@
element.forEachMember((_, Element member) {
if (!member.isInstanceMember) {
compiler.withCurrentElement(member, () {
- for (MetadataAnnotation metadata in member.metadata) {
+ for (MetadataAnnotation metadata in member.implementation.metadata) {
metadata.ensureResolved(compiler);
}
});
@@ -996,6 +996,7 @@
// [compileMetadata].
annotation.constant =
constantCompiler.compileMetadata(annotation, node, registry.mapping);
+ constantCompiler.evaluate(annotation.constant);
// TODO(johnniwinther): Register the relation between the annotation
// and the annotated element instead. This will allow the backend to
// retrieve the backend constant and only register metadata on the
@@ -1009,17 +1010,16 @@
compiler.reportError(node, kind, arguments);
}
- Link<MetadataAnnotation> resolveMetadata(Element element,
+ List<MetadataAnnotation> resolveMetadata(Element element,
VariableDefinitions node) {
- LinkBuilder<MetadataAnnotation> metadata =
- new LinkBuilder<MetadataAnnotation>();
+ List<MetadataAnnotation> metadata = <MetadataAnnotation>[];
for (Metadata annotation in node.metadata.nodes) {
ParameterMetadataAnnotation metadataAnnotation =
new ParameterMetadataAnnotation(annotation);
metadataAnnotation.annotatedElement = element;
- metadata.addLast(metadataAnnotation.ensureResolved(compiler));
+ metadata.add(metadataAnnotation.ensureResolved(compiler));
}
- return metadata.toLink();
+ return metadata;
}
}
diff --git a/pkg/compiler/lib/src/resolution/signatures.dart b/pkg/compiler/lib/src/resolution/signatures.dart
index 4dfd954..2a6aa6d 100644
--- a/pkg/compiler/lib/src/resolution/signatures.dart
+++ b/pkg/compiler/lib/src/resolution/signatures.dart
@@ -102,7 +102,8 @@
currentDefinitions = node;
FormalElementX element = definition.accept(this);
if (currentDefinitions.metadata != null) {
- element.metadata = compiler.resolver.resolveMetadata(element, node);
+ element.metadataInternal =
+ compiler.resolver.resolveMetadata(element, node);
}
currentDefinitions = null;
return element;
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index c72f916..9ef5187 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -39,6 +39,9 @@
TYPEVARIABLE,
PARAMETER,
INITIALIZING_FORMAL,
+ IMPORT,
+ EXPORT,
+ PREFIX,
}
/// Set of serializers used to serialize different kinds of elements by
@@ -58,6 +61,9 @@
const TypedefSerializer(),
const TypeVariableSerializer(),
const ParameterSerializer(),
+ const ImportSerializer(),
+ const ExportSerializer(),
+ const PrefixSerializer(),
];
/// Interface for a function that can serialize a set of element kinds.
@@ -150,32 +156,22 @@
SerializedElementKind kind) {
encoder.setUri(
Key.CANONICAL_URI, element.canonicalUri, element.canonicalUri);
- encoder.setString(Key.LIBRARY_NAME, element.getLibraryName());
+ encoder.setString(Key.LIBRARY_NAME, element.libraryName);
SerializerUtil.serializeMembers(element, encoder);
encoder.setElement(Key.COMPILATION_UNIT, element.entryCompilationUnit);
encoder.setElements(
Key.COMPILATION_UNITS, element.compilationUnits.toList());
- ListEncoder tags = encoder.createList(Key.TAGS);
+ encoder.setElements(Key.IMPORTS, element.imports);
+ encoder.setElements(Key.EXPORTS, element.exports);
- for (LibraryTag tag in element.tags) {
- if (tag is Import) {
- ObjectEncoder importTag = tags.createObject();
- importTag.setString(Key.KIND, 'import');
- importTag.setElement(Key.LIBRARY, element.getLibraryFromTag(tag));
- } else if (tag is Export) {
- ObjectEncoder exportTag = tags.createObject();
- exportTag.setString(Key.KIND, 'export');
- exportTag.setElement(Key.LIBRARY, element.getLibraryFromTag(tag));
- }
- }
+ List<Element> importedElements = <Element>[];
+ element.forEachImport(SerializerUtil.flattenElements(importedElements));
+ encoder.setElements(Key.IMPORT_SCOPE, importedElements);
- List<Element> imports = <Element>[];
- element.forEachImport(SerializerUtil.flattenElements(imports));
- encoder.setElements(Key.IMPORTS, imports);
+ List<Element> exportedElements = <Element>[];
+ element.forEachExport(SerializerUtil.flattenElements(exportedElements));
+ encoder.setElements(Key.EXPORT_SCOPE, exportedElements);
- List<Element> exports = <Element>[];
- element.forEachExport(SerializerUtil.flattenElements(exports));
- encoder.setElements(Key.EXPORTS, exports);
}
}
@@ -425,6 +421,75 @@
}
}
+class ImportSerializer implements ElementSerializer {
+ const ImportSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isImport) {
+ return SerializedElementKind.IMPORT;
+ }
+ return null;
+ }
+
+ void serialize(ImportElement element,
+ ObjectEncoder encoder,
+ SerializedElementKind kind) {
+ encoder.setElement(Key.LIBRARY, element.library);
+ encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
+ encoder.setElement(Key.LIBRARY_DEPENDENCY, element.importedLibrary);
+ if (element.prefix != null) {
+ encoder.setElement(Key.PREFIX, element.prefix);
+ }
+ encoder.setBool(Key.IS_DEFERRED, element.isDeferred);
+ // TODO(johnniwinther): What is the base for the URI?
+ encoder.setUri(Key.URI, element.uri, element.uri);
+ }
+}
+
+class ExportSerializer implements ElementSerializer {
+ const ExportSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isExport) {
+ return SerializedElementKind.EXPORT;
+ }
+ return null;
+ }
+
+ void serialize(ExportElement element,
+ ObjectEncoder encoder,
+ SerializedElementKind kind) {
+ encoder.setElement(Key.LIBRARY, element.library);
+ encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
+ encoder.setElement(Key.LIBRARY_DEPENDENCY, element.exportedLibrary);
+ // TODO(johnniwinther): What is the base for the URI?
+ encoder.setUri(Key.URI, element.uri, element.uri);
+ }
+}
+
+class PrefixSerializer implements ElementSerializer {
+ const PrefixSerializer();
+
+ SerializedElementKind getSerializedKind(Element element) {
+ if (element.isPrefix) {
+ return SerializedElementKind.PREFIX;
+ }
+ return null;
+ }
+
+ void serialize(PrefixElement element,
+ ObjectEncoder encoder,
+ SerializedElementKind kind) {
+ encoder.setString(Key.NAME, element.name);
+ encoder.setElement(Key.LIBRARY, element.library);
+ encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
+ if (element.deferredImport != null) {
+ encoder.setElement(Key.IMPORT, element.deferredImport);
+ }
+ encoder.setBool(Key.IS_DEFERRED, element.isDeferred);
+ }
+}
+
/// Utility class for deserializing [Element]s.
///
/// This is used by the [Deserializer].
@@ -482,6 +547,12 @@
return new ParameterElementZ(decoder);
case SerializedElementKind.INITIALIZING_FORMAL:
return new InitializingFormalElementZ(decoder);
+ case SerializedElementKind.IMPORT:
+ return new ImportElementZ(decoder);
+ case SerializedElementKind.EXPORT:
+ return new ExportElementZ(decoder);
+ case SerializedElementKind.PREFIX:
+ return new PrefixElementZ(decoder);
}
throw new UnsupportedError("Unexpected element kind '${elementKind}.");
}
diff --git a/pkg/compiler/lib/src/serialization/keys.dart b/pkg/compiler/lib/src/serialization/keys.dart
index a3c276e..de1af42 100644
--- a/pkg/compiler/lib/src/serialization/keys.dart
+++ b/pkg/compiler/lib/src/serialization/keys.dart
@@ -23,17 +23,21 @@
static const Key ELEMENT = const Key('element');
static const Key ELEMENTS = const Key('elements');
static const Key EXPORTS = const Key('exports');
+ static const Key EXPORT_SCOPE = const Key('export-scope');
static const Key EXPRESSION = const Key('expression');
static const Key FALSE = const Key('false');
static const Key FIELD = const Key('field');
static const Key FIELDS = const Key('fields');
static const Key FUNCTION = const Key('function');
static const Key ID = const Key('id');
+ static const Key IMPORT = const Key('import');
static const Key IMPORTS = const Key('imports');
+ static const Key IMPORT_SCOPE = const Key('import-scope');
static const Key INTERFACES = const Key('interfaces');
static const Key INDEX = const Key('index');
static const Key IS_ABSTRACT = const Key('isAbstract');
static const Key IS_CONST = const Key('isConst');
+ static const Key IS_DEFERRED = const Key('isDeferred');
static const Key IS_EXTERNAL = const Key('isExternal');
static const Key IS_FINAL = const Key('isFinal');
static const Key IS_NAMED = const Key('isNamed');
@@ -44,6 +48,7 @@
static const Key LEFT = const Key('left');
static const Key LENGTH = const Key('length');
static const Key LIBRARY = const Key('library');
+ static const Key LIBRARY_DEPENDENCY = const Key('library-dependency');
static const Key LIBRARY_NAME = const Key('library-name');
static const Key MEMBERS = const Key('members');
static const Key NAME = const Key('name');
@@ -57,6 +62,7 @@
const Key('optional-parameter-types');
static const Key PARAMETERS = const Key('parameters');
static const Key PARAMETER_TYPES = const Key('parameter-types');
+ static const Key PREFIX = const Key('prefix');
static const Key RETURN_TYPE = const Key('return-type');
static const Key RIGHT = const Key('right');
static const Key SUPERTYPE = const Key('supertype');
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index a0ba0a8..f246736 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -27,16 +27,12 @@
import '../io/source_file.dart';
import '../ordered_typeset.dart';
import '../resolution/class_members.dart' as class_members;
-import '../resolution/enum_creator.dart' show
- AstBuilder;
import '../resolution/tree_elements.dart' show
TreeElements;
import '../resolution/scope.dart' show
Scope;
import '../script.dart';
import '../serialization/constant_serialization.dart';
-import '../tokens/precedence_constants.dart' as Precedence show
- SEMICOLON_INFO;
import '../tokens/token.dart' show
Token;
import '../tree/tree.dart';
@@ -159,7 +155,7 @@
// TODO(johnniwinther): Support metadata.
@override
- Link<MetadataAnnotation> get metadata => const Link<MetadataAnnotation>();
+ Iterable<MetadataAnnotation> get metadata => const <MetadataAnnotation>[];
@override
Element get outermostEnclosingMemberOrTopLevel {
@@ -375,7 +371,8 @@
Uri _canonicalUri;
CompilationUnitElement _entryCompilationUnit;
Link<CompilationUnitElement> _compilationUnits;
- Link<Element> _exports;
+ List<ImportElement> _imports;
+ List<ExportElement> _exports;
ListedContainer _exportsMap;
ListedContainer _importsMap;
Map<LibraryTag, LibraryElement> _libraryDependencies;
@@ -426,12 +423,12 @@
}
@override
- bool hasLibraryName() {
- return getLibraryName() != '';
+ bool get hasLibraryName {
+ return libraryName != '';
}
@override
- String getLibraryName() {
+ String get libraryName {
return _decoder.getString(Key.LIBRARY_NAME);
}
@@ -439,20 +436,15 @@
bool get exportsHandled => true;
void _ensureExports() {
- if (_exports == null) {
- _exportsMap = new ListedContainer(_decoder.getElements(Key.EXPORTS));
- _exports = toLink(_exportsMap.values);
+ if (_exportsMap == null) {
+ _exportsMap = new ListedContainer(_decoder.getElements(Key.EXPORT_SCOPE));
}
}
- Link<Element> get exports {
- _ensureExports();
- return _exports;
- }
-
@override
void forEachExport(f(Element element)) {
- exports.forEach(f);
+ _ensureExports();
+ _exportsMap.forEach(f);
}
@override
@@ -470,53 +462,6 @@
return localLookup(elementName);
}
- void _ensureLibraryDependencies() {
- if (_libraryDependencies == null) {
- _libraryDependencies = <LibraryTag, LibraryElement>{};
- ListDecoder tags = _decoder.getList(Key.TAGS);
- AstBuilder builder = new AstBuilder(0);
- for (int i = 0; i < tags.length; i++) {
- ObjectDecoder dependency = tags.getObject(i);
- String kind = dependency.getString(Key.KIND);
- LibraryElement library = dependency.getElement(Key.LIBRARY);
- // TODO(johnniwinther): Add `ImportElement` and `ExportElement` to the
- // element model to avoid hacking up nodes.
- if (kind == 'import') {
- Import tag = new Import(
- builder.keywordToken('import'),
- builder.literalString(library.canonicalUri.toString())
- ..getEndToken().next =
- builder.symbolToken(Precedence.SEMICOLON_INFO),
- null, // prefix
- null, // combinators
- null, // metadata
- isDeferred: false);
- _libraryDependencies[tag] = library;
- } else if (kind == 'export') {
- Export tag = new Export(
- builder.keywordToken('export'),
- builder.literalString(library.canonicalUri.toString())
- ..getEndToken().next =
- builder.symbolToken(Precedence.SEMICOLON_INFO),
- null, // combinators
- null); // metadata
- _libraryDependencies[tag] = library;
- }
- }
- }
- }
-
- @override
- Iterable<LibraryTag> get tags {
- _ensureLibraryDependencies();
- return _libraryDependencies.keys;
- }
-
- LibraryElement getLibraryFromTag(LibraryDependency tag) {
- _ensureLibraryDependencies();
- return _libraryDependencies[tag];
- }
-
@override
bool get canUseNative => false;
@@ -525,7 +470,7 @@
void _ensureImports() {
if (_importsMap == null) {
- _importsMap = new ListedContainer(_decoder.getElements(Key.IMPORTS));
+ _importsMap = new ListedContainer(_decoder.getElements(Key.IMPORT_SCOPE));
}
}
@@ -536,14 +481,29 @@
}
@override
- Link<Import> getImportsFor(Element element) => _unsupported('getImportsFor');
-
- @override
- LibraryName get libraryTag => _unsupported('libraryTag');
+ Iterable<ImportElement> getImportsFor(Element element) {
+ return _unsupported('getImportsFor');
+ }
String toString() {
return 'Zlibrary(${canonicalUri})';
}
+
+ @override
+ Iterable<ExportElement> get exports {
+ if (_exports == null) {
+ _exports = _decoder.getElements(Key.EXPORTS, isOptional: true);
+ }
+ return _exports;
+ }
+
+ @override
+ Iterable<ImportElement> get imports {
+ if (_imports == null) {
+ _imports = _decoder.getElements(Key.IMPORTS, isOptional: true);
+ }
+ return _imports;
+ }
}
class ScriptZ implements Script {
@@ -940,6 +900,11 @@
@override
ClassElement get superclass => supertype != null ? supertype.element : null;
+
+ @override
+ void ensureResolved(Compiler compiler) {
+ compiler.world.registerClass(this);
+ }
}
abstract class ConstructorElementZ extends DeserializedElementZ
@@ -1280,9 +1245,6 @@
@override
bool get isResolved => true;
-
- @override
- void ensureResolved(Compiler compiler) {}
}
class TypedefElementZ extends DeserializedElementZ
@@ -1318,6 +1280,9 @@
}
@override
+ void ensureResolved(Compiler compiler) {}
+
+ @override
void checkCyclicReference(Compiler compiler) {}
}
@@ -1451,7 +1416,6 @@
MemberElement get memberContext => executableContext.memberContext;
}
-
class InitializingFormalElementZ extends ParameterElementZ
implements InitializingFormalElement {
FieldElement _fieldElement;
@@ -1474,5 +1438,142 @@
@override
ElementKind get kind => ElementKind.INITIALIZING_FORMAL;
+}
+class ImportElementZ extends DeserializedElementZ
+ with LibraryMemberMixin implements ImportElement {
+ bool _isDeferred;
+ PrefixElement _prefix;
+ LibraryElement _importedLibrary;
+ Uri _uri;
+
+ ImportElementZ(ObjectDecoder decoder)
+ : super(decoder);
+
+ @override
+ String get name => '';
+
+ @override
+ accept(ElementVisitor visitor, arg) => visitor.visitImportElement(this, arg);
+
+ @override
+ ElementKind get kind => ElementKind.IMPORT;
+
+ @override
+ LibraryElement get importedLibrary {
+ if (_importedLibrary == null) {
+ _importedLibrary = _decoder.getElement(Key.LIBRARY_DEPENDENCY);
+ }
+ return _importedLibrary;
+ }
+
+ void _ensurePrefixResolved() {
+ if (_isDeferred == null) {
+ _isDeferred = _decoder.getBool(Key.IS_DEFERRED);
+ _prefix = _decoder.getElement(Key.PREFIX, isOptional: true);
+ }
+ }
+
+ @override
+ bool get isDeferred {
+ _ensurePrefixResolved();
+ return _isDeferred;
+ }
+
+ @override
+ PrefixElement get prefix {
+ _ensurePrefixResolved();
+ return _prefix;
+ }
+
+ @override
+ Uri get uri {
+ if (_uri == null) {
+ _uri = _decoder.getUri(Key.URI);
+ }
+ return _uri;
+ }
+
+ @override
+ Import get node => _unsupported('node');
+
+ String toString() => 'Z$kind($uri)';
+}
+
+class ExportElementZ extends DeserializedElementZ
+ with LibraryMemberMixin implements ExportElement {
+ LibraryElement _exportedLibrary;
+ Uri _uri;
+
+ ExportElementZ(ObjectDecoder decoder)
+ : super(decoder);
+
+ @override
+ String get name => '';
+
+ @override
+ accept(ElementVisitor visitor, arg) => visitor.visitExportElement(this, arg);
+
+ @override
+ ElementKind get kind => ElementKind.EXPORT;
+
+ @override
+ LibraryElement get exportedLibrary {
+ if (_exportedLibrary == null) {
+ _exportedLibrary = _decoder.getElement(Key.LIBRARY_DEPENDENCY);
+ }
+ return _exportedLibrary;
+ }
+
+ @override
+ Uri get uri {
+ if (_uri == null) {
+ _uri = _decoder.getUri(Key.URI);
+ }
+ return _uri;
+ }
+
+ @override
+ Export get node => _unsupported('node');
+
+ String toString() => 'Z$kind($uri)';
+}
+
+class PrefixElementZ extends DeserializedElementZ
+ with LibraryMemberMixin implements PrefixElement {
+ bool _isDeferred;
+ ImportElement _deferredImport;
+
+ PrefixElementZ(ObjectDecoder decoder)
+ : super(decoder);
+
+ @override
+ accept(ElementVisitor visitor, arg) => visitor.visitPrefixElement(this, arg);
+
+ void _ensureDeferred() {
+ if (_isDeferred == null) {
+ _isDeferred = _decoder.getBool(Key.IS_DEFERRED);
+ _deferredImport = _decoder.getElement(Key.IMPORT, isOptional: true);
+ }
+ }
+
+ @override
+ ImportElement get deferredImport {
+ _ensureDeferred();
+ return _deferredImport;
+ }
+
+ @override
+ bool get isDeferred {
+ _ensureDeferred();
+ return _isDeferred;
+ }
+
+ @override
+ ElementKind get kind => ElementKind.PREFIX;
+
+ @override
+ Element lookupLocalMember(String memberName) {
+ return _unsupported('lookupLocalMember');
+ }
}
\ No newline at end of file
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 209e151..bf19f70 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -1097,6 +1097,7 @@
this.work = work,
this.rti = backend.rti,
this.elements = work.resolutionTree {
+ graph.element = work.element;
localsHandler = new LocalsHandler(this, work.element, null);
sourceElementStack.add(work.element);
sourceInformationBuilder =
@@ -3338,9 +3339,9 @@
ast.Node location) {
if (prefixElement == null) return;
String loadId =
- compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport];
+ compiler.deferredLoadTask.getImportDeferName(location, prefixElement);
HInstruction loadIdConstant = addConstantString(loadId);
- String uri = prefixElement.deferredImport.uri.dartString.slowToString();
+ String uri = prefixElement.deferredImport.uri.toString();
HInstruction uriConstant = addConstantString(uri);
Element helper = backend.getCheckDeferredIsLoaded();
pushInvokeStatic(location, helper, [loadIdConstant, uriConstant]);
@@ -4413,8 +4414,8 @@
invariant(node, deferredLoader.isDeferredLoaderGetter);
Element loadFunction = compiler.loadLibraryFunction;
PrefixElement prefixElement = deferredLoader.enclosingElement;
- String loadId = compiler.deferredLoadTask
- .importDeferName[prefixElement.deferredImport];
+ String loadId =
+ compiler.deferredLoadTask.getImportDeferName(node, prefixElement);
var inputs = [graph.addConstantString(
new ast.DartString.literal(loadId), compiler)];
push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType,
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 6a2002c..3e25aa9 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -2122,7 +2122,7 @@
js.Statement thenBody = new js.Block.empty();
js.Block oldContainer = currentContainer;
currentContainer = thenBody;
- generateThrowWithHelper('ioore', [node.array, node.index]);
+ generateThrowWithHelper('ioore', [node.array, node.reportedIndex]);
currentContainer = oldContainer;
thenBody = unwrapStatement(thenBody);
pushStatement(new js.If.noElse(underOver, thenBody)
@@ -2694,7 +2694,7 @@
checkString(input, '!==', input.sourceInformation);
return pop();
}
- compiler.internalError(input, 'Unexpected check.');
+ compiler.internalError(input, 'Unexpected check: $checkedType.');
return null;
}
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index b23f32d..8943e70 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -130,6 +130,7 @@
}
class HGraph {
+ Element element; // Used for debug printing.
HBasicBlock entry;
HBasicBlock exit;
HThis thisInstruction;
@@ -137,15 +138,13 @@
HParameterValue explicitReceiverParameter;
bool isRecursiveMethod = false;
bool calledInLoop = false;
- final List<HBasicBlock> blocks;
+ final List<HBasicBlock> blocks = <HBasicBlock>[];
// We canonicalize all constants used within a graph so we do not
// have to worry about them for global value numbering.
- Map<ConstantValue, HConstant> constants;
+ Map<ConstantValue, HConstant> constants = new Map<ConstantValue, HConstant>();
- HGraph()
- : blocks = new List<HBasicBlock>(),
- constants = new Map<ConstantValue, HConstant>() {
+ HGraph() {
entry = addNewBlock();
// The exit block will be added later, so it has an id that is
// after all others in the system.
@@ -262,6 +261,8 @@
validator.visitGraph(this);
return validator.isValid;
}
+
+ toString() => 'HGraph($element)';
}
class HBaseVisitor extends HGraphVisitor implements HVisitor {
@@ -882,6 +883,32 @@
return instructionType.isEmpty && !instructionType.isNullable;
}
+ /// Returns `true` if [typeMask] contains [cls].
+ static bool containsType(
+ TypeMask typeMask,
+ ClassElement cls,
+ ClassWorld classWorld) {
+ return classWorld.isInstantiated(cls) && typeMask.contains(cls, classWorld);
+ }
+
+ /// Returns `true` if [typeMask] contains only [cls].
+ static bool containsOnlyType(
+ TypeMask typeMask,
+ ClassElement cls,
+ ClassWorld classWorld) {
+ return classWorld.isInstantiated(cls) &&
+ typeMask.containsOnly(cls);
+ }
+
+ /// Returns `true` if [typeMask] is an instance of [cls].
+ static bool isInstanceOf(
+ TypeMask typeMask,
+ ClassElement cls,
+ ClassWorld classWorld) {
+ return classWorld.isInstantiated(cls) &&
+ typeMask.satisfies(cls, classWorld);
+ }
+
bool canBePrimitive(Compiler compiler) {
return canBePrimitiveNumber(compiler)
|| canBePrimitiveArray(compiler)
@@ -895,27 +922,28 @@
JavaScriptBackend backend = compiler.backend;
// TODO(sra): It should be possible to test only jsDoubleClass and
// jsUInt31Class, since all others are superclasses of these two.
- return instructionType.contains(backend.jsNumberClass, classWorld)
- || instructionType.contains(backend.jsIntClass, classWorld)
- || instructionType.contains(backend.jsPositiveIntClass, classWorld)
- || instructionType.contains(backend.jsUInt32Class, classWorld)
- || instructionType.contains(backend.jsUInt31Class, classWorld)
- || instructionType.contains(backend.jsDoubleClass, classWorld);
+ return containsType(instructionType, backend.jsNumberClass, classWorld)
+ || containsType(instructionType, backend.jsIntClass, classWorld)
+ || containsType(instructionType, backend.jsPositiveIntClass, classWorld)
+ || containsType(instructionType, backend.jsUInt32Class, classWorld)
+ || containsType(instructionType, backend.jsUInt31Class, classWorld)
+ || containsType(instructionType, backend.jsDoubleClass, classWorld);
}
bool canBePrimitiveBoolean(Compiler compiler) {
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
- return instructionType.contains(backend.jsBoolClass, classWorld);
+ return containsType(instructionType, backend.jsBoolClass, classWorld);
}
bool canBePrimitiveArray(Compiler compiler) {
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
- return instructionType.contains(backend.jsArrayClass, classWorld)
- || instructionType.contains(backend.jsFixedArrayClass, classWorld)
- || instructionType.contains(backend.jsExtendableArrayClass, classWorld)
- || instructionType.contains(
+ return containsType(instructionType, backend.jsArrayClass, classWorld)
+ || containsType(instructionType, backend.jsFixedArrayClass, classWorld)
+ || containsType(
+ instructionType, backend.jsExtendableArrayClass, classWorld)
+ || containsType(instructionType,
backend.jsUnmodifiableArrayClass, classWorld);
}
@@ -923,37 +951,43 @@
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
return instructionType.containsOnlyString(classWorld)
- || instructionType.satisfies(backend.jsIndexableClass, classWorld);
+ || isInstanceOf(instructionType, backend.jsIndexableClass, classWorld);
}
bool isFixedArray(Compiler compiler) {
+ ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
// TODO(sra): Recognize the union of these types as well.
- return instructionType.containsOnly(backend.jsFixedArrayClass)
- || instructionType.containsOnly(backend.jsUnmodifiableArrayClass);
+ return containsOnlyType(
+ instructionType, backend.jsFixedArrayClass, classWorld)
+ || containsOnlyType(
+ instructionType, backend.jsUnmodifiableArrayClass, classWorld);
}
bool isExtendableArray(Compiler compiler) {
+ ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
- return instructionType.containsOnly(backend.jsExtendableArrayClass);
+ return containsOnlyType(
+ instructionType, backend.jsExtendableArrayClass, classWorld);
}
bool isMutableArray(Compiler compiler) {
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
- return instructionType.satisfies(backend.jsMutableArrayClass, classWorld);
+ return isInstanceOf(
+ instructionType, backend.jsMutableArrayClass, classWorld);
}
bool isReadableArray(Compiler compiler) {
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
- return instructionType.satisfies(backend.jsArrayClass, classWorld);
+ return isInstanceOf(instructionType, backend.jsArrayClass, classWorld);
}
bool isMutableIndexable(Compiler compiler) {
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
- return instructionType.satisfies(
+ return isInstanceOf(instructionType,
backend.jsMutableIndexableClass, classWorld);
}
@@ -962,7 +996,7 @@
bool canBePrimitiveString(Compiler compiler) {
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
- return instructionType.contains(backend.jsStringClass, classWorld);
+ return containsType(instructionType, backend.jsStringClass, classWorld);
}
bool isInteger(Compiler compiler) {
@@ -975,27 +1009,28 @@
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
return !instructionType.isNullable
- && instructionType.satisfies(backend.jsUInt32Class, classWorld);
+ && isInstanceOf(instructionType, backend.jsUInt32Class, classWorld);
}
bool isUInt31(Compiler compiler) {
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
return !instructionType.isNullable
- && instructionType.satisfies(backend.jsUInt31Class, classWorld);
+ && isInstanceOf(instructionType, backend.jsUInt31Class, classWorld);
}
bool isPositiveInteger(Compiler compiler) {
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
- return !instructionType.isNullable
- && instructionType.satisfies(backend.jsPositiveIntClass, classWorld);
+ return !instructionType.isNullable &&
+ isInstanceOf(instructionType, backend.jsPositiveIntClass, classWorld);
}
bool isPositiveIntegerOrNull(Compiler compiler) {
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
- return instructionType.satisfies(backend.jsPositiveIntClass, classWorld);
+ return isInstanceOf(
+ instructionType, backend.jsPositiveIntClass, classWorld);
}
bool isIntegerOrNull(Compiler compiler) {
@@ -1393,6 +1428,9 @@
HInstruction get length => inputs[1];
HInstruction get index => inputs[0];
HInstruction get array => inputs[2];
+ // There can be an additional fourth input which is the index to report to
+ // [ioore]. This is used by the expansion of [JSArray.removeLast].
+ HInstruction get reportedIndex => inputs.length > 3 ? inputs[3] : index;
bool isControlFlow() => true;
accept(HVisitor visitor) => visitor.visitBoundsCheck(this);
@@ -1846,6 +1884,8 @@
accept(HVisitor visitor) => visitor.visitForeignNew(this);
bool get isAllocation => true;
+
+ String toString() => 'HForeignNew($element)';
}
abstract class HInvokeBinary extends HInstruction {
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 977900c..cb03183 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -268,9 +268,11 @@
ClassWorld classWorld = compiler.world;
TypeMask resultType = backend.positiveIntType;
// If we already have computed a more specific type, keep that type.
- if (actualType.satisfies(backend.jsUInt31Class, classWorld)) {
+ if (HInstruction.isInstanceOf(
+ actualType, backend.jsUInt31Class, classWorld)) {
resultType = backend.uint31Type;
- } else if (actualType.satisfies(backend.jsUInt32Class, classWorld)) {
+ } else if (HInstruction.isInstanceOf(
+ actualType, backend.jsUInt32Class, classWorld)) {
resultType = backend.uint32Type;
}
HFieldGet result = new HFieldGet(
@@ -1029,8 +1031,13 @@
if (node.isInterceptedCall) return;
if (element != backend.jsArrayRemoveLast) return;
if (boundsChecked.contains(node)) return;
- insertBoundsCheck(
+ // `0` is the index we want to check, but we want to report `-1`, as if we
+ // executed `a[a.length-1]`
+ HBoundsCheck check = insertBoundsCheck(
node, node.receiver, graph.addConstantInt(0, backend.compiler));
+ HInstruction minusOne = graph.addConstantInt(-1, backend.compiler);
+ check.inputs.add(minusOne);
+ minusOne.usedBy.add(check);
}
}
@@ -1954,17 +1961,57 @@
void visitForeignNew(HForeignNew instruction) {
memorySet.registerAllocation(instruction);
- int argumentIndex = 0;
- instruction.element.forEachInstanceField((_, Element member) {
- if (compiler.elementHasCompileTimeError(member)) return;
- memorySet.registerFieldValue(
- member, instruction, instruction.inputs[argumentIndex++]);
- }, includeSuperAndInjectedMembers: true);
+ if (shouldTrackInitialValues(instruction)) {
+ int argumentIndex = 0;
+ instruction.element.forEachInstanceField((_, Element member) {
+ if (compiler.elementHasCompileTimeError(member)) return;
+ memorySet.registerFieldValue(
+ member, instruction, instruction.inputs[argumentIndex++]);
+ }, includeSuperAndInjectedMembers: true);
+ }
// In case this instruction has as input non-escaping objects, we
// need to mark these objects as escaping.
memorySet.killAffectedBy(instruction);
}
+ bool shouldTrackInitialValues(HForeignNew instruction) {
+ // Don't track initial field values of an allocation that are
+ // unprofitable. We search the chain of single uses in allocations for a
+ // limited depth.
+
+ const MAX_HEAP_DEPTH = 5;
+
+ bool interestingUse(HInstruction instruction, int heapDepth) {
+ // Heuristic: if the allocation is too deep in heap it is unlikely we will
+ // recover a field by load-elimination.
+ // TODO(sra): We can measure this depth by looking at load chains.
+ if (heapDepth == MAX_HEAP_DEPTH) return false;
+ // There are multiple uses so do the full store analysis.
+ if (instruction.usedBy.length != 1) return true;
+ HInstruction use = instruction.usedBy.single;
+ // When the only use is an allocation, the allocation becomes the only
+ // heap alias for the current instruction.
+ if (use is HForeignNew) return interestingUse(use, heapDepth + 1);
+ if (use is HLiteralList) return interestingUse(use, heapDepth + 1);
+ if (use is HInvokeStatic) {
+ // Assume the argument escapes. All we do with our initial allocation is
+ // have it escape or store it into an object that escapes.
+ return false;
+ // TODO(sra): Handle more functions. `setRuntimeTypeInfo` does not
+ // actually kill it's input, but we don't make use of that elsewhere so
+ // there is not point in checking here.
+ }
+ if (use is HPhi) {
+ // The initial allocation (it's only alias) gets merged out of the model
+ // of the heap before load.
+ return false;
+ }
+ return true;
+ }
+
+ return interestingUse(instruction, 0);
+ }
+
void visitInstruction(HInstruction instruction) {
if (instruction.isAllocation) {
memorySet.registerAllocation(instruction);
diff --git a/pkg/compiler/lib/src/tree/nodes.dart b/pkg/compiler/lib/src/tree/nodes.dart
index 56f1f26..6c4516b 100644
--- a/pkg/compiler/lib/src/tree/nodes.dart
+++ b/pkg/compiler/lib/src/tree/nodes.dart
@@ -1897,7 +1897,7 @@
}
abstract class LibraryTag extends Node {
- final Link<MetadataAnnotation> metadata;
+ final List<MetadataAnnotation> metadata;
LibraryTag(this.metadata);
@@ -1915,7 +1915,7 @@
LibraryName(this.libraryKeyword,
this.name,
- Link<MetadataAnnotation> metadata)
+ List<MetadataAnnotation> metadata)
: super(metadata);
bool get isLibraryName => true;
@@ -1942,7 +1942,7 @@
LibraryDependency(this.uri,
this.combinators,
- Link<MetadataAnnotation> metadata)
+ List<MetadataAnnotation> metadata)
: super(metadata);
LibraryDependency asLibraryDependency() => this;
@@ -1962,7 +1962,7 @@
Import(this.importKeyword, StringNode uri,
this.prefix, NodeList combinators,
- Link<MetadataAnnotation> metadata,
+ List<MetadataAnnotation> metadata,
{this.isDeferred})
: super(uri, combinators, metadata);
@@ -2027,7 +2027,7 @@
Export(this.exportKeyword,
StringNode uri,
NodeList combinators,
- Link<MetadataAnnotation> metadata)
+ List<MetadataAnnotation> metadata)
: super(uri, combinators, metadata);
bool get isExport => true;
@@ -2054,7 +2054,7 @@
final Token partKeyword;
- Part(this.partKeyword, this.uri, Link<MetadataAnnotation> metadata)
+ Part(this.partKeyword, this.uri, List<MetadataAnnotation> metadata)
: super(metadata);
bool get isPart => true;
@@ -2075,7 +2075,7 @@
final Token partKeyword;
- final Link<MetadataAnnotation> metadata;
+ final List<MetadataAnnotation> metadata;
PartOf(this.partKeyword, this.name, this.metadata);
diff --git a/pkg/compiler/lib/src/tree/unparser.dart b/pkg/compiler/lib/src/tree/unparser.dart
index fd00ba3..a0156be 100644
--- a/pkg/compiler/lib/src/tree/unparser.dart
+++ b/pkg/compiler/lib/src/tree/unparser.dart
@@ -698,6 +698,11 @@
indentLess();
}
+ unparseLibraryName(String libraryName) {
+ write('library $libraryName;');
+ newline();
+ }
+
unparseImportTag(String uri, {String prefix,
List<String> shows: const <String>[],
bool isDeferred: false}) {
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index 9ad632c..c4b993b 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -392,14 +392,14 @@
Expression value = getVariableUse(node.value);
List<Expression> typeArgs = translateArguments(node.typeArguments);
Expression expression =
- new TypeOperator(value, node.type, typeArgs, isTypeTest: false);
+ new TypeOperator(value, node.dartType, typeArgs, isTypeTest: false);
return makeCallExpression(node, expression);
}
NodeCallback visitInvokeConstructor(cps_ir.InvokeConstructor node) {
List<Expression> arguments = translateArguments(node.arguments);
Expression invoke = new InvokeConstructor(
- node.type,
+ node.dartType,
node.target,
node.selector,
arguments,
@@ -580,13 +580,13 @@
Expression visitLiteralList(cps_ir.LiteralList node) {
return new LiteralList(
- node.type,
+ node.dartType,
translateArguments(node.values));
}
Expression visitLiteralMap(cps_ir.LiteralMap node) {
return new LiteralMap(
- node.type,
+ node.dartType,
new List<LiteralMapEntry>.generate(node.entries.length, (int index) {
return new LiteralMapEntry(
getVariableUse(node.entries[index].key),
@@ -625,7 +625,7 @@
Expression visitTypeTest(cps_ir.TypeTest node) {
Expression value = getVariableUse(node.value);
List<Expression> typeArgs = translateArguments(node.typeArguments);
- return new TypeOperator(value, node.type, typeArgs, isTypeTest: true);
+ return new TypeOperator(value, node.dartType, typeArgs, isTypeTest: true);
}
Expression visitGetStatic(cps_ir.GetStatic node) {
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_integrity.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_integrity.dart
index fa33492..3a1a0bc 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_integrity.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_integrity.dart
@@ -85,7 +85,7 @@
label2declaration[label] = target;
labelUses[label] = 0;
visitStatement(target.body);
- label2declaration.remove(target);
+ label2declaration.remove(label);
if (labelUses[label] != label.useCount) {
error('Label $label has ${labelUses[label]} uses '
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index 74b9659..cb64d9b 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -4,6 +4,8 @@
library dart2js.typechecker;
+import 'common/names.dart' show
+ Identifiers;
import 'common/tasks.dart' show
CompilerTask;
import 'compiler.dart' show
@@ -62,7 +64,7 @@
if (element.isClass) return;
if (element.isTypedef) return;
ResolvedAst resolvedAst = element.resolvedAst;
- compiler.withCurrentElement(element, () {
+ compiler.withCurrentElement(element.implementation, () {
measure(() {
TypeCheckerVisitor visitor = new TypeCheckerVisitor(
compiler, resolvedAst.elements, compiler.types);
@@ -420,6 +422,16 @@
compiler.reportWarning(spannable, kind, arguments);
}
+ reportMessage(Spannable spannable, MessageKind kind,
+ Map arguments,
+ {bool isHint: false}) {
+ if (isHint) {
+ compiler.reportHint(spannable, kind, arguments);
+ } else {
+ compiler.reportWarning(spannable, kind, arguments);
+ }
+ }
+
reportTypeInfo(Spannable spannable, MessageKind kind,
[Map arguments = const {}]) {
compiler.reportInfo(spannable, kind, arguments);
@@ -726,14 +738,15 @@
node,
MessageKind.PRIVATE_ACCESS,
{'name': name,
- 'libraryName': element.library.getLibraryOrScriptName()});
+ 'libraryName': element.library.libraryOrScriptName});
}
}
ElementAccess lookupMember(Node node, DartType receiverType, String name,
MemberKind memberKind, Element receiverElement,
- {bool lookupClassMember: false}) {
+ {bool lookupClassMember: false,
+ bool isHint: false}) {
if (receiverType.treatAsDynamic) {
return const DynamicAccess();
}
@@ -741,35 +754,6 @@
Name memberName = new Name(name, currentLibrary,
isSetter: memberKind == MemberKind.SETTER);
- // Compute the unaliased type of the first non type variable bound of
- // [type].
- DartType computeUnaliasedBound(DartType type) {
- DartType originalType = type;
- while (identical(type.kind, TypeKind.TYPE_VARIABLE)) {
- TypeVariableType variable = type;
- type = variable.element.bound;
- if (type == originalType) {
- type = compiler.objectClass.rawType;
- }
- }
- if (type.isMalformed) {
- return const DynamicType();
- }
- return type.unalias(compiler);
- }
-
- // Compute the interface type of [type]. For type variable it is the
- // interface type of the bound, for function types and typedefs it is the
- // `Function` type.
- InterfaceType computeInterfaceType(DartType type) {
- if (type.isFunctionType) {
- type = compiler.functionClass.rawType;
- }
- assert(invariant(node, type.isInterfaceType,
- message: "unexpected type kind ${type.kind}."));
- return type;
- }
-
// Lookup the class or interface member [name] in [interface].
MemberSignature lookupMemberSignature(Name name, InterfaceType interface) {
MembersCreator.computeClassMembersByName(
@@ -802,11 +786,13 @@
return null;
}
- DartType unaliasedBound = computeUnaliasedBound(receiverType);
+ DartType unaliasedBound =
+ Types.computeUnaliasedBound(compiler, receiverType);
if (unaliasedBound.treatAsDynamic) {
return new DynamicAccess();
}
- InterfaceType interface = computeInterfaceType(unaliasedBound);
+ InterfaceType interface =
+ Types.computeInterfaceType(compiler, unaliasedBound);
ElementAccess access = getAccess(memberName, unaliasedBound, interface);
if (access != null) {
return access;
@@ -818,9 +804,11 @@
while (!typePromotions.isEmpty) {
TypePromotion typePromotion = typePromotions.head;
if (!typePromotion.isValid) {
- DartType unaliasedBound = computeUnaliasedBound(typePromotion.type);
+ DartType unaliasedBound =
+ Types.computeUnaliasedBound(compiler, typePromotion.type);
if (!unaliasedBound.treatAsDynamic) {
- InterfaceType interface = computeInterfaceType(unaliasedBound);
+ InterfaceType interface =
+ Types.computeInterfaceType(compiler, unaliasedBound);
if (getAccess(memberName, unaliasedBound, interface) != null) {
reportTypePromotionHint(typePromotion);
}
@@ -840,11 +828,12 @@
void findPrivateMember(MemberSignature member) {
if (memberName.isSimilarTo(member.name)) {
PrivateName privateName = member.name;
- reportTypeWarning(
+ reportMessage(
node,
MessageKind.PRIVATE_ACCESS,
{'name': name,
- 'libraryName': privateName.library.getLibraryOrScriptName()});
+ 'libraryName': privateName.library.libraryOrScriptName},
+ isHint: isHint);
foundPrivateMember = true;
}
}
@@ -860,19 +849,22 @@
if (!foundPrivateMember) {
switch (memberKind) {
case MemberKind.METHOD:
- reportTypeWarning(node, MessageKind.METHOD_NOT_FOUND,
- {'className': receiverType.name, 'memberName': name});
+ reportMessage(node, MessageKind.METHOD_NOT_FOUND,
+ {'className': receiverType.name, 'memberName': name},
+ isHint: isHint);
break;
case MemberKind.OPERATOR:
- reportTypeWarning(node, MessageKind.OPERATOR_NOT_FOUND,
- {'className': receiverType.name, 'memberName': name});
+ reportMessage(node, MessageKind.OPERATOR_NOT_FOUND,
+ {'className': receiverType.name, 'memberName': name},
+ isHint: isHint);
break;
case MemberKind.GETTER:
if (lookupMemberSignature(memberName.setter, interface) != null) {
// A setter is present so warn explicitly about the missing
// getter.
- reportTypeWarning(node, MessageKind.GETTER_NOT_FOUND,
- {'className': receiverType.name, 'memberName': name});
+ reportMessage(node, MessageKind.GETTER_NOT_FOUND,
+ {'className': receiverType.name, 'memberName': name},
+ isHint: isHint);
} else if (name == 'await') {
Map arguments = {'className': receiverType.name};
String functionName = executableContext.name;
@@ -883,15 +875,17 @@
kind = MessageKind.AWAIT_MEMBER_NOT_FOUND;
arguments['functionName'] = functionName;
}
- reportTypeWarning(node, kind, arguments);
+ reportMessage(node, kind, arguments, isHint: isHint);
} else {
- reportTypeWarning(node, MessageKind.MEMBER_NOT_FOUND,
- {'className': receiverType.name, 'memberName': name});
+ reportMessage(node, MessageKind.MEMBER_NOT_FOUND,
+ {'className': receiverType.name, 'memberName': name},
+ isHint: isHint);
}
break;
case MemberKind.SETTER:
- reportTypeWarning(node, MessageKind.SETTER_NOT_FOUND,
- {'className': receiverType.name, 'memberName': name});
+ reportMessage(node, MessageKind.SETTER_NOT_FOUND,
+ {'className': receiverType.name, 'memberName': name},
+ isHint: isHint);
break;
}
}
@@ -900,8 +894,9 @@
}
DartType lookupMemberType(Node node, DartType type, String name,
- MemberKind memberKind) {
- return lookupMember(node, type, name, memberKind, null)
+ MemberKind memberKind,
+ {bool isHint: false}) {
+ return lookupMember(node, type, name, memberKind, null, isHint: isHint)
.computeType(compiler);
}
@@ -1797,14 +1792,67 @@
return const StatementType();
}
+ DartType computeForInElementType(ForIn node) {
+ VariableDefinitions declaredIdentifier =
+ node.declaredIdentifier.asVariableDefinitions();
+ if (declaredIdentifier != null) {
+ return
+ analyzeWithDefault(declaredIdentifier.type, const DynamicType());
+ } else {
+ return analyze(node.declaredIdentifier);
+ }
+ }
+
visitAsyncForIn(AsyncForIn node) {
- analyze(node.expression);
+ DartType elementType = computeForInElementType(node);
+ DartType expressionType = analyze(node.expression);
+ // TODO(johnniwinther): Move this to _CompilerCoreTypes.
+ compiler.streamClass.ensureResolved(compiler);
+ DartType streamOfDynamic = coreTypes.streamType();
+ if (!types.isAssignable(expressionType, streamOfDynamic)) {
+ reportMessage(node.expression,
+ MessageKind.NOT_ASSIGNABLE,
+ {'fromType': expressionType, 'toType': streamOfDynamic},
+ isHint: true);
+ } else {
+ InterfaceType interfaceType =
+ Types.computeInterfaceType(compiler, expressionType);
+ if (interfaceType != null) {
+ InterfaceType streamType =
+ interfaceType.asInstanceOf(compiler.streamClass);
+ if (streamType != null) {
+ DartType streamElementType = streamType.typeArguments.first;
+ if (!types.isAssignable(streamElementType, elementType)) {
+ reportMessage(node.expression,
+ MessageKind.FORIN_NOT_ASSIGNABLE,
+ {'currentType': streamElementType,
+ 'expressionType': expressionType,
+ 'elementType': elementType},
+ isHint: true);
+ }
+ }
+ }
+ }
analyze(node.body);
return const StatementType();
}
visitSyncForIn(SyncForIn node) {
- analyze(node.expression);
+ DartType elementType = computeForInElementType(node);
+ DartType expressionType = analyze(node.expression);
+ DartType iteratorType = lookupMemberType(node.expression,
+ expressionType, Identifiers.iterator, MemberKind.GETTER);
+ DartType currentType = lookupMemberType(node.expression,
+ iteratorType, Identifiers.current, MemberKind.GETTER,
+ isHint: true);
+ if (!types.isAssignable(currentType, elementType)) {
+ reportMessage(node.expression,
+ MessageKind.FORIN_NOT_ASSIGNABLE,
+ {'currentType': currentType,
+ 'expressionType': expressionType,
+ 'elementType': elementType},
+ isHint: true);
+ }
analyze(node.body);
return const StatementType();
}
diff --git a/pkg/compiler/lib/src/universe/call_structure.dart b/pkg/compiler/lib/src/universe/call_structure.dart
new file mode 100644
index 0000000..12e4fd8
--- /dev/null
+++ b/pkg/compiler/lib/src/universe/call_structure.dart
@@ -0,0 +1,282 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of universe;
+
+/// The structure of the arguments at a call-site.
+// TODO(johnniwinther): Should these be cached?
+// TODO(johnniwinther): Should isGetter/isSetter be part of the call structure
+// instead of the selector?
+class CallStructure {
+ static const CallStructure NO_ARGS = const CallStructure.unnamed(0);
+ static const CallStructure ONE_ARG = const CallStructure.unnamed(1);
+ static const CallStructure TWO_ARGS = const CallStructure.unnamed(2);
+
+ /// The numbers of arguments of the call. Includes named arguments.
+ final int argumentCount;
+
+ /// The number of named arguments of the call.
+ int get namedArgumentCount => 0;
+
+ /// The number of positional argument of the call.
+ int get positionalArgumentCount => argumentCount;
+
+ const CallStructure.unnamed(this.argumentCount);
+
+ factory CallStructure(int argumentCount, [List<String> namedArguments]) {
+ if (namedArguments == null || namedArguments.isEmpty) {
+ return new CallStructure.unnamed(argumentCount);
+ }
+ return new NamedCallStructure(argumentCount, namedArguments);
+ }
+
+ /// `true` if this call has named arguments.
+ bool get isNamed => false;
+
+ /// `true` if this call has no named arguments.
+ bool get isUnnamed => true;
+
+ /// The names of the named arguments in call-site order.
+ List<String> get namedArguments => const <String>[];
+
+ /// The names of the named arguments in canonicalized order.
+ List<String> getOrderedNamedArguments() => const <String>[];
+
+ /// A description of the argument structure.
+ String structureToString() => 'arity=$argumentCount';
+
+ String toString() => 'CallStructure(${structureToString()})';
+
+ Selector get callSelector {
+ return new Selector(SelectorKind.CALL, Selector.CALL_NAME, this);
+ }
+
+ bool match(CallStructure other) {
+ if (identical(this, other)) return true;
+ return this.argumentCount == other.argumentCount
+ && this.namedArgumentCount == other.namedArgumentCount
+ && sameNames(this.namedArguments, other.namedArguments);
+ }
+
+ // TODO(johnniwinther): Cache hash code?
+ int get hashCode {
+ return Hashing.listHash(namedArguments,
+ Hashing.objectHash(argumentCount, namedArguments.length));
+ }
+
+ bool operator ==(other) {
+ if (other is! CallStructure) return false;
+ return match(other);
+ }
+
+ bool signatureApplies(FunctionSignature parameters) {
+ if (argumentCount > parameters.parameterCount) return false;
+ int requiredParameterCount = parameters.requiredParameterCount;
+ int optionalParameterCount = parameters.optionalParameterCount;
+ if (positionalArgumentCount < requiredParameterCount) return false;
+
+ if (!parameters.optionalParametersAreNamed) {
+ // We have already checked that the number of arguments are
+ // not greater than the number of parameters. Therefore the
+ // number of positional arguments are not greater than the
+ // number of parameters.
+ assert(positionalArgumentCount <= parameters.parameterCount);
+ return namedArguments.isEmpty;
+ } else {
+ if (positionalArgumentCount > requiredParameterCount) return false;
+ assert(positionalArgumentCount == requiredParameterCount);
+ if (namedArgumentCount > optionalParameterCount) return false;
+ Set<String> nameSet = new Set<String>();
+ parameters.optionalParameters.forEach((Element element) {
+ nameSet.add(element.name);
+ });
+ for (String name in namedArguments) {
+ if (!nameSet.contains(name)) return false;
+ // TODO(5213): By removing from the set we are checking
+ // that we are not passing the name twice. We should have this
+ // check in the resolver also.
+ nameSet.remove(name);
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Returns a `List` with the evaluated arguments in the normalized order.
+ *
+ * [compileDefaultValue] is a function that returns a compiled constant
+ * of an optional argument that is not in [compiledArguments].
+ *
+ * Precondition: `this.applies(element, world)`.
+ *
+ * Invariant: [element] must be the implementation element.
+ */
+ /*<T>*/ List/*<T>*/ makeArgumentsList(
+ Link<Node> arguments,
+ FunctionElement element,
+ /*T*/ compileArgument(Node argument),
+ /*T*/ compileDefaultValue(ParameterElement element)) {
+ assert(invariant(element, element.isImplementation));
+ List/*<T>*/ result = new List();
+
+ FunctionSignature parameters = element.functionSignature;
+ parameters.forEachRequiredParameter((ParameterElement element) {
+ result.add(compileArgument(arguments.head));
+ arguments = arguments.tail;
+ });
+
+ if (!parameters.optionalParametersAreNamed) {
+ parameters.forEachOptionalParameter((ParameterElement element) {
+ if (!arguments.isEmpty) {
+ result.add(compileArgument(arguments.head));
+ arguments = arguments.tail;
+ } else {
+ result.add(compileDefaultValue(element));
+ }
+ });
+ } else {
+ // Visit named arguments and add them into a temporary list.
+ List compiledNamedArguments = [];
+ for (; !arguments.isEmpty; arguments = arguments.tail) {
+ NamedArgument namedArgument = arguments.head;
+ compiledNamedArguments.add(compileArgument(namedArgument.expression));
+ }
+ // Iterate over the optional parameters of the signature, and try to
+ // find them in [compiledNamedArguments]. If found, we use the
+ // value in the temporary list, otherwise the default value.
+ parameters.orderedOptionalParameters.forEach((ParameterElement element) {
+ int foundIndex = namedArguments.indexOf(element.name);
+ if (foundIndex != -1) {
+ result.add(compiledNamedArguments[foundIndex]);
+ } else {
+ result.add(compileDefaultValue(element));
+ }
+ });
+ }
+ return result;
+ }
+
+ /**
+ * Fills [list] with the arguments in the order expected by
+ * [callee], and where [caller] is a synthesized element
+ *
+ * [compileArgument] is a function that returns a compiled version
+ * of a parameter of [callee].
+ *
+ * [compileConstant] is a function that returns a compiled constant
+ * of an optional argument that is not in the parameters of [callee].
+ *
+ * Returns [:true:] if the signature of the [caller] matches the
+ * signature of the [callee], [:false:] otherwise.
+ */
+ static /*<T>*/ bool addForwardingElementArgumentsToList(
+ ConstructorElement caller,
+ List/*<T>*/ list,
+ ConstructorElement callee,
+ /*T*/ compileArgument(ParameterElement element),
+ /*T*/ compileConstant(ParameterElement element)) {
+ assert(invariant(caller, !callee.isErroneous,
+ message: "Cannot compute arguments to erroneous constructor: "
+ "$caller calling $callee."));
+
+ FunctionSignature signature = caller.functionSignature;
+ Map<Node, ParameterElement> mapping = <Node, ParameterElement>{};
+
+ // TODO(ngeoffray): This is a hack that fakes up AST nodes, so
+ // that we can call [addArgumentsToList].
+ Link<Node> computeCallNodesFromParameters() {
+ LinkBuilder<Node> builder = new LinkBuilder<Node>();
+ signature.forEachRequiredParameter((ParameterElement element) {
+ Node node = element.node;
+ mapping[node] = element;
+ builder.addLast(node);
+ });
+ if (signature.optionalParametersAreNamed) {
+ signature.forEachOptionalParameter((ParameterElement element) {
+ mapping[element.initializer] = element;
+ builder.addLast(new NamedArgument(null, null, element.initializer));
+ });
+ } else {
+ signature.forEachOptionalParameter((ParameterElement element) {
+ Node node = element.node;
+ mapping[node] = element;
+ builder.addLast(node);
+ });
+ }
+ return builder.toLink();
+ }
+
+ /*T*/ internalCompileArgument(Node node) {
+ return compileArgument(mapping[node]);
+ }
+
+ Link<Node> nodes = computeCallNodesFromParameters();
+
+ // Synthesize a structure for the call.
+ // TODO(ngeoffray): Should the resolver do it instead?
+ List<String> namedParameters;
+ if (signature.optionalParametersAreNamed) {
+ namedParameters =
+ signature.optionalParameters.map((e) => e.name).toList();
+ }
+ CallStructure callStructure =
+ new CallStructure(signature.parameterCount, namedParameters);
+ if (!callStructure.signatureApplies(signature)) {
+ return false;
+ }
+ list.addAll(callStructure.makeArgumentsList(
+ nodes,
+ callee,
+ internalCompileArgument,
+ compileConstant));
+
+ return true;
+ }
+
+ static bool sameNames(List<String> first, List<String> second) {
+ for (int i = 0; i < first.length; i++) {
+ if (first[i] != second[i]) return false;
+ }
+ return true;
+ }
+}
+
+///
+class NamedCallStructure extends CallStructure {
+ final List<String> namedArguments;
+ final List<String> _orderedNamedArguments = <String>[];
+
+ NamedCallStructure(int argumentCount, this.namedArguments)
+ : super.unnamed(argumentCount) {
+ assert(namedArguments.isNotEmpty);
+ }
+
+ @override
+ bool get isNamed => true;
+
+ @override
+ bool get isUnnamed => false;
+
+ @override
+ int get namedArgumentCount => namedArguments.length;
+
+ @override
+ int get positionalArgumentCount => argumentCount - namedArgumentCount;
+
+ @override
+ List<String> getOrderedNamedArguments() {
+ if (!_orderedNamedArguments.isEmpty) return _orderedNamedArguments;
+
+ _orderedNamedArguments.addAll(namedArguments);
+ _orderedNamedArguments.sort((String first, String second) {
+ return first.compareTo(second);
+ });
+ return _orderedNamedArguments;
+ }
+
+ @override
+ String structureToString() {
+ return 'arity=$argumentCount, named=[${namedArguments.join(', ')}]';
+ }
+}
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index 11d9e09..d19b2c1 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -12,7 +12,27 @@
///
/// This is used by the [ClassWorld] to perform queries on subclass and subtype
/// relations.
-// TODO(johnniwinther): Use this for `ClassWorld.subtypesOf`.
+///
+/// For this class hierarchy:
+///
+/// class A {}
+/// class B extends A {}
+/// class C extends A {}
+/// class D extends B {}
+/// class E extends D {}
+///
+/// the [ClassHierarchyNode]s form this subclass tree:
+///
+/// Object
+/// |
+/// A
+/// / \
+/// B C
+/// |
+/// D
+/// |
+/// E
+///
class ClassHierarchyNode {
final ClassElement cls;
@@ -47,39 +67,240 @@
_directSubclasses = _directSubclasses.prepend(subclass);
}
+ /// Returns `true` if [other] is contained in the subtree of this node.
+ ///
+ /// This means that [other] is a subclass of [cls].
+ bool contains(ClassElement other) {
+ while (other != null) {
+ if (cls == other) return true;
+ if (cls.hierarchyDepth >= other.hierarchyDepth) return false;
+ other = other.superclass;
+ }
+ return false;
+ }
+
/// `true` if [cls] has been directly or indirectly instantiated.
bool get isInstantiated => isDirectlyInstantiated || isIndirectlyInstantiated;
/// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
- /// If [directlyInstantiated] is `true`, the iterable only returns the
- /// directly instantiated subclasses of [cls].
- Iterable<ClassElement> subclasses({bool directlyInstantiated: true}) {
+ ///
+ /// The directly instantiated, indirectly instantiated and uninstantiated
+ /// subclasses of [cls] are returned if [includeDirectlyInstantiated],
+ /// [includeIndirectlyInstantiated], and [includeUninstantiated] are `true`,
+ /// respectively. If [strict] is `true`, [cls] itself is _not_ returned.
+ Iterable<ClassElement> subclasses(
+ {bool includeDirectlyInstantiated: true,
+ bool includeIndirectlyInstantiated: true,
+ bool includeUninstantiated: true,
+ bool strict: false}) {
return new ClassHierarchyNodeIterable(
- this, directlyInstantiatedOnly: directlyInstantiated);
+ this,
+ includeRoot: !strict,
+ includeDirectlyInstantiated: includeDirectlyInstantiated,
+ includeIndirectlyInstantiated: includeIndirectlyInstantiated,
+ includeUninstantiated: includeUninstantiated);
}
- /// Returns an [Iterable] of the strict subclasses of [cls] _not_ including
- /// [cls] itself. If [directlyInstantiated] is `true`, the iterable only
- /// returns the directly instantiated subclasses of [cls].
- Iterable<ClassElement> strictSubclasses(
- {bool directlyInstantiated: true}) {
- return new ClassHierarchyNodeIterable(this,
- includeRoot: false, directlyInstantiatedOnly: directlyInstantiated);
+ void dump(StringBuffer sb, String indentation) {
+ sb.write('$indentation$cls:[');
+ if (_directSubclasses.isEmpty) {
+ sb.write(']');
+ } else {
+ sb.write('\n');
+ bool needsComma = false;
+ for (Link<ClassHierarchyNode> link = _directSubclasses;
+ !link.isEmpty;
+ link = link.tail) {
+ if (needsComma) {
+ sb.write(',\n');
+ }
+ link.head.dump(sb, '$indentation ');
+ needsComma = true;
+ }
+ sb.write('\n');
+ sb.write('$indentation]');
+ }
}
String toString() => cls.toString();
}
+/// Object holding the subclass and subtype relation for a single
+/// [ClassElement].
+///
+/// The subclass relation for a class `C` is modelled through a reference to
+/// the [ClassHierarchyNode] for `C` in the global [ClassHierarchyNode] tree
+/// computed in [World].
+///
+/// The subtype relation for a class `C` is modelled through a collection of
+/// disjoint [ClassHierarchyNode] subtrees. The subclasses of `C`, modelled
+/// through the aforementioned [ClassHierarchyNode] pointer, are extended with
+/// the subtypes that do not extend `C` through a list of additional
+/// [ClassHierarchyNode] nodes. This list is normalized to contain only the
+/// nodes for the topmost subtypes and is furthermore ordered in increasing
+/// hierarchy depth order.
+///
+/// For this class hierarchy:
+///
+/// class A {}
+/// class B extends A {}
+/// class C implements B {}
+/// class D implements A {}
+/// class E extends D {}
+/// class F implements D {}
+///
+/// the [ClassHierarchyNode] tree is
+///
+/// Object
+/// / | | \
+/// A C D F
+/// | |
+/// B E
+///
+/// and the [ClassSet] for `A` holds these [ClassHierarchyNode] nodes:
+///
+/// A -> [C, D, F]
+///
+/// The subtypes `B` and `E` are not directly modeled because they are implied
+/// by their subclass relation to `A` and `D`, repectively. This can be seen
+/// if we expand the subclass subtrees:
+///
+/// A -> [C, D, F]
+/// | |
+/// B E
+///
+class ClassSet {
+ final ClassHierarchyNode node;
+
+ List<ClassHierarchyNode> _directSubtypes;
+
+ ClassSet(this.node);
+
+ ClassElement get cls => node.cls;
+
+ /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
+ ///
+ /// The directly instantiated, indirectly instantiated and uninstantiated
+ /// subclasses of [cls] are returned if [includeDirectlyInstantiated],
+ /// [includeIndirectlyInstantiated], and [includeUninstantiated] are `true`,
+ /// respectively. If [strict] is `true`, [cls] itself is _not_ returned.
+ Iterable<ClassElement> subclasses(
+ {bool includeDirectlyInstantiated: true,
+ bool includeIndirectlyInstantiated: true,
+ bool includeUninstantiated: true,
+ bool strict: false}) {
+ return node.subclasses(
+ strict: strict,
+ includeDirectlyInstantiated: includeDirectlyInstantiated,
+ includeIndirectlyInstantiated: includeIndirectlyInstantiated,
+ includeUninstantiated: includeUninstantiated);
+ }
+
+ /// Returns an [Iterable] of the subtypes of [cls] possibly including [cls].
+ ///
+ /// The directly instantiated, indirectly instantiated and uninstantiated
+ /// subtypes of [cls] are returned if [includeDirectlyInstantiated],
+ /// [includeIndirectlyInstantiated], and [includeUninstantiated] are `true`,
+ /// respectively. If [strict] is `true`, [cls] itself is _not_ returned.
+ Iterable<ClassElement> subtypes(
+ {bool includeDirectlyInstantiated: true,
+ bool includeIndirectlyInstantiated: true,
+ bool includeUninstantiated: true,
+ bool strict: false}) {
+ if (_directSubtypes == null) {
+ return node.subclasses(
+ strict: strict,
+ includeDirectlyInstantiated: includeDirectlyInstantiated,
+ includeIndirectlyInstantiated: includeIndirectlyInstantiated,
+ includeUninstantiated: includeUninstantiated);
+ }
+ return new SubtypesIterable.SubtypesIterator(this,
+ includeRoot: !strict,
+ includeDirectlyInstantiated: includeDirectlyInstantiated,
+ includeIndirectlyInstantiated: includeIndirectlyInstantiated,
+ includeUninstantiated: includeUninstantiated);
+ }
+
+ /// Adds [subtype] as a subtype of [cls].
+ void addSubtype(ClassHierarchyNode subtype) {
+ if (node.contains(subtype.cls)) {
+ return;
+ }
+ if (_directSubtypes == null) {
+ _directSubtypes = <ClassHierarchyNode>[subtype];
+ } else {
+ int hierarchyDepth = subtype.cls.hierarchyDepth;
+ List<ClassHierarchyNode> newSubtypes = <ClassHierarchyNode>[];
+ bool added = false;
+ for (ClassHierarchyNode otherSubtype in _directSubtypes) {
+ int otherHierarchyDepth = otherSubtype.cls.hierarchyDepth;
+ if (hierarchyDepth == otherHierarchyDepth) {
+ if (subtype == otherSubtype) {
+ return;
+ } else {
+ // [otherSubtype] is unrelated to [subtype].
+ newSubtypes.add(otherSubtype);
+ }
+ } else if (hierarchyDepth > otherSubtype.cls.hierarchyDepth) {
+ // [otherSubtype] could be a superclass of [subtype].
+ if (otherSubtype.contains(subtype.cls)) {
+ // [subtype] is already in this set.
+ return;
+ } else {
+ // [otherSubtype] is unrelated to [subtype].
+ newSubtypes.add(otherSubtype);
+ }
+ } else {
+ if (!added) {
+ // Insert [subtype] before other subtypes of higher hierarchy depth.
+ newSubtypes.add(subtype);
+ added = true;
+ }
+ // [subtype] could be a superclass of [otherSubtype].
+ if (subtype.contains(otherSubtype.cls)) {
+ // Replace [otherSubtype].
+ } else {
+ newSubtypes.add(otherSubtype);
+ }
+ }
+ }
+ if (!added) {
+ newSubtypes.add(subtype);
+ }
+ _directSubtypes = newSubtypes;
+ }
+ }
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('[\n');
+ node.dump(sb, ' ');
+ sb.write('\n');
+ if (_directSubtypes != null) {
+ for (ClassHierarchyNode node in _directSubtypes) {
+ node.dump(sb, ' ');
+ sb.write('\n');
+ }
+ }
+ sb.write(']');
+ return sb.toString();
+ }
+}
+
/// Iterable for subclasses of a [ClassHierarchyNode].
class ClassHierarchyNodeIterable extends IterableBase<ClassElement> {
final ClassHierarchyNode root;
final bool includeRoot;
- final bool directlyInstantiatedOnly;
+ final bool includeDirectlyInstantiated;
+ final bool includeIndirectlyInstantiated;
+ final bool includeUninstantiated;
ClassHierarchyNodeIterable(
this.root,
{this.includeRoot: true,
- this.directlyInstantiatedOnly: false}) {
+ this.includeDirectlyInstantiated: true,
+ this.includeIndirectlyInstantiated: true,
+ this.includeUninstantiated: true}) {
if (root == null) throw new StateError("No root for iterable.");
}
@@ -112,7 +333,13 @@
bool get includeRoot => iterable.includeRoot;
- bool get directlyInstantiatedOnly => iterable.directlyInstantiatedOnly;
+ bool get includeDirectlyInstantiated => iterable.includeDirectlyInstantiated;
+
+ bool get includeIndirectlyInstantiated {
+ return iterable.includeIndirectlyInstantiated;
+ }
+
+ bool get includeUninstantiated => iterable.includeUninstantiated;
@override
ClassElement get current {
@@ -143,6 +370,11 @@
}
currentNode = stack.head;
stack = stack.tail;
+ if (!includeUninstantiated && !currentNode.isInstantiated) {
+ // We're only iterating instantiated classes so there is no use in
+ // visiting the current node and its subtree.
+ continue;
+ }
for (Link<ClassHierarchyNode> link = currentNode._directSubclasses;
!link.isEmpty;
link = link.tail) {
@@ -157,9 +389,90 @@
/// Returns `true` if the class of [node] is a valid result for this iterator.
bool _isValid(ClassHierarchyNode node) {
if (!includeRoot && node == root) return false;
- if (directlyInstantiatedOnly && !node.isDirectlyInstantiated) return false;
- return true;
+ if (includeDirectlyInstantiated && node.isDirectlyInstantiated) {
+ return true;
+ }
+ if (includeIndirectlyInstantiated && node.isIndirectlyInstantiated) {
+ return true;
+ }
+ if (includeUninstantiated && !node.isInstantiated) {
+ return true;
+ }
+ return false;
}
}
+/// Iterable for the subtypes in a [ClassSet].
+class SubtypesIterable extends IterableBase<ClassElement> {
+ final ClassSet subtypeSet;
+ final bool includeRoot;
+ final bool includeDirectlyInstantiated;
+ final bool includeIndirectlyInstantiated;
+ final bool includeUninstantiated;
+ SubtypesIterable.SubtypesIterator(
+ this.subtypeSet,
+ {this.includeRoot: true,
+ this.includeDirectlyInstantiated: true,
+ this.includeIndirectlyInstantiated: true,
+ this.includeUninstantiated: true});
+
+ @override
+ Iterator<ClassElement> get iterator => new SubtypesIterator(this);
+}
+
+/// Iterator for the subtypes in a [ClassSet].
+class SubtypesIterator extends Iterator<ClassElement> {
+ final SubtypesIterable iterable;
+ Iterator<ClassElement> elements;
+ Iterator<ClassHierarchyNode> hierarchyNodes;
+
+ SubtypesIterator(this.iterable);
+
+ bool get includeRoot => iterable.includeRoot;
+
+ bool get includeDirectlyInstantiated => iterable.includeDirectlyInstantiated;
+
+ bool get includeIndirectlyInstantiated {
+ return iterable.includeIndirectlyInstantiated;
+ }
+
+ bool get includeUninstantiated => iterable.includeUninstantiated;
+
+ @override
+ ClassElement get current {
+ if (elements != null) {
+ return elements.current;
+ }
+ return null;
+ }
+
+ @override
+ bool moveNext() {
+ if (elements == null && hierarchyNodes == null) {
+ // Initial state. Iterate through subclasses.
+ elements = iterable.subtypeSet.node.subclasses(
+ strict: !includeRoot,
+ includeDirectlyInstantiated: includeDirectlyInstantiated,
+ includeIndirectlyInstantiated: includeIndirectlyInstantiated,
+ includeUninstantiated: includeUninstantiated).iterator;
+ }
+ if (elements != null && elements.moveNext()) {
+ return true;
+ }
+ if (hierarchyNodes == null) {
+ // Start iterating through subtypes.
+ hierarchyNodes = iterable.subtypeSet._directSubtypes.iterator;
+ }
+ while (hierarchyNodes.moveNext()) {
+ elements = hierarchyNodes.current.subclasses(
+ includeDirectlyInstantiated: includeDirectlyInstantiated,
+ includeIndirectlyInstantiated: includeIndirectlyInstantiated,
+ includeUninstantiated: includeUninstantiated).iterator;
+ if (elements.moveNext()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
new file mode 100644
index 0000000..94fa6b4
--- /dev/null
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -0,0 +1,271 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of universe;
+
+class SelectorKind {
+ final String name;
+ final int hashCode;
+ const SelectorKind(this.name, this.hashCode);
+
+ static const SelectorKind GETTER = const SelectorKind('getter', 0);
+ static const SelectorKind SETTER = const SelectorKind('setter', 1);
+ static const SelectorKind CALL = const SelectorKind('call', 2);
+ static const SelectorKind OPERATOR = const SelectorKind('operator', 3);
+ static const SelectorKind INDEX = const SelectorKind('index', 4);
+
+ String toString() => name;
+}
+
+class Selector {
+ final SelectorKind kind;
+ final Name memberName;
+ final CallStructure callStructure;
+
+ final int hashCode;
+
+ int get argumentCount => callStructure.argumentCount;
+ int get namedArgumentCount => callStructure.namedArgumentCount;
+ int get positionalArgumentCount => callStructure.positionalArgumentCount;
+ List<String> get namedArguments => callStructure.namedArguments;
+
+ String get name => memberName.text;
+
+ LibraryElement get library => memberName.library;
+
+ static const Name INDEX_NAME = const PublicName("[]");
+ static const Name INDEX_SET_NAME = const PublicName("[]=");
+ static const Name CALL_NAME = Names.call;
+
+ Selector.internal(this.kind,
+ this.memberName,
+ this.callStructure,
+ this.hashCode) {
+ assert(kind == SelectorKind.INDEX ||
+ (memberName != INDEX_NAME && memberName != INDEX_SET_NAME));
+ assert(kind == SelectorKind.OPERATOR ||
+ kind == SelectorKind.INDEX ||
+ !Elements.isOperatorName(memberName.text) ||
+ identical(memberName.text, '??'));
+ assert(kind == SelectorKind.CALL ||
+ kind == SelectorKind.GETTER ||
+ kind == SelectorKind.SETTER ||
+ Elements.isOperatorName(memberName.text) ||
+ identical(memberName.text, '??'));
+ }
+
+ // TODO(johnniwinther): Extract caching.
+ static Map<int, List<Selector>> canonicalizedValues =
+ new Map<int, List<Selector>>();
+
+ factory Selector(SelectorKind kind,
+ Name name,
+ CallStructure callStructure) {
+ // TODO(johnniwinther): Maybe use equality instead of implicit hashing.
+ int hashCode = computeHashCode(kind, name, callStructure);
+ List<Selector> list = canonicalizedValues.putIfAbsent(hashCode,
+ () => <Selector>[]);
+ for (int i = 0; i < list.length; i++) {
+ Selector existing = list[i];
+ if (existing.match(kind, name, callStructure)) {
+ assert(existing.hashCode == hashCode);
+ return existing;
+ }
+ }
+ Selector result = new Selector.internal(
+ kind, name, callStructure, hashCode);
+ list.add(result);
+ return result;
+ }
+
+ factory Selector.fromElement(Element element) {
+ Name name = new Name(element.name, element.library);
+ if (element.isFunction) {
+ if (name == INDEX_NAME) {
+ return new Selector.index();
+ } else if (name == INDEX_SET_NAME) {
+ return new Selector.indexSet();
+ }
+ FunctionSignature signature =
+ element.asFunctionElement().functionSignature;
+ int arity = signature.parameterCount;
+ List<String> namedArguments = null;
+ if (signature.optionalParametersAreNamed) {
+ namedArguments =
+ signature.orderedOptionalParameters.map((e) => e.name).toList();
+ }
+ if (element.isOperator) {
+ // Operators cannot have named arguments, however, that doesn't prevent
+ // a user from declaring such an operator.
+ return new Selector(
+ SelectorKind.OPERATOR,
+ name,
+ new CallStructure(arity, namedArguments));
+ } else {
+ return new Selector.call(
+ name, new CallStructure(arity, namedArguments));
+ }
+ } else if (element.isSetter) {
+ return new Selector.setter(name);
+ } else if (element.isGetter) {
+ return new Selector.getter(name);
+ } else if (element.isField) {
+ return new Selector.getter(name);
+ } else if (element.isConstructor) {
+ return new Selector.callConstructor(name);
+ } else {
+ throw new SpannableAssertionFailure(
+ element, "Can't get selector from $element");
+ }
+ }
+
+ factory Selector.getter(Name name)
+ => new Selector(SelectorKind.GETTER,
+ name.getter,
+ CallStructure.NO_ARGS);
+
+ factory Selector.setter(Name name)
+ => new Selector(SelectorKind.SETTER,
+ name.setter,
+ CallStructure.ONE_ARG);
+
+ factory Selector.unaryOperator(String name) => new Selector(
+ SelectorKind.OPERATOR,
+ new PublicName(Elements.constructOperatorName(name, true)),
+ CallStructure.NO_ARGS);
+
+ factory Selector.binaryOperator(String name) => new Selector(
+ SelectorKind.OPERATOR,
+ new PublicName(Elements.constructOperatorName(name, false)),
+ CallStructure.ONE_ARG);
+
+ factory Selector.index()
+ => new Selector(SelectorKind.INDEX, INDEX_NAME,
+ CallStructure.ONE_ARG);
+
+ factory Selector.indexSet()
+ => new Selector(SelectorKind.INDEX, INDEX_SET_NAME,
+ CallStructure.TWO_ARGS);
+
+ factory Selector.call(Name name, CallStructure callStructure)
+ => new Selector(SelectorKind.CALL, name, callStructure);
+
+ factory Selector.callClosure(int arity, [List<String> namedArguments])
+ => new Selector(SelectorKind.CALL, CALL_NAME,
+ new CallStructure(arity, namedArguments));
+
+ factory Selector.callClosureFrom(Selector selector)
+ => new Selector(SelectorKind.CALL, CALL_NAME, selector.callStructure);
+
+ factory Selector.callConstructor(Name name,
+ [int arity = 0,
+ List<String> namedArguments])
+ => new Selector(SelectorKind.CALL, name,
+ new CallStructure(arity, namedArguments));
+
+ factory Selector.callDefaultConstructor()
+ => new Selector(
+ SelectorKind.CALL,
+ const PublicName(''),
+ CallStructure.NO_ARGS);
+
+ bool get isGetter => kind == SelectorKind.GETTER;
+ bool get isSetter => kind == SelectorKind.SETTER;
+ bool get isCall => kind == SelectorKind.CALL;
+ bool get isClosureCall => isCall && memberName == CALL_NAME;
+
+ bool get isIndex => kind == SelectorKind.INDEX && argumentCount == 1;
+ bool get isIndexSet => kind == SelectorKind.INDEX && argumentCount == 2;
+
+ bool get isOperator => kind == SelectorKind.OPERATOR;
+ bool get isUnaryOperator => isOperator && argumentCount == 0;
+
+ /** Check whether this is a call to 'assert'. */
+ bool get isAssert => isCall && identical(name, "assert");
+
+ /**
+ * The member name for invocation mirrors created from this selector.
+ */
+ String get invocationMirrorMemberName =>
+ isSetter ? '$name=' : name;
+
+ int get invocationMirrorKind {
+ const int METHOD = 0;
+ const int GETTER = 1;
+ const int SETTER = 2;
+ int kind = METHOD;
+ if (isGetter) {
+ kind = GETTER;
+ } else if (isSetter) {
+ kind = SETTER;
+ }
+ return kind;
+ }
+
+ bool appliesUnnamed(Element element, World world) {
+ assert(sameNameHack(element, world));
+ return appliesUntyped(element, world);
+ }
+
+ bool appliesUntyped(Element element, World world) {
+ assert(sameNameHack(element, world));
+ if (Elements.isUnresolved(element)) return false;
+ if (memberName.isPrivate && memberName.library != element.library) {
+ // TODO(johnniwinther): Maybe this should be
+ // `memberName != element.memberName`.
+ return false;
+ }
+ if (world.isForeign(element)) return true;
+ if (element.isSetter) return isSetter;
+ if (element.isGetter) return isGetter || isCall;
+ if (element.isField) {
+ return isSetter
+ ? !element.isFinal && !element.isConst
+ : isGetter || isCall;
+ }
+ if (isGetter) return true;
+ if (isSetter) return false;
+ return signatureApplies(element);
+ }
+
+ bool signatureApplies(FunctionElement function) {
+ if (Elements.isUnresolved(function)) return false;
+ return callStructure.signatureApplies(function.functionSignature);
+ }
+
+ bool sameNameHack(Element element, World world) {
+ // TODO(ngeoffray): Remove workaround checks.
+ return element.isConstructor ||
+ name == element.name ||
+ name == 'assert' && world.isAssertMethod(element);
+ }
+
+ bool applies(Element element, World world) {
+ if (!sameNameHack(element, world)) return false;
+ return appliesUnnamed(element, world);
+ }
+
+ bool match(SelectorKind kind,
+ Name memberName,
+ CallStructure callStructure) {
+ return this.kind == kind
+ && this.memberName == memberName
+ && this.callStructure.match(callStructure);
+ }
+
+ static int computeHashCode(SelectorKind kind,
+ Name name,
+ CallStructure callStructure) {
+ // Add bits from name and kind.
+ int hash = Hashing.mixHashCodeBits(name.hashCode, kind.hashCode);
+ // Add bits from the call structure.
+ return Hashing.mixHashCodeBits(hash, callStructure.hashCode);
+ }
+
+ String toString() {
+ return 'Selector($kind, $name, ${callStructure.structureToString()})';
+ }
+
+ Selector toCallSelector() => new Selector.callClosureFrom(this);
+}
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index 4530400..5268be3 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -25,7 +25,9 @@
ClassWorld,
World;
+part 'call_structure.dart';
part 'function_set.dart';
+part 'selector.dart';
part 'side_effects.dart';
class UniverseSelector {
@@ -371,546 +373,3 @@
}));
}
}
-
-class SelectorKind {
- final String name;
- final int hashCode;
- const SelectorKind(this.name, this.hashCode);
-
- static const SelectorKind GETTER = const SelectorKind('getter', 0);
- static const SelectorKind SETTER = const SelectorKind('setter', 1);
- static const SelectorKind CALL = const SelectorKind('call', 2);
- static const SelectorKind OPERATOR = const SelectorKind('operator', 3);
- static const SelectorKind INDEX = const SelectorKind('index', 4);
-
- String toString() => name;
-}
-
-/// The structure of the arguments at a call-site.
-// TODO(johnniwinther): Should these be cached?
-// TODO(johnniwinther): Should isGetter/isSetter be part of the call structure
-// instead of the selector?
-class CallStructure {
- static const CallStructure NO_ARGS = const CallStructure.unnamed(0);
- static const CallStructure ONE_ARG = const CallStructure.unnamed(1);
- static const CallStructure TWO_ARGS = const CallStructure.unnamed(2);
-
- /// The numbers of arguments of the call. Includes named arguments.
- final int argumentCount;
-
- /// The number of named arguments of the call.
- int get namedArgumentCount => 0;
-
- /// The number of positional argument of the call.
- int get positionalArgumentCount => argumentCount;
-
- const CallStructure.unnamed(this.argumentCount);
-
- factory CallStructure(int argumentCount, [List<String> namedArguments]) {
- if (namedArguments == null || namedArguments.isEmpty) {
- return new CallStructure.unnamed(argumentCount);
- }
- return new NamedCallStructure(argumentCount, namedArguments);
- }
-
- /// `true` if this call has named arguments.
- bool get isNamed => false;
-
- /// `true` if this call has no named arguments.
- bool get isUnnamed => true;
-
- /// The names of the named arguments in call-site order.
- List<String> get namedArguments => const <String>[];
-
- /// The names of the named arguments in canonicalized order.
- List<String> getOrderedNamedArguments() => const <String>[];
-
- /// A description of the argument structure.
- String structureToString() => 'arity=$argumentCount';
-
- String toString() => 'CallStructure(${structureToString()})';
-
- Selector get callSelector {
- return new Selector(SelectorKind.CALL, Selector.CALL_NAME, this);
- }
-
- bool match(CallStructure other) {
- if (identical(this, other)) return true;
- return this.argumentCount == other.argumentCount
- && this.namedArgumentCount == other.namedArgumentCount
- && sameNames(this.namedArguments, other.namedArguments);
- }
-
- // TODO(johnniwinther): Cache hash code?
- int get hashCode {
- return Hashing.listHash(namedArguments,
- Hashing.objectHash(argumentCount, namedArguments.length));
- }
-
- bool operator ==(other) {
- if (other is! CallStructure) return false;
- return match(other);
- }
-
- bool signatureApplies(FunctionSignature parameters) {
- if (argumentCount > parameters.parameterCount) return false;
- int requiredParameterCount = parameters.requiredParameterCount;
- int optionalParameterCount = parameters.optionalParameterCount;
- if (positionalArgumentCount < requiredParameterCount) return false;
-
- if (!parameters.optionalParametersAreNamed) {
- // We have already checked that the number of arguments are
- // not greater than the number of parameters. Therefore the
- // number of positional arguments are not greater than the
- // number of parameters.
- assert(positionalArgumentCount <= parameters.parameterCount);
- return namedArguments.isEmpty;
- } else {
- if (positionalArgumentCount > requiredParameterCount) return false;
- assert(positionalArgumentCount == requiredParameterCount);
- if (namedArgumentCount > optionalParameterCount) return false;
- Set<String> nameSet = new Set<String>();
- parameters.optionalParameters.forEach((Element element) {
- nameSet.add(element.name);
- });
- for (String name in namedArguments) {
- if (!nameSet.contains(name)) return false;
- // TODO(5213): By removing from the set we are checking
- // that we are not passing the name twice. We should have this
- // check in the resolver also.
- nameSet.remove(name);
- }
- return true;
- }
- }
-
- /**
- * Returns a `List` with the evaluated arguments in the normalized order.
- *
- * [compileDefaultValue] is a function that returns a compiled constant
- * of an optional argument that is not in [compiledArguments].
- *
- * Precondition: `this.applies(element, world)`.
- *
- * Invariant: [element] must be the implementation element.
- */
- /*<T>*/ List/*<T>*/ makeArgumentsList(
- Link<Node> arguments,
- FunctionElement element,
- /*T*/ compileArgument(Node argument),
- /*T*/ compileDefaultValue(ParameterElement element)) {
- assert(invariant(element, element.isImplementation));
- List/*<T>*/ result = new List();
-
- FunctionSignature parameters = element.functionSignature;
- parameters.forEachRequiredParameter((ParameterElement element) {
- result.add(compileArgument(arguments.head));
- arguments = arguments.tail;
- });
-
- if (!parameters.optionalParametersAreNamed) {
- parameters.forEachOptionalParameter((ParameterElement element) {
- if (!arguments.isEmpty) {
- result.add(compileArgument(arguments.head));
- arguments = arguments.tail;
- } else {
- result.add(compileDefaultValue(element));
- }
- });
- } else {
- // Visit named arguments and add them into a temporary list.
- List compiledNamedArguments = [];
- for (; !arguments.isEmpty; arguments = arguments.tail) {
- NamedArgument namedArgument = arguments.head;
- compiledNamedArguments.add(compileArgument(namedArgument.expression));
- }
- // Iterate over the optional parameters of the signature, and try to
- // find them in [compiledNamedArguments]. If found, we use the
- // value in the temporary list, otherwise the default value.
- parameters.orderedOptionalParameters.forEach((ParameterElement element) {
- int foundIndex = namedArguments.indexOf(element.name);
- if (foundIndex != -1) {
- result.add(compiledNamedArguments[foundIndex]);
- } else {
- result.add(compileDefaultValue(element));
- }
- });
- }
- return result;
- }
-
- /**
- * Fills [list] with the arguments in the order expected by
- * [callee], and where [caller] is a synthesized element
- *
- * [compileArgument] is a function that returns a compiled version
- * of a parameter of [callee].
- *
- * [compileConstant] is a function that returns a compiled constant
- * of an optional argument that is not in the parameters of [callee].
- *
- * Returns [:true:] if the signature of the [caller] matches the
- * signature of the [callee], [:false:] otherwise.
- */
- static /*<T>*/ bool addForwardingElementArgumentsToList(
- ConstructorElement caller,
- List/*<T>*/ list,
- ConstructorElement callee,
- /*T*/ compileArgument(ParameterElement element),
- /*T*/ compileConstant(ParameterElement element)) {
- assert(invariant(caller, !callee.isErroneous,
- message: "Cannot compute arguments to erroneous constructor: "
- "$caller calling $callee."));
-
- FunctionSignature signature = caller.functionSignature;
- Map<Node, ParameterElement> mapping = <Node, ParameterElement>{};
-
- // TODO(ngeoffray): This is a hack that fakes up AST nodes, so
- // that we can call [addArgumentsToList].
- Link<Node> computeCallNodesFromParameters() {
- LinkBuilder<Node> builder = new LinkBuilder<Node>();
- signature.forEachRequiredParameter((ParameterElement element) {
- Node node = element.node;
- mapping[node] = element;
- builder.addLast(node);
- });
- if (signature.optionalParametersAreNamed) {
- signature.forEachOptionalParameter((ParameterElement element) {
- mapping[element.initializer] = element;
- builder.addLast(new NamedArgument(null, null, element.initializer));
- });
- } else {
- signature.forEachOptionalParameter((ParameterElement element) {
- Node node = element.node;
- mapping[node] = element;
- builder.addLast(node);
- });
- }
- return builder.toLink();
- }
-
- /*T*/ internalCompileArgument(Node node) {
- return compileArgument(mapping[node]);
- }
-
- Link<Node> nodes = computeCallNodesFromParameters();
-
- // Synthesize a structure for the call.
- // TODO(ngeoffray): Should the resolver do it instead?
- List<String> namedParameters;
- if (signature.optionalParametersAreNamed) {
- namedParameters =
- signature.optionalParameters.map((e) => e.name).toList();
- }
- CallStructure callStructure =
- new CallStructure(signature.parameterCount, namedParameters);
- if (!callStructure.signatureApplies(signature)) {
- return false;
- }
- list.addAll(callStructure.makeArgumentsList(
- nodes,
- callee,
- internalCompileArgument,
- compileConstant));
-
- return true;
- }
-
- static bool sameNames(List<String> first, List<String> second) {
- for (int i = 0; i < first.length; i++) {
- if (first[i] != second[i]) return false;
- }
- return true;
- }
-}
-
-///
-class NamedCallStructure extends CallStructure {
- final List<String> namedArguments;
- final List<String> _orderedNamedArguments = <String>[];
-
- NamedCallStructure(int argumentCount, this.namedArguments)
- : super.unnamed(argumentCount) {
- assert(namedArguments.isNotEmpty);
- }
-
- @override
- bool get isNamed => true;
-
- @override
- bool get isUnnamed => false;
-
- @override
- int get namedArgumentCount => namedArguments.length;
-
- @override
- int get positionalArgumentCount => argumentCount - namedArgumentCount;
-
- @override
- List<String> getOrderedNamedArguments() {
- if (!_orderedNamedArguments.isEmpty) return _orderedNamedArguments;
-
- _orderedNamedArguments.addAll(namedArguments);
- _orderedNamedArguments.sort((String first, String second) {
- return first.compareTo(second);
- });
- return _orderedNamedArguments;
- }
-
- @override
- String structureToString() {
- return 'arity=$argumentCount, named=[${namedArguments.join(', ')}]';
- }
-}
-
-class Selector {
- final SelectorKind kind;
- final Name memberName;
- final CallStructure callStructure;
-
- final int hashCode;
-
- int get argumentCount => callStructure.argumentCount;
- int get namedArgumentCount => callStructure.namedArgumentCount;
- int get positionalArgumentCount => callStructure.positionalArgumentCount;
- List<String> get namedArguments => callStructure.namedArguments;
-
- String get name => memberName.text;
-
- LibraryElement get library => memberName.library;
-
- static const Name INDEX_NAME = const PublicName("[]");
- static const Name INDEX_SET_NAME = const PublicName("[]=");
- static const Name CALL_NAME = Names.call;
-
- Selector.internal(this.kind,
- this.memberName,
- this.callStructure,
- this.hashCode) {
- assert(kind == SelectorKind.INDEX ||
- (memberName != INDEX_NAME && memberName != INDEX_SET_NAME));
- assert(kind == SelectorKind.OPERATOR ||
- kind == SelectorKind.INDEX ||
- !Elements.isOperatorName(memberName.text) ||
- identical(memberName.text, '??'));
- assert(kind == SelectorKind.CALL ||
- kind == SelectorKind.GETTER ||
- kind == SelectorKind.SETTER ||
- Elements.isOperatorName(memberName.text) ||
- identical(memberName.text, '??'));
- }
-
- // TODO(johnniwinther): Extract caching.
- static Map<int, List<Selector>> canonicalizedValues =
- new Map<int, List<Selector>>();
-
- factory Selector(SelectorKind kind,
- Name name,
- CallStructure callStructure) {
- // TODO(johnniwinther): Maybe use equality instead of implicit hashing.
- int hashCode = computeHashCode(kind, name, callStructure);
- List<Selector> list = canonicalizedValues.putIfAbsent(hashCode,
- () => <Selector>[]);
- for (int i = 0; i < list.length; i++) {
- Selector existing = list[i];
- if (existing.match(kind, name, callStructure)) {
- assert(existing.hashCode == hashCode);
- return existing;
- }
- }
- Selector result = new Selector.internal(
- kind, name, callStructure, hashCode);
- list.add(result);
- return result;
- }
-
- factory Selector.fromElement(Element element) {
- Name name = new Name(element.name, element.library);
- if (element.isFunction) {
- if (name == INDEX_NAME) {
- return new Selector.index();
- } else if (name == INDEX_SET_NAME) {
- return new Selector.indexSet();
- }
- FunctionSignature signature =
- element.asFunctionElement().functionSignature;
- int arity = signature.parameterCount;
- List<String> namedArguments = null;
- if (signature.optionalParametersAreNamed) {
- namedArguments =
- signature.orderedOptionalParameters.map((e) => e.name).toList();
- }
- if (element.isOperator) {
- // Operators cannot have named arguments, however, that doesn't prevent
- // a user from declaring such an operator.
- return new Selector(
- SelectorKind.OPERATOR,
- name,
- new CallStructure(arity, namedArguments));
- } else {
- return new Selector.call(
- name, new CallStructure(arity, namedArguments));
- }
- } else if (element.isSetter) {
- return new Selector.setter(name);
- } else if (element.isGetter) {
- return new Selector.getter(name);
- } else if (element.isField) {
- return new Selector.getter(name);
- } else if (element.isConstructor) {
- return new Selector.callConstructor(name);
- } else {
- throw new SpannableAssertionFailure(
- element, "Can't get selector from $element");
- }
- }
-
- factory Selector.getter(Name name)
- => new Selector(SelectorKind.GETTER,
- name.getter,
- CallStructure.NO_ARGS);
-
- factory Selector.setter(Name name)
- => new Selector(SelectorKind.SETTER,
- name.setter,
- CallStructure.ONE_ARG);
-
- factory Selector.unaryOperator(String name) => new Selector(
- SelectorKind.OPERATOR,
- new PublicName(Elements.constructOperatorName(name, true)),
- CallStructure.NO_ARGS);
-
- factory Selector.binaryOperator(String name) => new Selector(
- SelectorKind.OPERATOR,
- new PublicName(Elements.constructOperatorName(name, false)),
- CallStructure.ONE_ARG);
-
- factory Selector.index()
- => new Selector(SelectorKind.INDEX, INDEX_NAME,
- CallStructure.ONE_ARG);
-
- factory Selector.indexSet()
- => new Selector(SelectorKind.INDEX, INDEX_SET_NAME,
- CallStructure.TWO_ARGS);
-
- factory Selector.call(Name name, CallStructure callStructure)
- => new Selector(SelectorKind.CALL, name, callStructure);
-
- factory Selector.callClosure(int arity, [List<String> namedArguments])
- => new Selector(SelectorKind.CALL, CALL_NAME,
- new CallStructure(arity, namedArguments));
-
- factory Selector.callClosureFrom(Selector selector)
- => new Selector(SelectorKind.CALL, CALL_NAME, selector.callStructure);
-
- factory Selector.callConstructor(Name name,
- [int arity = 0,
- List<String> namedArguments])
- => new Selector(SelectorKind.CALL, name,
- new CallStructure(arity, namedArguments));
-
- factory Selector.callDefaultConstructor()
- => new Selector(
- SelectorKind.CALL,
- const PublicName(''),
- CallStructure.NO_ARGS);
-
- bool get isGetter => kind == SelectorKind.GETTER;
- bool get isSetter => kind == SelectorKind.SETTER;
- bool get isCall => kind == SelectorKind.CALL;
- bool get isClosureCall => isCall && memberName == CALL_NAME;
-
- bool get isIndex => kind == SelectorKind.INDEX && argumentCount == 1;
- bool get isIndexSet => kind == SelectorKind.INDEX && argumentCount == 2;
-
- bool get isOperator => kind == SelectorKind.OPERATOR;
- bool get isUnaryOperator => isOperator && argumentCount == 0;
-
- /** Check whether this is a call to 'assert'. */
- bool get isAssert => isCall && identical(name, "assert");
-
- /**
- * The member name for invocation mirrors created from this selector.
- */
- String get invocationMirrorMemberName =>
- isSetter ? '$name=' : name;
-
- int get invocationMirrorKind {
- const int METHOD = 0;
- const int GETTER = 1;
- const int SETTER = 2;
- int kind = METHOD;
- if (isGetter) {
- kind = GETTER;
- } else if (isSetter) {
- kind = SETTER;
- }
- return kind;
- }
-
- bool appliesUnnamed(Element element, World world) {
- assert(sameNameHack(element, world));
- return appliesUntyped(element, world);
- }
-
- bool appliesUntyped(Element element, World world) {
- assert(sameNameHack(element, world));
- if (Elements.isUnresolved(element)) return false;
- if (memberName.isPrivate && memberName.library != element.library) {
- // TODO(johnniwinther): Maybe this should be
- // `memberName != element.memberName`.
- return false;
- }
- if (world.isForeign(element)) return true;
- if (element.isSetter) return isSetter;
- if (element.isGetter) return isGetter || isCall;
- if (element.isField) {
- return isSetter
- ? !element.isFinal && !element.isConst
- : isGetter || isCall;
- }
- if (isGetter) return true;
- if (isSetter) return false;
- return signatureApplies(element);
- }
-
- bool signatureApplies(FunctionElement function) {
- if (Elements.isUnresolved(function)) return false;
- return callStructure.signatureApplies(function.functionSignature);
- }
-
- bool sameNameHack(Element element, World world) {
- // TODO(ngeoffray): Remove workaround checks.
- return element.isConstructor ||
- name == element.name ||
- name == 'assert' && world.isAssertMethod(element);
- }
-
- bool applies(Element element, World world) {
- if (!sameNameHack(element, world)) return false;
- return appliesUnnamed(element, world);
- }
-
- bool match(SelectorKind kind,
- Name memberName,
- CallStructure callStructure) {
- return this.kind == kind
- && this.memberName == memberName
- && this.callStructure.match(callStructure);
- }
-
- static int computeHashCode(SelectorKind kind,
- Name name,
- CallStructure callStructure) {
- // Add bits from name and kind.
- int hash = Hashing.mixHashCodeBits(name.hashCode, kind.hashCode);
- // Add bits from the call structure.
- return Hashing.mixHashCodeBits(hash, callStructure.hashCode);
- }
-
- String toString() {
- return 'Selector($kind, $name, ${callStructure.structureToString()})';
- }
-
- Selector toCallSelector() => new Selector.callClosureFrom(this);
-}
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index bdb0acf..d2e8648 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -144,6 +144,7 @@
..asFor()
..asFunctionDeclaration()
..asIf()
+ ..asImport()
..asLabeledStatement()
..asLibraryDependency()
..asLibraryName()
@@ -226,7 +227,7 @@
}
useJsBackend(js_backend.JavaScriptBackend backend) {
- backend.assembleCode(null);
+ backend.getGeneratedCode(null);
}
useConcreteTypesInferrer(concrete_types_inferrer.ConcreteTypesInferrer c) {
@@ -270,7 +271,9 @@
sourceFileProvider.getSourceFile(null);
world.hasAnyUserDefinedGetter(null, null);
world.subclassesOf(null);
- world.classHierarchyNode(null);
+ world.getClassHierarchyNode(null);
+ world.getClassSet(null);
+ world.haveAnyCommonSubtypes(null, null);
typeGraphInferrer.getCallersOf(null);
dart_types.Types.sorted(null);
new dart_types.Types(compiler).copy(compiler);
diff --git a/pkg/compiler/lib/src/util/link.dart b/pkg/compiler/lib/src/util/link.dart
index d09639c..3a9c133 100644
--- a/pkg/compiler/lib/src/util/link.dart
+++ b/pkg/compiler/lib/src/util/link.dart
@@ -122,19 +122,31 @@
Link copyWithout(e) => this;
}
+/// Builder object for creating linked lists using [Link] or fixed-length [List]
+/// objects.
abstract class LinkBuilder<T> {
factory LinkBuilder() = LinkBuilderImplementation;
- /**
- * Prepends all elements added to the builder to [tail]. The resulting list is
- * returned and the builder is cleared.
- */
+ /// Prepends all elements added to the builder to [tail]. The resulting list
+ /// is returned and the builder is cleared.
Link<T> toLink([Link<T> tail = const Link()]);
+ /// Creates a new fixed length containing all added elements. The
+ /// resulting list is returned and the builder is cleared.
List<T> toList();
+ /// Adds the element [t] to the end of the list being built.
Link<T> addLast(T t);
+ /// Returns the first element in the list being built.
+ T get first;
+
+ /// Returns the number of elements in the list being built.
final int length;
+
+ /// Returns `true` if the list being built is empty.
final bool isEmpty;
+
+ /// Removes all added elements and resets the builder.
+ void clear();
}
diff --git a/pkg/compiler/lib/src/util/link_implementation.dart b/pkg/compiler/lib/src/util/link_implementation.dart
index 74d9f23..973ef50 100644
--- a/pkg/compiler/lib/src/util/link_implementation.dart
+++ b/pkg/compiler/lib/src/util/link_implementation.dart
@@ -169,6 +169,7 @@
Link<T> link = head;
lastLink = null;
head = null;
+ length = 0;
return link;
}
@@ -184,6 +185,7 @@
}
lastLink = null;
head = null;
+ length = 0;
return list;
}
@@ -200,4 +202,17 @@
}
bool get isEmpty => length == 0;
+
+ T get first {
+ if (head != null) {
+ return head.head;
+ }
+ throw new StateError("no elements");
+ }
+
+ void clear() {
+ head = null;
+ lastLink = null;
+ length = 0;
+ }
}
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index e8c9b13..6cfa45f 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -89,6 +89,9 @@
/// including [cls] if it is live.
Iterable<ClassElement> strictSubtypesOf(ClassElement cls);
+ /// Returns `true` if [a] and [b] have any known common subtypes.
+ bool haveAnyCommonSubtypes(ClassElement a, ClassElement b);
+
/// Returns `true` if any live class other than [cls] extends [cls].
bool hasAnyStrictSubclass(ClassElement cls);
@@ -131,6 +134,7 @@
ClassElement get intClass => compiler.intClass;
ClassElement get doubleClass => compiler.doubleClass;
ClassElement get stringClass => compiler.stringClass;
+ ClassElement get nullClass => compiler.nullClass;
/// Cache of [ti.FlatTypeMask]s grouped by the 8 possible values of the
/// [ti.FlatTypeMask.flags] property.
@@ -185,9 +189,9 @@
Iterable<ClassElement> subclassesOf(ClassElement cls) {
ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration];
if (hierarchy == null) return const <ClassElement>[];
- assert(invariant(cls, isInstantiated(cls.declaration),
- message: 'Class $cls has not been instantiated.'));
- return hierarchy.subclasses();
+ return hierarchy.subclasses(
+ includeIndirectlyInstantiated: false,
+ includeUninstantiated: false);
}
/// Returns an iterable over the directly instantiated classes that extend
@@ -195,16 +199,39 @@
Iterable<ClassElement> strictSubclassesOf(ClassElement cls) {
ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
if (subclasses == null) return const <ClassElement>[];
- assert(invariant(cls, isInstantiated(cls.declaration),
- message: 'Class $cls has not been instantiated.'));
- return subclasses.strictSubclasses();
+ return subclasses.subclasses(
+ strict: true,
+ includeIndirectlyInstantiated: false,
+ includeUninstantiated: false);
}
/// Returns an iterable over the directly instantiated that implement [cls]
/// _not_ including [cls].
Iterable<ClassElement> strictSubtypesOf(ClassElement cls) {
- Set<ClassElement> subtypes = _subtypes[cls.declaration];
- return subtypes != null ? subtypes : const <ClassElement>[];
+ ClassSet classSet = _classSets[cls.declaration];
+ if (classSet == null) {
+ return const <ClassElement>[];
+ } else {
+ return classSet.subtypes(
+ strict: true,
+ includeIndirectlyInstantiated: false,
+ includeUninstantiated: false);
+ }
+ }
+
+ /// Returns `true` if [a] and [b] have any known common subtypes.
+ bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) {
+ ClassSet classSetA = _classSets[a.declaration];
+ ClassSet classSetB = _classSets[b.declaration];
+ if (classSetA == null || classSetB == null) return false;
+ // TODO(johnniwinther): Implement an optimized query on [ClassSet].
+ Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet();
+ for (ClassElement subtypeOfA in classSetA.subtypes()) {
+ if (subtypesOfB.contains(subtypeOfA)) {
+ return true;
+ }
+ }
+ return false;
}
/// Returns `true` if any directly instantiated class other than [cls] extends
@@ -212,8 +239,6 @@
bool hasAnyStrictSubclass(ClassElement cls) {
ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
if (subclasses == null) return false;
- assert(invariant(cls, isInstantiated(cls.declaration),
- message: 'Class $cls has not been instantiated.'));
return subclasses.isIndirectlyInstantiated;
}
@@ -338,8 +363,8 @@
// distinct sets to make class hierarchy analysis faster.
final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes =
<ClassElement, ClassHierarchyNode>{};
- final Map<ClassElement, Set<ClassElement>> _subtypes =
- new Map<ClassElement, Set<ClassElement>>();
+ final Map<ClassElement, ClassSet> _classSets =
+ <ClassElement, ClassSet>{};
final Set<Element> sideEffectsFreeElements = new Set<Element>();
@@ -371,38 +396,81 @@
this.compiler = compiler,
alreadyPopulated = compiler.cacheStrategy.newSet();
- ClassHierarchyNode classHierarchyNode(ClassElement cls) {
- return _classHierarchyNodes[cls];
+ /// Called to add [cls] to the set of known classes.
+ ///
+ /// This ensures that class hierarchy queries can be performed on [cls] and
+ /// classes that extend or implement it.
+ void registerClass(ClassElement cls) {
+ _ensureClassSet(cls);
+ }
+
+ /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
+ /// of known classes.
+ ///
+ /// This method is only provided for testing. For queries on classes, use the
+ /// methods defined in [ClassWorld].
+ ClassHierarchyNode getClassHierarchyNode(ClassElement cls) {
+ return _classHierarchyNodes[cls.declaration];
+ }
+
+ ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) {
+ cls = cls.declaration;
+ return _classHierarchyNodes.putIfAbsent(cls, () {
+ ClassHierarchyNode node = new ClassHierarchyNode(cls);
+ if (cls.superclass != null) {
+ _ensureClassHierarchyNode(cls.superclass).addDirectSubclass(node);
+ }
+ return node;
+ });
+ }
+
+ /// Returns [ClassSet] for [cls] used to model the extends and implements
+ /// relations of known classes.
+ ///
+ /// This method is only provided for testing. For queries on classes, use the
+ /// methods defined in [ClassWorld].
+ ClassSet getClassSet(ClassElement cls) {
+ return _classSets[cls.declaration];
+ }
+
+ ClassSet _ensureClassSet(ClassElement cls) {
+ cls = cls.declaration;
+ return _classSets.putIfAbsent(cls, () {
+ ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
+ ClassSet classSet = new ClassSet(node);
+
+ for (InterfaceType type in cls.allSupertypes) {
+ // TODO(johnniwinther): Optimization: Avoid adding [cls] to
+ // superclasses.
+ ClassSet subtypeSet = _ensureClassSet(type.element);
+ subtypeSet.addSubtype(node);
+ }
+ return classSet;
+ });
}
void populate() {
-
- /// Ensure that a [ClassHierarchyNode] exists for [cls]. Updates the
- /// `isDirectlyInstantiated` and `isIndirectlyInstantiated` property of the
- /// node according the provided arguments and returns the node.
- ClassHierarchyNode createClassHierarchyNodeForClass(
+ /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
+ /// properties of the [ClassHierarchyNode] for [cls].
+ void updateClassHierarchyNodeForClass(
ClassElement cls,
{bool directlyInstantiated: false,
bool indirectlyInstantiated: false}) {
- assert(isInstantiated(cls));
-
- ClassHierarchyNode node = _classHierarchyNodes.putIfAbsent(cls, () {
- ClassHierarchyNode node = new ClassHierarchyNode(cls);
- if (cls.superclass != null) {
- createClassHierarchyNodeForClass(cls.superclass,
- indirectlyInstantiated:
- directlyInstantiated || indirectlyInstantiated)
- .addDirectSubclass(node);
- }
- return node;
- });
- if (directlyInstantiated) {
+ assert(!directlyInstantiated || isInstantiated(cls));
+ ClassHierarchyNode node = getClassHierarchyNode(cls);
+ bool changed = false;
+ if (directlyInstantiated && !node.isDirectlyInstantiated) {
node.isDirectlyInstantiated = true;
+ changed = true;
}
- if (indirectlyInstantiated) {
+ if (indirectlyInstantiated && !node.isIndirectlyInstantiated) {
node.isIndirectlyInstantiated = true;
+ changed = true;
}
- return node;
+ if (changed && cls.superclass != null) {
+ updateClassHierarchyNodeForClass(
+ cls.superclass, indirectlyInstantiated: true);
+ }
}
void addSubtypes(ClassElement cls) {
@@ -414,13 +482,7 @@
compiler.internalError(cls, 'Class "${cls.name}" is not resolved.');
}
- createClassHierarchyNodeForClass(cls, directlyInstantiated: true);
-
- for (DartType type in cls.allSupertypes) {
- Set<Element> subtypesOfSupertype =
- _subtypes.putIfAbsent(type.element, () => new Set<ClassElement>());
- subtypesOfSupertype.add(cls);
- }
+ updateClassHierarchyNodeForClass(cls, directlyInstantiated: true);
// Walk through the superclasses, and record the types
// implemented by that type on the superclasses.
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index fe774b2..8e74b36 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -4,6 +4,7 @@
#version: do-not-upload
dependencies:
package_config: ^0.1.1
+ pub_semver: ^1.2.1
js_ast:
path: ../js_ast
js_runtime:
diff --git a/pkg/js_ast/lib/src/printer.dart b/pkg/js_ast/lib/src/printer.dart
index 8523916..7a1124f 100644
--- a/pkg/js_ast/lib/src/printer.dart
+++ b/pkg/js_ast/lib/src/printer.dart
@@ -136,7 +136,7 @@
int get lastCharCode {
if (lastAddedString == null) return 0;
- assert(lastAddedString.length != "");
+ assert(lastAddedString.length != 0);
return lastAddedString.codeUnitAt(lastAddedString.length - 1);
}
diff --git a/pkg/lookup_map/CHANGELOG.md b/pkg/lookup_map/CHANGELOG.md
index cbe7954a..beb0eb0 100644
--- a/pkg/lookup_map/CHANGELOG.md
+++ b/pkg/lookup_map/CHANGELOG.md
@@ -1,4 +1,7 @@
# Changelog
+## 0.0.1+1
+- Fix minor typo in readme.
+
## 0.0.1
- Initial version of `LookupMap`
diff --git a/pkg/lookup_map/README.md b/pkg/lookup_map/README.md
index ecab6b5..a333791 100644
--- a/pkg/lookup_map/README.md
+++ b/pkg/lookup_map/README.md
@@ -2,7 +2,7 @@
This package contains the definition of `LookupMap`: a simple, but very
restricted map. The map can only hold constant keys and the only way to use the
-map is to retrieve values with a key you already have. Expect for lookup, any
+map is to retrieve values with a key you already have. Except for lookup, any
other operation in `Map` (like forEach, keys, values, length, etc) is not
available.
diff --git a/pkg/lookup_map/lib/lookup_map.dart b/pkg/lookup_map/lib/lookup_map.dart
index 0c03094..65ac754 100644
--- a/pkg/lookup_map/lib/lookup_map.dart
+++ b/pkg/lookup_map/lib/lookup_map.dart
@@ -7,7 +7,7 @@
/// [LookupMap] is a simple, but very restricted map. The map can only hold
/// constant keys and the only way to use the map is to retrieve values with a
-/// key you already have. Expect for lookup, any other operation in [Map] (like
+/// key you already have. Except for lookup, any other operation in [Map] (like
/// forEach, keys, values, length, etc) is not available.
///
/// Constant [LookupMap]s are understood by dart2js and can be tree-shaken
@@ -97,4 +97,4 @@
/// this code.
// Note: this needs to be kept in sync with the pubspec, otherwise
// test/version_check_test would fail.
-final _version = '0.0.1';
+final _version = '0.0.1+1';
diff --git a/pkg/lookup_map/pubspec.yaml b/pkg/lookup_map/pubspec.yaml
index 8c420d0..adaee09e 100644
--- a/pkg/lookup_map/pubspec.yaml
+++ b/pkg/lookup_map/pubspec.yaml
@@ -2,7 +2,7 @@
description: a lookup-only map that can be tree-shaken by dart2js
# Note: the version needs to be kept in sync with the string in
# lib/lookup_map.dart, otherwise test/version_check_test would fail.
-version: 0.0.1
+version: 0.0.1+1
author: "Dart Team <misc@dartlang.org>"
homepage: https://github.com/dart-lang/sdk/blob/master/pkg/lookup_map/README.md
dev_dependencies:
diff --git a/pkg/lookup_map/test/version_check_test.dart b/pkg/lookup_map/test/version_check_test.dart
index 2da0873..2bee1a6 100644
--- a/pkg/lookup_map/test/version_check_test.dart
+++ b/pkg/lookup_map/test/version_check_test.dart
@@ -11,8 +11,8 @@
/// This dartdoc helps remove a warning for the unused import on [LookupMap].
main() {
test('validate version number matches', () {
- var pubspecPath = Platform.script.resolve('../pubspec.yaml').path;
- var yaml = loadYaml(new File(pubspecPath).readAsStringSync());
+ var pubspec = Platform.script.resolve('../pubspec.yaml');
+ var yaml = loadYaml(new File.fromUri(pubspec).readAsStringSync());
var version1 = yaml['version'];
var library = currentMirrorSystem().findLibrary(#lookup_map);
var version2 = library.getField(new Symbol('_version')).reflectee;
diff --git a/pkg/pkgbuild.status b/pkg/pkgbuild.status
index aa7e83e..3cf95f1 100644
--- a/pkg/pkgbuild.status
+++ b/pkg/pkgbuild.status
@@ -8,7 +8,6 @@
[ $use_repository_packages ]
pkg/analyzer: PubGetError
-third_party/pkg/shelf: PubGetError # either shelf needs to be updated, or dart2js_info needs to be downgraded.
samples/third_party/angular_todo: Fail # angular needs to be updated
samples/third_party/todomvc_performance: Skip # dependencies are not in the repo
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index bbc4d3e..253d8d7 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -175,7 +175,7 @@
}
-static_library("libdart_embedder_noio") {
+source_set("libdart_embedder_noio") {
configs += ["..:dart_config",]
deps = [
"..:libdart",
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index dfe9a74..78a71e7 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -295,7 +295,7 @@
'conditions': [
['dart_io_support==1', {
'dependencies': [
- 'bin/net/zlib.gyp:zlib_dart',
+ 'bin/zlib.gyp:zlib_dart',
],
}],
['dart_io_support==1 and dart_io_secure_socket==1', {
diff --git a/runtime/bin/builtin.h b/runtime/bin/builtin.h
index a943dc8..ab871af 100644
--- a/runtime/bin/builtin.h
+++ b/runtime/bin/builtin.h
@@ -49,7 +49,7 @@
// load it.
static Dart_Handle LoadAndCheckLibrary(BuiltinLibraryId id);
- static void SetLoadPort(Dart_Port port);
+ static Dart_Handle SetLoadPort(Dart_Port port);
private:
// Map specified URI to an actual file name from 'source_paths' and read
diff --git a/runtime/bin/builtin_common.cc b/runtime/bin/builtin_common.cc
index da754a5..678e48b 100644
--- a/runtime/bin/builtin_common.cc
+++ b/runtime/bin/builtin_common.cc
@@ -10,27 +10,37 @@
#include "bin/dartutils.h"
#include "bin/platform.h"
+// Return the error from the containing function if handle is in error handle.
+#define RETURN_IF_ERROR(handle) \
+ { \
+ Dart_Handle __handle = handle; \
+ if (Dart_IsError((__handle))) { \
+ return __handle; \
+ } \
+ }
+
namespace dart {
namespace bin {
-void Builtin::SetLoadPort(Dart_Port port) {
+Dart_Handle Builtin::SetLoadPort(Dart_Port port) {
load_port_ = port;
ASSERT(load_port_ != ILLEGAL_PORT);
Dart_Handle field_name = DartUtils::NewString("_loadPort");
- ASSERT(!Dart_IsError(field_name));
+ RETURN_IF_ERROR(field_name);
Dart_Handle builtin_lib =
Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
- ASSERT(!Dart_IsError(builtin_lib));
+ RETURN_IF_ERROR(builtin_lib);
Dart_Handle send_port = Dart_GetField(builtin_lib, field_name);
- ASSERT(!Dart_IsError(send_port));
+ RETURN_IF_ERROR(send_port);
if (!Dart_IsNull(send_port)) {
// Already created and set.
- return;
+ return Dart_True();
}
send_port = Dart_NewSendPort(load_port_);
- ASSERT(!Dart_IsError(send_port));
+ RETURN_IF_ERROR(send_port);
Dart_Handle result = Dart_SetField(builtin_lib, field_name, send_port);
- ASSERT(!Dart_IsError(result));
+ RETURN_IF_ERROR(result);
+ return Dart_True();
}
} // namespace bin
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 1c77820..a4fc2e2 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -21,6 +21,15 @@
#include "bin/socket.h"
#include "bin/utils.h"
+// Return the error from the containing function if handle is in error handle.
+#define RETURN_IF_ERROR(handle) \
+ { \
+ Dart_Handle __handle = handle; \
+ if (Dart_IsError((__handle))) { \
+ return __handle; \
+ } \
+ }
+
namespace dart {
namespace bin {
@@ -126,21 +135,17 @@
}
-void DartUtils::SetIntegerField(Dart_Handle handle,
- const char* name,
- int64_t val) {
- Dart_Handle result = Dart_SetField(handle,
- NewString(name),
- Dart_NewInteger(val));
- if (Dart_IsError(result)) Dart_PropagateError(result);
+Dart_Handle DartUtils::SetIntegerField(Dart_Handle handle,
+ const char* name,
+ int64_t val) {
+ return Dart_SetField(handle, NewString(name), Dart_NewInteger(val));
}
-void DartUtils::SetStringField(Dart_Handle handle,
+Dart_Handle DartUtils::SetStringField(Dart_Handle handle,
const char* name,
const char* val) {
- Dart_Handle result = Dart_SetField(handle, NewString(name), NewString(val));
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ return Dart_SetField(handle, NewString(name), NewString(val));
}
@@ -383,7 +388,7 @@
// Resolve the url within the context of the library's URL.
Dart_Handle builtin_lib =
Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
- DART_CHECK_VALID(builtin_lib);
+ RETURN_IF_ERROR(builtin_lib);
return ResolveUri(library_url, url, builtin_lib);
}
@@ -423,7 +428,7 @@
Dart_Handle builtin_lib =
Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
- DART_CHECK_VALID(builtin_lib);
+ RETURN_IF_ERROR(builtin_lib);
if (DartUtils::IsDartExtensionSchemeURL(url_string)) {
// Load a native code shared library to use in a native extension
if (tag != Dart_kImportTag) {
@@ -569,7 +574,9 @@
} else {
ASSERT(tag == Dart_kSourceTag);
Dart_Handle library = Dart_LookupLibrary(library_uri);
- DART_CHECK_VALID(library);
+ if (Dart_IsError(library)) {
+ Dart_PropagateError(library);
+ }
result = Dart_LoadSource(library, resolved_script_uri, source, 0, 0);
}
}
@@ -630,37 +637,38 @@
// Setup the internal library's 'internalPrint' function.
Dart_Handle print = Dart_Invoke(
builtin_lib, NewString("_getPrintClosure"), 0, NULL);
- DART_CHECK_VALID(print);
+ RETURN_IF_ERROR(print);
Dart_Handle result =
Dart_SetField(internal_lib, NewString("_printClosure"), print);
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
if (!is_service_isolate) {
if (IsWindowsHost()) {
result = Dart_SetField(builtin_lib, NewString("_isWindows"), Dart_True());
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
}
if (trace_loading) {
result = Dart_SetField(builtin_lib,
NewString("_traceLoading"), Dart_True());
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
}
// Set current working directory.
result = SetWorkingDirectory(builtin_lib);
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
// Wait for the service isolate to initialize the load port.
Dart_Port load_port = Dart_ServiceWaitForLoadPort();
if (load_port == ILLEGAL_PORT) {
return NewDartUnsupportedError("Service did not return load port.");
}
- Builtin::SetLoadPort(load_port);
+ result = Builtin::SetLoadPort(load_port);
+ RETURN_IF_ERROR(result);
}
// Set up package root if specified.
if (package_root != NULL) {
ASSERT(packages_file == NULL);
result = NewString(package_root);
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
const int kNumArgs = 1;
Dart_Handle dart_args[kNumArgs];
dart_args[0] = result;
@@ -668,10 +676,10 @@
NewString("_setPackageRoot"),
kNumArgs,
dart_args);
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
} else if (packages_file != NULL) {
result = NewString(packages_file);
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
const int kNumArgs = 1;
Dart_Handle dart_args[kNumArgs];
dart_args[0] = result;
@@ -679,47 +687,49 @@
NewString("_loadPackagesMap"),
kNumArgs,
dart_args);
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
}
return Dart_True();
}
-void DartUtils::PrepareCoreLibrary(Dart_Handle core_lib,
- Dart_Handle builtin_lib,
- bool is_service_isolate) {
+Dart_Handle DartUtils::PrepareCoreLibrary(Dart_Handle core_lib,
+ Dart_Handle builtin_lib,
+ bool is_service_isolate) {
if (!is_service_isolate) {
// Setup the 'Uri.base' getter in dart:core.
Dart_Handle uri_base = Dart_Invoke(
builtin_lib, NewString("_getUriBaseClosure"), 0, NULL);
- DART_CHECK_VALID(uri_base);
+ RETURN_IF_ERROR(uri_base);
Dart_Handle result = Dart_SetField(core_lib,
NewString("_uriBaseClosure"),
uri_base);
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
}
+ return Dart_True();
}
-void DartUtils::PrepareAsyncLibrary(Dart_Handle async_lib,
- Dart_Handle isolate_lib) {
+Dart_Handle DartUtils::PrepareAsyncLibrary(Dart_Handle async_lib,
+ Dart_Handle isolate_lib) {
Dart_Handle schedule_immediate_closure =
Dart_Invoke(isolate_lib, NewString("_getIsolateScheduleImmediateClosure"),
0, NULL);
+ RETURN_IF_ERROR(schedule_immediate_closure);
Dart_Handle args[1];
args[0] = schedule_immediate_closure;
- DART_CHECK_VALID(Dart_Invoke(
- async_lib, NewString("_setScheduleImmediateClosure"), 1, args));
+ return Dart_Invoke(
+ async_lib, NewString("_setScheduleImmediateClosure"), 1, args);
}
-void DartUtils::PrepareIOLibrary(Dart_Handle io_lib) {
- DART_CHECK_VALID(Dart_Invoke(io_lib, NewString("_setupHooks"), 0, NULL));
+Dart_Handle DartUtils::PrepareIOLibrary(Dart_Handle io_lib) {
+ return Dart_Invoke(io_lib, NewString("_setupHooks"), 0, NULL);
}
-void DartUtils::PrepareIsolateLibrary(Dart_Handle isolate_lib) {
- DART_CHECK_VALID(Dart_Invoke(isolate_lib, NewString("_setupHooks"), 0, NULL));
+Dart_Handle DartUtils::PrepareIsolateLibrary(Dart_Handle isolate_lib) {
+ return Dart_Invoke(isolate_lib, NewString("_setupHooks"), 0, NULL);
}
@@ -730,28 +740,28 @@
Dart_Handle builtin_lib) {
// First ensure all required libraries are available.
Dart_Handle url = NewString(kCoreLibURL);
- DART_CHECK_VALID(url);
+ RETURN_IF_ERROR(url);
Dart_Handle core_lib = Dart_LookupLibrary(url);
- DART_CHECK_VALID(core_lib);
+ RETURN_IF_ERROR(core_lib);
url = NewString(kAsyncLibURL);
- DART_CHECK_VALID(url);
+ RETURN_IF_ERROR(url);
Dart_Handle async_lib = Dart_LookupLibrary(url);
- DART_CHECK_VALID(async_lib);
+ RETURN_IF_ERROR(async_lib);
url = NewString(kIsolateLibURL);
- DART_CHECK_VALID(url);
+ RETURN_IF_ERROR(url);
Dart_Handle isolate_lib = Dart_LookupLibrary(url);
- DART_CHECK_VALID(isolate_lib);
+ RETURN_IF_ERROR(isolate_lib);
url = NewString(kInternalLibURL);
- DART_CHECK_VALID(url);
+ RETURN_IF_ERROR(url);
Dart_Handle internal_lib = Dart_LookupLibrary(url);
- DART_CHECK_VALID(internal_lib);
+ RETURN_IF_ERROR(internal_lib);
Dart_Handle io_lib = Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
- DART_CHECK_VALID(io_lib);
+ RETURN_IF_ERROR(io_lib);
// We need to ensure that all the scripts loaded so far are finalized
// as we are about to invoke some Dart code below to setup closures.
Dart_Handle result = Dart_FinalizeLoading(false);
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
result = PrepareBuiltinLibrary(builtin_lib,
internal_lib,
@@ -759,30 +769,32 @@
trace_loading,
package_root,
packages_file);
- DART_CHECK_VALID(result);
+ RETURN_IF_ERROR(result);
- PrepareAsyncLibrary(async_lib, isolate_lib);
- PrepareCoreLibrary(core_lib, builtin_lib, is_service_isolate);
- PrepareIsolateLibrary(isolate_lib);
- PrepareIOLibrary(io_lib);
+ RETURN_IF_ERROR(PrepareAsyncLibrary(async_lib, isolate_lib));
+ RETURN_IF_ERROR(PrepareCoreLibrary(
+ core_lib, builtin_lib, is_service_isolate));
+ RETURN_IF_ERROR(PrepareIsolateLibrary(isolate_lib));
+ RETURN_IF_ERROR(PrepareIOLibrary(io_lib));
return result;
}
-void DartUtils::SetupIOLibrary(const char* script_uri) {
+Dart_Handle DartUtils::SetupIOLibrary(const char* script_uri) {
Dart_Handle io_lib_url = NewString(kIOLibURL);
- DART_CHECK_VALID(io_lib_url);
+ RETURN_IF_ERROR(io_lib_url);
Dart_Handle io_lib = Dart_LookupLibrary(io_lib_url);
- DART_CHECK_VALID(io_lib);
+ RETURN_IF_ERROR(io_lib);
Dart_Handle platform_type = GetDartType(DartUtils::kIOLibURL, "_Platform");
- DART_CHECK_VALID(platform_type);
+ RETURN_IF_ERROR(platform_type);
Dart_Handle script_name = NewString("_nativeScript");
- DART_CHECK_VALID(script_name);
+ RETURN_IF_ERROR(script_name);
Dart_Handle dart_script = NewString(script_uri);
- DART_CHECK_VALID(dart_script);
+ RETURN_IF_ERROR(dart_script);
Dart_Handle set_script_name =
Dart_SetField(platform_type, script_name, dart_script);
- DART_CHECK_VALID(set_script_name);
+ RETURN_IF_ERROR(set_script_name);
+ return Dart_Null();
}
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 8a9c953..3118950 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -102,12 +102,12 @@
// a boolean value an API error is propagated.
static bool GetBooleanValue(Dart_Handle bool_obj);
- static void SetIntegerField(Dart_Handle handle,
- const char* name,
- int64_t val);
- static void SetStringField(Dart_Handle handle,
- const char* name,
- const char* val);
+ static Dart_Handle SetIntegerField(Dart_Handle handle,
+ const char* name,
+ int64_t val);
+ static Dart_Handle SetStringField(Dart_Handle handle,
+ const char* name,
+ const char* val);
static bool IsDartSchemeURL(const char* url_name);
static bool IsDartExtensionSchemeURL(const char* url_name);
static bool IsDartIOLibURL(const char* url_name);
@@ -130,19 +130,19 @@
bool trace_loading,
const char* package_root,
const char* packages_file);
- static void PrepareCoreLibrary(Dart_Handle core_lib,
+ static Dart_Handle PrepareCoreLibrary(Dart_Handle core_lib,
Dart_Handle builtin_lib,
bool is_service_isolate);
- static void PrepareAsyncLibrary(Dart_Handle async_lib,
+ static Dart_Handle PrepareAsyncLibrary(Dart_Handle async_lib,
Dart_Handle isolate_lib);
- static void PrepareIOLibrary(Dart_Handle io_lib);
- static void PrepareIsolateLibrary(Dart_Handle isolate_lib);
+ static Dart_Handle PrepareIOLibrary(Dart_Handle io_lib);
+ static Dart_Handle PrepareIsolateLibrary(Dart_Handle isolate_lib);
static Dart_Handle PrepareForScriptLoading(const char* package_root,
const char* packages_file,
bool is_service_isolate,
bool trace_loading,
Dart_Handle builtin_lib);
- static void SetupIOLibrary(const char* script_uri);
+ static Dart_Handle SetupIOLibrary(const char* script_uri);
static bool PostNull(Dart_Port port_id);
static bool PostInt32(Dart_Port port_id, int32_t value);
diff --git a/runtime/bin/dbg_message.cc b/runtime/bin/dbg_message.cc
index a635880..0a3038a 100644
--- a/runtime/bin/dbg_message.cc
+++ b/runtime/bin/dbg_message.cc
@@ -1402,14 +1402,17 @@
void DbgMsgQueueList::IsolateEventHandler(Dart_IsolateId isolate_id,
Dart_IsolateEvent kind) {
- DebuggerConnectionHandler::WaitForConnection();
- Dart_EnterScope();
if (kind == kCreated) {
+ DebuggerConnectionHandler::WaitForConnection();
+ Dart_EnterScope();
DbgMsgQueue* msg_queue = AddIsolateMsgQueue(isolate_id);
msg_queue->SendIsolateEvent(isolate_id, kind);
+ Dart_ExitScope();
} else {
DbgMsgQueue* msg_queue = GetIsolateMsgQueue(isolate_id);
if (msg_queue != NULL) {
+ DebuggerConnectionHandler::WaitForConnection();
+ Dart_EnterScope();
msg_queue->SendQueuedMsgs();
msg_queue->SendIsolateEvent(isolate_id, kind);
if (kind == kInterrupted) {
@@ -1418,9 +1421,11 @@
ASSERT(kind == kShutdown);
RemoveIsolateMsgQueue(isolate_id);
}
+ Dart_ExitScope();
}
+ // If there is no receive message queue, do not wait for a connection, and
+ // ignore the message.
}
- Dart_ExitScope();
}
} // namespace bin
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 4c18137..7c6c798 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -544,18 +544,19 @@
// Initialize the Dart VM.
// Note: We don't expect isolates to be created from dart code during
// snapshot generation.
- if (!Dart_Initialize(NULL, NULL,
- NULL, NULL, NULL, NULL,
- DartUtils::OpenFile,
- DartUtils::ReadFile,
- DartUtils::WriteFile,
- DartUtils::CloseFile,
- DartUtils::EntropySource)) {
- Log::PrintErr("VM initialization failed\n");
+ char* error = Dart_Initialize(NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ DartUtils::OpenFile,
+ DartUtils::ReadFile,
+ DartUtils::WriteFile,
+ DartUtils::CloseFile,
+ DartUtils::EntropySource);
+ if (error != NULL) {
+ Log::PrintErr("VM initialization failed: %s\n", error);
+ free(error);
return 255;
}
- char* error;
Dart_Isolate isolate = Dart_CreateIsolate(
NULL, NULL, NULL, NULL, NULL, &error);
if (isolate == NULL) {
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index ee7b80d..702a8a2 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -110,6 +110,7 @@
// Exit code indicating an unhandled error that is not a compilation error.
static const int kErrorExitCode = 255;
+extern bool do_vm_shutdown; // Defined in bin/process.cc
static void ErrorExit(int exit_code, const char* format, ...) {
va_list arguments;
va_start(arguments, format);
@@ -120,11 +121,19 @@
Dart_ExitScope();
Dart_ShutdownIsolate();
- Dart_Cleanup();
+ // Terminate process exit-code handler.
+ Process::TerminateExitCodeHandler();
- DebuggerConnectionHandler::StopHandler();
- // TODO(zra): Stop the EventHandler once thread shutdown is enabled.
- // EventHandler::Stop();
+ char* error = Dart_Cleanup();
+ if (error != NULL) {
+ Log::PrintErr("VM cleanup failed: %s\n", error);
+ free(error);
+ }
+
+ if (do_vm_shutdown) {
+ DebuggerConnectionHandler::StopHandler();
+ EventHandler::Stop();
+ }
exit(exit_code);
}
@@ -430,30 +439,60 @@
}
+
+static bool ProcessShutdownOption(const char* arg,
+ CommandLineOptions* vm_options) {
+ ASSERT(arg != NULL);
+ if (*arg == '\0') {
+ do_vm_shutdown = true;
+ vm_options->AddArgument("--shutdown");
+ return true;
+ }
+
+ if ((*arg != '=') && (*arg != ':')) {
+ return false;
+ }
+
+ if (strcmp(arg + 1, "true") == 0) {
+ do_vm_shutdown = true;
+ vm_options->AddArgument("--shutdown");
+ return true;
+ } else if (strcmp(arg + 1, "false") == 0) {
+ do_vm_shutdown = false;
+ vm_options->AddArgument("--no-shutdown");
+ return true;
+ }
+
+ return false;
+}
+
+
static struct {
const char* option_name;
bool (*process)(const char* option, CommandLineOptions* vm_options);
} main_options[] = {
// Standard options shared with dart2js.
- { "--version", ProcessVersionOption },
- { "--help", ProcessHelpOption },
- { "-h", ProcessHelpOption },
- { "--verbose", ProcessVerboseOption },
- { "-v", ProcessVerboseOption },
- { "--package-root=", ProcessPackageRootOption },
- { "--packages=", ProcessPackagesOption },
{ "-D", ProcessEnvironmentOption },
+ { "-h", ProcessHelpOption },
+ { "--help", ProcessHelpOption },
+ { "--packages=", ProcessPackagesOption },
+ { "--package-root=", ProcessPackageRootOption },
+ { "-v", ProcessVerboseOption },
+ { "--verbose", ProcessVerboseOption },
+ { "--version", ProcessVersionOption },
+
// VM specific options to the standalone dart program.
{ "--break-at=", ProcessBreakpointOption },
{ "--compile_all", ProcessCompileAllOption },
- { "--gen-precompiled-snapshot", ProcessGenPrecompiledSnapshotOption },
- { "--run-precompiled-snapshot", ProcessRunPrecompiledSnapshotOption },
{ "--debug", ProcessDebugOption },
- { "--snapshot=", ProcessGenScriptSnapshotOption },
{ "--enable-vm-service", ProcessEnableVmServiceOption },
+ { "--gen-precompiled-snapshot", ProcessGenPrecompiledSnapshotOption },
{ "--observe", ProcessObserveOption },
+ { "--run-precompiled-snapshot", ProcessRunPrecompiledSnapshotOption },
+ { "--shutdown", ProcessShutdownOption },
+ { "--snapshot=", ProcessGenScriptSnapshotOption },
{ "--trace-debug-protocol", ProcessTraceDebugProtocolOption },
- { "--trace-loading", ProcessTraceLoadingOption},
+ { "--trace-loading", ProcessTraceLoadingOption },
{ NULL, NULL }
};
@@ -660,6 +699,7 @@
error);
if (isolate == NULL) {
+ delete isolate_data;
return NULL;
}
@@ -681,10 +721,7 @@
*error = strdup(VmService::GetErrorMessage());
return NULL;
}
- if (has_gen_precompiled_snapshot) {
- result = Dart_Precompile();
- CHECK_RESULT(result);
- } else if (has_compile_all) {
+ if (has_compile_all) {
result = Dart_CompileAll();
CHECK_RESULT(result);
}
@@ -728,7 +765,8 @@
Platform::SetPackageRoot(package_root);
- DartUtils::SetupIOLibrary(script_uri);
+ result = DartUtils::SetupIOLibrary(script_uri);
+ CHECK_RESULT(result);
// Make the isolate runnable so that it is ready to handle messages.
Dart_ExitScope();
@@ -1001,7 +1039,9 @@
File* file = File::Open(filename, File::kWriteTruncate);
ASSERT(file != NULL);
if (!file->WriteFully(buffer, size)) {
- Log::PrintErr("Error: Failed to write snapshot file.\n\n");
+ ErrorExit(kErrorExitCode,
+ "Unable to open file %s for writing snapshot\n",
+ filename);
}
delete file;
}
@@ -1011,14 +1051,14 @@
const uint8_t** buffer) {
void* file = DartUtils::OpenFile(filename, false);
if (file == NULL) {
- Log::PrintErr("Error: Failed to open '%s'.\n\n", filename);
- exit(kErrorExitCode);
+ ErrorExit(kErrorExitCode,
+ "Error: Unable to open file %s for reading snapshot\n", filename);
}
intptr_t len = -1;
DartUtils::ReadFile(buffer, &len, file);
if (*buffer == NULL || len == -1) {
- Log::PrintErr("Error: Failed to read '%s'.\n\n", filename);
- exit(kErrorExitCode);
+ ErrorExit(kErrorExitCode,
+ "Error: Unable to read snapshot file %s\n", filename);
}
DartUtils::CloseFile(file);
}
@@ -1027,13 +1067,13 @@
static void* LoadLibrarySymbol(const char* libname, const char* symname) {
void* library = Extensions::LoadExtensionLibrary(libname);
if (library == NULL) {
- Log::PrintErr("Error: Failed to load library '%s'.\n\n", libname);
- exit(kErrorExitCode);
+ ErrorExit(kErrorExitCode,
+ "Error: Failed to load library '%s'\n", libname);
}
void* symbol = Extensions::ResolveSymbol(library, symname);
if (symbol == NULL) {
- Log::PrintErr("Failed to load symbol '%s'\n", symname);
- exit(kErrorExitCode);
+ ErrorExit(kErrorExitCode,
+ "Error: Failed to load symbol '%s'\n", symname);
}
return symbol;
}
@@ -1121,18 +1161,22 @@
}
// Initialize the Dart VM.
- if (!Dart_Initialize(vm_isolate_snapshot_buffer, instructions_snapshot,
- CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
- DartUtils::OpenFile,
- DartUtils::ReadFile,
- DartUtils::WriteFile,
- DartUtils::CloseFile,
- DartUtils::EntropySource)) {
- fprintf(stderr, "%s", "VM initialization failed\n");
+ char* error = Dart_Initialize(
+ vm_isolate_snapshot_buffer, instructions_snapshot,
+ CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
+ DartUtils::OpenFile,
+ DartUtils::ReadFile,
+ DartUtils::WriteFile,
+ DartUtils::CloseFile,
+ DartUtils::EntropySource);
+ if (error != NULL) {
+ if (do_vm_shutdown) {
+ DebuggerConnectionHandler::StopHandler();
+ EventHandler::Stop();
+ }
+ fprintf(stderr, "VM initialization failed: %s\n", error);
fflush(stderr);
- DebuggerConnectionHandler::StopHandler();
- // TODO(zra): Stop the EventHandler once thread shutdown is enabled.
- // EventHandler::Stop();
+ free(error);
exit(kErrorExitCode);
}
@@ -1143,7 +1187,6 @@
// Call CreateIsolateAndSetup which creates an isolate and loads up
// the specified application script.
- char* error = NULL;
int exit_code = 0;
char* isolate_name = BuildIsolateName(script_name, "main");
Dart_Isolate isolate = CreateIsolateAndSetupHelper(script_name,
@@ -1156,10 +1199,18 @@
if (isolate == NULL) {
Log::PrintErr("%s\n", error);
free(error);
+ error = NULL;
delete [] isolate_name;
- DebuggerConnectionHandler::StopHandler();
- // TODO(zra): Stop the EventHandler once thread shutdown is enabled.
- // EventHandler::Stop();
+ Process::TerminateExitCodeHandler();
+ error = Dart_Cleanup();
+ if (error != NULL) {
+ Log::PrintErr("VM cleanup failed: %s\n", error);
+ free(error);
+ }
+ if (do_vm_shutdown) {
+ DebuggerConnectionHandler::StopHandler();
+ EventHandler::Stop();
+ }
exit((exit_code != 0) ? exit_code : kErrorExitCode);
}
delete [] isolate_name;
@@ -1231,53 +1282,55 @@
WriteSnapshotFile(kPrecompiledInstructionsName,
instructions_buffer,
instructions_size);
- } else if (has_compile_all) {
- result = Dart_CompileAll();
+ } else {
+ if (has_compile_all) {
+ result = Dart_CompileAll();
+ DartExitOnError(result);
+ }
+
+ if (Dart_IsNull(root_lib)) {
+ ErrorExit(kErrorExitCode,
+ "Unable to find root library for '%s'\n",
+ script_name);
+ }
+
+ // The helper function _getMainClosure creates a closure for the main
+ // entry point which is either explicitly or implictly exported from the
+ // root library.
+ Dart_Handle main_closure = Dart_Invoke(builtin_lib,
+ Dart_NewStringFromCString("_getMainClosure"), 0, NULL);
+ DartExitOnError(main_closure);
+
+ // Set debug breakpoint if specified on the command line before calling
+ // the main function.
+ if (breakpoint_at != NULL) {
+ result = SetBreakpoint(breakpoint_at, root_lib);
+ if (Dart_IsError(result)) {
+ ErrorExit(kErrorExitCode,
+ "Error setting breakpoint at '%s': %s\n",
+ breakpoint_at,
+ Dart_GetError(result));
+ }
+ }
+
+ // Call _startIsolate in the isolate library to enable dispatching the
+ // initial startup message.
+ const intptr_t kNumIsolateArgs = 2;
+ Dart_Handle isolate_args[kNumIsolateArgs];
+ isolate_args[0] = main_closure; // entryPoint
+ isolate_args[1] = CreateRuntimeOptions(&dart_options); // args
+
+ Dart_Handle isolate_lib =
+ Dart_LookupLibrary(Dart_NewStringFromCString("dart:isolate"));
+ result = Dart_Invoke(isolate_lib,
+ Dart_NewStringFromCString("_startMainIsolate"),
+ kNumIsolateArgs, isolate_args);
+ DartExitOnError(result);
+
+ // Keep handling messages until the last active receive port is closed.
+ result = Dart_RunLoop();
DartExitOnError(result);
}
-
- if (Dart_IsNull(root_lib)) {
- ErrorExit(kErrorExitCode,
- "Unable to find root library for '%s'\n",
- script_name);
- }
-
- // The helper function _getMainClosure creates a closure for the main
- // entry point which is either explicitly or implictly exported from the
- // root library.
- Dart_Handle main_closure = Dart_Invoke(
- builtin_lib, Dart_NewStringFromCString("_getMainClosure"), 0, NULL);
- DartExitOnError(main_closure);
-
- // Set debug breakpoint if specified on the command line before calling
- // the main function.
- if (breakpoint_at != NULL) {
- result = SetBreakpoint(breakpoint_at, root_lib);
- if (Dart_IsError(result)) {
- ErrorExit(kErrorExitCode,
- "Error setting breakpoint at '%s': %s\n",
- breakpoint_at,
- Dart_GetError(result));
- }
- }
-
- // Call _startIsolate in the isolate library to enable dispatching the
- // initial startup message.
- const intptr_t kNumIsolateArgs = 2;
- Dart_Handle isolate_args[kNumIsolateArgs];
- isolate_args[0] = main_closure; // entryPoint
- isolate_args[1] = CreateRuntimeOptions(&dart_options); // args
-
- Dart_Handle isolate_lib = Dart_LookupLibrary(
- Dart_NewStringFromCString("dart:isolate"));
- result = Dart_Invoke(isolate_lib,
- Dart_NewStringFromCString("_startMainIsolate"),
- kNumIsolateArgs, isolate_args);
- DartExitOnError(result);
-
- // Keep handling messages until the last active receive port is closed.
- result = Dart_RunLoop();
- DartExitOnError(result);
}
Dart_ExitScope();
@@ -1286,11 +1339,15 @@
// Terminate process exit-code handler.
Process::TerminateExitCodeHandler();
- Dart_Cleanup();
-
- DebuggerConnectionHandler::StopHandler();
- // TODO(zra): Stop the EventHandler once thread shutdown is enabled.
- // EventHandler::Stop();
+ error = Dart_Cleanup();
+ if (error != NULL) {
+ Log::PrintErr("VM cleanup failed: %s\n", error);
+ free(error);
+ }
+ if (do_vm_shutdown) {
+ DebuggerConnectionHandler::StopHandler();
+ EventHandler::Stop();
+ }
// Free copied argument strings if converted.
if (argv_converted) {
diff --git a/runtime/bin/net/.gitignore b/runtime/bin/net/.gitignore
deleted file mode 100644
index 3ca2cc5..0000000
--- a/runtime/bin/net/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-/*.Makefile
-/*.sln
-/*.target.mk
-/*.vcproj
-/*.vcxproj
-/*.vcxproj.filters
-/*.vcxproj.user
-/*.xcodeproj
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index 242ef1c..3c345b7 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -6,6 +6,7 @@
#include "bin/dbg_connection.h"
#include "bin/eventhandler.h"
#include "bin/io_buffer.h"
+#include "bin/log.h"
#include "bin/platform.h"
#include "bin/process.h"
#include "bin/socket.h"
@@ -16,6 +17,10 @@
namespace dart {
namespace bin {
+// Global flag that is used to indicate that the VM should do a clean
+// shutdown.
+bool do_vm_shutdown = true;
+
static const int kProcessIdNativeField = 0;
int Process::global_exit_code_ = 0;
@@ -36,9 +41,15 @@
// Protect against user-defined list implementations that can have
// arbitrary length.
if (len < 0 || len > kMaxArgumentListLength) {
- DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
- DartUtils::SetStringField(
+ result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ result = DartUtils::SetStringField(
status_handle, "_errorMessage", "Max argument list length exceeded");
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
return NULL;
}
*length = len;
@@ -50,9 +61,15 @@
Dart_PropagateError(arg);
}
if (!Dart_IsString(arg)) {
- DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
- DartUtils::SetStringField(
+ result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ result = DartUtils::SetStringField(
status_handle, "_errorMessage", error_msg);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
delete[] string_args;
return NULL;
}
@@ -67,15 +84,22 @@
intptr_t process_stdout;
intptr_t process_stderr;
intptr_t exit_event;
+ Dart_Handle result;
Dart_Handle status_handle = Dart_GetNativeArgument(args, 10);
Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
// The Dart code verifies that the path implements the String
// interface. However, only builtin Strings are handled by
// GetStringValue.
if (!Dart_IsString(path_handle)) {
- DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
- DartUtils::SetStringField(
+ result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ result = DartUtils::SetStringField(
status_handle, "_errorMessage", "Path must be a builtin string");
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
Dart_SetReturnValue(args, Dart_NewBoolean(false));
return;
}
@@ -98,10 +122,16 @@
working_directory = DartUtils::GetStringValue(working_directory_handle);
} else if (!Dart_IsNull(working_directory_handle)) {
delete[] string_args;
- DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
- DartUtils::SetStringField(
+ result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ result = DartUtils::SetStringField(
status_handle, "_errorMessage",
"WorkingDirectory must be a builtin string");
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
Dart_SetReturnValue(args, Dart_NewBoolean(false));
return;
}
@@ -153,13 +183,19 @@
}
Process::SetProcessIdNativeField(process, pid);
} else {
- DartUtils::SetIntegerField(
+ result = DartUtils::SetIntegerField(
status_handle, "_errorCode", error_code);
- DartUtils::SetStringField(
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ result = DartUtils::SetStringField(
status_handle,
"_errorMessage",
os_error_message != NULL ? os_error_message
: "Cannot get error message");
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
}
delete[] string_args;
delete[] string_environment;
@@ -218,11 +254,17 @@
int64_t status = 0;
// Ignore result if passing invalid argument and just exit 0.
DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 0), &status);
- Dart_ExitIsolate();
- Dart_Cleanup();
- DebuggerConnectionHandler::StopHandler();
- // TODO(zra): Stop the EventHandler once thread shutdown is enabled.
- // EventHandler::Stop();
+ Dart_ShutdownIsolate();
+ Process::TerminateExitCodeHandler();
+ char* error = Dart_Cleanup();
+ if (error != NULL) {
+ Log::PrintErr("VM cleanup failed: %s\n", error);
+ free(error);
+ }
+ if (do_vm_shutdown) {
+ DebuggerConnectionHandler::StopHandler();
+ EventHandler::Stop();
+ }
exit(static_cast<int>(status));
}
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index b6d40ee..1917b46 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -176,10 +176,9 @@
// implicit constructor.
class _ProcessImplNativeWrapper extends NativeFieldWrapperClass1 {}
-class _ProcessImpl extends _ProcessImplNativeWrapper with _ServiceObject
- implements Process {
- // Use default Map so we keep order.
- static Map<int, _ProcessImpl> _processes = new Map<int, _ProcessImpl>();
+class _ProcessImpl extends _ProcessImplNativeWrapper implements Process {
+ _ProcessResourceInfo _resourceInfo;
+ static bool connectedResourceHandler = false;
_ProcessImpl(String path,
List<String> arguments,
@@ -188,7 +187,14 @@
bool includeParentEnvironment,
bool runInShell,
ProcessStartMode mode) : super() {
- _processes[_serviceId] = this;
+ if (!connectedResourceHandler) {
+ registerExtension('__getProcesses',
+ _ProcessResourceInfo.getStartedProcesses);
+ registerExtension('__getProcessById',
+ _ProcessResourceInfo.getProcessInfoMapById);
+ connectedResourceHandler = true;
+ }
+
if (runInShell) {
arguments = _getShellArguments(path, arguments);
path = _getShellCommand();
@@ -267,38 +273,6 @@
_started = false;
}
- String get _serviceTypePath => 'io/processes';
- String get _serviceTypeName => 'Process';
-
- Map _toJSON(bool ref) {
- var r = {
- 'id': _servicePath,
- 'type': _serviceType(ref),
- 'name': '$_path',
- 'user_name': '$_path',
- 'pid': '$pid',
- 'arguments': _arguments.join(' '),
- };
- if (ref) {
- return r;
- }
- r['started'] = _started;
- r['ended'] = _ended;
- r['path'] = _path;
- r['environment'] = _environment;
- r['workingDirectory'] = _workingDirectory == null ? '.' : _workingDirectory;
- if (_stdin._sink._nativeSocket.owner != null) {
- r['stdin'] = _stdin._sink._nativeSocket._toJSON(true);
- }
- if (_stdout._stream._nativeSocket.owner != null) {
- r['stdout'] = _stdout._stream._nativeSocket._toJSON(true);
- }
- if (_stderr._stream._nativeSocket.owner != null) {
- r['stderr'] = _stderr._stream._nativeSocket._toJSON(true);
- }
- return r;
- }
-
static String _getShellCommand() {
if (Platform.isWindows) {
return 'cmd.exe';
@@ -418,6 +392,7 @@
}
_started = true;
+ _resourceInfo = new _ProcessResourceInfo(this);
// Setup an exit handler to handle internal cleanup and possible
// callback when a process terminates.
@@ -439,7 +414,7 @@
_exitCode.complete(exitCode(exitDataBuffer));
// Kill stdin, helping hand if the user forgot to do it.
_stdin._sink.destroy();
- _processes.remove(_serviceId);
+ _resourceInfo.stopped();
}
exitDataBuffer.setRange(
@@ -477,6 +452,8 @@
status._errorCode);
}
+ _resourceInfo = new _ProcessResourceInfo(this);
+
var result = _wait(
_stdin._sink._nativeSocket,
_stdout._stream._nativeSocket,
@@ -488,7 +465,7 @@
return encoding.decode(output);
}
- _processes.remove(_serviceId);
+ _resourceInfo.stopped();
return new ProcessResult(
result[0],
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index e821cc2..c45a2a0 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -114,6 +114,12 @@
TestCaseBase::RunAll();
// Apply the filter to all registered benchmarks.
Benchmark::RunAll(argv[0]);
+
+ if (Flags::IsSet("shutdown")) {
+ err_msg = Dart::Cleanup();
+ ASSERT(err_msg == NULL);
+ }
+
// Print a warning message if no tests or benchmarks were matched.
if (run_matches == 0) {
fprintf(stderr, "No tests matched: %s\n", run_filter);
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index be459ba..47e5f44 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -313,8 +313,6 @@
bool writeEventIssued = false;
bool writeAvailable = false;
- static final Stopwatch sw = new Stopwatch()..start();
-
static bool connectedResourceHandler = false;
_ReadWriteResourceInfo resourceInfo;
@@ -584,8 +582,7 @@
// TODO(ricow): Remove when we track internal and pipe uses.
assert(resourceInfo != null || isPipe || isInternal);
if (resourceInfo != null) {
- resourceInfo.readCount++;
- resourceInfo.lastRead = timestamp;
+ resourceInfo.didRead();
}
return result;
}
@@ -612,8 +609,7 @@
// TODO(ricow): Remove when we track internal and pipe uses.
assert(resourceInfo != null || isPipe || isInternal);
if (resourceInfo != null) {
- resourceInfo.readCount++;
- resourceInfo.lastRead = timestamp;
+ resourceInfo.didRead();
}
return result;
}
@@ -656,9 +652,7 @@
// TODO(ricow): Remove when we track internal and pipe uses.
assert(resourceInfo != null || isPipe || isInternal);
if (resourceInfo != null) {
- resourceInfo.totalWritten += result;
- resourceInfo.writeCount++;
- resourceInfo.lastWrite = timestamp;
+ resourceInfo.addWrite(result);
}
return result;
}
@@ -679,9 +673,7 @@
// TODO(ricow): Remove when we track internal and pipe uses.
assert(resourceInfo != null || isPipe || isInternal);
if (resourceInfo != null) {
- resourceInfo.totalWritten += result;
- resourceInfo.writeCount++;
- resourceInfo.lastWrite = timestamp;
+ resourceInfo.addWrite(result);
}
return result;
}
@@ -701,8 +693,8 @@
// TODO(ricow): Remove when we track internal and pipe uses.
assert(resourceInfo != null || isPipe || isInternal);
if (resourceInfo != null) {
- resourceInfo.totalRead += 1;
- resourceInfo.lastRead = timestamp;
+ // We track this as read one byte.
+ resourceInfo.addRead(1);
}
return socket;
}
diff --git a/runtime/bin/utils.h b/runtime/bin/utils.h
index bb55a76..2c3f1fc 100644
--- a/runtime/bin/utils.h
+++ b/runtime/bin/utils.h
@@ -11,7 +11,6 @@
#include "include/dart_api.h"
#include "platform/globals.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index a672bf2..34d5715 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -16,6 +16,12 @@
socket.done.then((_) => close());
}
+ disconnect() {
+ if (socket != null) {
+ socket.close();
+ }
+ }
+
void onWebSocketMessage(message) {
if (message is String) {
var map;
@@ -68,6 +74,11 @@
HttpRequestClient(this.request, VMService service)
: super(service, sendEvents:false);
+ disconnect() {
+ request.response.close();
+ close();
+ }
+
void post(String result) {
if (result == null) {
close();
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index 409bc59..d9b0c75 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -89,6 +89,15 @@
// scheduled microtasks.
Timer.run(() {});
}
+ // TODO(johnmccutchan, turnidge) Creating a VMService object here causes
+ // strange behavior from the legacy debug protocol and coverage tool.
+ // Enable this code, and remove the call to Isolate::KillIsolate() from
+ // service_isolate.cc when the strange behavior is solved.
+ // See: https://github.com/dart-lang/sdk/issues/23977
+ // else {
+ // var service = new VMService();
+ // service.onShutdown = _onShutdown;
+ // }
scriptLoadPort.handler = _processLoadRequest;
// Register signal handler after a small delay to avoid stalling main
// isolate startup.
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 3037ad6..553093f 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -159,6 +159,7 @@
char VmService::server_ip_[kServerIpStringBufferSize];
intptr_t VmService::server_port_ = 0;
+
bool VmService::Setup(const char* server_ip, intptr_t server_port) {
Dart_Isolate isolate = Dart_CurrentIsolate();
ASSERT(isolate != NULL);
@@ -203,7 +204,8 @@
SHUTDOWN_ON_ERROR(library);
// Set HTTP server state.
- DartUtils::SetStringField(library, "_ip", server_ip);
+ result = DartUtils::SetStringField(library, "_ip", server_ip);
+ SHUTDOWN_ON_ERROR(result);
// If we have a port specified, start the server immediately.
bool auto_start = server_port >= 0;
if (server_port < 0) {
@@ -211,7 +213,8 @@
// port when the HTTP server is started.
server_port = 0;
}
- DartUtils::SetIntegerField(library, "_port", server_port);
+ result = DartUtils::SetIntegerField(library, "_port", server_port);
+ SHUTDOWN_ON_ERROR(result);
result = Dart_SetField(library,
DartUtils::NewString("_autoStart"),
Dart_NewBoolean(auto_start));
diff --git a/runtime/bin/net/zlib.gyp b/runtime/bin/zlib.gyp
similarity index 87%
rename from runtime/bin/net/zlib.gyp
rename to runtime/bin/zlib.gyp
index 8aa920d..6f2f913 100644
--- a/runtime/bin/net/zlib.gyp
+++ b/runtime/bin/zlib.gyp
@@ -6,17 +6,18 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-# This file is a modified copy of src/third_party/zlib/zlib.gyp from Chromium.
-# Revision 291806 (this should agree with "nss_rev" in DEPS).
+# This file is a modified copy of
+# https://chromium.googlesource.com/chromium/src/third_party/zlib/zlib.gyp
+# at revision c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f.
{
# Added by Dart. All Dart comments refer to the following block or line.
'includes': [
- '../../tools/gyp/runtime-configurations.gypi',
- '../../tools/gyp/nss_configurations.gypi',
+ '../tools/gyp/runtime-configurations.gypi',
+ '../tools/gyp/nss_configurations.gypi',
],
'variables': {
# Added by Dart.
- 'zlib_path': '../../../third_party/zlib',
+ 'zlib_path': '../../third_party/zlib',
},
# Added by Dart. We do not indent, so diffs with the original are clearer.
'conditions': [[ 'dart_io_support==1', {
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 15114a6..9042eff 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -368,7 +368,6 @@
} \
} \
-
/**
* Converts an object to a string.
*
@@ -863,9 +862,10 @@
* \param shutdown A function to be called when an isolate is shutdown.
* See Dart_IsolateShutdownCallback.
*
- * \return True if initialization is successful.
+ * \return NULL if initialization is successful. Returns an error message
+ * otherwise. The caller is responsible for freeing the error message.
*/
-DART_EXPORT bool Dart_Initialize(
+DART_EXPORT char* Dart_Initialize(
const uint8_t* vm_isolate_snapshot,
const uint8_t* instructions_snapshot,
Dart_IsolateCreateCallback create,
@@ -881,9 +881,10 @@
/**
* Cleanup state in the VM before process termination.
*
- * \return True if cleanup is successful.
+ * \return NULL if cleanup is successful. Returns an error message otherwise.
+ * The caller is responsible for freeing the error message.
*/
-DART_EXPORT bool Dart_Cleanup();
+DART_EXPORT char* Dart_Cleanup();
/**
* Sets command line flags. Should be called before Dart_Initialize.
diff --git a/runtime/lib/array.cc b/runtime/lib/array.cc
index 003f12f..b95e6b0 100644
--- a/runtime/lib/array.cc
+++ b/runtime/lib/array.cc
@@ -22,7 +22,7 @@
const Array& array = Array::CheckedHandle(arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
if ((index.Value() < 0) || (index.Value() >= array.Length())) {
- Exceptions::ThrowRangeError("index", index, 0, array.Length());
+ Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
}
return array.At(index.Value());
}
@@ -33,7 +33,7 @@
GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
const Instance& value = Instance::CheckedHandle(arguments->NativeArgAt(2));
if ((index.Value() < 0) || (index.Value() >= array.Length())) {
- Exceptions::ThrowRangeError("index", index, 0, array.Length());
+ Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
}
array.SetAt(index.Value(), value);
return Object::null();
@@ -52,22 +52,22 @@
GET_NON_NULL_NATIVE_ARGUMENT(Smi, start, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, count, arguments->NativeArgAt(2));
GET_NON_NULL_NATIVE_ARGUMENT(Bool, needs_type_arg, arguments->NativeArgAt(3));
+ intptr_t istart = start.Value();
+ if ((istart < 0) || (istart > src.Length())) {
+ Exceptions::ThrowRangeError(
+ "start",
+ start,
+ 0,
+ src.Length());
+ }
intptr_t icount = count.Value();
// Zero count should be handled outside already.
if ((icount <= 0) || (icount > src.Length())) {
Exceptions::ThrowRangeError(
"count",
- Smi::Handle(Smi::New(icount)),
- 1,
- src.Length() + 1);
- }
- intptr_t istart = start.Value();
- if ((istart < 0) || ((istart + icount) > src.Length())) {
- Exceptions::ThrowRangeError(
- "start",
- Smi::Handle(Smi::New(istart)),
- 0,
- src.Length() - icount + 1);
+ count,
+ 0, // This is the limit the user sees.
+ src.Length() - istart);
}
return src.Slice(istart, icount, needs_type_arg.value());
diff --git a/runtime/lib/bigint.dart b/runtime/lib/bigint.dart
index a278595..ae941b7 100644
--- a/runtime/lib/bigint.dart
+++ b/runtime/lib/bigint.dart
@@ -1745,7 +1745,7 @@
_absSub(d_digits, abcd_used, b_digits, abcd_used, d_digits);
} else {
_absSub(b_digits, abcd_used, d_digits, abcd_used, d_digits);
- d_neg = !d_neg && (d_cmp_ab != 0);
+ d_neg = !d_neg && (d_cmp_b != 0);
}
} else {
_absAdd(d_digits, abcd_used, b_digits, abcd_used, d_digits);
diff --git a/runtime/lib/growable_array.cc b/runtime/lib/growable_array.cc
index 8181e73..e892813 100644
--- a/runtime/lib/growable_array.cc
+++ b/runtime/lib/growable_array.cc
@@ -20,7 +20,7 @@
Exceptions::ThrowRangeError(
"length",
Integer::Handle(Integer::New(data.Length())),
- 1,
+ 0, // This is the limit the user sees.
Array::kMaxElements);
}
const GrowableObjectArray& new_array =
@@ -35,7 +35,7 @@
GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
if ((index.Value() < 0) || (index.Value() >= array.Length())) {
- Exceptions::ThrowRangeError("index", index, 0, array.Length());
+ Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
}
const Instance& obj = Instance::CheckedHandle(array.At(index.Value()));
return obj.raw();
@@ -47,7 +47,7 @@
GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
if ((index.Value() < 0) || (index.Value() >= array.Length())) {
- Exceptions::ThrowRangeError("index", index, 0, array.Length());
+ Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
}
GET_NON_NULL_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(2));
array.SetAt(index.Value(), value);
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index bd79837..39b4522 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -70,14 +70,13 @@
}
void removeRange(int start, int end) {
- Lists.indicesCheck(this, start, end);
+ RangeError.checkValidRange(start, end, this.length);
Lists.copy(this, end, this, start, this.length - end);
this.length = this.length - (end - start);
}
List<T> sublist(int start, [int end]) {
- Lists.indicesCheck(this, start, end);
- if (end == null) end = this.length;
+ end = RangeError.checkValidRange(start, end, this.length);
int length = end - start;
if (length == 0) return <T>[];
List list = new _List(length);
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index b1ca62c..e8d655c 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -275,7 +275,9 @@
case Token::kSHL:
return Integer::New(mint_value << shift_count, Heap::kNew, silent);
case Token::kSHR:
- return Integer::New(mint_value >> -shift_count, Heap::kNew, silent);
+ shift_count =
+ (-shift_count > Mint::kBits) ? Mint::kBits : -shift_count;
+ return Integer::New(mint_value >> shift_count, Heap::kNew, silent);
default:
UNIMPLEMENTED();
}
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index e3dbec1..51b7ac0 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -130,6 +130,8 @@
return sendPort.hashCode();
}
+ Uri get remotePortUri => new Uri.https('localhost', '55');
+
/**** Internal implementation details ****/
_get_id() native "RawReceivePortImpl_get_id";
_get_sendport() native "RawReceivePortImpl_get_sendport";
@@ -306,11 +308,17 @@
/* patch */ static Future<Isolate> spawnUri(
Uri uri, List<String> args, var message,
- {bool paused: false, bool checked, Uri packageRoot, bool errorsAreFatal,
- SendPort onExit, SendPort onError}) {
+ {bool paused: false,
+ bool checked,
+ Uri packageRoot,
+ Map<String, Uri> packages,
+ bool errorsAreFatal,
+ SendPort onExit,
+ SendPort onError}) {
RawReceivePort readyPort;
try {
// The VM will invoke [_startIsolate] and not `main`.
+ // TODO: Handle [packages].
readyPort = new RawReceivePort();
var packageRootString =
(packageRoot == null) ? null : packageRoot.toString();
diff --git a/runtime/lib/map_patch.dart b/runtime/lib/map_patch.dart
index 682ba03..8a8359a 100644
--- a/runtime/lib/map_patch.dart
+++ b/runtime/lib/map_patch.dart
@@ -20,4 +20,6 @@
/* patch */ factory Map.unmodifiable(Map other) {
return new UnmodifiableMapView<K, V>(new Map.from(other));
}
+
+ /* patch */ factory Map() = LinkedHashMap<K, V>;
}
diff --git a/runtime/lib/simd128.cc b/runtime/lib/simd128.cc
index b9bf55c..4492555 100644
--- a/runtime/lib/simd128.cc
+++ b/runtime/lib/simd128.cc
@@ -14,7 +14,7 @@
static void ThrowMaskRangeException(int64_t m) {
if ((m < 0) || (m > 255)) {
Exceptions::ThrowRangeError(
- "mask", Integer::Handle(Integer::New(m)), 0, 256);
+ "mask", Integer::Handle(Integer::New(m)), 0, 255);
}
}
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 9d4137d..2eae245 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -515,7 +515,7 @@
}
// An index larger than Smi is always illegal.
- Exceptions::ThrowRangeError("index", index, 0, str.Length());
+ Exceptions::ThrowRangeError("index", index, 0, str.Length() - 1);
return 0;
}
@@ -601,7 +601,7 @@
intptr_t array_length = codeUnits.Length();
intptr_t length_value = length.Value();
if (length_value < 0 || length_value > array_length) {
- Exceptions::ThrowRangeError("length", length, 0, array_length + 1);
+ Exceptions::ThrowRangeError("length", length, 0, array_length);
}
const String& result = isLatin1.value()
? String::Handle(OneByteString::New(length_value, Heap::kNew))
diff --git a/runtime/lib/typed_data.dart b/runtime/lib/typed_data.dart
index f70781a..a56c39f 100644
--- a/runtime/lib/typed_data.dart
+++ b/runtime/lib/typed_data.dart
@@ -477,9 +477,8 @@
}
List sublist(int start, [int end]) {
- if (end == null) end = this.length;
+ end = RangeError.checkValidRange(start, end, this.length);
var length = end - start;
- _rangeCheck(this.length, start, length);
List result = _createList(length);
result.setRange(0, length, this, start);
return result;
diff --git a/runtime/observatory/lib/service_common.dart b/runtime/observatory/lib/service_common.dart
index cde76a2..ba55349 100644
--- a/runtime/observatory/lib/service_common.dart
+++ b/runtime/observatory/lib/service_common.dart
@@ -88,7 +88,7 @@
int _requestSerial = 0;
bool _hasInitiatedConnect = false;
bool _hasFinishedConnect = false;
- Utf8Decoder _utf8Decoder = new Utf8Decoder();
+ Utf8Decoder _utf8Decoder = const Utf8Decoder();
CommonWebSocket _webSocket;
diff --git a/runtime/observatory/lib/src/debugger/debugger_location.dart b/runtime/observatory/lib/src/debugger/debugger_location.dart
index 469609b..a517cd2 100644
--- a/runtime/observatory/lib/src/debugger/debugger_location.dart
+++ b/runtime/observatory/lib/src/debugger/debugger_location.dart
@@ -52,8 +52,8 @@
Script script = frame.location.script;
return script.load().then((_) {
var line = script.tokenToLine(frame.location.tokenPos);
- // TODO(turnidge): Pass in the column here once the protocol supports it.
- return new Future.value(new DebuggerLocation.file(script, line, null));
+ var col = script.tokenToCol(frame.location.tokenPos);
+ return new Future.value(new DebuggerLocation.file(script, line, col));
});
}
@@ -101,8 +101,11 @@
return new Future.value(new DebuggerLocation.error(
'A script must be provided when the stack is empty'));
}
- Script script = stack['frames'][0].location.script;
- return new Future.value(new DebuggerLocation.file(script, line, col));
+ var frame = stack['frames'][debugger.currentFrame];
+ Script script = frame.location.script;
+ return script.load().then((_) {
+ return new Future.value(new DebuggerLocation.file(script, line, col));
+ });
}
}
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index f652da1..66c9609 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -637,7 +637,7 @@
Future run(List<String> args) async {
if (args.length > 1) {
debugger.console.print('not implemented');
- return new Future.value(null);
+ return;
}
var arg = (args.length == 0 ? '' : args[0]);
var loc = await DebuggerLocation.parse(debugger, arg);
@@ -654,14 +654,15 @@
}
} else {
assert(loc.script != null);
- if (loc.col != null) {
- // TODO(turnidge): Add tokenPos breakpoint support.
+ var script = loc.script;
+ await script.load();
+ if (loc.line < 1 || loc.line > script.lines.length) {
debugger.console.print(
- 'Ignoring column: '
- 'adding breakpoint at a specific column not yet implemented');
- }
+ 'line number must be in range [1,${script.lines.length}]');
+ return;
+ }
try {
- await debugger.isolate.addBreakpoint(loc.script, loc.line);
+ await debugger.isolate.addBreakpoint(script, loc.line, loc.col);
} on ServerRpcException catch(e) {
if (e.code == ServerRpcException.kCannotAddBreakpoint) {
debugger.console.print('Unable to set breakpoint at ${loc}');
@@ -718,48 +719,50 @@
class ClearCommand extends DebuggerCommand {
ClearCommand(Debugger debugger) : super(debugger, 'clear', []);
- Future run(List<String> args) {
+ Future run(List<String> args) async {
if (args.length > 1) {
debugger.console.print('not implemented');
- return new Future.value(null);
+ return;
}
var arg = (args.length == 0 ? '' : args[0]);
- return DebuggerLocation.parse(debugger, arg).then((loc) {
- if (loc.valid) {
- if (loc.function != null) {
- debugger.console.print(
- 'Ignoring breakpoint at $loc: '
- 'Function entry breakpoints not yet implemented');
- return null;
- }
- if (loc.col != null) {
- // TODO(turnidge): Add tokenPos clear support.
- debugger.console.print(
- 'Ignoring column: '
- 'clearing breakpoint at a specific column not yet implemented');
- }
+ var loc = await DebuggerLocation.parse(debugger, arg);
+ if (!loc.valid) {
+ debugger.console.print(loc.errorMessage);
+ return;
+ }
+ if (loc.function != null) {
+ debugger.console.print(
+ 'Ignoring breakpoint at $loc: '
+ 'Clearing function breakpoints not yet implemented');
+ return;
+ }
- for (var bpt in debugger.isolate.breakpoints.values) {
- var script = bpt.location.script;
- if (script.id == loc.script.id) {
- assert(script.loaded);
- var line = script.tokenToLine(bpt.location.tokenPos);
- if (line == loc.line) {
- return debugger.isolate.removeBreakpoint(bpt).then((result) {
- if (result is DartError) {
- debugger.console.print(
- 'Unable to clear breakpoint at ${loc}: ${result.message}');
- return;
- }
- });
- }
+ var script = loc.script;
+ if (loc.line < 1 || loc.line > script.lines.length) {
+ debugger.console.print(
+ 'line number must be in range [1,${script.lines.length}]');
+ return;
+ }
+ var lineInfo = script.getLine(loc.line);
+ var bpts = lineInfo.breakpoints;
+ var foundBreakpoint = false;
+ if (bpts != null) {
+ var bptList = bpts.toList();
+ for (var bpt in bptList) {
+ if (loc.col == null ||
+ loc.col == script.tokenToCol(bpt.location.tokenPos)) {
+ foundBreakpoint = true;
+ var result = await debugger.isolate.removeBreakpoint(bpt);
+ if (result is DartError) {
+ debugger.console.print(
+ 'Error clearing breakpoint ${bpt.number}: ${result.message}');
}
}
- debugger.console.print('No breakpoint found at ${loc}');
- } else {
- debugger.console.print(loc.errorMessage);
}
- });
+ }
+ if (!foundBreakpoint) {
+ debugger.console.print('No breakpoint found at ${loc}');
+ }
}
Future<List<String>> complete(List<String> args) {
@@ -846,7 +849,7 @@
InfoBreakpointsCommand(Debugger debugger)
: super(debugger, 'breakpoints', []);
- Future run(List<String> args) {
+ Future run(List<String> args) async {
if (debugger.isolate.breakpoints.isEmpty) {
debugger.console.print('No breakpoints');
}
@@ -854,19 +857,15 @@
bpts.sort((a, b) => a.number - b.number);
for (var bpt in bpts) {
var bpId = bpt.number;
- var script = bpt.location.script;
- var tokenPos = bpt.location.tokenPos;
- var line = script.tokenToLine(tokenPos);
- var col = script.tokenToCol(tokenPos);
+ var locString = await bpt.location.toUserString();
if (!bpt.resolved) {
debugger.console.print(
- 'Future breakpoint ${bpId} at ${script.name}:${line}:${col}');
+ 'Future breakpoint ${bpId} at ${locString}');
} else {
debugger.console.print(
- 'Breakpoint ${bpId} at ${script.name}:${line}:${col}');
+ 'Breakpoint ${bpId} at ${locString}');
}
}
- return new Future.value(null);
}
String helpShort = 'List all breakpoints';
@@ -1388,7 +1387,7 @@
}
}
- Future _reportBreakpointEvent(ServiceEvent event) {
+ Future _reportBreakpointEvent(ServiceEvent event) async {
var bpt = event.breakpoint;
var verb = null;
switch (event.kind) {
@@ -1405,19 +1404,17 @@
break;
}
var script = bpt.location.script;
- return script.load().then((_) {
- var bpId = bpt.number;
- var tokenPos = bpt.location.tokenPos;
- var line = script.tokenToLine(tokenPos);
- var col = script.tokenToCol(tokenPos);
- if (bpt.resolved) {
- console.print(
- 'Breakpoint ${bpId} ${verb} at ${script.name}:${line}:${col}');
- } else {
- console.print(
- 'Future breakpoint ${bpId} ${verb} at ${script.name}:${line}:${col}');
- }
- });
+ await script.load();
+
+ var bpId = bpt.number;
+ var locString = await bpt.location.toUserString();
+ if (bpt.resolved) {
+ console.print(
+ 'Breakpoint ${bpId} ${verb} at ${locString}');
+ } else {
+ console.print(
+ 'Future breakpoint ${bpId} ${verb} at ${locString}');
+ }
}
void onEvent(ServiceEvent event) {
@@ -1658,16 +1655,16 @@
var event = isolate.pauseEvent;
if (event.kind == ServiceEvent.kPauseStart) {
console.print("Type 'continue' [F7] or 'step' [F10] to start the isolate");
- return;
+ return null;
}
if (event.kind == ServiceEvent.kPauseExit) {
console.print("Type 'continue' [F7] to exit the isolate");
- return;
+ return null;
}
return isolate.stepOver();
} else {
console.print('The program is already running');
- return;
+ return null;
}
}
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index 8a95467..d9d9b64 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -121,9 +121,18 @@
BreakpointAnnotation(this.bpt) {
var script = bpt.location.script;
- var pos = bpt.location.tokenPos;
- line = script.tokenToLine(pos);
- columnStart = script.tokenToCol(pos) - 1; // tokenToCol is 1-origin.
+ var location = bpt.location;
+ if (location.tokenPos != null) {
+ var pos = location.tokenPos;
+ line = script.tokenToLine(pos);
+ columnStart = script.tokenToCol(pos) - 1; // tokenToCol is 1-origin.
+ } else if (location is UnresolvedSourceLocation) {
+ line = location.line;
+ columnStart = location.column;
+ if (columnStart == null) {
+ columnStart = 0;
+ }
+ }
var length = script.guessTokenLength(line, columnStart);
if (length == null) {
length = 1;
@@ -139,7 +148,11 @@
var pos = bpt.location.tokenPos;
int line = script.tokenToLine(pos);
int column = script.tokenToCol(pos);
- element.classes.add("breakAnnotation");
+ if (bpt.resolved) {
+ element.classes.add("resolvedBreakAnnotation");
+ } else {
+ element.classes.add("unresolvedBreakAnnotation");
+ }
element.title = "Breakpoint ${bpt.number} at ${line}:${column}";
}
}
@@ -448,6 +461,11 @@
Element a(String text) => new AnchorElement()..text = text;
Element span(String text) => new SpanElement()..text = text;
+ Element hitsCurrent(Element element) {
+ element.classes.add('hitsCurrent');
+ element.title = "";
+ return element;
+ }
Element hitsUnknown(Element element) {
element.classes.add('hitsNone');
element.title = "";
@@ -930,7 +948,9 @@
var e = span("$nbsp$lineNumber$nbsp");
e.classes.add('noCopy');
- if ((line == null) || (line.hits == null)) {
+ if (lineNumber == _currentLine) {
+ hitsCurrent(e);
+ } else if ((line == null) || (line.hits == null)) {
hitsUnknown(e);
} else if (line.hits == 0) {
hitsNotExecuted(e);
@@ -1000,4 +1020,3 @@
@published bool inDebuggerContext = false;
@published ObservableList variables;
}
-
diff --git a/runtime/observatory/lib/src/elements/script_inset.html b/runtime/observatory/lib/src/elements/script_inset.html
index ac2c08c..a76ae42 100644
--- a/runtime/observatory/lib/src/elements/script_inset.html
+++ b/runtime/observatory/lib/src/elements/script_inset.html
@@ -39,11 +39,7 @@
.currentCol {
background-color: #6cf;
}
- .breakAnnotation {
- background-color: #e66;
- color: white;
- }
- .hitsNone, .hitsNotExecuted, .hitsExecuted {
+ .hitsCurrent, .hitsNone, .hitsNotExecuted, .hitsExecuted {
display: table-cell;
vertical-align: top;
font: 400 14px consolas, courier, monospace;
@@ -52,6 +48,10 @@
text-align: right;
color: #a8a8a8;
}
+ .hitsCurrent {
+ background-color: #6cf;
+ color: black;
+ }
.hitsNotExecuted {
background-color: #faa;
}
@@ -87,6 +87,14 @@
color: white;
background-color: #e66;
}
+ .unresolvedBreakAnnotation {
+ color: white;
+ background-color: #cac;
+ }
+ .resolvedBreakAnnotation {
+ color: white;
+ background-color: #e66;
+ }
</style>
</template>
</polymer-element>
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index cf244e4..fac9fc5 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -217,6 +217,9 @@
case 'SourceLocation':
obj = new SourceLocation._empty(owner);
break;
+ case 'UnresolvedSourceLocation':
+ obj = new UnresolvedSourceLocation._empty(owner);
+ break;
case 'Object':
switch (vmType) {
case 'ICData':
@@ -426,12 +429,27 @@
ServiceObject getFromMap(ObservableMap map);
}
+abstract class Location {
+ Script get script;
+ int get tokenPos;
+}
+
/// A [SourceLocation] represents a location or range in the source code.
-class SourceLocation extends ServiceObject {
+class SourceLocation extends ServiceObject implements Location {
Script script;
int tokenPos;
int endTokenPos;
+ Future<int> getLine() async {
+ await script.load();
+ return script.tokenToLine(tokenPos);
+ }
+
+ Future<int> getColumn() async {
+ await script.load();
+ return script.tokenToCol(tokenPos);
+ }
+
SourceLocation._empty(ServiceObject owner) : super._empty(owner);
void _update(ObservableMap map, bool mapIsRef) {
@@ -439,8 +457,15 @@
_upgradeCollection(map, owner);
script = map['script'];
tokenPos = map['tokenPos'];
- assert(script != null && tokenPos != null);
endTokenPos = map['endTokenPos'];
+
+ assert(script != null && tokenPos != null);
+ }
+
+ Future<String> toUserString() async {
+ int line = await getLine();
+ int column = await getColumn();
+ return '${script.name}:${line}:${column}';
}
String toString() {
@@ -452,6 +477,86 @@
}
}
+/// An [UnresolvedSourceLocation] represents a location in the source
+// code which has not been precisely mapped to a token position.
+class UnresolvedSourceLocation extends ServiceObject implements Location {
+ Script script;
+ String scriptUri;
+ int line;
+ int column;
+ int tokenPos;
+
+ Future<int> getLine() async {
+ if (tokenPos != null) {
+ await script.load();
+ return script.tokenToLine(tokenPos);
+ } else {
+ return line;
+ }
+ }
+
+ Future<int> getColumn() async {
+ if (tokenPos != null) {
+ await script.load();
+ return script.tokenToCol(tokenPos);
+ } else {
+ return column;
+ }
+ }
+
+ UnresolvedSourceLocation._empty(ServiceObject owner) : super._empty(owner);
+
+ void _update(ObservableMap map, bool mapIsRef) {
+ assert(!mapIsRef);
+ _upgradeCollection(map, owner);
+ script = map['script'];
+ scriptUri = map['scriptUri'];
+ line = map['line'];
+ column = map['column'];
+ tokenPos = map['tokenPos'];
+
+ assert(script != null || scriptUri != null);
+ assert(line != null || tokenPos != null);
+ }
+
+ Future<String> toUserString() async {
+ StringBuffer sb = new StringBuffer();
+
+ int line = await getLine();
+ int column = await getColumn();
+
+ if (script != null) {
+ sb.write('${script.name}:');
+ } else {
+ sb.write('${scriptUri}:');
+ }
+ if (column != null) {
+ sb.write('${line}:${column}');
+ } else {
+ sb.write('${line}');
+ }
+ return sb.toString();
+ }
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ if (script != null) {
+ sb.write('${script.name}:');
+ } else {
+ sb.write('${scriptUri}:');
+ }
+ if (tokenPos != null) {
+ sb.write('token(${tokenPos})');
+ } else if (column != null) {
+ sb.write('${line}:${column}');
+ } else {
+ sb.write('${line}');
+ }
+ sb.write('[unresolved]');
+ return sb.toString();
+ }
+}
+
class _EventStreamState {
VM _vm;
String streamId;
@@ -1390,19 +1495,23 @@
}
}
- Future<ServiceObject> addBreakpoint(Script script, int line) async {
+ Future<ServiceObject> addBreakpoint(
+ Script script, int line, [int col]) async {
// TODO(turnidge): Pass line as an int instead of a string.
try {
Map params = {
'scriptId': script.id,
- 'line': '$line',
+ 'line': line.toString(),
};
+ if (col != null) {
+ params['column'] = col.toString();
+ }
Breakpoint bpt = await invokeRpc('addBreakpoint', params);
- if (bpt.resolved &&
- script.loaded &&
- script.tokenToLine(bpt.location.tokenPos) != line) {
- // TODO(turnidge): Can this still happen?
- script.getLine(line).possibleBpt = false;
+ if (bpt.resolved && script.loaded) {
+ SourceLocation loc = bpt.location;
+ if (script.tokenToLine(loc.tokenPos) != line) {
+ script.getLine(line).possibleBpt = false;
+ }
}
return bpt;
} on ServerRpcException catch(e) {
@@ -1414,6 +1523,18 @@
}
}
+ Future<ServiceObject> addBreakpointByScriptUri(
+ String uri, int line, [int col]) {
+ Map params = {
+ 'scriptUri': uri,
+ 'line': line.toString(),
+ };
+ if (col != null) {
+ params['column'] = col.toString();
+ }
+ return invokeRpc('addBreakpoint', params);
+ }
+
Future<ServiceObject> addBreakpointAtEntry(ServiceFunction function) {
return invokeRpc('addBreakpointAtEntry',
{ 'functionId': function.id });
@@ -1855,8 +1976,11 @@
// A unique integer identifier for this breakpoint.
@observable int number;
- // Source location information.
- @observable SourceLocation location;
+ // Either SourceLocation or UnresolvedSourceLocation.
+ @observable Location location;
+
+ // The breakpoint is in a file which is not yet loaded.
+ @observable bool latent;
// The breakpoint has been assigned to a final source location.
@observable bool resolved;
@@ -1869,38 +1993,25 @@
// number never changes.
assert((number == null) || (number == newNumber));
number = newNumber;
-
resolved = map['resolved'];
var oldLocation = location;
var newLocation = map['location'];
- var oldScript;
- var newScript;
- var oldTokenPos;
- var newTokenPos;
- if (oldLocation != null) {
- oldScript = location.script;
- oldTokenPos = location.tokenPos;
- }
- if (newLocation != null) {
- newScript = newLocation.script;
- newTokenPos = newLocation.tokenPos;
- }
- // script never changes
- assert((oldScript == null) || (oldScript == newScript));
- bool tokenPosChanged = oldTokenPos != newTokenPos;
- if (newScript.loaded &&
- (newTokenPos != null) &&
- tokenPosChanged) {
- // The breakpoint has moved. Remove it and add it later.
- if (oldScript != null) {
+ if (oldLocation is UnresolvedSourceLocation &&
+ newLocation is SourceLocation) {
+ // Breakpoint has been resolved. Remove old breakpoint.
+ var oldScript = oldLocation.script;
+ if (oldScript != null && oldScript.loaded) {
oldScript._removeBreakpoint(this);
}
}
location = newLocation;
- if (newScript.loaded && tokenPosChanged) {
+ var newScript = location.script;
+ if (newScript != null && newScript.loaded) {
newScript._addBreakpoint(this);
}
+
+ assert(resolved || location is UnresolvedSourceLocation);
}
void remove() {
@@ -2893,12 +3004,24 @@
}
void _addBreakpoint(Breakpoint bpt) {
- var line = tokenToLine(bpt.location.tokenPos);
+ var line;
+ if (bpt.location.tokenPos != null) {
+ line = tokenToLine(bpt.location.tokenPos);
+ } else {
+ UnresolvedSourceLocation loc = bpt.location;
+ line = loc.line;
+ }
getLine(line).addBreakpoint(bpt);
}
void _removeBreakpoint(Breakpoint bpt) {
- var line = tokenToLine(bpt.location.tokenPos);
+ var line;
+ if (bpt.location.tokenPos != null) {
+ line = tokenToLine(bpt.location.tokenPos);
+ } else {
+ UnresolvedSourceLocation loc = bpt.location;
+ line = loc.line;
+ }
if (line != null) {
getLine(line).removeBreakpoint(bpt);
}
diff --git a/runtime/observatory/observatory.gypi b/runtime/observatory/observatory.gypi
index 50cd334..4971524 100644
--- a/runtime/observatory/observatory.gypi
+++ b/runtime/observatory/observatory.gypi
@@ -30,6 +30,7 @@
'action': [
'python',
'../tools/observatory_tool.py',
+ '--sdk=True',
'--package-root', '<(PRODUCT_DIR)/packages',
'--dart-executable',
'<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart_bootstrap<(EXECUTABLE_SUFFIX)',
@@ -63,6 +64,7 @@
'action': [
'python',
'../tools/observatory_tool.py',
+ '--sdk=True',
'--package-root', '<(PRODUCT_DIR)/packages',
'--dart-executable',
'<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart_bootstrap<(EXECUTABLE_SUFFIX)',
@@ -83,6 +85,7 @@
'action': [
'python',
'../tools/observatory_tool.py',
+ '--sdk=True',
'--package-root', '<(PRODUCT_DIR)/packages',
'--dart-executable',
'<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart_bootstrap<(EXECUTABLE_SUFFIX)',
diff --git a/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart b/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
new file mode 100644
index 0000000..f1b3a10
--- /dev/null
+++ b/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
@@ -0,0 +1,215 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'deferred_library.dart' deferred as deferredLib;
+import 'dart:async';
+import 'dart:developer' as developer;
+
+int value = 0;
+
+int incValue(int amount) {
+ value += amount;
+ return amount;
+}
+
+Future testMain() async {
+ incValue(incValue(1)); // line 21
+
+ incValue(incValue(1)); // line 23
+
+ await deferredLib.loadLibrary();
+ deferredLib.deferredTest();
+}
+
+var tests = [
+ hasPausedAtStart,
+
+ // Test future breakpoints.
+ (Isolate isolate) async {
+ var rootLib = isolate.rootLibrary;
+ await rootLib.load();
+ var script = rootLib.scripts[0];
+
+ // Future breakpoint.
+ var futureBpt1 = await isolate.addBreakpoint(script, 21);
+ expect(futureBpt1.number, equals(1));
+ expect(futureBpt1.resolved, isFalse);
+ expect(await futureBpt1.location.getLine(), equals(21));
+ expect(await futureBpt1.location.getColumn(), equals(null));
+
+ // Future breakpoint with specific column.
+ var futureBpt2 = await isolate.addBreakpoint(script, 21, 3);
+ expect(futureBpt2.number, equals(2));
+ expect(futureBpt2.resolved, isFalse);
+ expect(await futureBpt2.location.getLine(), equals(21));
+ expect(await futureBpt2.location.getColumn(), equals(3));
+
+ var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+ Completer completer = new Completer();
+ var subscription;
+ var resolvedCount = 0;
+ subscription = stream.listen((ServiceEvent event) async {
+ if (event.kind == ServiceEvent.kBreakpointResolved) {
+ resolvedCount++;
+ }
+ if (event.kind == ServiceEvent.kPauseBreakpoint) {
+ subscription.cancel();
+ completer.complete(null);
+ }
+ });
+ await isolate.resume();
+ await completer.future;
+
+ // After resolution the breakpoints have assigned line & column.
+ expect(resolvedCount, equals(2));
+ expect(futureBpt1.resolved, isTrue);
+ expect(await futureBpt1.location.getLine(), equals(21));
+ expect(await futureBpt1.location.getColumn(), equals(12));
+ expect(futureBpt2.resolved, isTrue);
+ expect(await futureBpt2.location.getLine(), equals(21));
+ expect(await futureBpt2.location.getColumn(), equals(3));
+
+ // The first breakpoint hits before value is modified.
+ expect((await rootLib.evaluate('value')).valueAsString, equals('0'));
+
+ stream = await isolate.vm.getEventStream(VM.kDebugStream);
+ completer = new Completer();
+ subscription = stream.listen((ServiceEvent event) async {
+ if (event.kind == ServiceEvent.kPauseBreakpoint) {
+ subscription.cancel();
+ completer.complete(null);
+ }
+ });
+ await isolate.resume();
+ await completer.future;
+
+ // The second breakpoint hits after value has been modified once.
+ expect((await rootLib.evaluate('value')).valueAsString, equals('1'));
+
+ // Remove the breakpoints.
+ expect((await isolate.removeBreakpoint(futureBpt1)).type,
+ equals('Success'));
+ expect((await isolate.removeBreakpoint(futureBpt2)).type,
+ equals('Success'));
+ },
+
+ // Test breakpoints in deferred libraries (latent breakpoints).
+ (Isolate isolate) async {
+ var rootLib = isolate.rootLibrary;
+ var uri = rootLib.scripts[0].uri;
+ var lastSlashPos = uri.lastIndexOf('/');
+ var deferredUri =uri.substring(0, lastSlashPos) + '/deferred_library.dart';
+
+ // Latent breakpoint.
+ var latentBpt1 = await isolate.addBreakpointByScriptUri(deferredUri, 15);
+ expect(latentBpt1.number, equals(3));
+ expect(latentBpt1.resolved, isFalse);
+ expect(await latentBpt1.location.getLine(), equals(15));
+ expect(await latentBpt1.location.getColumn(), equals(null));
+
+ // Latent breakpoint with specific column.
+ var latentBpt2 =
+ await isolate.addBreakpointByScriptUri(deferredUri, 15, 3);
+ expect(latentBpt2.number, equals(4));
+ expect(latentBpt2.resolved, isFalse);
+ expect(await latentBpt2.location.getLine(), equals(15));
+ expect(await latentBpt2.location.getColumn(), equals(3));
+
+ var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+ Completer completer = new Completer();
+ var subscription;
+ var resolvedCount = 0;
+ subscription = stream.listen((ServiceEvent event) async {
+ if (event.kind == ServiceEvent.kBreakpointResolved) {
+ resolvedCount++;
+ }
+ if (event.kind == ServiceEvent.kPauseBreakpoint) {
+ subscription.cancel();
+ completer.complete(null);
+ }
+ });
+ await isolate.resume();
+ await completer.future;
+
+ // After resolution the breakpoints have assigned line & column.
+ expect(resolvedCount, equals(2));
+ expect(latentBpt1.resolved, isTrue);
+ expect(await latentBpt1.location.getLine(), equals(15));
+ expect(await latentBpt1.location.getColumn(), equals(12));
+ expect(latentBpt2.resolved, isTrue);
+ expect(await latentBpt2.location.getLine(), equals(15));
+ expect(await latentBpt2.location.getColumn(), equals(3));
+
+ // The first breakpoint hits before value is modified.
+ expect((await rootLib.evaluate('deferredLib.value')).valueAsString,
+ equals('0'));
+
+ stream = await isolate.vm.getEventStream(VM.kDebugStream);
+ completer = new Completer();
+ subscription = stream.listen((ServiceEvent event) async {
+ if (event.kind == ServiceEvent.kPauseBreakpoint) {
+ subscription.cancel();
+ completer.complete(null);
+ }
+ });
+ await isolate.resume();
+ await completer.future;
+
+ // The second breakpoint hits after value has been modified once.
+ expect((await rootLib.evaluate('deferredLib.value')).valueAsString,
+ equals('-1'));
+
+ // Remove the breakpoints.
+ expect((await isolate.removeBreakpoint(latentBpt1)).type,
+ equals('Success'));
+ expect((await isolate.removeBreakpoint(latentBpt2)).type,
+ equals('Success'));
+ },
+
+
+ // Test resolution of column breakpoints.
+ (Isolate isolate) async {
+ var script = isolate.rootLibrary.scripts[0];
+ // Try all columns, including some columns that are too big.
+ for (int col = 1; col <= 50; col++) {
+ var bpt = await isolate.addBreakpoint(script, 21, col);
+ expect(bpt.resolved, isTrue);
+ int resolvedLine = await bpt.location.getLine();
+ int resolvedCol = await bpt.location.getColumn();
+ print('21:${col} -> ${resolvedLine}:${resolvedCol}');
+ if (col <= 10) {
+ expect(resolvedLine, equals(21));
+ expect(resolvedCol, equals(3));
+ } else if (col <= 19) {
+ expect(resolvedLine, equals(21));
+ expect(resolvedCol, equals(12));
+ } else {
+ expect(resolvedLine, equals(23));
+ expect(resolvedCol, equals(12));
+ }
+ expect((await isolate.removeBreakpoint(bpt)).type, equals('Success'));
+ }
+
+ // Make sure that a zero column is an error.
+ var caughtException = false;
+ try {
+ await isolate.addBreakpoint(script, 21, 0);
+ expect(false, isTrue, reason:'Unreachable');
+ } on ServerRpcException catch(e) {
+ caughtException = true;
+ expect(e.code, equals(ServerRpcException.kInvalidParams));
+ expect(e.message,
+ "addBreakpoint: invalid 'column' parameter: 0");
+ }
+ expect(caughtException, isTrue);
+ },
+];
+
+main(args) => runIsolateTests(args, tests,
+ testeeConcurrent: testMain,
+ pause_on_start: true);
diff --git a/runtime/observatory/tests/service/debugger_location_test.dart b/runtime/observatory/tests/service/debugger_location_test.dart
index 407bd52..33ca476 100644
--- a/runtime/observatory/tests/service/debugger_location_test.dart
+++ b/runtime/observatory/tests/service/debugger_location_test.dart
@@ -59,7 +59,7 @@
return initDebugger(isolate).then((debugger) {
return DebuggerLocation.parse(debugger, '').then((DebuggerLocation loc) {
expect(loc.valid, isTrue);
- expect(loc.toString(), equals('debugger_location_test.dart:17'));
+ expect(loc.toString(), equals('debugger_location_test.dart:17:5'));
});
});
},
diff --git a/runtime/observatory/tests/service/deferred_library.dart b/runtime/observatory/tests/service/deferred_library.dart
new file mode 100644
index 0000000..d2074ee
--- /dev/null
+++ b/runtime/observatory/tests/service/deferred_library.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library deferred_library;
+
+int value = 0;
+
+int decValue(int amount) {
+ value -= amount;
+ return amount;
+}
+
+void deferredTest() {
+ decValue(decValue(1)); // line 15
+
+ decValue(decValue(1)); // line 17
+}
diff --git a/runtime/observatory/tests/service/file_service_test.dart b/runtime/observatory/tests/service/file_service_test.dart
index dbb8e53..22b5827 100644
--- a/runtime/observatory/tests/service/file_service_test.dart
+++ b/runtime/observatory/tests/service/file_service_test.dart
@@ -79,19 +79,23 @@
var writing = await isolate.invokeRpcNoUpgrade(
'__getFileByID', { 'id' : result['data'][0]['id'] });
- expect(writing['total_read'], equals(0));
- expect(writing['read_count'], equals(0));
- expect(writing['write_count'], equals(3));
- expect(writing['total_written'], equals(3));
+ expect(writing['totalRead'], equals(0));
+ expect(writing['readCount'], equals(0));
+ expect(writing['writeCount'], equals(3));
+ expect(writing['totalWritten'], equals(3));
+ expect(writing['lastWrite'], greaterThan(0));
+ expect(writing['lastRead'], equals(0));
var reading = await isolate.invokeRpcNoUpgrade(
- '__getFileByID', { 'id' : result['data'][1]['id'] });
+ '__getFileByID', { 'id' : result['data'][1]['id'] });
+ expect(reading['totalRead'], equals(5));
+ expect(reading['readCount'], equals(5));
+ expect(reading['writeCount'], equals(0));
+ expect(reading['totalWritten'], equals(0));
+ expect(reading['lastWrite'], equals(0));
+ expect(reading['lastRead'], greaterThan(0));
- expect(reading['total_read'], equals(5));
- expect(reading['read_count'], equals(5));
- expect(reading['write_count'], equals(0));
- expect(reading['total_written'], equals(0));
} finally {
await isolate.invokeRpcNoUpgrade('__cleanup', {});
}
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 8c33998..3df8d67 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,8 +12,8 @@
(VM vm) async {
var result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], equals('Version'));
- expect(result['major'], equals(2));
- expect(result['minor'], equals(1));
+ expect(result['major'], equals(3));
+ expect(result['minor'], equals(0));
expect(result['_privateMajor'], equals(0));
expect(result['_privateMinor'], equals(0));
},
diff --git a/runtime/observatory/tests/service/process_service_test.dart b/runtime/observatory/tests/service/process_service_test.dart
new file mode 100644
index 0000000..956cc77
--- /dev/null
+++ b/runtime/observatory/tests/service/process_service_test.dart
@@ -0,0 +1,127 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+Future setupProcesses() async {
+ var dir = await io.Directory.systemTemp.createTemp('file_service');
+
+ var args = ['--pause_isolates_on_start', io.Platform.script.toFilePath()];
+ var process1;
+ var process2;
+ var process3;
+
+ void closeDown() {
+ if (process1 != null) {
+ process1.kill();
+ }
+ if (process2 != null) {
+ process2.kill();
+ }
+ if (process3 != null) {
+ process3.kill();
+ }
+ dir.deleteSync(recursive: true);
+ }
+
+ Future<ServiceExtensionResponse> cleanup(ignored_a, ignored_b) {
+ closeDown();
+ var result = JSON.encode({'type' : 'foobar'});
+ return new Future.value(new ServiceExtensionResponse.result(result));
+ }
+
+ Future<ServiceExtensionResponse> setup(ignored_a, ignored_b) async {
+ try {
+ process1 = await io.Process.start(io.Platform.executable, args);
+ process2 = await io.Process.start(io.Platform.executable,
+ args..add('foobar'));
+ var codeFilePath = dir.path + io.Platform.pathSeparator + "other_file";
+ var codeFile = new io.File(codeFilePath);
+ await codeFile.writeAsString(
+ '''
+ import "dart:io";
+
+ void main() async {
+ await stdin.drain();
+ }
+ ''');
+ process3 = await io.Process.start(io.Platform.executable,
+ [codeFilePath]);
+ } catch (e) {
+ closeDown();
+ throw e;
+ }
+
+ var result =
+ JSON.encode({'type': 'foobar',
+ 'pids' : [process1.pid, process2.pid, process3.pid]});
+ return new Future.value(new ServiceExtensionResponse.result(result));
+ }
+
+ Future<ServiceExtensionResponse> closeStdin(ignored_a, ignored_b) async {
+ process3.stdin.close();
+ var result = JSON.encode({'type' : 'foobar'});
+ var returnValue =
+ new Future.value(new ServiceExtensionResponse.result(result));
+ return process3.exitCode.then((int exit) => returnValue);
+ }
+
+ registerExtension('__cleanup', cleanup);
+ registerExtension('__setup', setup);
+ registerExtension('__closeStdin', closeStdin);
+
+}
+
+var processTests = [
+ // Initial.
+ (Isolate isolate) async {
+ var setup = await isolate.invokeRpcNoUpgrade('__setup', {});
+ try {
+ var all = await isolate.invokeRpcNoUpgrade('__getProcesses', {});
+ expect(all['type'], equals('_startedprocesses'));
+
+ expect(all['data'].length, equals(3));
+
+ var first = await isolate.invokeRpcNoUpgrade(
+ '__getProcessById', { 'id' : all['data'][0]['id'] });
+ expect(first['name'], io.Platform.executable);
+ expect(first['pid'], equals(setup['pids'][0]));
+ expect(first['arguments'].contains('foobar'), isFalse);
+ expect(first['startedAt'], greaterThan(0));
+
+ var second = await isolate.invokeRpcNoUpgrade(
+ '__getProcessById', { 'id' : all['data'][1]['id'] });
+ expect(second['name'], io.Platform.executable);
+ expect(second['pid'], equals(setup['pids'][1]));
+ expect(second['arguments'].contains('foobar'), isTrue);
+ expect(second['pid'] != first['pid'], isTrue);
+ expect(second['startedAt'], greaterThan(0));
+ expect(second['startedAt'], greaterThanOrEqualTo(first['startedAt']));
+
+ var third = await isolate.invokeRpcNoUpgrade(
+ '__getProcessById', { 'id' : all['data'][2]['id'] });
+ expect(third['name'], io.Platform.executable);
+ expect(third['pid'], equals(setup['pids'][2]));
+ expect(third['pid'] != first['pid'], isTrue);
+ expect(third['pid'] != second['pid'], isTrue);
+ expect(third['startedAt'], greaterThanOrEqualTo(second['startedAt']));
+
+ await isolate.invokeRpcNoUpgrade('__closeStdin', {});
+ all = await isolate.invokeRpcNoUpgrade('__getProcesses', {});
+ expect(all['type'], equals('_startedprocesses'));
+ expect(all['data'].length, equals(2));
+ } finally {
+ await isolate.invokeRpcNoUpgrade('__cleanup', {});
+ }
+ },
+];
+
+main(args) async => runIsolateTests(args, processTests,
+ testeeBefore:setupProcesses);
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 75b4f95..088c36a 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -17,3 +17,6 @@
# Tests with known analyzer issues
[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
developer_extension_test: SkipByDesign
+
+[ $arch == arm ]
+process_service_test: Fail # Issue 24344
diff --git a/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart b/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
index aef5571..20a9b76 100644
--- a/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
+++ b/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
@@ -62,12 +62,12 @@
var server = await isolate.invokeRpcNoUpgrade(
'__getSocketByID', { 'id' : result['data'][0]['id'] });
expect(server['listening'], isTrue);
- expect(server['last_read'], equals(0));
- expect(server['total_read'], equals(0));
- expect(server['last_write'], equals(0));
- expect(server['total_written'], equals(0));
- expect(server['write_count'], equals(0));
- expect(server['read_count'], equals(0));
+ expect(server['lastRead'], equals(0));
+ expect(server['totalRead'], equals(0));
+ expect(server['lastWrite'], equals(0));
+ expect(server['totalWritten'], equals(0));
+ expect(server['writeCount'], equals(0));
+ expect(server['readCount'], equals(0));
},
];
diff --git a/runtime/observatory/tests/service/tcp_socket_service_test.dart b/runtime/observatory/tests/service/tcp_socket_service_test.dart
index 0a85611..f8dff03 100644
--- a/runtime/observatory/tests/service/tcp_socket_service_test.dart
+++ b/runtime/observatory/tests/service/tcp_socket_service_test.dart
@@ -27,15 +27,6 @@
await socket2.flush();
}
-void expectTimeBiggerThanZero(time) {
- // Stopwatch resolution on windows makes us sometimes report 0;
- if (io.Platform.isWindows) {
- expect(time, greaterThanOrEqualTo(0));
- } else {
- expect(time, greaterThan(0));
- }
-}
-
var tcpTests = [
// Initial.
(Isolate isolate) async {
@@ -57,17 +48,17 @@
'__getSocketByID', { 'id' : result['data'][0]['id'] });
expect(listening['id'], equals(result['data'][0]['id']));
expect(listening['listening'], isTrue);
- expect(listening['socket_type'], equals('TCP'));
+ expect(listening['socketType'], equals('TCP'));
expect(listening['port'], greaterThanOrEqualTo(1024));
- expectTimeBiggerThanZero(listening['last_read']);
+ expect(listening['lastRead'], greaterThan(0));
- expect(listening['total_read'], equals(2));
- expect(listening['last_write'], equals(0));
- expect(listening['total_written'], equals(0));
- expect(listening['write_count'], equals(0));
- expect(listening['read_count'], equals(0));
- expect(listening['remote_host'], equals('NA'));
- expect(listening['remote_port'], equals('NA'));
+ expect(listening['totalRead'], equals(2));
+ expect(listening['lastWrite'], equals(0));
+ expect(listening['totalWritten'], equals(0));
+ expect(listening['writeCount'], equals(0));
+ expect(listening['readCount'], equals(2));
+ expect(listening['remoteHost'], equals('NA'));
+ expect(listening['remotePort'], equals('NA'));
var client = await isolate.invokeRpcNoUpgrade(
'__getSocketByID', { 'id' : result['data'][1]['id'] });
@@ -79,8 +70,8 @@
// We expect the client to be connected on the port and
// host of the listening socket.
- expect(client['remote_port'], equals(listening['port']));
- expect(client['remote_host'], equals(listening['host']));
+ expect(client['remotePort'], equals(listening['port']));
+ expect(client['remoteHost'], equals(listening['host']));
// We expect the third socket (accepted server) to be connected to the
// same port and host as the listening socket (the listening one).
expect(server['port'], equals(listening['port']));
@@ -89,8 +80,8 @@
expect(client['listening'], isFalse);
expect(server['listening'], isFalse);
- expect(client['socket_type'], equals('TCP'));
- expect(server['socket_type'], equals('TCP'));
+ expect(client['socketType'], equals('TCP'));
+ expect(server['socketType'], equals('TCP'));
// We are using no reserved ports.
expect(client['port'], greaterThanOrEqualTo(1024));
@@ -98,76 +89,76 @@
// The client and server "mirror" each other in reads and writes, and the
// timestamps are in correct order.
- expect(client['last_read'], equals(0));
- expectTimeBiggerThanZero(server['last_read']);
- expect(client['total_read'], equals(0));
- expect(server['total_read'], equals(12));
- expect(client['read_count'], equals(0));
- expect(server['read_count'], greaterThanOrEqualTo(1));
+ expect(client['lastRead'], equals(0));
+ expect(server['lastRead'], greaterThan(0));
+ expect(client['totalRead'], equals(0));
+ expect(server['totalRead'], equals(12));
+ expect(client['readCount'], equals(0));
+ expect(server['readCount'], greaterThanOrEqualTo(1));
- expectTimeBiggerThanZero(client['last_write']);
- expect(server['last_write'], equals(0));
- expect(client['total_written'], equals(12));
- expect(server['total_written'], equals(0));
- expect(client['write_count'], greaterThanOrEqualTo(2));
- expect(server['write_count'], equals(0));
+ expect(client['lastWrite'], greaterThan(0));
+ expect(server['lastWrite'], equals(0));
+ expect(client['totalWritten'], equals(12));
+ expect(server['totalWritten'], equals(0));
+ expect(client['writeCount'], greaterThanOrEqualTo(2));
+ expect(server['writeCount'], equals(0));
// Order
// Stopwatch resolution on windows can make us have the same timestamp.
if (io.Platform.isWindows) {
- expect(server['last_read'], greaterThanOrEqualTo(client['last_write']));
+ expect(server['lastRead'], greaterThanOrEqualTo(client['lastWrite']));
} else {
- expect(server['last_read'], greaterThan(client['last_write']));
+ expect(server['lastRead'], greaterThan(client['lastWrite']));
}
- var second_client = await isolate.invokeRpcNoUpgrade(
+ var secondClient = await isolate.invokeRpcNoUpgrade(
'__getSocketByID', { 'id' : result['data'][3]['id'] });
- expect(second_client['id'], equals(result['data'][3]['id']));
- var second_server = await isolate.invokeRpcNoUpgrade(
+ expect(secondClient['id'], equals(result['data'][3]['id']));
+ var secondServer = await isolate.invokeRpcNoUpgrade(
'__getSocketByID', { 'id' : result['data'][4]['id'] });
- expect(second_server['id'], equals(result['data'][4]['id']));
+ expect(secondServer['id'], equals(result['data'][4]['id']));
// We expect the client to be connected on the port and
// host of the listening socket.
- expect(second_client['remote_port'], equals(listening['port']));
- expect(second_client['remote_host'], equals(listening['host']));
+ expect(secondClient['remotePort'], equals(listening['port']));
+ expect(secondClient['remoteHost'], equals(listening['host']));
// We expect the third socket (accepted server) to be connected to the
// same port and host as the listening socket (the listening one).
- expect(second_server['port'], equals(listening['port']));
- expect(second_server['host'], equals(listening['host']));
+ expect(secondServer['port'], equals(listening['port']));
+ expect(secondServer['host'], equals(listening['host']));
- expect(second_client['listening'], isFalse);
- expect(second_server['listening'], isFalse);
+ expect(secondClient['listening'], isFalse);
+ expect(secondServer['listening'], isFalse);
- expect(second_client['socket_type'], equals('TCP'));
- expect(second_server['socket_type'], equals('TCP'));
+ expect(secondClient['socketType'], equals('TCP'));
+ expect(secondServer['socketType'], equals('TCP'));
// We are using no reserved ports.
- expect(second_client['port'], greaterThanOrEqualTo(1024));
- expect(second_server['port'], greaterThanOrEqualTo(1024));
+ expect(secondClient['port'], greaterThanOrEqualTo(1024));
+ expect(secondServer['port'], greaterThanOrEqualTo(1024));
// The client and server "mirror" each other in reads and writes, and the
// timestamps are in correct order.
- expect(second_client['last_read'], equals(0));
- expectTimeBiggerThanZero(second_server['last_read']);
- expect(second_client['total_read'], equals(0));
- expect(second_server['total_read'], equals(12));
- expect(second_client['read_count'], equals(0));
- expect(second_server['read_count'], greaterThanOrEqualTo(1));
+ expect(secondClient['lastRead'], equals(0));
+ expect(secondServer['lastRead'], greaterThan(0));
+ expect(secondClient['totalRead'], equals(0));
+ expect(secondServer['totalRead'], equals(12));
+ expect(secondClient['readCount'], equals(0));
+ expect(secondServer['readCount'], greaterThanOrEqualTo(1));
- expectTimeBiggerThanZero(second_client['last_write']);
- expect(second_server['last_write'], equals(0));
- expect(second_client['total_written'], equals(12));
- expect(second_server['total_written'], equals(0));
- expect(second_client['write_count'], greaterThanOrEqualTo(1));
- expect(second_server['write_count'], equals(0));
+ expect(secondClient['lastWrite'], greaterThan(0));
+ expect(secondServer['lastWrite'], equals(0));
+ expect(secondClient['totalWritten'], equals(12));
+ expect(secondServer['totalWritten'], equals(0));
+ expect(secondClient['writeCount'], greaterThanOrEqualTo(1));
+ expect(secondServer['writeCount'], equals(0));
// Order
// Stopwatch resolution on windows make us sometimes report the same value.
if (io.Platform.isWindows) {
- expect(server['last_read'], greaterThanOrEqualTo(client['last_write']));
+ expect(server['lastRead'], greaterThanOrEqualTo(client['lastWrite']));
} else {
- expect(server['last_read'], greaterThan(client['last_write']));
+ expect(server['lastRead'], greaterThan(client['lastWrite']));
}
},
];
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 6c6c223..fa453df 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -164,7 +164,6 @@
isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
var subscription;
subscription = stream.listen((ServiceEvent event) {
- print("Event: $event");
if (event.kind == ServiceEvent.kPauseBreakpoint) {
print('Breakpoint reached');
subscription.cancel();
@@ -195,6 +194,41 @@
}
+Future<Isolate> hasPausedAtStart(Isolate isolate) {
+ // Set up a listener to wait for breakpoint events.
+ Completer completer = new Completer();
+ isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+ var subscription;
+ subscription = stream.listen((ServiceEvent event) {
+ if (event.kind == ServiceEvent.kPauseStart) {
+ print('Paused at isolate start');
+ subscription.cancel();
+ if (completer != null) {
+ // Reload to update isolate.pauseEvent.
+ completer.complete(isolate.reload());
+ completer = null;
+ }
+ }
+ });
+
+ // Pause may have happened before we subscribed.
+ isolate.reload().then((_) {
+ if ((isolate.pauseEvent != null) &&
+ (isolate.pauseEvent.kind == ServiceEvent.kPauseStart)) {
+ print('Paused at isolate start');
+ subscription.cancel();
+ if (completer != null) {
+ completer.complete(isolate);
+ completer = null;
+ }
+ }
+ });
+ });
+
+ return completer.future;
+}
+
+
// Currying is your friend.
IsolateTest setBreakpointAtLine(int line) {
return (Isolate isolate) async {
diff --git a/runtime/observatory/tests/service/udp_socket_service_test.dart b/runtime/observatory/tests/service/udp_socket_service_test.dart
index 6b4b3b9..49ff5e4 100644
--- a/runtime/observatory/tests/service/udp_socket_service_test.dart
+++ b/runtime/observatory/tests/service/udp_socket_service_test.dart
@@ -40,42 +40,42 @@
var server = await isolate.invokeRpcNoUpgrade(
'__getSocketByID', { 'id' : result['data'][0]['id'] });
expect(server['id'], equals(result['data'][0]['id']));
- expect(server['remote_port'], equals('NA'));
- expect(server['remote_host'], equals('NA'));
+ expect(server['remotePort'], equals('NA'));
+ expect(server['remoteHost'], equals('NA'));
expect(server['listening'], isFalse);
- expect(server['socket_type'], equals('UDP'));
+ expect(server['socketType'], equals('UDP'));
expect(server['port'], greaterThanOrEqualTo(1024));
// Stopwatch resolution on windows makes us sometimes report 0;
if (io.Platform.isWindows) {
- expect(server['last_read'], greaterThanOrEqualTo(0));
+ expect(server['lastRead'], greaterThanOrEqualTo(0));
} else {
- expect(server['last_read'], greaterThan(0));
+ expect(server['lastRead'], greaterThan(0));
}
- expect(server['total_read'], equals(6));
- expect(server['last_write'], equals(0));
- expect(server['total_written'], equals(0));
- expect(server['write_count'], equals(0));
- expect(server['read_count'], greaterThanOrEqualTo(1));
+ expect(server['totalRead'], equals(6));
+ expect(server['lastWrite'], equals(0));
+ expect(server['totalWritten'], equals(0));
+ expect(server['writeCount'], equals(0));
+ expect(server['readCount'], greaterThanOrEqualTo(1));
var client = await isolate.invokeRpcNoUpgrade(
'__getSocketByID', { 'id' : result['data'][1]['id'] });
expect(client['id'], equals(result['data'][1]['id']));
- expect(client['remote_port'], equals('NA'));
- expect(client['remote_host'], equals('NA'));
+ expect(client['remotePort'], equals('NA'));
+ expect(client['remoteHost'], equals('NA'));
expect(client['listening'], isFalse);
- expect(client['socket_type'], equals('UDP'));
+ expect(client['socketType'], equals('UDP'));
expect(client['port'], greaterThanOrEqualTo(1024));
- expect(client['last_read'], equals(0));
- expect(client['total_read'], equals(0));
+ expect(client['lastRead'], equals(0));
+ expect(client['totalRead'], equals(0));
// Stopwatch resolution on windows makes us sometimes report 0;
if (io.Platform.isWindows) {
- expect(client['last_write'], greaterThanOrEqualTo(0));
+ expect(client['lastWrite'], greaterThanOrEqualTo(0));
} else {
- expect(client['last_write'], greaterThan(0));
+ expect(client['lastWrite'], greaterThan(0));
}
- expect(client['total_written'], equals(6));
- expect(client['write_count'], greaterThanOrEqualTo(1));
- expect(client['read_count'], equals(0));
+ expect(client['totalWritten'], equals(6));
+ expect(client['writeCount'], greaterThanOrEqualTo(1));
+ expect(client['readCount'], equals(0));
},
];
diff --git a/runtime/observatory/tests/ui/inspector.dart b/runtime/observatory/tests/ui/inspector.dart
index b133e91..fd6d0c3 100644
--- a/runtime/observatory/tests/ui/inspector.dart
+++ b/runtime/observatory/tests/ui/inspector.dart
@@ -6,7 +6,6 @@
library manual_inspector_test;
-import 'dart:async';
import 'dart:isolate';
import 'dart:mirrors';
import 'dart:developer';
diff --git a/runtime/tests/vm/dart/spawn_infinite_loop_test.dart b/runtime/tests/vm/dart/spawn_infinite_loop_test.dart
new file mode 100644
index 0000000..cc0fb42
--- /dev/null
+++ b/runtime/tests/vm/dart/spawn_infinite_loop_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+// This test ensures that the VM can kill the spawned isolate during VM
+// shutdown even when the isolate is in an infinite loop and will not finish
+// on its own.
+
+void loop(msg) {
+ while (true) {}
+ throw "Unreachable";
+}
+
+void main() {
+ Isolate.spawn(loop, []);
+}
diff --git a/runtime/tests/vm/dart/spawn_shutdown_test.dart b/runtime/tests/vm/dart/spawn_shutdown_test.dart
new file mode 100644
index 0000000..794e737
--- /dev/null
+++ b/runtime/tests/vm/dart/spawn_shutdown_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:isolate';
+
+// Spawn an isolate |foo| that will continue trying to spawn isolates even after
+// the timer in |main| completes. This test ensures that the VM can shutdown
+// correctly even while an isolate is attempting to spawn more isolates.
+
+isolate1(sendPort) {
+ var receivePort = new ReceivePort();
+ sendPort.send(receivePort.sendPort);
+ receivePort.listen((msg) {});
+}
+
+void foo(_) {
+ while (true) {
+ var receivePort = new ReceivePort();
+ Isolate.spawn(isolate1, receivePort.sendPort);
+ receivePort.listen((sendPort) {
+ Isolate.spawn(isolate1,sendPort);
+ receivePort.close();
+ });
+ }
+}
+
+void main() {
+ Isolate.spawn(foo, null);
+ new Timer(const Duration(seconds: 10), () {});
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index d0ffb46..7f82dcb 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -88,6 +88,8 @@
[ $runtime != vm ]
dart/snapshot_version_test: SkipByDesign # Spawns processes
+dart/spawn_infinite_loop_test: Skip # VM shutdown test
+dart/spawn_shutdown_test: Skip # VM Shutdown test
[ $runtime == vm && $mode == debug && $builder_tag == asan ]
cc/Dart2JSCompileAll: Skip # Timeout.
diff --git a/runtime/vm/assembler.cc b/runtime/vm/assembler.cc
index 489f090..5fe8c2f 100644
--- a/runtime/vm/assembler.cc
+++ b/runtime/vm/assembler.cc
@@ -306,6 +306,14 @@
}
+intptr_t ObjectPoolWrapper::FindNativeEntry(const ExternalLabel* label,
+ Patchability patchable) {
+ return FindObject(ObjectPool::Entry(label->address(),
+ ObjectPool::kNativeEntry),
+ patchable);
+}
+
+
RawObjectPool* ObjectPoolWrapper::MakeObjectPool() {
intptr_t len = object_pool_.length();
if (len == 0) {
diff --git a/runtime/vm/assembler.h b/runtime/vm/assembler.h
index f2ad6fe..3f4d5ea 100644
--- a/runtime/vm/assembler.h
+++ b/runtime/vm/assembler.h
@@ -296,6 +296,8 @@
intptr_t FindImmediate(uword imm);
intptr_t FindExternalLabel(const ExternalLabel* label,
Patchability patchable);
+ intptr_t FindNativeEntry(const ExternalLabel* label,
+ Patchability patchable);
RawObjectPool* MakeObjectPool();
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 71a9608..afb5744 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -20,6 +20,7 @@
namespace dart {
+DECLARE_FLAG(bool, allow_absolute_addresses);
DEFINE_FLAG(bool, print_stop_message, true, "Print stop message.");
DECLARE_FLAG(bool, inline_alloc);
@@ -1583,6 +1584,7 @@
if (object.IsSmi()) {
LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()), cond);
} else if (object.InVMHeap() || !constant_pool_allowed()) {
+ ASSERT(FLAG_allow_absolute_addresses);
// Make sure that class CallPattern is able to decode this load immediate.
const int32_t object_raw = reinterpret_cast<int32_t>(object.raw());
LoadImmediate(rd, object_raw, cond);
@@ -1619,6 +1621,16 @@
}
+void Assembler::LoadNativeEntry(Register rd,
+ const ExternalLabel* label,
+ Patchability patchable,
+ Condition cond) {
+ const int32_t offset = ObjectPool::element_offset(
+ object_pool_wrapper_.FindNativeEntry(label, patchable));
+ LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond);
+}
+
+
void Assembler::PushObject(const Object& object) {
LoadObject(IP, object);
Push(IP);
@@ -1767,7 +1779,7 @@
LoadImmediate(temp, Heap::kZap32Bits);
cmp(old_value, Operand(temp));
b(&ok, EQ);
- LoadImmediate(temp, reinterpret_cast<uint32_t>(Object::null()));
+ LoadObject(temp, Object::null_object());
cmp(old_value, Operand(temp));
b(&ok, EQ);
Stop("Expected zapped, Smi or null");
@@ -1997,12 +2009,9 @@
void Assembler::LoadClassIdMayBeSmi(Register result, Register object) {
- static const intptr_t kSmiCidSource = kSmiCid << RawObject::kClassIdTagPos;
-
- LoadImmediate(TMP, reinterpret_cast<int32_t>(&kSmiCidSource) + 1);
tst(object, Operand(kSmiTagMask));
- mov(TMP, Operand(object), NE);
- LoadClassId(result, TMP);
+ LoadClassId(result, object, NE);
+ LoadImmediate(result, kSmiCid, EQ);
}
@@ -2708,7 +2717,7 @@
// use 'blx ip' in a non-patchable sequence (see other BranchLink flavors).
const int32_t offset = ObjectPool::element_offset(
object_pool_wrapper_.FindExternalLabel(label, patchable));
- LoadWordFromPoolOffset(LR, offset - kHeapObjectTag);
+ LoadWordFromPoolOffset(LR, offset - kHeapObjectTag, AL);
blx(LR); // Use blx instruction so that the return branch prediction works.
}
@@ -2761,7 +2770,7 @@
if ((version == ARMv5TE) || (version == ARMv6)) {
if (constant_pool_allowed()) {
const int32_t offset = Array::element_offset(FindImmediate(value));
- LoadWordFromPoolOffset(rd, offset - kHeapObjectTag);
+ LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond);
} else {
LoadPatchableImmediate(rd, value, cond);
}
@@ -3377,6 +3386,7 @@
ASSERT(cid > 0);
const intptr_t class_offset = ClassTable::ClassOffsetFor(cid);
if (inline_isolate) {
+ ASSERT(FLAG_allow_absolute_addresses);
ClassTable* class_table = Isolate::Current()->class_table();
ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
if (cid < kNumPredefinedCids) {
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 79dbea8..6fb2da7 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -671,6 +671,10 @@
const ExternalLabel* label,
Patchability patchable,
Condition cond = AL);
+ void LoadNativeEntry(Register dst,
+ const ExternalLabel* label,
+ Patchability patchable,
+ Condition cond = AL);
void PushObject(const Object& object);
void CompareObject(Register rn, const Object& object);
@@ -756,7 +760,6 @@
Label* miss);
intptr_t FindImmediate(int32_t imm);
- void LoadWordFromPoolOffset(Register rd, int32_t offset, Condition cond = AL);
void LoadFromOffset(OperandSize type,
Register reg,
Register base,
@@ -992,6 +995,8 @@
void BranchLink(const ExternalLabel* label);
+ void LoadWordFromPoolOffset(Register rd, int32_t offset, Condition cond);
+
class CodeComment : public ZoneAllocated {
public:
CodeComment(intptr_t pc_offset, const String& comment)
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 7ea74a2..a360a2d 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -20,6 +20,7 @@
namespace dart {
+DECLARE_FLAG(bool, allow_absolute_addresses);
DEFINE_FLAG(bool, use_far_branches, false, "Always use far branches");
DEFINE_FLAG(bool, print_stop_message, false, "Print stop message.");
DECLARE_FLAG(bool, inline_alloc);
@@ -396,6 +397,14 @@
}
+void Assembler::LoadNativeEntry(Register dst,
+ const ExternalLabel* label) {
+ const int32_t offset = ObjectPool::element_offset(
+ object_pool_wrapper_.FindNativeEntry(label, kNotPatchable));
+ LoadWordFromPoolOffset(dst, offset);
+}
+
+
void Assembler::LoadExternalLabelFixed(Register dst,
const ExternalLabel* label,
Patchability patchable) {
@@ -422,6 +431,7 @@
LoadWordFromPoolOffset(dst, offset);
} else {
ASSERT(object.IsSmi() || object.InVMHeap());
+ ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
LoadDecodableImmediate(dst, reinterpret_cast<int64_t>(object.raw()));
}
}
@@ -457,6 +467,7 @@
LoadObject(TMP, object);
CompareRegisters(reg, TMP);
} else {
+ ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
CompareImmediate(reg, reinterpret_cast<int64_t>(object.raw()));
}
}
@@ -1245,6 +1256,7 @@
intptr_t counter_offset =
ClassTable::CounterOffsetFor(cid, space == Heap::kNew);
if (inline_isolate) {
+ ASSERT(FLAG_allow_absolute_addresses);
ClassTable* class_table = Isolate::Current()->class_table();
ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
if (cid < kNumPredefinedCids) {
@@ -1314,6 +1326,7 @@
ASSERT(cid > 0);
intptr_t state_offset = ClassTable::StateOffsetFor(cid);
if (inline_isolate) {
+ ASSERT(FLAG_allow_absolute_addresses);
ClassTable* class_table = Isolate::Current()->class_table();
ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
if (cid < kNumPredefinedCids) {
diff --git a/runtime/vm/assembler_arm64.h b/runtime/vm/assembler_arm64.h
index dbb4a3b..6a70ff8 100644
--- a/runtime/vm/assembler_arm64.h
+++ b/runtime/vm/assembler_arm64.h
@@ -1288,6 +1288,7 @@
intptr_t FindImmediate(int64_t imm);
bool CanLoadFromObjectPool(const Object& object) const;
void LoadExternalLabel(Register dst, const ExternalLabel* label);
+ void LoadNativeEntry(Register dst, const ExternalLabel* label);
void LoadExternalLabelFixed(Register dst,
const ExternalLabel* label,
Patchability patchable);
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index a839a58..4bdc206 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -17,6 +17,7 @@
#if defined(USING_SIMULATOR)
DECLARE_FLAG(int, trace_sim_after);
#endif
+DECLARE_FLAG(bool, allow_absolute_addresses);
DEFINE_FLAG(bool, print_stop_message, false, "Print stop message.");
DECLARE_FLAG(bool, inline_alloc);
@@ -519,6 +520,7 @@
if (object.IsSmi()) {
LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()));
} else if (object.InVMHeap() || !constant_pool_allowed()) {
+ ASSERT(FLAG_allow_absolute_addresses);
// Make sure that class CallPattern is able to decode this load immediate.
int32_t object_raw = reinterpret_cast<int32_t>(object.raw());
const uint16_t object_low = Utils::Low16Bits(object_raw);
@@ -555,6 +557,15 @@
}
+void Assembler::LoadNativeEntry(Register rd,
+ const ExternalLabel* label,
+ Patchability patchable) {
+ const int32_t offset = ObjectPool::element_offset(
+ object_pool_wrapper_.FindNativeEntry(label, patchable));
+ LoadWordFromPoolOffset(rd, offset - kHeapObjectTag);
+}
+
+
void Assembler::PushObject(const Object& object) {
ASSERT(!in_delay_slot_);
LoadObject(TMP, object);
@@ -738,15 +749,14 @@
void Assembler::LoadClassIdMayBeSmi(Register result, Register object) {
- static const intptr_t kSmiCidSource = kSmiCid << RawObject::kClassIdTagPos;
-
- LoadImmediate(TMP, reinterpret_cast<int32_t>(&kSmiCidSource) + 1);
+ Label heap_object, done;
andi(CMPRES1, object, Immediate(kSmiTagMask));
- if (result != object) {
- mov(result, object);
- }
- movz(result, TMP, CMPRES1);
- LoadClassId(result, result);
+ bne(CMPRES1, ZR, &heap_object);
+ LoadImmediate(result, kSmiCid);
+ b(&done);
+ Bind(&heap_object);
+ LoadClassId(result, object);
+ Bind(&done);
}
@@ -859,6 +869,7 @@
intptr_t counter_offset =
ClassTable::CounterOffsetFor(cid, space == Heap::kNew);
if (inline_isolate) {
+ ASSERT(FLAG_allow_absolute_addresses);
ClassTable* class_table = Isolate::Current()->class_table();
ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
if (cid < kNumPredefinedCids) {
@@ -937,6 +948,7 @@
ASSERT(temp_reg != TMP);
intptr_t state_offset = ClassTable::StateOffsetFor(cid);
if (inline_isolate) {
+ ASSERT(FLAG_allow_absolute_addresses);
ClassTable* class_table = Isolate::Current()->class_table();
ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
if (cid < kNumPredefinedCids) {
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index c9b4025..2ae9456 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -1524,6 +1524,9 @@
void LoadExternalLabel(Register rd,
const ExternalLabel* label,
Patchability patchable);
+ void LoadNativeEntry(Register rd,
+ const ExternalLabel* label,
+ Patchability patchable);
void PushObject(const Object& object);
void LoadIsolate(Register result);
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index fcab5ea..523f29f 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -17,6 +17,7 @@
namespace dart {
+DECLARE_FLAG(bool, allow_absolute_addresses);
DEFINE_FLAG(bool, print_stop_message, true, "Print stop message.");
DECLARE_FLAG(bool, inline_alloc);
@@ -70,6 +71,15 @@
}
+void Assembler::LoadNativeEntry(Register dst,
+ const ExternalLabel* label,
+ Patchability patchable) {
+ const int32_t offset = ObjectPool::element_offset(
+ object_pool_wrapper_.FindNativeEntry(label, patchable));
+ LoadWordFromPoolOffset(dst, offset - kHeapObjectTag);
+}
+
+
void Assembler::call(const ExternalLabel* label) {
{ // Encode movq(TMP, Immediate(label->address())), but always as imm64.
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
@@ -2818,6 +2828,7 @@
LoadWordFromPoolOffset(dst, offset - kHeapObjectTag);
} else {
ASSERT(object.IsSmi() || object.InVMHeap());
+ ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
}
}
@@ -2852,6 +2863,7 @@
LoadObject(TMP, object);
movq(dst, TMP);
} else {
+ ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
MoveImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
}
}
@@ -2864,6 +2876,7 @@
LoadObject(TMP, object);
pushq(TMP);
} else {
+ ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())));
}
}
@@ -2877,6 +2890,7 @@
ObjectPool::element_offset(object_pool_wrapper_.FindObject(object));
cmpq(reg, Address(PP, offset-kHeapObjectTag));
} else {
+ ASSERT(object.IsSmi() || FLAG_allow_absolute_addresses);
CompareImmediate(
reg, Immediate(reinterpret_cast<int64_t>(object.raw())));
}
@@ -3026,7 +3040,8 @@
#else
#error Only supported in DEBUG mode
#endif
- cmpq(dest, Immediate(reinterpret_cast<uint64_t>(Object::null())));
+ LoadObject(TMP, Object::null_object());
+ cmpq(dest, TMP);
j(EQUAL, &ok, Assembler::kNearJump);
static const bool kFixedLengthEncoding = true;
Stop("Expected zapped, Smi or null", kFixedLengthEncoding);
@@ -3444,6 +3459,7 @@
intptr_t state_offset = ClassTable::StateOffsetFor(cid);
Register temp_reg = TMP;
if (inline_isolate) {
+ ASSERT(FLAG_allow_absolute_addresses);
ClassTable* class_table = Isolate::Current()->class_table();
ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
if (cid < kNumPredefinedCids) {
@@ -3474,6 +3490,7 @@
ClassTable::CounterOffsetFor(cid, space == Heap::kNew);
Register temp_reg = TMP;
if (inline_isolate) {
+ ASSERT(FLAG_allow_absolute_addresses);
ClassTable* class_table = Isolate::Current()->class_table();
ClassHeapStats** table_ptr = class_table->TableAddressFor(cid);
if (cid < kNumPredefinedCids) {
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index 5cb3c17..a6d64db0 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -763,6 +763,9 @@
void LoadExternalLabel(Register dst,
const ExternalLabel* label,
Patchability patchable);
+ void LoadNativeEntry(Register dst,
+ const ExternalLabel* label,
+ Patchability patchable);
void LoadFunctionFromCalleePool(Register dst,
const Function& function,
Register new_pp);
diff --git a/runtime/vm/ast_printer.cc b/runtime/vm/ast_printer.cc
index aa5c29f..7cc69d4 100644
--- a/runtime/vm/ast_printer.cc
+++ b/runtime/vm/ast_printer.cc
@@ -19,38 +19,38 @@
void AstPrinter::VisitGenericAstNode(AstNode* node) {
- ISL_Print("(%s ", node->PrettyName());
+ THR_Print("(%s ", node->PrettyName());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitSequenceNode(SequenceNode* node) {
indent_++;
LocalScope* scope = node->scope();
- ISL_Print("(%s (scope \"%p\"", node->PrettyName(), scope);
+ THR_Print("(%s (scope \"%p\"", node->PrettyName(), scope);
if (scope != NULL) {
- ISL_Print(" (%" Pd "-%" Pd ") loop %d",
+ THR_Print(" (%" Pd "-%" Pd ") loop %d",
scope->begin_token_pos(),
scope->end_token_pos(),
scope->loop_level());
if (scope->HasContextLevel()) {
- ISL_Print(" context %d captures %d",
+ THR_Print(" context %d captures %d",
scope->context_level(),
scope->num_context_variables());
} else {
ASSERT(scope->num_context_variables() == 0);
}
}
- ISL_Print(")");
+ THR_Print(")");
for (int i = 0; i < node->length(); ++i) {
- ISL_Print("\n");
+ THR_Print("\n");
for (intptr_t p = 0; p < indent_; p++) {
- ISL_Print(" ");
+ THR_Print(" ");
}
node->NodeAt(i)->Visit(this);
}
- ISL_Print(")");
+ THR_Print(")");
indent_--;
}
@@ -81,29 +81,29 @@
kind = "";
UNREACHABLE();
}
- ISL_Print("(%s %s", node->PrettyName(), kind);
+ THR_Print("(%s %s", node->PrettyName(), kind);
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitGenericLocalNode(AstNode* node,
const LocalVariable& var) {
- ISL_Print("(%s %s%s \"%s\"",
+ THR_Print("(%s %s%s \"%s\"",
node->PrettyName(),
var.is_final() ? "final " : "",
String::Handle(var.type().Name()).ToCString(),
var.name().ToCString());
if (var.HasIndex()) {
if (var.is_captured()) {
- ISL_Print(" (context %d %d)", var.owner()->context_level(), var.index());
+ THR_Print(" (context %d %d)", var.owner()->context_level(), var.index());
} else {
- ISL_Print(" (stack %d)", var.index());
+ THR_Print(" (stack %d)", var.index());
}
}
- ISL_Print(" ");
+ THR_Print(" ");
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
@@ -118,14 +118,14 @@
void AstPrinter::VisitGenericFieldNode(AstNode* node, const Field& field) {
- ISL_Print("(%s %s%s \"%s\" ",
+ THR_Print("(%s %s%s \"%s\" ",
node->PrettyName(),
field.is_final() ? "final " : "",
String::Handle(AbstractType::Handle(field.type()).Name()).
ToCString(),
String::Handle(field.name()).ToCString());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
@@ -166,13 +166,13 @@
void AstPrinter::VisitLiteralNode(LiteralNode* node) {
const Instance& literal = node->literal();
- ISL_Print("(%s \"%s\")", node->PrettyName(), literal.ToCString());
+ THR_Print("(%s \"%s\")", node->PrettyName(), literal.ToCString());
}
void AstPrinter::VisitTypeNode(TypeNode* node) {
const AbstractType& type = node->type();
- ISL_Print("(%s \"%s\")",
+ THR_Print("(%s \"%s\")",
node->PrettyName(),
String::Handle(type.Name()).ToCString());
}
@@ -181,24 +181,24 @@
void AstPrinter::VisitAssignableNode(AssignableNode* node) {
const AbstractType& type = node->type();
const String& dst_name = node->dst_name();
- ISL_Print("(%s (type \"%s\") (of \"%s\") ",
+ THR_Print("(%s (type \"%s\") (of \"%s\") ",
node->PrettyName(),
String::Handle(type.Name()).ToCString(),
dst_name.ToCString());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitAwaitNode(AwaitNode* node) {
- ISL_Print("(*****%s***** (scope \"%p\") ", node->PrettyName(), node->scope());
+ THR_Print("(*****%s***** (scope \"%p\") ", node->PrettyName(), node->scope());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitAwaitMarkerNode(AwaitMarkerNode* node) {
- ISL_Print("(%s (async_scope \"%p\" await_scope \"%p\"))",
+ THR_Print("(%s (async_scope \"%p\" await_scope \"%p\"))",
node->PrettyName(),
node->async_scope(),
node->await_scope());
@@ -206,38 +206,38 @@
void AstPrinter::VisitPrimaryNode(PrimaryNode* node) {
- ISL_Print("(*****%s***** \"%s\")",
+ THR_Print("(*****%s***** \"%s\")",
node->PrettyName(),
node->primary().ToCString());
}
void AstPrinter::VisitComparisonNode(ComparisonNode* node) {
- ISL_Print("(%s %s ", node->PrettyName(), node->TokenName());
+ THR_Print("(%s %s ", node->PrettyName(), node->TokenName());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitBinaryOpNode(BinaryOpNode* node) {
- ISL_Print("(%s %s ", node->PrettyName(), node->TokenName());
+ THR_Print("(%s %s ", node->PrettyName(), node->TokenName());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitBinaryOpWithMask32Node(BinaryOpWithMask32Node* node) {
- ISL_Print("(%s %s ", node->PrettyName(), node->TokenName());
+ THR_Print("(%s %s ", node->PrettyName(), node->TokenName());
node->VisitChildren(this);
- ISL_Print(" & \"0x%" Px64 "", node->mask32());
- ISL_Print("\")");
+ THR_Print(" & \"0x%" Px64 "", node->mask32());
+ THR_Print("\")");
}
void AstPrinter::VisitUnaryOpNode(UnaryOpNode* node) {
- ISL_Print("(%s %s ", node->PrettyName(), node->TokenName());
+ THR_Print("(%s %s ", node->PrettyName(), node->TokenName());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
@@ -252,16 +252,16 @@
void AstPrinter::VisitCaseNode(CaseNode* node) {
- ISL_Print("(%s (", node->PrettyName());
+ THR_Print("(%s (", node->PrettyName());
for (int i = 0; i < node->case_expressions()->length(); i++) {
node->case_expressions()->NodeAt(i)->Visit(this);
}
if (node->contains_default()) {
- ISL_Print(" default");
+ THR_Print(" default");
}
- ISL_Print(")");
+ THR_Print(")");
node->statements()->Visit(this);
- ISL_Print(")");
+ THR_Print(")");
}
@@ -278,17 +278,17 @@
void AstPrinter::VisitForNode(ForNode* node) {
// Complicated because the condition is optional and so we clearly want to
// indicate the subparts.
- ISL_Print("(%s (init ", node->PrettyName());
+ THR_Print("(%s (init ", node->PrettyName());
node->initializer()->Visit(this);
if (node->condition() != NULL) {
- ISL_Print(") (cond ");
+ THR_Print(") (cond ");
node->condition()->Visit(this);
}
- ISL_Print(") (update ");
+ THR_Print(") (update ");
node->increment()->Visit(this);
- ISL_Print(") ");
+ THR_Print(") ");
node->body()->Visit(this);
- ISL_Print(")");
+ THR_Print(")");
}
@@ -298,7 +298,7 @@
void AstPrinter::VisitJumpNode(JumpNode* node) {
- ISL_Print("(%s %s %s (scope \"%p\"))",
+ THR_Print("(%s %s %s (scope \"%p\"))",
node->PrettyName(),
node->TokenName(),
node->label()->name().ToCString(),
@@ -307,25 +307,25 @@
void AstPrinter::VisitInstanceCallNode(InstanceCallNode* node) {
- ISL_Print("(%s \"%s\" ",
+ THR_Print("(%s \"%s\" ",
node->PrettyName(),
node->function_name().ToCString());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitStaticCallNode(StaticCallNode* node) {
const char* function_fullname = node->function().ToFullyQualifiedCString();
- ISL_Print("(%s \"%s\" ", node->PrettyName(), function_fullname);
+ THR_Print("(%s \"%s\" ", node->PrettyName(), function_fullname);
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitClosureNode(ClosureNode* node) {
const char* function_fullname = node->function().ToFullyQualifiedCString();
- ISL_Print("(%s \"%s\")", node->PrettyName(), function_fullname);
+ THR_Print("(%s \"%s\")", node->PrettyName(), function_fullname);
}
@@ -337,39 +337,39 @@
void AstPrinter::VisitConstructorCallNode(ConstructorCallNode* node) {
const char* kind = node->constructor().IsFactory() ? "factory " : "";
const char* constructor_name = node->constructor().ToFullyQualifiedCString();
- ISL_Print("(%s %s \"%s\" ", node->PrettyName(), kind, constructor_name);
+ THR_Print("(%s %s \"%s\" ", node->PrettyName(), kind, constructor_name);
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitInstanceGetterNode(InstanceGetterNode* node) {
- ISL_Print("(%s \"%s\" ",
+ THR_Print("(%s \"%s\" ",
node->PrettyName(),
node->field_name().ToCString());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitInstanceSetterNode(InstanceSetterNode* node) {
- ISL_Print("(%s \"%s\" ",
+ THR_Print("(%s \"%s\" ",
node->PrettyName(),
node->field_name().ToCString());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitInitStaticFieldNode(InitStaticFieldNode* node) {
- ISL_Print("(%s \"%s\")", node->PrettyName(),
+ THR_Print("(%s \"%s\")", node->PrettyName(),
String::Handle(node->field().name()).ToCString());
}
void AstPrinter::VisitStaticGetterNode(StaticGetterNode* node) {
String& class_name = String::Handle(node->cls().Name());
- ISL_Print("(%s \"%s.%s\")",
+ THR_Print("(%s \"%s.%s\")",
node->PrettyName(),
class_name.ToCString(),
node->field_name().ToCString());
@@ -378,31 +378,31 @@
void AstPrinter::VisitStaticSetterNode(StaticSetterNode* node) {
String& class_name = String::Handle(node->cls().Name());
- ISL_Print("(%s \"%s.%s\" ",
+ THR_Print("(%s \"%s.%s\" ",
node->PrettyName(),
class_name.ToCString(),
node->field_name().ToCString());
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitLoadIndexedNode(LoadIndexedNode* node) {
- ISL_Print("(%s%s ", node->PrettyName(), node->IsSuperLoad() ? " super" : "");
+ THR_Print("(%s%s ", node->PrettyName(), node->IsSuperLoad() ? " super" : "");
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitStoreIndexedNode(StoreIndexedNode* node) {
- ISL_Print("(%s%s ", node->PrettyName(), node->IsSuperStore() ? " super" : "");
+ THR_Print("(%s%s ", node->PrettyName(), node->IsSuperStore() ? " super" : "");
node->VisitChildren(this);
- ISL_Print(")");
+ THR_Print(")");
}
void AstPrinter::VisitNativeBodyNode(NativeBodyNode* node) {
- ISL_Print("(%s \"%s\" (%" Pd " args))",
+ THR_Print("(%s \"%s\" (%" Pd " args))",
node->PrettyName(),
node->native_c_function_name().ToCString(),
NativeArguments::ParameterCountForResolution(node->function()));
@@ -415,15 +415,15 @@
void AstPrinter::VisitTryCatchNode(TryCatchNode* node) {
- ISL_Print("(%s ", node->PrettyName());
+ THR_Print("(%s ", node->PrettyName());
node->try_block()->Visit(this);
node->catch_block()->Visit(this);
if (node->finally_block() != NULL) {
- ISL_Print("(finally ");
+ THR_Print("(finally ");
node->finally_block()->Visit(this);
- ISL_Print(")");
+ THR_Print(")");
}
- ISL_Print(")");
+ THR_Print(")");
}
@@ -433,7 +433,7 @@
void AstPrinter::VisitStopNode(StopNode* node) {
- ISL_Print("(%s %s)", node->PrettyName(), node->message());
+ THR_Print("(%s %s)", node->PrettyName(), node->message());
}
@@ -446,13 +446,13 @@
ASSERT(node != NULL);
AstPrinter ast_printer;
node->Visit(&ast_printer);
- ISL_Print("\n");
+ THR_Print("\n");
}
static void IndentN(int count) {
for (int i = 0; i < count; i++) {
- ISL_Print(" ");
+ THR_Print(" ");
}
}
@@ -463,22 +463,22 @@
ASSERT(scope != NULL);
ASSERT(var != NULL);
IndentN(indent);
- ISL_Print("(%s%s '%s'",
+ THR_Print("(%s%s '%s'",
var->is_final() ? "final " : "",
String::Handle(var->type().Name()).ToCString(),
var->name().ToCString());
if (var->owner() != scope) {
- ISL_Print(" alias");
+ THR_Print(" alias");
}
if (var->HasIndex()) {
- ISL_Print(" @%d", var->index());
+ THR_Print(" @%d", var->index());
if (var->is_captured()) {
- ISL_Print(" ctx %d", var->owner()->context_level());
+ THR_Print(" ctx %d", var->owner()->context_level());
}
} else if (var->owner()->function_level() != 0) {
- ISL_Print(" lev %d", var->owner()->function_level());
+ THR_Print(" lev %d", var->owner()->function_level());
}
- ISL_Print(" valid %" Pd "-%" Pd ")\n",
+ THR_Print(" valid %" Pd "-%" Pd ")\n",
var->token_pos(),
scope->end_token_pos());
}
@@ -495,16 +495,16 @@
const LocalScope* child = scope->child();
while (child != NULL) {
IndentN(indent);
- ISL_Print("{scope %p ", child);
+ THR_Print("{scope %p ", child);
if (child->HasContextLevel()) {
- ISL_Print("ctx %d numctxvar %d ",
+ THR_Print("ctx %d numctxvar %d ",
child->context_level(),
child->num_context_variables());
}
- ISL_Print("llev %d\n", child->loop_level());
+ THR_Print("llev %d\n", child->loop_level());
PrintLocalScope(child, 0, indent + kScopeIndent);
IndentN(indent);
- ISL_Print("}\n");
+ THR_Print("}\n");
child = child->sibling();
}
}
@@ -518,13 +518,13 @@
const LocalScope* scope = node_sequence->scope();
ASSERT(scope != NULL);
const char* function_name = function.ToFullyQualifiedCString();
- ISL_Print("Scope for function '%s'\n{scope %p ", function_name, scope);
+ THR_Print("Scope for function '%s'\n{scope %p ", function_name, scope);
if (scope->HasContextLevel()) {
- ISL_Print("ctx %d numctxvar %d ",
+ THR_Print("ctx %d numctxvar %d ",
scope->context_level(),
scope->num_context_variables());
}
- ISL_Print("llev %d\n", scope->loop_level());
+ THR_Print("llev %d\n", scope->loop_level());
const int num_fixed_params = function.num_fixed_parameters();
const int num_params = num_fixed_params + function.NumOptionalParameters();
// Parameters must be listed first and must all appear in the top scope.
@@ -535,7 +535,7 @@
LocalVariable* param = scope->VariableAt(pos);
ASSERT(param->owner() == scope); // No aliases should precede parameters.
IndentN(indent);
- ISL_Print("(param %s%s '%s'",
+ THR_Print("(param %s%s '%s'",
param->is_final() ? "final " : "",
String::Handle(param->type().Name()).ToCString(),
param->name().ToCString());
@@ -543,22 +543,22 @@
if (pos >= num_fixed_params && pos < num_params) {
const Instance& default_parameter_value =
parsed_function.DefaultParameterValueAt(pos - num_fixed_params);
- ISL_Print(" =%s", default_parameter_value.ToCString());
+ THR_Print(" =%s", default_parameter_value.ToCString());
}
if (param->HasIndex()) {
- ISL_Print(" @%d", param->index());
+ THR_Print(" @%d", param->index());
if (param->is_captured()) {
- ISL_Print(" ctx %d", param->owner()->context_level());
+ THR_Print(" ctx %d", param->owner()->context_level());
}
}
- ISL_Print(" valid %" Pd "-%" Pd ")\n",
+ THR_Print(" valid %" Pd "-%" Pd ")\n",
param->token_pos(),
scope->end_token_pos());
pos++;
}
// Visit remaining non-parameter variables and children scopes.
PrintLocalScope(scope, pos, indent);
- ISL_Print("}\n");
+ THR_Print("}\n");
}
@@ -569,9 +569,9 @@
AstPrinter ast_printer;
const char* function_name =
parsed_function.function().ToFullyQualifiedCString();
- ISL_Print("Ast for function '%s' {\n", function_name);
+ THR_Print("Ast for function '%s' {\n", function_name);
node_sequence->Visit(&ast_printer);
- ISL_Print("}\n");
+ THR_Print("}\n");
}
} // namespace dart
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index ee3ca57..36dfae2 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -354,12 +354,8 @@
char* script = NULL;
if (dart_root != NULL) {
HANDLESCOPE(thread);
- const char* kFormatStr =
- "import '%s/pkg/compiler/lib/compiler.dart';";
- intptr_t len = OS::SNPrint(NULL, 0, kFormatStr, dart_root) + 1;
- script = reinterpret_cast<char*>(malloc(len));
- EXPECT(script != NULL);
- OS::SNPrint(script, len, kFormatStr, dart_root);
+ script = OS::SCreate(NULL,
+ "import '%s/pkg/compiler/lib/compiler.dart';", dart_root);
Dart_Handle lib = TestCase::LoadTestScript(
script,
reinterpret_cast<Dart_NativeEntryResolver>(NativeResolver));
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 494a42d..83df7a9 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -338,7 +338,7 @@
// Target is not resolved yet.
if (FLAG_trace_class_finalization) {
- ISL_Print("Resolving redirecting factory: %s\n",
+ THR_Print("Resolving redirecting factory: %s\n",
String::Handle(factory.name()).ToCString());
}
type ^= FinalizeType(cls, type, kCanonicalize);
@@ -460,7 +460,7 @@
return;
}
if (FLAG_trace_type_finalization) {
- ISL_Print("Resolve type class of '%s'\n",
+ THR_Print("Resolve type class of '%s'\n",
String::Handle(type.Name()).ToCString());
}
@@ -499,7 +499,7 @@
}
ASSERT(type.IsType());
if (FLAG_trace_type_finalization) {
- ISL_Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString());
+ THR_Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString());
}
ResolveTypeClass(cls, type);
if (type.IsMalformed()) {
@@ -526,7 +526,7 @@
const Class& cls,
PendingTypes* pending_types) {
if (FLAG_trace_type_finalization) {
- ISL_Print("Finalizing type parameters of '%s'\n",
+ THR_Print("Finalizing type parameters of '%s'\n",
String::Handle(cls.Name()).ToCString());
}
if (cls.IsMixinApplication()) {
@@ -565,7 +565,7 @@
PendingTypes* pending_types) {
Isolate* isolate = Isolate::Current();
if (FLAG_trace_type_finalization) {
- ISL_Print("Checking recursive type '%s': %s\n",
+ THR_Print("Checking recursive type '%s': %s\n",
String::Handle(type.Name()).ToCString(),
type.ToCString());
}
@@ -595,7 +595,7 @@
for (intptr_t i = num_pending_types - 1; i >= 0; i--) {
const Type& pending_type = Type::Cast(pending_types->At(i));
if (FLAG_trace_type_finalization) {
- ISL_Print(" Comparing with pending type '%s': %s\n",
+ THR_Print(" Comparing with pending type '%s': %s\n",
String::Handle(pending_type.Name()).ToCString(),
pending_type.ToCString());
}
@@ -687,7 +687,7 @@
ASSERT(super_type_arg.IsType());
CheckRecursiveType(cls, Type::Cast(super_type_arg), pending_types);
if (FLAG_trace_type_finalization) {
- ISL_Print("Creating TypeRef '%s': '%s'\n",
+ THR_Print("Creating TypeRef '%s': '%s'\n",
String::Handle(super_type_arg.Name()).ToCString(),
super_type_arg.ToCString());
}
@@ -708,7 +708,7 @@
if (FLAG_trace_type_finalization && super_type_arg.IsTypeRef()) {
AbstractType& ref_type = AbstractType::Handle(
TypeRef::Cast(super_type_arg).type());
- ISL_Print("Instantiating TypeRef '%s': '%s'\n"
+ THR_Print("Instantiating TypeRef '%s': '%s'\n"
" instantiator: '%s'\n",
String::Handle(super_type_arg.Name()).ToCString(),
ref_type.ToCString(),
@@ -895,7 +895,7 @@
"type '%s' has an out of bound type argument",
type_name.ToCString());
if (FLAG_trace_type_finalization) {
- ISL_Print("Marking type '%s' as malbounded: %s\n",
+ THR_Print("Marking type '%s' as malbounded: %s\n",
String::Handle(type.Name()).ToCString(),
bound_error.ToCString());
}
@@ -940,7 +940,7 @@
Zone* Z = Thread::Current()->zone();
if (FLAG_trace_type_finalization) {
- ISL_Print("Finalizing type '%s' for class '%s'\n",
+ THR_Print("Finalizing type '%s' for class '%s'\n",
String::Handle(Z, type.Name()).ToCString(),
cls.ToCString());
}
@@ -967,7 +967,7 @@
}
if (FLAG_trace_type_finalization) {
- ISL_Print("Done finalizing type parameter '%s' with index %" Pd "\n",
+ THR_Print("Done finalizing type parameter '%s' with index %" Pd "\n",
String::Handle(Z, type_parameter.name()).ToCString(),
type_parameter.index());
}
@@ -1122,7 +1122,7 @@
for (intptr_t i = pending_types->length() - 1; i >= 0; i--) {
CheckTypeBounds(cls, Type::Cast(pending_types->At(i)));
if (FLAG_trace_type_finalization && type.IsRecursive()) {
- ISL_Print("Done finalizing recursive type '%s': %s\n",
+ THR_Print("Done finalizing recursive type '%s': %s\n",
String::Handle(Z, type.Name()).ToCString(),
type.ToCString());
}
@@ -1141,7 +1141,7 @@
}
if (FLAG_trace_type_finalization) {
- ISL_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
+ THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
String::Handle(Z, parameterized_type.Name()).ToCString(),
parameterized_type.arguments() == TypeArguments::null() ?
0 : num_type_arguments,
@@ -1152,7 +1152,7 @@
if (FLAG_trace_type_finalization && parameterized_type.IsRecursive()) {
AbstractType& type = Type::Handle(Z);
type = parameterized_type.Canonicalize();
- ISL_Print("Done canonicalizing recursive type '%s': %s\n",
+ THR_Print("Done canonicalizing recursive type '%s': %s\n",
String::Handle(Z, type.Name()).ToCString(),
type.ToCString());
return type.raw();
@@ -1853,7 +1853,7 @@
library.AddClass(inserted_class);
if (FLAG_trace_class_finalization) {
- ISL_Print("Creating mixin application alias %s\n",
+ THR_Print("Creating mixin application alias %s\n",
inserted_class.ToCString());
}
@@ -1988,7 +1988,7 @@
ASSERT(!mixin_app_class.is_type_finalized());
ASSERT(!mixin_app_class.is_mixin_type_applied());
if (FLAG_trace_class_finalization) {
- ISL_Print("Inserting class '%s' %s\n"
+ THR_Print("Inserting class '%s' %s\n"
" as super type '%s' with %" Pd " type args: %s\n"
" of mixin application alias '%s' %s\n",
String::Handle(inserted_class.Name()).ToCString(),
@@ -2015,7 +2015,7 @@
const Class& mixin_class = Class::Handle(mixin_type.type_class());
if (FLAG_trace_class_finalization) {
- ISL_Print("Applying mixin type '%s' to %s at pos %" Pd "\n",
+ THR_Print("Applying mixin type '%s' to %s at pos %" Pd "\n",
String::Handle(mixin_type.Name()).ToCString(),
mixin_app_class.ToCString(),
mixin_app_class.token_pos());
@@ -2058,7 +2058,7 @@
ResolveSuperTypeAndInterfaces(mixin_app_class, &visited_interfaces);
if (FLAG_trace_class_finalization) {
- ISL_Print("Done applying mixin type '%s' to class '%s' %s extending '%s'\n",
+ THR_Print("Done applying mixin type '%s' to class '%s' %s extending '%s'\n",
String::Handle(mixin_type.Name()).ToCString(),
String::Handle(mixin_app_class.Name()).ToCString(),
TypeArguments::Handle(
@@ -2103,7 +2103,7 @@
clone_name = Symbols::FromConcat(mixin_name, clone_name);
if (FLAG_trace_class_finalization) {
- ISL_Print("Cloning constructor '%s' as '%s'\n",
+ THR_Print("Cloning constructor '%s' as '%s'\n",
ctor_name.ToCString(),
clone_name.ToCString());
}
@@ -2158,7 +2158,7 @@
// A default constructor will be created for the mixin app alias class.
if (FLAG_trace_class_finalization) {
- ISL_Print("Applying mixin members of %s to %s at pos %" Pd "\n",
+ THR_Print("Applying mixin members of %s to %s at pos %" Pd "\n",
mixin_cls.ToCString(),
cls.ToCString(),
cls.token_pos());
@@ -2217,7 +2217,7 @@
cls.AddFields(cloned_fields);
if (FLAG_trace_class_finalization) {
- ISL_Print("Done applying mixin members of %s to %s\n",
+ THR_Print("Done applying mixin members of %s to %s\n",
mixin_cls.ToCString(),
cls.ToCString());
}
@@ -2231,7 +2231,7 @@
return;
}
if (FLAG_trace_class_finalization) {
- ISL_Print("Finalize types in %s\n", cls.ToCString());
+ THR_Print("Finalize types in %s\n", cls.ToCString());
}
if (!IsSuperCycleFree(cls)) {
const String& name = String::Handle(cls.Name());
@@ -2365,7 +2365,7 @@
return;
}
if (FLAG_trace_class_finalization) {
- ISL_Print("Finalize %s\n", cls.ToCString());
+ THR_Print("Finalize %s\n", cls.ToCString());
}
if (cls.is_patch()) {
// The fields and functions of a patch class are copied to the
@@ -2739,7 +2739,7 @@
// processed via the super_type chain of a pending class.
if (FLAG_trace_class_finalization) {
- ISL_Print("Creating mixin application %s\n",
+ THR_Print("Creating mixin application %s\n",
mixin_app_class.ToCString());
}
}
@@ -2760,7 +2760,7 @@
}
}
if (FLAG_trace_class_finalization) {
- ISL_Print("ResolveMixinAppType: mixin appl type args: %s\n",
+ THR_Print("ResolveMixinAppType: mixin appl type args: %s\n",
mixin_app_args.ToCString());
}
// The mixin application class at depth k is a subclass of mixin application
@@ -2787,7 +2787,7 @@
}
ASSERT(visited != NULL);
if (FLAG_trace_class_finalization) {
- ISL_Print("Resolving super and interfaces: %s\n", cls.ToCString());
+ THR_Print("Resolving super and interfaces: %s\n", cls.ToCString());
}
Isolate* isolate = Isolate::Current();
const intptr_t cls_index = cls.id();
@@ -2994,46 +2994,46 @@
Thread* thread = Thread::Current();
HANDLESCOPE(thread);
const String& class_name = String::Handle(cls.Name());
- ISL_Print("class '%s'", class_name.ToCString());
+ THR_Print("class '%s'", class_name.ToCString());
const Library& library = Library::Handle(cls.library());
if (!library.IsNull()) {
- ISL_Print(" library '%s%s':\n",
+ THR_Print(" library '%s%s':\n",
String::Handle(library.url()).ToCString(),
String::Handle(library.private_key()).ToCString());
} else {
- ISL_Print(" (null library):\n");
+ THR_Print(" (null library):\n");
}
const AbstractType& super_type = AbstractType::Handle(cls.super_type());
if (super_type.IsNull()) {
- ISL_Print(" Super: NULL");
+ THR_Print(" Super: NULL");
} else {
const String& super_name = String::Handle(super_type.Name());
- ISL_Print(" Super: %s", super_name.ToCString());
+ THR_Print(" Super: %s", super_name.ToCString());
}
const Array& interfaces_array = Array::Handle(cls.interfaces());
if (interfaces_array.Length() > 0) {
- ISL_Print("; interfaces: ");
+ THR_Print("; interfaces: ");
AbstractType& interface = AbstractType::Handle();
intptr_t len = interfaces_array.Length();
for (intptr_t i = 0; i < len; i++) {
interface ^= interfaces_array.At(i);
- ISL_Print(" %s ", interface.ToCString());
+ THR_Print(" %s ", interface.ToCString());
}
}
- ISL_Print("\n");
+ THR_Print("\n");
const Array& functions_array = Array::Handle(cls.functions());
Function& function = Function::Handle();
intptr_t len = functions_array.Length();
for (intptr_t i = 0; i < len; i++) {
function ^= functions_array.At(i);
- ISL_Print(" %s\n", function.ToCString());
+ THR_Print(" %s\n", function.ToCString());
}
const Array& fields_array = Array::Handle(cls.fields());
Field& field = Field::Handle();
len = fields_array.Length();
for (intptr_t i = 0; i < len; i++) {
field ^= fields_array.At(i);
- ISL_Print(" %s\n", field.ToCString());
+ THR_Print(" %s\n", field.ToCString());
}
}
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index daa15fd..53ee195 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -138,7 +138,7 @@
args.SetAt(1, Integer::Handle(Integer::New(0)));
args.SetAt(2, Integer::Handle(Integer::New(Array::kMaxElements)));
args.SetAt(3, Symbols::Length());
- Exceptions::ThrowByType(Exceptions::kRangeRange, args);
+ Exceptions::ThrowByType(Exceptions::kRange, args);
}
@@ -1012,7 +1012,7 @@
const Array& descriptor = Array::CheckedHandle(arguments.ArgAt(2));
const String& name = String::Handle(ic_data.target_name());
const MegamorphicCache& cache = MegamorphicCache::Handle(
- isolate->megamorphic_cache_table()->Lookup(name, descriptor));
+ MegamorphicCacheTable::Lookup(isolate, name, descriptor));
Class& cls = Class::Handle(receiver.clazz());
ASSERT(!cls.IsNull());
if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) {
@@ -1476,7 +1476,7 @@
function.set_usage_counter(0);
if (FLAG_trace_compiler) {
if (function.HasOptimizedCode()) {
- ISL_Print("ReCompiling function: '%s' \n",
+ THR_Print("ReCompiling function: '%s' \n",
function.ToFullyQualifiedCString());
}
}
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index b02e904..fe4fc64 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -192,7 +192,7 @@
if (FLAG_trace_compiler) {
const String& script_url = String::Handle(script.url());
// TODO(iposva): Extract script kind.
- ISL_Print("Compiling %s '%s'\n", "", script_url.ToCString());
+ THR_Print("Compiling %s '%s'\n", "", script_url.ToCString());
}
const String& library_key = String::Handle(library.private_key());
script.Tokenize(library_key);
@@ -304,7 +304,7 @@
LongJumpScope jump;
if (setjmp(*jump.Set()) == 0) {
if (FLAG_trace_compiler) {
- ISL_Print("Compiling Class %s '%s'\n", "", cls.ToCString());
+ THR_Print("Compiling Class %s '%s'\n", "", cls.ToCString());
}
// Add the primary class which needs to be parsed to the parse list.
@@ -427,7 +427,7 @@
if (FLAG_print_ic_data_map) {
for (intptr_t i = 0; i < ic_data_array->length(); i++) {
if ((*ic_data_array)[i] != NULL) {
- ISL_Print("%" Pd " ", i);
+ THR_Print("%" Pd " ", i);
FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]);
}
}
@@ -761,9 +761,9 @@
CodePatcher::PatchEntry(Code::Handle(function.CurrentCode()));
if (FLAG_trace_compiler || FLAG_trace_patching) {
if (FLAG_trace_compiler) {
- ISL_Print(" ");
+ THR_Print(" ");
}
- ISL_Print("Patch unoptimized '%s' entry point %#" Px "\n",
+ THR_Print("Patch unoptimized '%s' entry point %#" Px "\n",
function.ToFullyQualifiedCString(),
Code::Handle(function.unoptimized_code()).EntryPoint());
}
@@ -822,7 +822,7 @@
// try again (done = true), and indicate that we did not finish
// compiling (is_compiled = false).
if (FLAG_trace_bailout) {
- ISL_Print("%s\n", error.ToErrorCString());
+ THR_Print("%s\n", error.ToErrorCString());
}
done = true;
ASSERT(optimized);
@@ -844,35 +844,35 @@
static void DisassembleCode(const Function& function, bool optimized) {
const char* function_fullname = function.ToFullyQualifiedCString();
- ISL_Print("Code for %sfunction '%s' {\n",
+ THR_Print("Code for %sfunction '%s' {\n",
optimized ? "optimized " : "",
function_fullname);
const Code& code = Code::Handle(function.CurrentCode());
code.Disassemble();
- ISL_Print("}\n");
+ THR_Print("}\n");
- ISL_Print("Pointer offsets for function: {\n");
+ THR_Print("Pointer offsets for function: {\n");
// Pointer offsets are stored in descending order.
Object& obj = Object::Handle();
for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) {
const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint();
obj = *reinterpret_cast<RawObject**>(addr);
- ISL_Print(" %d : %#" Px " '%s'\n",
+ THR_Print(" %d : %#" Px " '%s'\n",
code.GetPointerOffsetAt(i), addr, obj.ToCString());
}
- ISL_Print("}\n");
+ THR_Print("}\n");
- ISL_Print("PC Descriptors for function '%s' {\n", function_fullname);
+ THR_Print("PC Descriptors for function '%s' {\n", function_fullname);
PcDescriptors::PrintHeaderString();
const PcDescriptors& descriptors =
PcDescriptors::Handle(code.pc_descriptors());
- ISL_Print("%s}\n", descriptors.ToCString());
+ THR_Print("%s}\n", descriptors.ToCString());
uword start = Instructions::Handle(code.instructions()).EntryPoint();
const Array& deopt_table = Array::Handle(code.deopt_info_array());
intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table);
if (deopt_table_length > 0) {
- ISL_Print("DeoptInfo: {\n");
+ THR_Print("DeoptInfo: {\n");
Smi& offset = Smi::Handle();
TypedData& info = TypedData::Handle();
Smi& reason_and_flags = Smi::Handle();
@@ -881,31 +881,31 @@
const intptr_t reason =
DeoptTable::ReasonField::decode(reason_and_flags.Value());
ASSERT((0 <= reason) && (reason < ICData::kDeoptNumReasons));
- ISL_Print("%4" Pd ": 0x%" Px " %s (%s)\n",
+ THR_Print("%4" Pd ": 0x%" Px " %s (%s)\n",
i,
start + offset.Value(),
DeoptInfo::ToCString(deopt_table, info),
DeoptReasonToCString(
static_cast<ICData::DeoptReasonId>(reason)));
}
- ISL_Print("}\n");
+ THR_Print("}\n");
}
const ObjectPool& object_pool = ObjectPool::Handle(code.GetObjectPool());
object_pool.DebugPrint();
- ISL_Print("Stackmaps for function '%s' {\n", function_fullname);
+ THR_Print("Stackmaps for function '%s' {\n", function_fullname);
if (code.stackmaps() != Array::null()) {
const Array& stackmap_table = Array::Handle(code.stackmaps());
Stackmap& map = Stackmap::Handle();
for (intptr_t i = 0; i < stackmap_table.Length(); ++i) {
map ^= stackmap_table.At(i);
- ISL_Print("%s\n", map.ToCString());
+ THR_Print("%s\n", map.ToCString());
}
}
- ISL_Print("}\n");
+ THR_Print("}\n");
- ISL_Print("Variable Descriptors for function '%s' {\n",
+ THR_Print("Variable Descriptors for function '%s' {\n",
function_fullname);
const LocalVarDescriptors& var_descriptors =
LocalVarDescriptors::Handle(code.GetLocalVarDescriptors());
@@ -918,34 +918,34 @@
var_descriptors.GetInfo(i, &var_info);
const int8_t kind = var_info.kind();
if (kind == RawLocalVarDescriptors::kSavedCurrentContext) {
- ISL_Print(" saved current CTX reg offset %d\n", var_info.index());
+ THR_Print(" saved current CTX reg offset %d\n", var_info.index());
} else {
if (kind == RawLocalVarDescriptors::kContextLevel) {
- ISL_Print(" context level %d scope %d", var_info.index(),
+ THR_Print(" context level %d scope %d", var_info.index(),
var_info.scope_id);
} else if (kind == RawLocalVarDescriptors::kStackVar) {
- ISL_Print(" stack var '%s' offset %d",
+ THR_Print(" stack var '%s' offset %d",
var_name.ToCString(), var_info.index());
} else if (kind == RawLocalVarDescriptors::kContextVar) {
- ISL_Print(" context var '%s' level %d offset %d",
+ THR_Print(" context var '%s' level %d offset %d",
var_name.ToCString(), var_info.scope_id, var_info.index());
} else {
ASSERT(kind == RawLocalVarDescriptors::kAsyncOperation);
- ISL_Print(" async operation '%s' level %d offset %d",
+ THR_Print(" async operation '%s' level %d offset %d",
var_name.ToCString(), var_info.scope_id, var_info.index());
}
- ISL_Print(" (valid %d-%d)\n", var_info.begin_pos, var_info.end_pos);
+ THR_Print(" (valid %d-%d)\n", var_info.begin_pos, var_info.end_pos);
}
}
- ISL_Print("}\n");
+ THR_Print("}\n");
- ISL_Print("Exception Handlers for function '%s' {\n", function_fullname);
+ THR_Print("Exception Handlers for function '%s' {\n", function_fullname);
const ExceptionHandlers& handlers =
ExceptionHandlers::Handle(code.exception_handlers());
- ISL_Print("%s}\n", handlers.ToCString());
+ THR_Print("%s}\n", handlers.ToCString());
{
- ISL_Print("Static call target functions {\n");
+ THR_Print("Static call target functions {\n");
const Array& table = Array::Handle(code.static_calls_target_table());
Smi& offset = Smi::Handle();
Function& function = Function::Handle();
@@ -960,24 +960,24 @@
cls ^= code.owner();
if (cls.IsNull()) {
const String& code_name = String::Handle(code.Name());
- ISL_Print(" 0x%" Px ": %s, %p\n",
+ THR_Print(" 0x%" Px ": %s, %p\n",
start + offset.Value(),
code_name.ToCString(),
code.raw());
} else {
- ISL_Print(" 0x%" Px ": allocation stub for %s, %p\n",
+ THR_Print(" 0x%" Px ": allocation stub for %s, %p\n",
start + offset.Value(),
cls.ToCString(),
code.raw());
}
} else {
- ISL_Print(" 0x%" Px ": %s, %p\n",
+ THR_Print(" 0x%" Px ": %s, %p\n",
start + offset.Value(),
function.ToFullyQualifiedCString(),
code.raw());
}
}
- ISL_Print("}\n");
+ THR_Print("}\n");
}
if (optimized && FLAG_trace_inlining_intervals) {
code.DumpInlinedIntervals();
@@ -1039,7 +1039,7 @@
ParsedFunction* parsed_function = new(zone) ParsedFunction(
thread, Function::ZoneHandle(zone, function.raw()));
if (FLAG_trace_compiler) {
- ISL_Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n",
+ THR_Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n",
(osr_id == Isolate::kNoDeoptId ? "" : "osr "),
(optimized ? "optimized " : ""),
function.ToFullyQualifiedCString(),
@@ -1069,10 +1069,10 @@
ASSERT(!Compiler::always_optimize()); // Optimized is the only code.
// Optimizer bailed out. Disable optimizations and never try again.
if (FLAG_trace_compiler) {
- ISL_Print("--> disabling optimizations for '%s'\n",
+ THR_Print("--> disabling optimizations for '%s'\n",
function.ToFullyQualifiedCString());
} else if (FLAG_trace_failed_optimization_attempts) {
- ISL_Print("Cannot optimize: %s\n",
+ THR_Print("Cannot optimize: %s\n",
function.ToFullyQualifiedCString());
}
function.SetIsOptimizable(false);
@@ -1084,7 +1084,7 @@
per_compile_timer.Stop();
if (FLAG_trace_compiler) {
- ISL_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n",
+ THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n",
function.ToFullyQualifiedCString(),
Code::Handle(function.CurrentCode()).EntryPoint(),
Code::Handle(function.CurrentCode()).Size(),
@@ -1099,9 +1099,9 @@
optimized &&
FlowGraphPrinter::ShouldPrint(function)) {
// TODO(fschneider): Print unoptimized code along with the optimized code.
- ISL_Print("*** BEGIN CODE\n");
+ THR_Print("*** BEGIN CODE\n");
DisassembleCode(function, true);
- ISL_Print("*** END CODE\n");
+ THR_Print("*** END CODE\n");
}
#if defined(DEBUG)
CheckInliningIntervals(function);
@@ -1170,7 +1170,7 @@
}
ASSERT(function.unoptimized_code() != Object::null());
if (FLAG_trace_compiler) {
- ISL_Print("Ensure unoptimized code for %s\n", function.ToCString());
+ THR_Print("Ensure unoptimized code for %s\n", function.ToCString());
}
return Error::null();
}
@@ -1288,13 +1288,12 @@
void Compiler::CompileStaticInitializer(const Field& field) {
ASSERT(field.is_static());
- if (field.PrecompiledInitializer() != Function::null()) {
+ if (field.HasPrecompiledInitializer()) {
// TODO(rmacnak): Investigate why this happens for _enum_names.
OS::Print("Warning: Ignoring repeated request for initializer for %s\n",
field.ToCString());
return;
}
- ASSERT(field.PrecompiledInitializer() == Function::null());
Thread* thread = Thread::Current();
StackZone zone(thread);
@@ -1339,6 +1338,8 @@
false, // optimized
Isolate::kNoDeoptId);
initializer = parsed_function->function().raw();
+ Code::Handle(initializer.unoptimized_code()).set_var_descriptors(
+ Object::empty_var_descriptors());
} else {
initializer ^= field.PrecompiledInitializer();
}
@@ -1364,7 +1365,7 @@
if (setjmp(*jump.Set()) == 0) {
Thread* const thread = Thread::Current();
if (FLAG_trace_compiler) {
- ISL_Print("compiling expression: ");
+ THR_Print("compiling expression: ");
AstPrinter::PrintNode(fragment);
}
@@ -1406,6 +1407,8 @@
parsed_function,
false,
Isolate::kNoDeoptId);
+ Code::Handle(func.unoptimized_code()).set_var_descriptors(
+ Object::empty_var_descriptors());
const Object& result = PassiveObject::Handle(
DartEntry::InvokeFunction(func, Object::empty_array()));
diff --git a/runtime/vm/compiler_stats.cc b/runtime/vm/compiler_stats.cc
index e04c0c0..86da700 100644
--- a/runtime/vm/compiler_stats.cc
+++ b/runtime/vm/compiler_stats.cc
@@ -124,7 +124,7 @@
Dart::vm_isolate()->heap()->IterateObjects(&visitor);
Log log(PrintToStats);
- LogBlock lb(isolate_, &log);
+ LogBlock lb(Thread::Current(), &log);
log.Print("==== Compiler Stats for isolate '%s' ====\n",
isolate_->debugger_name());
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc
index d18ce19..82e7b54 100644
--- a/runtime/vm/coverage.cc
+++ b/runtime/vm/coverage.cc
@@ -247,13 +247,10 @@
JSONStream stream;
PrintJSON(isolate, &stream, NULL, false);
- const char* format = "%s/dart-cov-%" Pd "-%" Pd64 ".json";
intptr_t pid = OS::ProcessId();
- intptr_t len = OS::SNPrint(NULL, 0, format,
- FLAG_coverage_dir, pid, isolate->main_port());
- char* filename = Thread::Current()->zone()->Alloc<char>(len + 1);
- OS::SNPrint(filename, len + 1, format,
- FLAG_coverage_dir, pid, isolate->main_port());
+ char* filename = OS::SCreate(Thread::Current()->zone(),
+ "%s/dart-cov-%" Pd "-%" Pd64 ".json",
+ FLAG_coverage_dir, pid, isolate->main_port());
void* file = (*file_open)(filename, true);
if (file == NULL) {
OS::Print("Failed to write coverage file: %s\n", filename);
diff --git a/runtime/vm/cpuinfo_test.cc b/runtime/vm/cpuinfo_test.cc
index e717d28..860c407 100644
--- a/runtime/vm/cpuinfo_test.cc
+++ b/runtime/vm/cpuinfo_test.cc
@@ -10,10 +10,8 @@
namespace dart {
UNIT_TEST_CASE(GetCpuModelTest) {
- CpuInfo::InitOnce();
const char* cpumodel = CpuInfo::GetCpuModel();
EXPECT_NE(strlen(cpumodel), 0UL);
- CpuInfo::Cleanup();
}
} // namespace dart
diff --git a/runtime/vm/custom_isolate_test.cc b/runtime/vm/custom_isolate_test.cc
index af30507..2cb2e00 100644
--- a/runtime/vm/custom_isolate_test.cc
+++ b/runtime/vm/custom_isolate_test.cc
@@ -59,6 +59,7 @@
" var replyTo = message[1];\n"
" echo('Received: $data');\n"
" replyTo.send(data + 1);\n"
+ " mainPort.close();\n"
" };\n"
"}\n"
"\n"
@@ -179,6 +180,7 @@
free(const_cast<char*>(main_));
main_ = NULL;
+ Dart_SetMessageNotifyCallback(NULL);
Dart_ExitScope();
Dart_ExitIsolate();
}
@@ -207,6 +209,7 @@
if (!Dart_HasLivePorts()) {
OS::Print("<< Shutting down isolate(%p)\n", isolate());
event_queue->RemoveEventsForIsolate(isolate());
+ Dart_SetMessageNotifyCallback(NULL);
Dart_ShutdownIsolate();
} else {
Dart_ExitScope();
@@ -350,6 +353,7 @@
free(const_cast<char*>(saved_echo));
delete event_queue;
+ event_queue = NULL;
}
} // namespace dart
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index e59c411..89d9fc5 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -35,8 +35,10 @@
DECLARE_FLAG(bool, print_class_table);
DECLARE_FLAG(bool, trace_isolates);
+DECLARE_FLAG(bool, trace_time_all);
DEFINE_FLAG(bool, keep_code, false,
"Keep deoptimized code for profiling.");
+DEFINE_FLAG(bool, shutdown, true, "Do a clean shutdown of the VM");
Isolate* Dart::vm_isolate_ = NULL;
ThreadPool* Dart::thread_pool_ = NULL;
@@ -118,12 +120,14 @@
ASSERT(vm_isolate_ == NULL);
ASSERT(Flags::Initialized());
const bool is_vm_isolate = true;
+ const bool precompiled = instructions_snapshot != NULL;
// Setup default flags for the VM isolate.
Isolate::Flags vm_flags;
Dart_IsolateFlags api_flags;
vm_flags.CopyTo(&api_flags);
vm_isolate_ = Isolate::Init("vm-isolate", api_flags, is_vm_isolate);
+ vm_isolate_->set_compilation_allowed(!precompiled);
// Verify assumptions about executing in the VM isolate.
ASSERT(vm_isolate_ == Isolate::Current());
ASSERT(vm_isolate_ == Thread::Current()->isolate());
@@ -135,10 +139,10 @@
TargetCPUFeatures::InitOnce();
Object::InitOnce(vm_isolate_);
ArgumentsDescriptor::InitOnce();
- StubCode::InitOnce();
- Thread::InitOnceAfterObjectAndStubCode();
- // Now that the needed stub has been generated, set the stack limit.
- vm_isolate_->InitializeStackLimit();
+ // When precompiled the stub code is initialized from the snapshot.
+ if (!precompiled) {
+ StubCode::InitOnce();
+ }
if (vm_isolate_snapshot != NULL) {
const Snapshot* snapshot = Snapshot::SetupFromBuffer(vm_isolate_snapshot);
if (snapshot == NULL) {
@@ -157,7 +161,7 @@
OS::Print("Size of vm isolate snapshot = %" Pd "\n",
snapshot->length());
vm_isolate_->heap()->PrintSizes();
- vm_isolate_->megamorphic_cache_table()->PrintSizes();
+ MegamorphicCacheTable::PrintSizes(vm_isolate_);
intptr_t size;
intptr_t capacity;
Symbols::GetStats(vm_isolate_, &size, &capacity);
@@ -167,6 +171,9 @@
} else {
Symbols::InitOnce(vm_isolate_);
}
+ Thread::InitOnceAfterObjectAndStubCode();
+ // Now that the needed stub has been generated, set the stack limit.
+ vm_isolate_->InitializeStackLimit();
Scanner::InitOnce();
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
// Dart VM requires at least SSE2.
@@ -195,38 +202,60 @@
}
+// This waits until only the VM isolate remains in the list.
+void Dart::WaitForIsolateShutdown() {
+ ASSERT(!Isolate::creation_enabled_);
+ MonitorLocker ml(Isolate::isolates_list_monitor_);
+ while ((Isolate::isolates_list_head_ != NULL) &&
+ (Isolate::isolates_list_head_->next_ != NULL)) {
+ ml.Wait();
+ }
+ ASSERT(Isolate::isolates_list_head_ == Dart::vm_isolate());
+}
+
+
const char* Dart::Cleanup() {
- // Shutdown the service isolate before shutting down the thread pool.
- ServiceIsolate::Shutdown();
-#if 0
- // Ideally we should shutdown the VM isolate here, but the thread pool
- // shutdown does not seem to ensure that all the threads have stopped
- // execution before it terminates, this results in racing isolates.
+ ASSERT(Isolate::Current() == NULL);
if (vm_isolate_ == NULL) {
return "VM already terminated.";
}
- ASSERT(Isolate::Current() == NULL);
-
- delete thread_pool_;
- thread_pool_ = NULL;
-
- // Set the VM isolate as current isolate.
- Thread::EnsureInit();
- Thread::EnterIsolate(vm_isolate_);
-
- // There is a planned and known asymmetry here: We exit one scope for the VM
- // isolate to account for the scope that was entered in Dart_InitOnce.
- Dart_ExitScope();
-
- ShutdownIsolate();
- vm_isolate_ = NULL;
-
- TargetCPUFeatures::Cleanup();
- StoreBuffer::ShutDown();
-#endif
-
+ // Shut down profiling.
Profiler::Shutdown();
+
+ if (FLAG_shutdown) {
+ // Disable the creation of new isolates.
+ Isolate::DisableIsolateCreation();
+
+ // Send the OOB Kill message to all remaining application isolates.
+ Isolate::KillAllIsolates();
+
+ // Shutdown the service isolate.
+ ServiceIsolate::Shutdown();
+
+ // Wait for all application isolates and the service isolate to shutdown
+ // before shutting down the thread pool.
+ WaitForIsolateShutdown();
+
+ // Shutdown the thread pool. On return, all thread pool threads have exited.
+ delete thread_pool_;
+ thread_pool_ = NULL;
+
+ // Set the VM isolate as current isolate.
+ Thread::EnsureInit();
+ Thread::EnterIsolate(vm_isolate_);
+
+ ShutdownIsolate();
+ vm_isolate_ = NULL;
+ ASSERT(Isolate::IsolateListLength() == 0);
+
+ TargetCPUFeatures::Cleanup();
+ StoreBuffer::ShutDown();
+ } else {
+ // Shutdown the service isolate.
+ ServiceIsolate::Shutdown();
+ }
+
CodeObservers::DeleteAll();
Timeline::Shutdown();
Metric::Cleanup();
@@ -293,7 +322,7 @@
}
if (FLAG_trace_isolates) {
I->heap()->PrintSizes();
- I->megamorphic_cache_table()->PrintSizes();
+ MegamorphicCacheTable::PrintSizes(I);
}
} else {
// Populate the isolate's symbol table with all symbols from the
@@ -310,7 +339,7 @@
StubCode::Init(I);
}
- I->megamorphic_cache_table()->InitMissHandler();
+ MegamorphicCacheTable::InitMissHandler(I);
if (snapshot_buffer == NULL) {
if (!I->object_store()->PreallocateObjects()) {
return I->object_store()->sticky_error();
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index e06ae4e..c0203cc 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -55,6 +55,8 @@
static bool IsReadOnlyHandle(uword address);
private:
+ static void WaitForIsolateShutdown();
+
static Isolate* vm_isolate_;
static ThreadPool* thread_pool_;
static DebugInfo* pprof_symbol_generator_;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index f3f1f52..5e1105a 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1254,7 +1254,7 @@
return Version::String();
}
-DART_EXPORT bool Dart_Initialize(
+DART_EXPORT char* Dart_Initialize(
const uint8_t* vm_isolate_snapshot,
const uint8_t* instructions_snapshot,
Dart_IsolateCreateCallback create,
@@ -1272,21 +1272,19 @@
file_open, file_read, file_write,
file_close, entropy_source);
if (err_msg != NULL) {
- OS::PrintErr("Dart_Initialize: %s\n", err_msg);
- return false;
+ return strdup(err_msg);
}
- return true;
+ return NULL;
}
-DART_EXPORT bool Dart_Cleanup() {
+DART_EXPORT char* Dart_Cleanup() {
CHECK_NO_ISOLATE(Isolate::Current());
const char* err_msg = Dart::Cleanup();
if (err_msg != NULL) {
- OS::PrintErr("Dart_Cleanup: %s\n", err_msg);
- return false;
+ return strdup(err_msg);
}
- return true;
+ return NULL;
}
@@ -1357,6 +1355,10 @@
}
Isolate* I = Dart::CreateIsolate(isolate_name, *flags);
free(isolate_name);
+ if (I == NULL) {
+ *error = strdup("Isolate creation failed");
+ return reinterpret_cast<Dart_Isolate>(NULL);
+ }
{
Thread* T = Thread::Current();
StackZone zone(T);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index f79106e..bf4ec2a 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -1107,13 +1107,22 @@
TEST_CASE(MalformedStringToUTF8) {
+ // 1D11E = treble clef
+ // [0] should be high surrogate D834
+ // [1] should be low surrogate DD1E
+ // Strings are allowed to have individual or out of order surrogates, even
+ // if that doesn't make sense as renderable characters.
const char* kScriptChars =
- "String testMain() {"
+ "String lowSurrogate() {"
" return '\\u{1D11E}'[1];"
- "}";
+ "}"
+ "String highSurrogate() {"
+ " return '\\u{1D11E}'[0];"
+ "}"
+ "String reversed() => lowSurrogate() + highSurrogate();";
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
- Dart_Handle str1 = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
+ Dart_Handle str1 = Dart_Invoke(lib, NewString("lowSurrogate"), 0, NULL);
EXPECT_VALID(str1);
uint8_t* utf8_encoded = NULL;
@@ -1126,7 +1135,20 @@
EXPECT_EQ(158, static_cast<intptr_t>(utf8_encoded[2]));
Dart_Handle str2 = Dart_NewStringFromUTF8(utf8_encoded, utf8_length);
- EXPECT(Dart_IsError(str2)); // Invalid UTF-8.
+ EXPECT_VALID(str2); // Standalone low surrogate, but still valid
+
+ Dart_Handle reversed = Dart_Invoke(lib, NewString("reversed"), 0, NULL);
+ EXPECT_VALID(reversed); // This is also allowed.
+ uint8_t* utf8_encoded_reversed = NULL;
+ intptr_t utf8_length_reversed = 0;
+ result = Dart_StringToUTF8(reversed,
+ &utf8_encoded_reversed, &utf8_length_reversed);
+ EXPECT_VALID(result);
+ EXPECT_EQ(6, utf8_length_reversed);
+ uint8_t expected[6] = {237, 180, 158, 237, 160, 180};
+ for (int i = 0; i < 6; i++) {
+ EXPECT_EQ(expected[i], utf8_encoded_reversed[i]);
+ }
}
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 92e8562..016f3ce 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -60,6 +60,10 @@
// Initialize the preallocated fixed length arguments descriptors cache.
static void InitOnce();
+ enum {
+ kCachedDescriptorCount = 32
+ };
+
private:
// Absolute indexes into the array.
enum {
@@ -75,10 +79,6 @@
kNamedEntrySize,
};
- enum {
- kCachedDescriptorCount = 32
- };
-
static intptr_t LengthFor(intptr_t count) {
// Add 1 for the terminating null.
return kFirstNamedEntryIndex + (kNamedEntrySize * count) + 1;
@@ -91,8 +91,8 @@
// A cache of VM heap allocated arguments descriptors.
static RawArray* cached_args_descriptors_[kCachedDescriptorCount];
- friend class FullSnapshotWriter;
- friend class VmIsolateSnapshotReader;
+ friend class SnapshotReader;
+ friend class SnapshotWriter;
DISALLOW_COPY_AND_ASSIGN(ArgumentsDescriptor);
};
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 96966d9..e0dd4a9 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -65,7 +65,9 @@
// Create an unresolved breakpoint in given token range and script.
BreakpointLocation::BreakpointLocation(const Script& script,
intptr_t token_pos,
- intptr_t end_token_pos)
+ intptr_t end_token_pos,
+ intptr_t requested_line_number,
+ intptr_t requested_column_number)
: script_(script.raw()),
url_(script.url()),
token_pos_(token_pos),
@@ -73,15 +75,19 @@
is_resolved_(false),
next_(NULL),
conditions_(NULL),
+ requested_line_number_(requested_line_number),
+ requested_column_number_(requested_column_number),
function_(Function::null()),
- line_number_(-1) {
+ line_number_(-1),
+ column_number_(-1) {
ASSERT(!script.IsNull());
ASSERT(token_pos_ >= 0);
}
// Create a latent breakpoint at given url and line number.
BreakpointLocation::BreakpointLocation(const String& url,
- intptr_t line_number)
+ intptr_t requested_line_number,
+ intptr_t requested_column_number)
: script_(Script::null()),
url_(url.raw()),
token_pos_(-1),
@@ -89,9 +95,12 @@
is_resolved_(false),
next_(NULL),
conditions_(NULL),
+ requested_line_number_(requested_line_number),
+ requested_column_number_(requested_column_number),
function_(Function::null()),
- line_number_(line_number) {
- ASSERT(line_number_ >= 0);
+ line_number_(-1),
+ column_number_(-1) {
+ ASSERT(requested_line_number_ >= 0);
}
@@ -119,7 +128,6 @@
function_ = func.raw();
token_pos_ = token_pos;
end_token_pos_ = token_pos;
- line_number_ = -1; // Recalculate lazily.
is_resolved_ = true;
}
@@ -129,7 +137,7 @@
// in more than one library, e.g. the text location of mixin functions.
void BreakpointLocation::GetCodeLocation(Library* lib,
Script* script,
- intptr_t* pos) {
+ intptr_t* pos) const {
if (IsLatent()) {
*lib = Library::null();
*script = Script::null();
@@ -150,8 +158,7 @@
intptr_t BreakpointLocation::LineNumber() {
- // Latent breakpoints must have a requested line number >= 0.
- ASSERT(!IsLatent() || line_number_ >= 0);
+ ASSERT(IsResolved());
// Compute line number lazily since it causes scanning of the script.
if (line_number_ < 0) {
const Script& script = Script::Handle(this->script());
@@ -161,6 +168,17 @@
}
+intptr_t BreakpointLocation::ColumnNumber() {
+ ASSERT(IsResolved());
+ // Compute column number lazily since it causes scanning of the script.
+ if (column_number_ < 0) {
+ const Script& script = Script::Handle(this->script());
+ script.GetTokenLocation(token_pos_, &line_number_, &column_number_);
+ }
+ return column_number_;
+}
+
+
void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) {
ASSERT(bpt_location_->IsLatent()); // Only reason to move.
bpt_location_ = new_bpt_location;
@@ -186,20 +204,17 @@
void Breakpoint::PrintJSON(JSONStream* stream) {
- Isolate* isolate = Isolate::Current();
-
JSONObject jsobj(stream);
jsobj.AddProperty("type", "Breakpoint");
jsobj.AddFixedServiceId("breakpoints/%" Pd "", id());
jsobj.AddProperty("breakpointNumber", id());
jsobj.AddProperty("resolved", bpt_location_->IsResolved());
-
- Library& library = Library::Handle(isolate);
- Script& script = Script::Handle(isolate);
- intptr_t token_pos;
- bpt_location_->GetCodeLocation(&library, &script, &token_pos);
- jsobj.AddLocation(script, token_pos);
+ if (bpt_location_->IsResolved()) {
+ jsobj.AddLocation(bpt_location_);
+ } else {
+ jsobj.AddUnresolvedLocation(bpt_location_);
+ }
}
@@ -403,18 +418,10 @@
Class& func_class = Class::Handle(func.Owner());
String& class_name = String::Handle(func_class.Name());
- const char* kFormat = "%s%s%s";
- intptr_t len = OS::SNPrint(NULL, 0, kFormat,
- func_class.IsTopLevel() ? "" : class_name.ToCString(),
- func_class.IsTopLevel() ? "" : ".",
- func_name.ToCString());
- len++; // String terminator.
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat,
- func_class.IsTopLevel() ? "" : class_name.ToCString(),
+ return OS::SCreate(Thread::Current()->zone(),
+ "%s%s%s", func_class.IsTopLevel() ? "" : class_name.ToCString(),
func_class.IsTopLevel() ? "" : ".",
func_name.ToCString());
- return chars;
}
@@ -667,7 +674,6 @@
return ctx_;
}
}
- UNREACHABLE();
return Context::ZoneHandle(Context::null());
}
@@ -1602,13 +1608,66 @@
}
-// Given a function and a token range, return the best fit
-// token position to set a breakpoint. The best fit is the safe point
-// in the line closest to the beginning of the token range, and within
-// that line, the safe point with the lowest compiled code address.
+// Returns the best fit token position for a breakpoint.
+//
+// Takes a range of tokens [requested_token_pos, last_token_pos] and
+// an optional column (requested_column). The range of tokens usually
+// represents one line of the program text, but can represent a larger
+// range on recursive calls.
+//
+// The best fit is found in two passes.
+//
+// The first pass finds a candidate token which:
+//
+// - is a safepoint,
+// - has the lowest column number compatible with the requested column
+// if a column has been specified,
+// and:
+// - has the lowest token position number which satisfies the above.
+//
+// When we consider a column number, we look for the closed token
+// which intersects the desired column. For example:
+//
+// 1 2 3
+// 12345678901234567890 0
+//
+// var x = function(function(y));
+// ^
+//
+// If we request a breakpoint at column 14, the lowest column number
+// compatible with that would for column 11 (beginning of the
+// 'function' token) in the example above.
+//
+// Once this candidate token from the first pass is found, we then
+// have a second pass which considers only those tokens on the same
+// line as the candidate token.
+//
+// The second pass finds a best fit token which:
+//
+// - is a safepoint,
+// - has the same column number as the candidate token (perhaps
+// more than one token has the same column number),
+// and:
+// - has the lowest code address in the generated code.
+//
+// We prefer the lowest compiled code address, because this tends to
+// select the first subexpression on a line. For example in a line
+// with nested function calls f(g(x)), the call to g() will have a
+// lower compiled code address than the call to f().
+//
+// If no best fit token can be found, the search is expanded,
+// searching through the rest of the current function by calling this
+// function recursively.
+//
+// TODO(turnidge): Given that we usually call this function with a
+// token range restricted to a single line, this could be a one-pass
+// algorithm, which would be simpler. I believe that it only needs
+// two passes to support the recursive try-the-whole-function case.
+// Rewrite this later, once there are more tests in place.
intptr_t Debugger::ResolveBreakpointPos(const Function& func,
intptr_t requested_token_pos,
- intptr_t last_token_pos) {
+ intptr_t last_token_pos,
+ intptr_t requested_column) {
ASSERT(func.HasCode());
ASSERT(!func.HasOptimizedCode());
@@ -1619,6 +1678,7 @@
last_token_pos = func.end_token_pos();
}
+ Script& script = Script::Handle(func.script());
Code& code = Code::Handle(func.unoptimized_code());
ASSERT(!code.IsNull());
PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
@@ -1626,22 +1686,47 @@
// First pass: find the safe point which is closest to the beginning
// of the given token range.
intptr_t best_fit_pos = INT_MAX;
+ intptr_t best_column = INT_MAX;
PcDescriptors::Iterator iter(desc, kSafepointKind);
while (iter.MoveNext()) {
- const intptr_t desc_token_pos = iter.TokenPos();
- if ((desc_token_pos != Scanner::kNoSourcePos) &&
- (desc_token_pos < best_fit_pos) &&
- (desc_token_pos >= requested_token_pos) &&
- (desc_token_pos <= last_token_pos)) {
- best_fit_pos = desc_token_pos;
+ const intptr_t pos = iter.TokenPos();
+ if ((pos == Scanner::kNoSourcePos) ||
+ (pos < requested_token_pos) ||
+ (pos > last_token_pos)) {
+ // Token is not in the target range.
+ continue;
+ }
+
+ intptr_t token_start_column = -1;
+ if (requested_column >= 0) {
+ intptr_t ignored = -1;
+ intptr_t token_len = -1;
+ // TODO(turnidge): GetTokenLocation is a very expensive
+ // operation, and this code will blow up when we are setting
+ // column breakpoints on, for example, a large, single-line
+ // program. Consider rewriting this code so that it only scans
+ // the program code once and caches the token positions and
+ // lengths.
+ script.GetTokenLocation(pos, &ignored, &token_start_column, &token_len);
+ intptr_t token_end_column = token_start_column + token_len - 1;
+ if ((token_end_column < requested_column) ||
+ (token_start_column > best_column)) {
+ // Prefer the token with the lowest column number compatible
+ // with the requested column.
+ continue;
+ }
+ }
+
+ // Prefer the lowest (first) token pos.
+ if (pos < best_fit_pos) {
+ best_fit_pos = pos;
+ best_column = token_start_column;
}
}
- // Second pass (if we found a safe point in the first pass):
- // For all token positions on the same line, select the one
- // with the lowest compiled code address. E.g., in a line with
- // the nested function calls f(g(x)), the call g() will have a lower
- // compiled code address but is not the lowest token position in the
- // line.
+
+ // Second pass (if we found a safe point in the first pass). Find
+ // the token on the line which is at the best fit column (if column
+ // was specified) and has the lowest code address.
if (best_fit_pos != INT_MAX) {
const Script& script = Script::Handle(func.script());
const TokenStream& tokens = TokenStream::Handle(script.tokens());
@@ -1651,9 +1736,26 @@
PcDescriptors::Iterator iter(desc, kSafepointKind);
while (iter.MoveNext()) {
const intptr_t pos = iter.TokenPos();
- if ((pos != Scanner::kNoSourcePos) &&
- (begin_pos <= pos) && (pos <= end_of_line_pos) &&
- (iter.PcOffset() < lowest_pc_offset)) {
+ if ((pos == Scanner::kNoSourcePos) ||
+ (pos < begin_pos) ||
+ (pos > end_of_line_pos)) {
+ // Token is not on same line as best fit.
+ continue;
+ }
+
+ if (requested_column >= 0) {
+ intptr_t ignored = -1;
+ intptr_t token_start_column = -1;
+ // We look for other tokens at the best column in case there
+ // is more than one token at the same column offset.
+ script.GetTokenLocation(pos, &ignored, &token_start_column);
+ if (token_start_column != best_column) {
+ continue;
+ }
+ }
+
+ // Prefer the lowest pc offset.
+ if (iter.PcOffset() < lowest_pc_offset) {
lowest_pc_offset = iter.PcOffset();
best_fit_pos = pos;
}
@@ -1661,10 +1763,13 @@
return best_fit_pos;
}
- // We didn't find a safe point in the given token range. Try and find
- // a safe point in the remaining source code of the function.
+ // We didn't find a safe point in the given token range. Try and
+ // find a safe point in the remaining source code of the function.
+ // Since we have moved to the next line of the function, we no
+ // longer are requesting a specific column number.
if (last_token_pos < func.end_token_pos()) {
- return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos());
+ return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(),
+ -1 /* no column */);
}
return -1;
}
@@ -1857,7 +1962,9 @@
BreakpointLocation* Debugger::SetBreakpoint(const Script& script,
intptr_t token_pos,
- intptr_t last_token_pos) {
+ intptr_t last_token_pos,
+ intptr_t requested_line,
+ intptr_t requested_column) {
Function& func = Function::Handle(isolate_);
func = FindBestFit(script, token_pos);
if (func.IsNull()) {
@@ -1881,14 +1988,16 @@
DeoptimizeWorld();
func ^= functions.At(0);
intptr_t breakpoint_pos =
- ResolveBreakpointPos(func, token_pos, last_token_pos);
+ ResolveBreakpointPos(func, token_pos, last_token_pos, requested_column);
if (breakpoint_pos >= 0) {
- BreakpointLocation* bpt = GetBreakpointLocation(script, breakpoint_pos);
+ BreakpointLocation* bpt =
+ GetBreakpointLocation(script, breakpoint_pos, requested_column);
if (bpt != NULL) {
// A source breakpoint for this location already exists.
return bpt;
}
- bpt = new BreakpointLocation(script, token_pos, last_token_pos);
+ bpt = new BreakpointLocation(script, token_pos, last_token_pos,
+ requested_line, requested_column);
bpt->SetResolved(func, breakpoint_pos);
RegisterBreakpointLocation(bpt);
@@ -1901,11 +2010,12 @@
}
if (FLAG_verbose_debug) {
intptr_t line_number;
- script.GetTokenLocation(breakpoint_pos, &line_number, NULL);
+ intptr_t column_number;
+ script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
OS::Print("Resolved BP for "
- "function '%s' at line %" Pd "\n",
+ "function '%s' at line %" Pd " col %" Pd "\n",
func.ToFullyQualifiedCString(),
- line_number);
+ line_number, column_number);
}
return bpt;
}
@@ -1914,15 +2024,18 @@
// Register an unresolved breakpoint.
if (FLAG_verbose_debug && !func.IsNull()) {
intptr_t line_number;
- script.GetTokenLocation(token_pos, &line_number, NULL);
+ intptr_t column_number;
+ script.GetTokenLocation(token_pos, &line_number, &column_number);
OS::Print("Registering pending breakpoint for "
- "uncompiled function '%s' at line %" Pd "\n",
+ "uncompiled function '%s' at line %" Pd " col %" Pd "\n",
func.ToFullyQualifiedCString(),
- line_number);
+ line_number, column_number);
}
- BreakpointLocation* bpt = GetBreakpointLocation(script, token_pos);
+ BreakpointLocation* bpt =
+ GetBreakpointLocation(script, token_pos, requested_column);
if (bpt == NULL) {
- bpt = new BreakpointLocation(script, token_pos, last_token_pos);
+ bpt = new BreakpointLocation(script, token_pos, last_token_pos,
+ requested_line, requested_column);
RegisterBreakpointLocation(bpt);
}
return bpt;
@@ -1969,7 +2082,8 @@
BreakpointLocation* bpt_location =
SetBreakpoint(script,
target_function.token_pos(),
- target_function.end_token_pos());
+ target_function.end_token_pos(),
+ -1, -1 /* no requested line/col */);
if (single_shot) {
return bpt_location->AddSingleShot(this);
} else {
@@ -1986,7 +2100,8 @@
const Script& script = Script::Handle(func.script());
BreakpointLocation* bpt_location = SetBreakpoint(script,
func.token_pos(),
- func.end_token_pos());
+ func.end_token_pos(),
+ -1, -1 /* no line/col */);
return bpt_location->AddPerClosure(this, closure);
}
@@ -2016,7 +2131,8 @@
Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
intptr_t line_number) {
- BreakpointLocation* loc = BreakpointLocationAtLine(script_url, line_number);
+ BreakpointLocation* loc =
+ BreakpointLocationAtLineCol(script_url, line_number, -1 /* no column */);
if (loc != NULL) {
return loc->AddRepeated(this);
}
@@ -2024,8 +2140,23 @@
}
-BreakpointLocation* Debugger::BreakpointLocationAtLine(const String& script_url,
- intptr_t line_number) {
+Breakpoint* Debugger::SetBreakpointAtLineCol(const String& script_url,
+ intptr_t line_number,
+ intptr_t column_number) {
+ BreakpointLocation* loc = BreakpointLocationAtLineCol(script_url,
+ line_number,
+ column_number);
+ if (loc != NULL) {
+ return loc->AddRepeated(this);
+ }
+ return NULL;
+}
+
+
+BreakpointLocation* Debugger::BreakpointLocationAtLineCol(
+ const String& script_url,
+ intptr_t line_number,
+ intptr_t column_number) {
Library& lib = Library::Handle(isolate_);
Script& script = Script::Handle(isolate_);
const GrowableObjectArray& libs =
@@ -2043,11 +2174,13 @@
// No script found with given url. Create a latent breakpoint which
// will be set if the url is loaded later.
BreakpointLocation* latent_bpt = GetLatentBreakpoint(script_url,
- line_number);
+ line_number,
+ column_number);
if (FLAG_verbose_debug) {
- OS::Print("Set latent breakpoint in url '%s' at line %" Pd "\n",
+ OS::Print("Set latent breakpoint in url '%s' at "
+ "line %" Pd " col %" Pd "\n",
script_url.ToCString(),
- line_number);
+ line_number, column_number);
}
return latent_bpt;
}
@@ -2079,7 +2212,8 @@
BreakpointLocation* bpt = NULL;
ASSERT(first_token_idx <= last_token_idx);
while ((bpt == NULL) && (first_token_idx <= last_token_idx)) {
- bpt = SetBreakpoint(script, first_token_idx, last_token_idx);
+ bpt = SetBreakpoint(script, first_token_idx, last_token_idx,
+ line_number, column_number);
first_token_idx++;
}
if ((bpt == NULL) && FLAG_verbose_debug) {
@@ -2680,7 +2814,8 @@
if (!loc->IsResolved()) {
// Resolve source breakpoint in the newly compiled function.
intptr_t bp_pos =
- ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos());
+ ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(),
+ loc->requested_column_number());
if (bp_pos < 0) {
if (FLAG_verbose_debug) {
OS::Print("Failed resolving breakpoint for function '%s'\n",
@@ -2694,14 +2829,18 @@
Breakpoint* bpt = loc->breakpoints();
while (bpt != NULL) {
if (FLAG_verbose_debug) {
- OS::Print("Resolved BP %" Pd " to pos %" Pd ", line %" Pd ", "
- "function '%s' (requested range %" Pd "-%" Pd ")\n",
+ OS::Print("Resolved BP %" Pd " to pos %" Pd ", "
+ "line %" Pd " col %" Pd ", "
+ "function '%s' (requested range %" Pd "-%" Pd ", "
+ "requested col %" Pd ")\n",
bpt->id(),
loc->token_pos(),
loc->LineNumber(),
+ loc->ColumnNumber(),
func.ToFullyQualifiedCString(),
requested_pos,
- requested_end_pos);
+ requested_end_pos,
+ loc->requested_column_number());
}
SignalBpResolved(bpt);
SendServiceBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
@@ -2712,9 +2851,11 @@
if (FLAG_verbose_debug) {
Breakpoint* bpt = loc->breakpoints();
while (bpt != NULL) {
- OS::Print("Setting breakpoint %" Pd " at line %" Pd " for %s '%s'\n",
+ OS::Print("Setting breakpoint %" Pd " at line %" Pd " col %" Pd ""
+ " for %s '%s'\n",
bpt->id(),
loc->LineNumber(),
+ loc->ColumnNumber(),
func.IsClosureFunction() ? "closure" : "function",
String::Handle(func.name()).ToCString());
bpt = bpt->next();
@@ -2757,7 +2898,8 @@
}
// Now find the token range at the requested line and make a
// new unresolved source breakpoint.
- intptr_t line_number = matched_loc->LineNumber();
+ intptr_t line_number = matched_loc->requested_line_number();
+ intptr_t column_number = matched_loc->requested_column_number();
ASSERT(line_number >= 0);
intptr_t first_token_pos, last_token_pos;
script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
@@ -2784,15 +2926,15 @@
// If there is one, assert in debug build but silently drop
// the latent breakpoint in release build.
BreakpointLocation* existing_loc =
- GetBreakpointLocation(script, first_token_pos);
+ GetBreakpointLocation(script, first_token_pos, column_number);
ASSERT(existing_loc == NULL);
if (existing_loc == NULL) {
// Create and register a new source breakpoint for the
// latent breakpoint.
BreakpointLocation* unresolved_loc =
new BreakpointLocation(script,
- first_token_pos,
- last_token_pos);
+ first_token_pos, last_token_pos,
+ line_number, column_number);
RegisterBreakpointLocation(unresolved_loc);
// Move breakpoints over.
@@ -2803,10 +2945,10 @@
bpt->set_bpt_location(unresolved_loc);
if (FLAG_verbose_debug) {
OS::Print("Converted latent breakpoint "
- "%" Pd " in '%s' at line %" Pd "\n",
+ "%" Pd " in '%s' at line %" Pd " col %" Pd "\n",
bpt->id(),
url.ToCString(),
- line_number);
+ line_number, column_number);
}
bpt = bpt->next();
}
@@ -2970,10 +3112,13 @@
BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script,
- intptr_t token_pos) {
+ intptr_t token_pos,
+ intptr_t requested_column) {
BreakpointLocation* bpt = breakpoint_locations_;
while (bpt != NULL) {
- if ((bpt->script_ == script.raw()) && (bpt->token_pos_ == token_pos)) {
+ if ((bpt->script_ == script.raw()) &&
+ (bpt->token_pos_ == token_pos) &&
+ (bpt->requested_column_number_ == requested_column)) {
return bpt;
}
bpt = bpt->next();
@@ -2999,18 +3144,21 @@
BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url,
- intptr_t line) {
+ intptr_t line,
+ intptr_t column) {
BreakpointLocation* bpt = latent_locations_;
String& bpt_url = String::Handle(isolate_);
while (bpt != NULL) {
bpt_url = bpt->url();
- if (bpt_url.Equals(url) && (bpt->LineNumber() == line)) {
+ if (bpt_url.Equals(url) &&
+ (bpt->requested_line_number() == line) &&
+ (bpt->requested_column_number() == column)) {
return bpt;
}
bpt = bpt->next();
}
- // No breakpint for this url and line requested. Allocate new one.
- bpt = new BreakpointLocation(url, line);
+ // No breakpoint for this location requested. Allocate new one.
+ bpt = new BreakpointLocation(url, line, column);
bpt->set_next(latent_locations_);
latent_locations_ = bpt;
return bpt;
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 396e8b2..685e5b5 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -99,10 +99,13 @@
// Create a new unresolved breakpoint.
BreakpointLocation(const Script& script,
intptr_t token_pos,
- intptr_t end_token_pos);
+ intptr_t end_token_pos,
+ intptr_t requested_line_number,
+ intptr_t requested_column_number);
// Create a new latent breakpoint.
BreakpointLocation(const String& url,
- intptr_t line_number);
+ intptr_t requested_line_number,
+ intptr_t requested_column_number);
~BreakpointLocation();
@@ -112,9 +115,16 @@
RawScript* script() const { return script_; }
RawString* url() const { return url_; }
- intptr_t LineNumber();
- void GetCodeLocation(Library* lib, Script* script, intptr_t* token_pos);
+ intptr_t requested_line_number() const { return requested_line_number_; }
+ intptr_t requested_column_number() const { return requested_column_number_; }
+
+ intptr_t LineNumber();
+ intptr_t ColumnNumber();
+
+ void GetCodeLocation(Library* lib,
+ Script* script,
+ intptr_t* token_pos) const;
Breakpoint* AddRepeated(Debugger* dbg);
Breakpoint* AddSingleShot(Debugger* dbg);
@@ -144,10 +154,13 @@
bool is_resolved_;
BreakpointLocation* next_;
Breakpoint* conditions_;
+ intptr_t requested_line_number_;
+ intptr_t requested_column_number_;
// Valid for resolved breakpoints:
RawFunction* function_;
intptr_t line_number_;
+ intptr_t column_number_;
friend class Debugger;
DISALLOW_COPY_AND_ASSIGN(BreakpointLocation);
@@ -460,10 +473,14 @@
// TODO(turnidge): script_url may no longer be specific enough.
Breakpoint* SetBreakpointAtLine(const String& script_url,
intptr_t line_number);
+ Breakpoint* SetBreakpointAtLineCol(const String& script_url,
+ intptr_t line_number,
+ intptr_t column_number);
RawError* OneTimeBreakAtEntry(const Function& target_function);
- BreakpointLocation* BreakpointLocationAtLine(const String& script_url,
- intptr_t line_number);
+ BreakpointLocation* BreakpointLocationAtLineCol(const String& script_url,
+ intptr_t line_number,
+ intptr_t column_number);
void RemoveBreakpoint(intptr_t bp_id);
@@ -555,6 +572,8 @@
static bool IsDebuggable(const Function& func);
+ intptr_t limitBreakpointId() { return next_id_; }
+
private:
enum ResumeAction {
kContinue,
@@ -575,18 +594,24 @@
intptr_t token_pos);
intptr_t ResolveBreakpointPos(const Function& func,
intptr_t requested_token_pos,
- intptr_t last_token_pos);
+ intptr_t last_token_pos,
+ intptr_t requested_column);
void DeoptimizeWorld();
BreakpointLocation* SetBreakpoint(const Script& script,
intptr_t token_pos,
- intptr_t last_token_pos);
+ intptr_t last_token_pos,
+ intptr_t requested_line,
+ intptr_t requested_column);
void RemoveInternalBreakpoints();
void UnlinkCodeBreakpoints(BreakpointLocation* bpt_location);
- BreakpointLocation* GetLatentBreakpoint(const String& url, intptr_t line);
+ BreakpointLocation* GetLatentBreakpoint(const String& url,
+ intptr_t line,
+ intptr_t column);
void RegisterBreakpointLocation(BreakpointLocation* bpt);
void RegisterCodeBreakpoint(CodeBreakpoint* bpt);
BreakpointLocation* GetBreakpointLocation(const Script& script,
- intptr_t token_pos);
+ intptr_t token_pos,
+ intptr_t requested_column);
void MakeCodeBreakpointAt(const Function& func,
BreakpointLocation* bpt);
// Returns NULL if no breakpoint exists for the given address.
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 9fd26d8..ad0198b 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -361,7 +361,11 @@
return Api::NewError("%s: breakpoint with id %" Pd " does not exist",
CURRENT_FUNC, bp_id);
}
- return Dart_NewInteger(bpt->bpt_location()->LineNumber());
+ if (bpt->bpt_location()->IsResolved()) {
+ return Dart_NewInteger(bpt->bpt_location()->LineNumber());
+ } else {
+ return Dart_NewInteger(bpt->bpt_location()->requested_line_number());
+ }
}
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index e539374..bd9e3e1 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -1405,6 +1405,7 @@
EXPECT(Dart_GetIsolateId(isolate) == test_isolate_id);
Dart_ExitScope();
Dart_ShutdownIsolate();
+ Dart_SetIsolateEventHandler(NULL);
EXPECT(verify_callback == 0x5); // Only created and shutdown events.
}
diff --git a/runtime/vm/debugger_test.cc b/runtime/vm/debugger_test.cc
index 7393c67..b418cbf 100644
--- a/runtime/vm/debugger_test.cc
+++ b/runtime/vm/debugger_test.cc
@@ -69,18 +69,18 @@
js.ToCString(),
"[{\"type\":\"Breakpoint\",\"fixedId\":true,\"id\":\"breakpoints\\/2\","
"\"breakpointNumber\":2,\"resolved\":false,"
- "\"location\":{\"type\":\"SourceLocation\","
+ "\"location\":{\"type\":\"UnresolvedSourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
"\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
"\"uri\":\"test-lib\","
- "\"_kind\":\"script\"},\"tokenPos\":14}},"
+ "\"_kind\":\"script\"},\"line\":3}},"
"{\"type\":\"Breakpoint\",\"fixedId\":true,\"id\":\"breakpoints\\/1\","
"\"breakpointNumber\":1,\"resolved\":false,"
- "\"location\":{\"type\":\"SourceLocation\","
+ "\"location\":{\"type\":\"UnresolvedSourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
"\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
"\"uri\":\"test-lib\","
- "\"_kind\":\"script\"},\"tokenPos\":5}}]",
+ "\"_kind\":\"script\"},\"line\":2}}]",
vmlib.index(), vmlib.index());
}
}
diff --git a/runtime/vm/disassembler.cc b/runtime/vm/disassembler.cc
index 1a92450..c63d459 100644
--- a/runtime/vm/disassembler.cc
+++ b/runtime/vm/disassembler.cc
@@ -21,22 +21,22 @@
uword pc) {
static const int kHexColumnWidth = 23;
uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc);
- ISL_Print("%p %s", pc_ptr, hex_buffer);
+ THR_Print("%p %s", pc_ptr, hex_buffer);
int hex_length = strlen(hex_buffer);
if (hex_length < kHexColumnWidth) {
for (int i = kHexColumnWidth - hex_length; i > 0; i--) {
- ISL_Print(" ");
+ THR_Print(" ");
}
}
- ISL_Print("%s", human_buffer);
- ISL_Print("\n");
+ THR_Print("%s", human_buffer);
+ THR_Print("\n");
}
void DisassembleToStdout::Print(const char* format, ...) {
va_list args;
va_start(args, format);
- ISL_VPrint(format, args);
+ THR_VPrint(format, args);
va_end(args);
}
diff --git a/runtime/vm/disassembler.h b/runtime/vm/disassembler.h
index 86413f8..1becc4d 100644
--- a/runtime/vm/disassembler.h
+++ b/runtime/vm/disassembler.h
@@ -99,13 +99,13 @@
uword end,
const Code& code) {
DisassembleToStdout stdout_formatter;
- LogBlock lb(Isolate::Current());
+ LogBlock lb;
Disassemble(start, end, &stdout_formatter, code);
}
static void Disassemble(uword start, uword end) {
DisassembleToStdout stdout_formatter;
- LogBlock lb(Isolate::Current());
+ LogBlock lb;
Disassemble(start, end, &stdout_formatter);
}
diff --git a/runtime/vm/disassembler_ia32.cc b/runtime/vm/disassembler_ia32.cc
index b18dd3f..036f5d0 100644
--- a/runtime/vm/disassembler_ia32.cc
+++ b/runtime/vm/disassembler_ia32.cc
@@ -479,11 +479,8 @@
const Class& clazz = Class::Handle(obj.clazz());
const char* full_class_name = clazz.ToCString();
- const char* format = "instance of %s";
- intptr_t len = OS::SNPrint(NULL, 0, format, full_class_name) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, full_class_name);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "instance of %s", full_class_name);
}
diff --git a/runtime/vm/disassembler_x64.cc b/runtime/vm/disassembler_x64.cc
index 9f43a38..ffd6108 100644
--- a/runtime/vm/disassembler_x64.cc
+++ b/runtime/vm/disassembler_x64.cc
@@ -796,11 +796,8 @@
const Class& clazz = Class::Handle(obj.clazz());
const char* full_class_name = clazz.ToCString();
- const char* format = "instance of %s";
- intptr_t len = OS::SNPrint(NULL, 0, format, full_class_name) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, full_class_name);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "instance of %s", full_class_name);
}
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index de44cf0..9f99503 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -571,7 +571,7 @@
args.SetAt(1, Integer::Handle(Integer::New(expected_from)));
args.SetAt(2, Integer::Handle(Integer::New(expected_to)));
args.SetAt(3, String::Handle(String::New(argument_name)));
- Exceptions::ThrowByType(Exceptions::kRangeRange, args);
+ Exceptions::ThrowByType(Exceptions::kRange, args);
}
@@ -588,10 +588,6 @@
case kRange:
library = Library::CoreLibrary();
class_name = &Symbols::RangeError();
- break;
- case kRangeRange:
- library = Library::CoreLibrary();
- class_name = &Symbols::RangeError();
constructor_name = &Symbols::DotRange();
break;
case kArgument:
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 75addb2..0bd97f8 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -51,7 +51,6 @@
enum ExceptionType {
kNone,
kRange,
- kRangeRange,
kArgument,
kArgumentValue,
kNoSuchMethod,
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 6f5deb4..93d964a 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -450,21 +450,21 @@
return;
}
- ISL_Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ", vreg(),
+ THR_Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ", vreg(),
Start(),
End());
assigned_location().Print();
if (spill_slot_.HasStackIndex()) {
intptr_t stack_slot = spill_slot_.stack_index();
- ISL_Print(" allocated spill slot: %" Pd "", stack_slot);
+ THR_Print(" allocated spill slot: %" Pd "", stack_slot);
}
- ISL_Print("\n");
+ THR_Print("\n");
SafepointPosition* safepoint = first_safepoint();
while (safepoint != NULL) {
- ISL_Print(" Safepoint [%" Pd "]: ", safepoint->pos());
+ THR_Print(" Safepoint [%" Pd "]: ", safepoint->pos());
safepoint->locs()->stack_bitmap()->Print();
- ISL_Print("\n");
+ THR_Print("\n");
safepoint = safepoint->next();
}
@@ -472,16 +472,16 @@
for (UseInterval* interval = first_use_interval_;
interval != NULL;
interval = interval->next()) {
- ISL_Print(" use interval [%" Pd ", %" Pd ")\n",
+ THR_Print(" use interval [%" Pd ", %" Pd ")\n",
interval->start(),
interval->end());
while ((use_pos != NULL) && (use_pos->pos() <= interval->end())) {
- ISL_Print(" use at %" Pd "", use_pos->pos());
+ THR_Print(" use at %" Pd "", use_pos->pos());
if (use_pos->location_slot() != NULL) {
- ISL_Print(" as ");
+ THR_Print(" as ");
use_pos->location_slot()->Print();
}
- ISL_Print("\n");
+ THR_Print("\n");
use_pos = use_pos->next();
}
}
@@ -1784,7 +1784,7 @@
first_safepoint_after_split,
next_sibling_);
- TRACE_ALLOC(ISL_Print(" split sibling [%" Pd ", %" Pd ")\n",
+ TRACE_ALLOC(THR_Print(" split sibling [%" Pd ", %" Pd ")\n",
next_sibling_->Start(), next_sibling_->End()));
last_use_interval_ = last_before_split;
@@ -1801,7 +1801,7 @@
LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range,
intptr_t from,
intptr_t to) {
- TRACE_ALLOC(ISL_Print("split v%" Pd " [%" Pd ", %" Pd
+ TRACE_ALLOC(THR_Print("split v%" Pd " [%" Pd ", %" Pd
") between [%" Pd ", %" Pd ")\n",
range->vreg(), range->Start(), range->End(), from, to));
@@ -1841,7 +1841,7 @@
intptr_t from,
intptr_t to) {
ASSERT(from < to);
- TRACE_ALLOC(ISL_Print("spill v%" Pd " [%" Pd ", %" Pd ") "
+ TRACE_ALLOC(THR_Print("spill v%" Pd " [%" Pd ", %" Pd ") "
"between [%" Pd ", %" Pd ")\n",
range->vreg(), range->Start(), range->End(), from, to));
LiveRange* tail = range->SplitAt(from);
@@ -1859,7 +1859,7 @@
void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) {
- TRACE_ALLOC(ISL_Print("spill v%" Pd " [%" Pd ", %" Pd ") after %" Pd "\n",
+ TRACE_ALLOC(THR_Print("spill v%" Pd " [%" Pd ", %" Pd ") after %" Pd "\n",
range->vreg(), range->Start(), range->End(), from));
// When spilling the value inside the loop check if this spill can
@@ -1873,7 +1873,7 @@
RangeHasOnlyUnconstrainedUsesInLoop(range, loop_header->loop_id())) {
ASSERT(loop_header->entry()->start_pos() <= from);
from = loop_header->entry()->start_pos();
- TRACE_ALLOC(ISL_Print(" moved spill position to loop header %" Pd "\n",
+ TRACE_ALLOC(THR_Print(" moved spill position to loop header %" Pd "\n",
from));
}
}
@@ -2105,7 +2105,7 @@
candidate = hint.register_code();
}
- TRACE_ALLOC(ISL_Print("found hint %s for v%" Pd ": free until %" Pd "\n",
+ TRACE_ALLOC(THR_Print("found hint %s for v%" Pd ": free until %" Pd "\n",
hint.Name(),
unallocated->vreg(),
free_until));
@@ -2168,7 +2168,7 @@
}
if (used_on_backedge[candidate]) {
- TRACE_ALLOC(ISL_Print(
+ TRACE_ALLOC(THR_Print(
"considering %s for v%" Pd ": has interference on the back edge"
" {loop [%" Pd ", %" Pd ")}\n",
MakeRegisterLocation(candidate).Name(),
@@ -2187,7 +2187,7 @@
if (intersection >= free_until) {
candidate = reg;
free_until = intersection;
- TRACE_ALLOC(ISL_Print(
+ TRACE_ALLOC(THR_Print(
"found %s for v%" Pd " with no interference on the back edge\n",
MakeRegisterLocation(candidate).Name(),
candidate));
@@ -2197,13 +2197,13 @@
}
}
- TRACE_ALLOC(ISL_Print("assigning free register "));
+ TRACE_ALLOC(THR_Print("assigning free register "));
TRACE_ALLOC(MakeRegisterLocation(candidate).Print());
- TRACE_ALLOC(ISL_Print(" to v%" Pd "\n", unallocated->vreg()));
+ TRACE_ALLOC(THR_Print(" to v%" Pd "\n", unallocated->vreg()));
if (free_until != kMaxPosition) {
// There was an intersection. Split unallocated.
- TRACE_ALLOC(ISL_Print(" splitting at %" Pd "\n", free_until));
+ TRACE_ALLOC(THR_Print(" splitting at %" Pd "\n", free_until));
LiveRange* tail = unallocated->SplitAt(free_until);
AddToUnallocated(tail);
}
@@ -2302,9 +2302,9 @@
ASSERT(candidate != kNoRegister);
- TRACE_ALLOC(ISL_Print("assigning blocked register "));
+ TRACE_ALLOC(THR_Print("assigning blocked register "));
TRACE_ALLOC(MakeRegisterLocation(candidate).Print());
- TRACE_ALLOC(ISL_Print(" to live range v%" Pd " until %" Pd "\n",
+ TRACE_ALLOC(THR_Print(" to live range v%" Pd " until %" Pd "\n",
unallocated->vreg(), blocked_at));
if (blocked_at < unallocated->End()) {
@@ -2469,9 +2469,9 @@
ASSERT(use->location_slot() != NULL);
Location* slot = use->location_slot();
ASSERT(slot->IsUnallocated());
- TRACE_ALLOC(ISL_Print(" use at %" Pd " converted to ", use->pos()));
+ TRACE_ALLOC(THR_Print(" use at %" Pd " converted to ", use->pos()));
TRACE_ALLOC(loc.Print());
- TRACE_ALLOC(ISL_Print("\n"));
+ TRACE_ALLOC(THR_Print("\n"));
*slot = loc;
}
@@ -2482,11 +2482,11 @@
const Location loc = range->assigned_location();
ASSERT(!loc.IsInvalid());
- TRACE_ALLOC(ISL_Print("range [%" Pd ", %" Pd ") "
+ TRACE_ALLOC(THR_Print("range [%" Pd ", %" Pd ") "
"for v%" Pd " has been allocated to ",
range->Start(), range->End(), range->vreg()));
TRACE_ALLOC(loc.Print());
- TRACE_ALLOC(ISL_Print(":\n"));
+ TRACE_ALLOC(THR_Print(":\n"));
for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) {
ConvertUseTo(use, loc);
@@ -2662,7 +2662,7 @@
while (!unallocated_.is_empty()) {
LiveRange* range = unallocated_.RemoveLast();
const intptr_t start = range->Start();
- TRACE_ALLOC(ISL_Print("Processing live range for v%" Pd " "
+ TRACE_ALLOC(THR_Print("Processing live range for v%" Pd " "
"starting at %" Pd "\n",
range->vreg(),
start));
@@ -2686,7 +2686,7 @@
// Finish allocation.
AdvanceActiveIntervals(kMaxPosition);
- TRACE_ALLOC(ISL_Print("Allocation completed\n"));
+ TRACE_ALLOC(THR_Print("Allocation completed\n"));
}
@@ -2705,13 +2705,13 @@
void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent,
BlockEntryInstr* source_block,
BlockEntryInstr* target_block) {
- TRACE_ALLOC(ISL_Print("Connect v%" Pd " on the edge B%" Pd " -> B%" Pd "\n",
+ TRACE_ALLOC(THR_Print("Connect v%" Pd " on the edge B%" Pd " -> B%" Pd "\n",
parent->vreg(),
source_block->block_id(),
target_block->block_id()));
if (parent->next_sibling() == NULL) {
// Nothing to connect. The whole range was allocated to the same location.
- TRACE_ALLOC(ISL_Print("range v%" Pd " has no siblings\n", parent->vreg()));
+ TRACE_ALLOC(THR_Print("range v%" Pd " has no siblings\n", parent->vreg()));
return;
}
@@ -2748,7 +2748,7 @@
range = range->next_sibling();
}
- TRACE_ALLOC(ISL_Print("connecting v%" Pd " between [%" Pd ", %" Pd ") {%s} "
+ TRACE_ALLOC(THR_Print("connecting v%" Pd " between [%" Pd ", %" Pd ") {%s} "
"to [%" Pd ", %" Pd ") {%s}\n",
parent->vreg(),
source_cover->Start(),
@@ -2785,13 +2785,13 @@
while (range->next_sibling() != NULL) {
LiveRange* sibling = range->next_sibling();
- TRACE_ALLOC(ISL_Print("connecting [%" Pd ", %" Pd ") [",
+ TRACE_ALLOC(THR_Print("connecting [%" Pd ", %" Pd ") [",
range->Start(), range->End()));
TRACE_ALLOC(range->assigned_location().Print());
- TRACE_ALLOC(ISL_Print("] to [%" Pd ", %" Pd ") [",
+ TRACE_ALLOC(THR_Print("] to [%" Pd ", %" Pd ") [",
sibling->Start(), sibling->End()));
TRACE_ALLOC(sibling->assigned_location().Print());
- TRACE_ALLOC(ISL_Print("]\n"));
+ TRACE_ALLOC(THR_Print("]\n"));
if ((range->End() == sibling->Start()) &&
!TargetLocationIsSpillSlot(range, sibling->assigned_location()) &&
!range->assigned_location().Equals(sibling->assigned_location()) &&
@@ -2922,16 +2922,16 @@
if (FLAG_print_ssa_liveranges) {
const Function& function = flow_graph_.function();
- ISL_Print("-- [before ssa allocator] ranges [%s] ---------\n",
+ THR_Print("-- [before ssa allocator] ranges [%s] ---------\n",
function.ToFullyQualifiedCString());
PrintLiveRanges();
- ISL_Print("----------------------------------------------\n");
+ THR_Print("----------------------------------------------\n");
- ISL_Print("-- [before ssa allocator] ir [%s] -------------\n",
+ THR_Print("-- [before ssa allocator] ir [%s] -------------\n",
function.ToFullyQualifiedCString());
FlowGraphPrinter printer(flow_graph_, true);
printer.PrintBlocks();
- ISL_Print("----------------------------------------------\n");
+ THR_Print("----------------------------------------------\n");
}
PrepareForAllocation(Location::kRegister,
@@ -2963,16 +2963,16 @@
if (FLAG_print_ssa_liveranges) {
const Function& function = flow_graph_.function();
- ISL_Print("-- [after ssa allocator] ranges [%s] ---------\n",
+ THR_Print("-- [after ssa allocator] ranges [%s] ---------\n",
function.ToFullyQualifiedCString());
PrintLiveRanges();
- ISL_Print("----------------------------------------------\n");
+ THR_Print("----------------------------------------------\n");
- ISL_Print("-- [after ssa allocator] ir [%s] -------------\n",
+ THR_Print("-- [after ssa allocator] ir [%s] -------------\n",
function.ToFullyQualifiedCString());
FlowGraphPrinter printer(flow_graph_, true);
printer.PrintBlocks();
- ISL_Print("----------------------------------------------\n");
+ THR_Print("----------------------------------------------\n");
}
}
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index c1d94b4..54f18c1 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -28,6 +28,8 @@
namespace dart {
+DEFINE_FLAG(bool, allow_absolute_addresses, true,
+ "Allow embedding absolute addresses in generated code.");
DEFINE_FLAG(bool, always_megamorphic_calls, false,
"Instance call always as megamorphic.");
DEFINE_FLAG(bool, enable_simd_inline, true,
@@ -51,6 +53,7 @@
DECLARE_FLAG(bool, disassemble);
DECLARE_FLAG(bool, disassemble_optimized);
DECLARE_FLAG(bool, emit_edge_counters);
+DECLARE_FLAG(bool, fields_may_be_reset);
DECLARE_FLAG(bool, guess_other_cid);
DECLARE_FLAG(bool, ic_range_profiling);
DECLARE_FLAG(bool, intrinsify);
@@ -120,6 +123,8 @@
FLAG_enable_mirrors = false;
FLAG_precompile_collect_closures = true;
FLAG_link_natives_lazily = true;
+ FLAG_fields_may_be_reset = true;
+ FLAG_allow_absolute_addresses = false;
}
}
@@ -431,7 +436,7 @@
intptr_t inlining_id;
IntervalStruct(intptr_t s, intptr_t id) : start(s), inlining_id(id) {}
void Dump() {
- ISL_Print("start: 0x%" Px " iid: %" Pd " ", start, inlining_id);
+ THR_Print("start: 0x%" Px " iid: %" Pd " ", start, inlining_id);
}
};
@@ -520,7 +525,7 @@
}
if (is_optimizing()) {
- LogBlock lb(Thread::Current());
+ LogBlock lb;
intervals.Add(IntervalStruct(prev_offset, prev_inlining_id));
inlined_code_intervals_ =
Array::New(intervals.length() * Code::kInlIntNumEntries, Heap::kOld);
@@ -532,7 +537,7 @@
const Function& function =
*inline_id_to_function_.At(intervals[i].inlining_id);
intervals[i].Dump();
- ISL_Print(" parent iid %" Pd " %s\n",
+ THR_Print(" parent iid %" Pd " %s\n",
caller_inline_id_[intervals[i].inlining_id],
function.ToQualifiedCString());
}
@@ -549,10 +554,10 @@
}
set_current_block(NULL);
if (FLAG_trace_inlining_intervals && is_optimizing()) {
- LogBlock lb(Isolate::Current());
- ISL_Print("Intervals:\n");
+ LogBlock lb;
+ THR_Print("Intervals:\n");
for (intptr_t cc = 0; cc < caller_inline_id_.length(); cc++) {
- ISL_Print(" iid: %" Pd " caller iid: %" Pd "\n",
+ THR_Print(" iid: %" Pd " caller iid: %" Pd "\n",
cc, caller_inline_id_[cc]);
}
Smi& temp = Smi::Handle();
@@ -560,9 +565,9 @@
i += Code::kInlIntNumEntries) {
temp ^= inlined_code_intervals_.At(i + Code::kInlIntStart);
ASSERT(!temp.IsNull());
- ISL_Print("% " Pd " start: 0x%" Px " ", i, temp.Value());
+ THR_Print("% " Pd " start: 0x%" Px " ", i, temp.Value());
temp ^= inlined_code_intervals_.At(i + Code::kInlIntInliningId);
- ISL_Print("iid: %" Pd " ", temp.Value());
+ THR_Print("iid: %" Pd " ", temp.Value());
}
}
}
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 17f61ac..5781c29 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -210,8 +210,7 @@
Label* is_true,
Label* is_false) {
Label fall_through;
- __ CompareImmediate(bool_register,
- reinterpret_cast<intptr_t>(Object::null()));
+ __ CompareObject(bool_register, Object::null_object());
__ b(&fall_through, EQ);
__ CompareObject(bool_register, Bool::True());
__ b(is_true, EQ);
@@ -236,11 +235,11 @@
__ LoadUniqueObject(R2, type_test_cache);
if (test_kind == kTestTypeOneArg) {
ASSERT(type_arguments_reg == kNoRegister);
- __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R1, Object::null_object());
__ BranchLink(*StubCode::Subtype1TestCache_entry());
} else if (test_kind == kTestTypeTwoArgs) {
ASSERT(type_arguments_reg == kNoRegister);
- __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R1, Object::null_object());
__ BranchLink(*StubCode::Subtype2TestCache_entry());
} else if (test_kind == kTestTypeThreeArgs) {
ASSERT(type_arguments_reg == R1);
@@ -390,7 +389,7 @@
// Check if instance is a closure.
__ LoadClassById(R3, kClassIdReg);
__ ldr(R3, FieldAddress(R3, Class::signature_function_offset()));
- __ CompareImmediate(R3, reinterpret_cast<int32_t>(Object::null()));
+ __ CompareObject(R3, Object::null_object());
__ b(is_instance_lbl, NE);
}
// Custom checking for numbers (Smi, Mint, Bigint and Double).
@@ -458,7 +457,7 @@
__ ldr(R1, Address(SP, 0)); // Get instantiator type arguments.
// R1: instantiator type arguments.
// Check if type arguments are null, i.e. equivalent to vector of dynamic.
- __ CompareImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
+ __ CompareObject(R1, Object::null_object());
__ b(is_instance_lbl, EQ);
__ ldr(R2,
FieldAddress(R1, TypeArguments::type_at_offset(type_param.index())));
@@ -603,7 +602,7 @@
// We can only inline this null check if the type is instantiated at compile
// time, since an uninstantiated type at compile time could be Object or
// dynamic at run time.
- __ CompareImmediate(R0, reinterpret_cast<int32_t>(Object::null()));
+ __ CompareObject(R0, Object::null_object());
__ b(type.IsNullType() ? &is_instance : &is_not_instance, EQ);
}
@@ -679,7 +678,7 @@
__ PushList((1 << R1) | (1 << R2));
// A null object is always assignable and is returned as result.
Label is_assignable, runtime_call;
- __ CompareImmediate(R0, reinterpret_cast<int32_t>(Object::null()));
+ __ CompareObject(R0, Object::null_object());
__ b(&is_assignable, EQ);
// Generate throw new TypeError() if the type is malformed or malbounded.
@@ -877,7 +876,7 @@
// Check that R6 now points to the null terminator in the arguments
// descriptor.
__ ldr(R5, Address(R6, 0));
- __ CompareImmediate(R5, reinterpret_cast<int32_t>(Object::null()));
+ __ CompareObject(R5, Object::null_object());
__ b(&all_arguments_processed, EQ);
}
} else {
@@ -939,7 +938,7 @@
__ SmiUntag(R9);
__ add(R7, FP, Operand((kParamEndSlotFromFp + 1) * kWordSize));
const Address original_argument_addr(R7, R9, LSL, 2);
- __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(IP, Object::null_object());
Label null_args_loop, null_args_loop_condition;
__ b(&null_args_loop_condition);
__ Bind(&null_args_loop);
@@ -970,7 +969,7 @@
__ ldr(R0, Address(SP, 1 * kWordSize)); // Receiver.
__ ldr(R1, Address(SP, 0 * kWordSize)); // Value.
__ StoreIntoObjectOffset(R0, offset, R1);
- __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R0, Object::null_object());
__ Ret();
}
@@ -1104,7 +1103,7 @@
const intptr_t context_index =
parsed_function().current_context_var()->index();
if (num_locals > 1) {
- __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R0, Object::null_object());
}
for (intptr_t i = 0; i < num_locals; ++i) {
// Subtract index i (locals lie at lower addresses than FP).
@@ -1285,13 +1284,12 @@
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
- MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
const String& name = String::Handle(zone(), ic_data.target_name());
const Array& arguments_descriptor =
Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
- const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
- zone(), table->Lookup(name, arguments_descriptor));
+ const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
+ MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
const Register receiverR = R0;
const Register cacheR = R1;
const Register targetR = R1;
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 11bc02d..f7ce841 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -1257,13 +1257,12 @@
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
- MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
const String& name = String::Handle(zone(), ic_data.target_name());
const Array& arguments_descriptor =
Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
- const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
- zone(), table->Lookup(name, arguments_descriptor));
+ const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
+ MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
const Register receiverR = R0;
const Register cacheR = R1;
const Register targetR = R1;
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 8df27db..81befda 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1296,13 +1296,12 @@
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
- MegamorphicCacheTable* table = isolate()->megamorphic_cache_table();
const String& name = String::Handle(zone(), ic_data.target_name());
const Array& arguments_descriptor =
Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
- table->Lookup(name, arguments_descriptor));
+ MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
const Register receiverR = EDI;
const Register cacheR = EBX;
const Register targetR = EBX;
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 93716a8..f9dea83 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -227,11 +227,11 @@
__ LoadUniqueObject(A2, type_test_cache);
if (test_kind == kTestTypeOneArg) {
ASSERT(type_arguments_reg == kNoRegister);
- __ LoadImmediate(A1, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(A1, Object::null_object());
__ BranchLink(*StubCode::Subtype1TestCache_entry());
} else if (test_kind == kTestTypeTwoArgs) {
ASSERT(type_arguments_reg == kNoRegister);
- __ LoadImmediate(A1, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(A1, Object::null_object());
__ BranchLink(*StubCode::Subtype2TestCache_entry());
} else if (test_kind == kTestTypeThreeArgs) {
ASSERT(type_arguments_reg == A1);
@@ -445,7 +445,7 @@
__ lw(A1, Address(SP, 0)); // Get instantiator type arguments.
// A1: instantiator type arguments.
// Check if type arguments are null, i.e. equivalent to vector of dynamic.
- __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(T7, Object::null_object());
__ beq(A1, T7, is_instance_lbl);
__ lw(T2,
FieldAddress(A1, TypeArguments::type_at_offset(type_param.index())));
@@ -954,7 +954,7 @@
__ Bind(&null_args_loop);
__ addiu(T2, T2, Immediate(-kWordSize));
__ addu(T3, T1, T2);
- __ LoadImmediate(T5, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(T5, Object::null_object());
__ bgtz(T2, &null_args_loop);
__ delay_slot()->sw(T5, Address(T3));
__ Bind(&null_args_loop_exit);
@@ -981,7 +981,7 @@
__ lw(T0, Address(SP, 1 * kWordSize)); // Receiver.
__ lw(T1, Address(SP, 0 * kWordSize)); // Value.
__ StoreIntoObjectOffset(T0, offset, T1);
- __ LoadImmediate(V0, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(V0, Object::null_object());
__ Ret();
}
@@ -1121,7 +1121,7 @@
const intptr_t context_index =
parsed_function().current_context_var()->index();
if (num_locals > 1) {
- __ LoadImmediate(V0, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(V0, Object::null_object());
}
for (intptr_t i = 0; i < num_locals; ++i) {
// Subtract index i (locals lie at lower addresses than FP).
@@ -1282,13 +1282,12 @@
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
- MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
const String& name = String::Handle(zone(), ic_data.target_name());
const Array& arguments_descriptor =
Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
- const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
- zone(), table->Lookup(name, arguments_descriptor));
+ const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
+ MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
__ Comment("MegamorphicInstanceCall");
const Register receiverR = T0;
const Register cacheR = T1;
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 40143d4..59934cd 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1311,13 +1311,12 @@
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
- MegamorphicCacheTable* table = isolate()->megamorphic_cache_table();
const String& name = String::Handle(zone(), ic_data.target_name());
const Array& arguments_descriptor =
Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
- const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
- zone(), table->Lookup(name, arguments_descriptor));
+ const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
+ MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
const Register receiverR = RDI;
const Register cacheR = RBX;
const Register targetR = RCX;
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 6c14228..09cc2c7 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -563,13 +563,13 @@
inlining_depth_,
&inlined_info_);
while (collected_call_sites_->HasCalls()) {
- TRACE_INLINING(ISL_Print(" Depth %" Pd " ----------\n",
+ TRACE_INLINING(THR_Print(" Depth %" Pd " ----------\n",
inlining_depth_));
if (collected_call_sites_->NumCalls() > FLAG_max_inlined_per_depth) {
break;
}
if (FLAG_print_inlining_tree) {
- ISL_Print("**Depth % " Pd " calls to inline %" Pd "\n",
+ THR_Print("**Depth % " Pd " calls to inline %" Pd "\n",
inlining_depth_, collected_call_sites_->NumCalls());
}
// Swap collected and inlining arrays and clear the new collecting array.
@@ -614,7 +614,7 @@
bool TryInlining(const Function& function,
const Array& argument_names,
InlinedCallData* call_data) {
- TRACE_INLINING(ISL_Print(" => %s (deopt count %d)\n",
+ TRACE_INLINING(THR_Print(" => %s (deopt count %d)\n",
function.ToCString(),
function.deoptimization_counter()));
@@ -623,7 +623,7 @@
const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
// Abort if the inlinable bit on the function is low.
if (!function.CanBeInlined()) {
- TRACE_INLINING(ISL_Print(" Bailout: not inlinable\n"));
+ TRACE_INLINING(THR_Print(" Bailout: not inlinable\n"));
PRINT_INLINING_TREE("Not inlinable",
&call_data->caller, &function, call_data->call);
return false;
@@ -633,7 +633,7 @@
if (function.deoptimization_counter() >=
FLAG_deoptimization_counter_threshold) {
function.set_is_inlinable(false);
- TRACE_INLINING(ISL_Print(" Bailout: deoptimization threshold\n"));
+ TRACE_INLINING(THR_Print(" Bailout: deoptimization threshold\n"));
PRINT_INLINING_TREE("Deoptimization threshold exceeded",
&call_data->caller, &function, call_data->call);
return false;
@@ -642,7 +642,7 @@
const char* kNeverInlineAnnotation = "NeverInline";
if (FLAG_enable_inlining_annotations &&
HasAnnotation(function, kNeverInlineAnnotation)) {
- TRACE_INLINING(ISL_Print(" Bailout: NeverInline annotation\n"));
+ TRACE_INLINING(THR_Print(" Bailout: NeverInline annotation\n"));
return false;
}
@@ -652,7 +652,7 @@
function.optimized_instruction_count(),
function.optimized_call_site_count(),
constant_arguments)) {
- TRACE_INLINING(ISL_Print(" Bailout: early heuristics with "
+ TRACE_INLINING(THR_Print(" Bailout: early heuristics with "
"code size: %" Pd ", "
"call sites: %" Pd ", "
"const args: %" Pd "\n",
@@ -670,7 +670,7 @@
volatile bool is_recursive_call = IsCallRecursive(function, call);
if (is_recursive_call &&
inlining_recursion_depth_ >= FLAG_inlining_recursion_depth_threshold) {
- TRACE_INLINING(ISL_Print(" Bailout: recursive function\n"));
+ TRACE_INLINING(THR_Print(" Bailout: recursive function\n"));
PRINT_INLINING_TREE("Recursive function",
&call_data->caller, &function, call_data->call);
return false;
@@ -733,14 +733,14 @@
// arrays so that actual arguments are in one-to-one with the formal
// parameters.
if (function.HasOptionalParameters()) {
- TRACE_INLINING(ISL_Print(" adjusting for optional parameters\n"));
+ TRACE_INLINING(THR_Print(" adjusting for optional parameters\n"));
if (!AdjustForOptionalParameters(*parsed_function,
argument_names,
arguments,
param_stubs,
callee_graph)) {
function.set_is_inlinable(false);
- TRACE_INLINING(ISL_Print(" Bailout: optional arg mismatch\n"));
+ TRACE_INLINING(THR_Print(" Bailout: optional arg mismatch\n"));
PRINT_INLINING_TREE("Optional arg mismatch",
&call_data->caller, &function, call_data->call);
return false;
@@ -791,7 +791,7 @@
if (FLAG_trace_inlining &&
(FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
- ISL_Print("Callee graph for inlining %s\n",
+ THR_Print("Callee graph for inlining %s\n",
function.ToFullyQualifiedCString());
FlowGraphPrinter printer(*callee_graph);
printer.PrintBlocks();
@@ -821,7 +821,7 @@
function.set_is_inlinable(false);
}
isolate()->set_deopt_id(prev_deopt_id);
- TRACE_INLINING(ISL_Print(" Bailout: heuristics with "
+ TRACE_INLINING(THR_Print(" Bailout: heuristics with "
"code size: %" Pd ", "
"call sites: %" Pd ", "
"const args: %" Pd "\n",
@@ -872,7 +872,7 @@
// We allocate a ZoneHandle for the unoptimized code so that it cannot be
// disconnected from its function during the rest of compilation.
Code::ZoneHandle(unoptimized_code.raw());
- TRACE_INLINING(ISL_Print(" Success\n"));
+ TRACE_INLINING(THR_Print(" Success\n"));
PRINT_INLINING_TREE(NULL,
&call_data->caller, &function, call);
return true;
@@ -881,7 +881,7 @@
error = isolate()->object_store()->sticky_error();
isolate()->object_store()->clear_sticky_error();
isolate()->set_deopt_id(prev_deopt_id);
- TRACE_INLINING(ISL_Print(" Bailout: %s\n", error.ToErrorCString()));
+ TRACE_INLINING(THR_Print(" Bailout: %s\n", error.ToErrorCString()));
PRINT_INLINING_TREE("Bailout",
&call_data->caller, &function, call);
return false;
@@ -890,7 +890,7 @@
void PrintInlinedInfo(const Function& top) {
if (inlined_info_.length() > 0) {
- ISL_Print("Inlining into: '%s' growth: %f (%" Pd " -> %" Pd ")\n",
+ THR_Print("Inlining into: '%s' growth: %f (%" Pd " -> %" Pd ")\n",
top.ToFullyQualifiedCString(),
GrowthFactor(),
initial_size_,
@@ -923,9 +923,9 @@
(info.caller->raw() == caller.raw()) &&
!Contains(call_instructions_printed, info.call_instr->GetDeoptId())) {
for (int t = 0; t < depth; t++) {
- ISL_Print(" ");
+ THR_Print(" ");
}
- ISL_Print("%" Pd " %s\n",
+ THR_Print("%" Pd " %s\n",
info.call_instr->GetDeoptId(),
info.inlined->ToQualifiedCString());
PrintInlinedInfoFor(*info.inlined, depth + 1);
@@ -943,9 +943,9 @@
(info.caller->raw() == caller.raw()) &&
!Contains(call_instructions_printed, info.call_instr->GetDeoptId())) {
for (int t = 0; t < depth; t++) {
- ISL_Print(" ");
+ THR_Print(" ");
}
- ISL_Print("NO %" Pd " %s - %s\n",
+ THR_Print("NO %" Pd " %s - %s\n",
info.call_instr->GetDeoptId(),
info.inlined->ToQualifiedCString(),
info.bailout_reason);
@@ -1043,7 +1043,7 @@
void InlineStaticCalls() {
const GrowableArray<CallSites::StaticCallInfo>& call_info =
inlining_call_sites_->static_calls();
- TRACE_INLINING(ISL_Print(" Static Calls (%" Pd ")\n", call_info.length()));
+ TRACE_INLINING(THR_Print(" Static Calls (%" Pd ")\n", call_info.length()));
for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) {
StaticCallInstr* call = call_info[call_idx].call;
if (call->function().name() == Symbols::ListFactory().raw()) {
@@ -1061,7 +1061,7 @@
const Function& target = call->function();
if (!inliner_->AlwaysInline(target) &&
(call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
- TRACE_INLINING(ISL_Print(
+ TRACE_INLINING(THR_Print(
" => %s (deopt count %d)\n Bailout: cold %f\n",
target.ToCString(),
target.deoptimization_counter(),
@@ -1086,7 +1086,7 @@
void InlineClosureCalls() {
const GrowableArray<CallSites::ClosureCallInfo>& call_info =
inlining_call_sites_->closure_calls();
- TRACE_INLINING(ISL_Print(" Closure Calls (%" Pd ")\n",
+ TRACE_INLINING(THR_Print(" Closure Calls (%" Pd ")\n",
call_info.length()));
for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) {
ClosureCallInstr* call = call_info[call_idx].call;
@@ -1108,7 +1108,7 @@
}
if (target.IsNull()) {
- TRACE_INLINING(ISL_Print(" Bailout: non-closure operator\n"));
+ TRACE_INLINING(THR_Print(" Bailout: non-closure operator\n"));
continue;
}
GrowableArray<Value*> arguments(call->ArgumentCount());
@@ -1129,7 +1129,7 @@
void InlineInstanceCalls() {
const GrowableArray<CallSites::InstanceCallInfo>& call_info =
inlining_call_sites_->instance_calls();
- TRACE_INLINING(ISL_Print(" Polymorphic Instance Calls (%" Pd ")\n",
+ TRACE_INLINING(THR_Print(" Polymorphic Instance Calls (%" Pd ")\n",
call_info.length()));
for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) {
PolymorphicInstanceCallInstr* call = call_info[call_idx].call;
@@ -1148,7 +1148,7 @@
const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
if (!inliner_->AlwaysInline(target) &&
(call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
- TRACE_INLINING(ISL_Print(
+ TRACE_INLINING(THR_Print(
" => %s (deopt count %d)\n Bailout: cold %f\n",
target.ToCString(),
target.deoptimization_counter(),
@@ -1829,7 +1829,7 @@
const char* kAlwaysInlineAnnotation = "AlwaysInline";
if (FLAG_enable_inlining_annotations &&
HasAnnotation(function, kAlwaysInlineAnnotation)) {
- TRACE_INLINING(ISL_Print("AlwaysInline annotation for %s\n",
+ TRACE_INLINING(THR_Print("AlwaysInline annotation for %s\n",
function.ToCString()));
return true;
}
@@ -1857,11 +1857,11 @@
return;
}
- TRACE_INLINING(ISL_Print("Inlining calls in %s\n", top.ToCString()));
+ TRACE_INLINING(THR_Print("Inlining calls in %s\n", top.ToCString()));
if (trace_inlining() &&
(FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
- ISL_Print("Before Inlining of %s\n", flow_graph_->
+ THR_Print("Before Inlining of %s\n", flow_graph_->
function().ToFullyQualifiedCString());
FlowGraphPrinter printer(*flow_graph_);
printer.PrintBlocks();
@@ -1876,9 +1876,9 @@
if (inliner.inlined()) {
flow_graph_->DiscoverBlocks();
if (trace_inlining()) {
- ISL_Print("Inlining growth factor: %f\n", inliner.GrowthFactor());
+ THR_Print("Inlining growth factor: %f\n", inliner.GrowthFactor());
if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
- ISL_Print("After Inlining of %s\n", flow_graph_->
+ THR_Print("After Inlining of %s\n", flow_graph_->
function().ToFullyQualifiedCString());
FlowGraphPrinter printer(*flow_graph_);
printer.PrintBlocks();
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 95ea36e..54a571a 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -637,16 +637,16 @@
EnsureSSATempIndex(graph, current_defn, replacement_defn);
if (FLAG_trace_optimization) {
- ISL_Print("Replacing v%" Pd " with v%" Pd "\n",
+ THR_Print("Replacing v%" Pd " with v%" Pd "\n",
current_defn->ssa_temp_index(),
replacement_defn->ssa_temp_index());
}
} else if (FLAG_trace_optimization) {
if (current_defn == NULL) {
- ISL_Print("Removing %s\n", current->DebugName());
+ THR_Print("Removing %s\n", current->DebugName());
} else {
ASSERT(!current_defn->HasUses());
- ISL_Print("Removing v%" Pd ".\n", current_defn->ssa_temp_index());
+ THR_Print("Removing v%" Pd ".\n", current_defn->ssa_temp_index());
}
}
iterator->RemoveCurrentFromGraph();
@@ -2337,7 +2337,7 @@
const Class& cls = Class::Handle(Z, function.Owner());
if (!thread()->cha()->HasOverride(cls, name)) {
if (FLAG_trace_cha) {
- ISL_Print(" **(CHA) Instance call needs no check, "
+ THR_Print(" **(CHA) Instance call needs no check, "
"no overrides of '%s' '%s'\n",
name.ToCString(), cls.ToCString());
}
@@ -4036,7 +4036,7 @@
if (!type_class.IsPrivate()) {
if (FLAG_use_cha_deopt) {
if (FLAG_trace_cha) {
- ISL_Print(" **(CHA) Typecheck as class equality since no "
+ THR_Print(" **(CHA) Typecheck as class equality since no "
"subclasses: %s\n",
type_class.ToCString());
}
@@ -4620,7 +4620,7 @@
}
if (!unboxed_field) {
if (FLAG_trace_optimization || FLAG_trace_field_guards) {
- ISL_Print("Disabling unboxing of %s\n", field.ToCString());
+ THR_Print("Disabling unboxing of %s\n", field.ToCString());
if (!setter.IsNull()) {
OS::Print(" setter usage count: %" Pd "\n", setter.usage_counter());
}
@@ -4849,7 +4849,7 @@
}
if (FLAG_trace_smi_widening) {
- ISL_Print("analysing candidate: %s\n", op->ToCString());
+ THR_Print("analysing candidate: %s\n", op->ToCString());
}
worklist.Clear();
worklist.Add(op);
@@ -4861,14 +4861,14 @@
Definition* defn = worklist.definitions()[j];
if (FLAG_trace_smi_widening) {
- ISL_Print("> %s\n", defn->ToCString());
+ THR_Print("> %s\n", defn->ToCString());
}
if (defn->IsBinarySmiOp() &&
BenefitsFromWidening(defn->AsBinarySmiOp())) {
gain++;
if (FLAG_trace_smi_widening) {
- ISL_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString());
+ THR_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString());
}
}
@@ -4886,7 +4886,7 @@
// Mint operation produces untagged result. We avoid tagging.
gain++;
if (FLAG_trace_smi_widening) {
- ISL_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString());
+ THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString());
}
} else if (defn_loop == loops[input->GetBlock()->preorder_number()] &&
(input->Type()->ToCid() == kSmiCid)) {
@@ -4897,7 +4897,7 @@
// coalesced with untagging. Start coalescing them.
gain--;
if (FLAG_trace_smi_widening) {
- ISL_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString());
+ THR_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString());
}
}
}
@@ -4914,7 +4914,7 @@
if (!instr->IsReturn() && !instr->IsPushArgument()) {
gain--;
if (FLAG_trace_smi_widening) {
- ISL_Print("v [%" Pd "] (u) %s\n",
+ THR_Print("v [%" Pd "] (u) %s\n",
gain,
use->instruction()->ToCString());
}
@@ -4932,14 +4932,14 @@
// sign extension operation.
gain++;
if (FLAG_trace_smi_widening) {
- ISL_Print("^ [%" Pd "] (u) %s\n",
+ THR_Print("^ [%" Pd "] (u) %s\n",
gain,
use->instruction()->ToCString());
}
} else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) {
gain--;
if (FLAG_trace_smi_widening) {
- ISL_Print("v [%" Pd "] (u) %s\n",
+ THR_Print("v [%" Pd "] (u) %s\n",
gain,
use->instruction()->ToCString());
}
@@ -4950,7 +4950,7 @@
processed->AddAll(worklist.contains_vector());
if (FLAG_trace_smi_widening) {
- ISL_Print("~ %s gain %" Pd "\n", op->ToCString(), gain);
+ THR_Print("~ %s gain %" Pd "\n", op->ToCString(), gain);
}
if (gain > 0) {
@@ -5078,7 +5078,7 @@
current->AsCheckArrayBound()->set_licm_hoisted(true);
}
if (FLAG_trace_optimization) {
- ISL_Print("Hoisting instruction %s:%" Pd " from B%" Pd " to B%" Pd "\n",
+ THR_Print("Hoisting instruction %s:%" Pd " from B%" Pd " to B%" Pd "\n",
current->DebugName(),
current->GetDeoptId(),
current->GetBlock()->block_id(),
@@ -5895,9 +5895,9 @@
!it.Done();
it.Advance()) {
if (comma) {
- ISL_Print(", ");
+ THR_Print(", ");
}
- ISL_Print("%s", places_[it.Current()]->ToCString());
+ THR_Print("%s", places_[it.Current()]->ToCString());
comma = true;
}
}
@@ -5992,16 +5992,16 @@
}
if (FLAG_trace_load_optimization) {
- ISL_Print("Aliases KILL sets:\n");
+ THR_Print("Aliases KILL sets:\n");
for (intptr_t i = 0; i < aliases_.length(); ++i) {
const Place* alias = aliases_[i];
BitVector* kill = GetKilledSet(alias->id());
- ISL_Print("%s: ", alias->ToCString());
+ THR_Print("%s: ", alias->ToCString());
if (kill != NULL) {
PrintSet(kill);
}
- ISL_Print("\n");
+ THR_Print("\n");
}
}
}
@@ -6388,7 +6388,7 @@
BlockEntryInstr* block = phi->GetBlock();
if (FLAG_trace_optimization) {
- ISL_Print("phi dependent place %s\n", place->ToCString());
+ THR_Print("phi dependent place %s\n", place->ToCString());
}
Place input_place(*place);
@@ -6401,7 +6401,7 @@
map->Insert(result);
places->Add(result);
if (FLAG_trace_optimization) {
- ISL_Print(" adding place %s as %" Pd "\n",
+ THR_Print(" adding place %s as %" Pd "\n",
result->ToCString(),
result->id());
}
@@ -6457,7 +6457,7 @@
places->Add(result);
if (FLAG_trace_optimization) {
- ISL_Print("numbering %s as %" Pd "\n",
+ THR_Print("numbering %s as %" Pd "\n",
result->ToCString(),
result->id());
}
@@ -6726,7 +6726,7 @@
Definition* replacement = (*out_values)[place_id];
EnsureSSATempIndex(graph_, defn, replacement);
if (FLAG_trace_optimization) {
- ISL_Print("Replacing load v%" Pd " with v%" Pd "\n",
+ THR_Print("Replacing load v%" Pd " with v%" Pd "\n",
defn->ssa_temp_index(),
replacement->ssa_temp_index());
}
@@ -6934,18 +6934,18 @@
}
if (FLAG_trace_load_optimization) {
- ISL_Print("B%" Pd "\n", block->block_id());
- ISL_Print(" IN: ");
+ THR_Print("B%" Pd "\n", block->block_id());
+ THR_Print(" IN: ");
aliased_set_->PrintSet(in_[preorder_number]);
- ISL_Print("\n");
+ THR_Print("\n");
- ISL_Print(" KILL: ");
+ THR_Print(" KILL: ");
aliased_set_->PrintSet(kill_[preorder_number]);
- ISL_Print("\n");
+ THR_Print("\n");
- ISL_Print(" OUT: ");
+ THR_Print(" OUT: ");
aliased_set_->PrintSet(out_[preorder_number]);
- ISL_Print("\n");
+ THR_Print("\n");
}
}
@@ -6998,7 +6998,7 @@
if (FLAG_trace_optimization) {
for (BitVector::Iterator it(loop_gen); !it.Done(); it.Advance()) {
- ISL_Print("place %s is loop invariant for B%" Pd "\n",
+ THR_Print("place %s is loop invariant for B%" Pd "\n",
aliased_set_->places()[it.Current()]->ToCString(),
header->block_id());
}
@@ -7069,7 +7069,7 @@
phis_.Add(phi); // Postpone phi insertion until after load forwarding.
if (FLAG_trace_load_optimization) {
- ISL_Print("created pending phi %s for %s at B%" Pd "\n",
+ THR_Print("created pending phi %s for %s at B%" Pd "\n",
phi->ToCString(),
aliased_set_->places()[place_id]->ToCString(),
block->block_id());
@@ -7108,7 +7108,7 @@
EnsureSSATempIndex(graph_, load, replacement);
if (FLAG_trace_optimization) {
- ISL_Print("Replacing load v%" Pd " with v%" Pd "\n",
+ THR_Print("Replacing load v%" Pd " with v%" Pd "\n",
load->ssa_temp_index(),
replacement->ssa_temp_index());
}
@@ -7297,7 +7297,7 @@
}
if (FLAG_trace_load_optimization) {
- ISL_Print("Replacing %s with congruent %s\n",
+ THR_Print("Replacing %s with congruent %s\n",
a->ToCString(),
b->ToCString());
}
@@ -7503,7 +7503,7 @@
if (!live_in->Contains(instr->place_id()) &&
CanEliminateStore(instr)) {
if (FLAG_trace_optimization) {
- ISL_Print(
+ THR_Print(
"Removing dead store to place %" Pd " in block B%" Pd "\n",
instr->place_id(), block->block_id());
}
@@ -7556,7 +7556,7 @@
}
if (FLAG_trace_load_optimization) {
Dump();
- ISL_Print("---\n");
+ THR_Print("---\n");
}
}
@@ -7590,7 +7590,7 @@
if (!live_out->Contains(instr->place_id()) &&
CanEliminateStore(instr)) {
if (FLAG_trace_optimization) {
- ISL_Print("Removing dead store to place %" Pd " block B%" Pd "\n",
+ THR_Print("Removing dead store to place %" Pd " block B%" Pd "\n",
instr->place_id(), block->block_id());
}
instr->RemoveFromGraph(/* ignored */ false);
@@ -7684,14 +7684,14 @@
phi->UnuseAllInputs();
(*join->phis_)[i] = NULL;
if (FLAG_trace_optimization) {
- ISL_Print("Removing dead phi v%" Pd "\n", phi->ssa_temp_index());
+ THR_Print("Removing dead phi v%" Pd "\n", phi->ssa_temp_index());
}
} else if (phi->IsRedundant()) {
phi->ReplaceUsesWith(phi->InputAt(0)->definition());
phi->UnuseAllInputs();
(*join->phis_)[i] = NULL;
if (FLAG_trace_optimization) {
- ISL_Print("Removing redundant phi v%" Pd "\n",
+ THR_Print("Removing redundant phi v%" Pd "\n",
phi->ssa_temp_index());
}
} else {
@@ -8234,7 +8234,7 @@
use = use->next_use()) {
if (!IsSafeUse(use, check_type)) {
if (FLAG_trace_optimization) {
- ISL_Print("use of %s at %s is unsafe for allocation sinking\n",
+ THR_Print("use of %s at %s is unsafe for allocation sinking\n",
alloc->ToCString(),
use->instruction()->ToCString());
}
@@ -8264,7 +8264,7 @@
ASSERT(IsAllocationSinkingCandidate(alloc, kStrictCheck));
if (FLAG_trace_optimization) {
- ISL_Print("removing allocation from the graph: v%" Pd "\n",
+ THR_Print("removing allocation from the graph: v%" Pd "\n",
alloc->ssa_temp_index());
}
@@ -8345,7 +8345,7 @@
Definition* alloc = candidates_[i];
if (alloc->Identity().IsAllocationSinkingCandidate()) {
if (FLAG_trace_optimization) {
- ISL_Print("discovered allocation sinking candidate: v%" Pd "\n",
+ THR_Print("discovered allocation sinking candidate: v%" Pd "\n",
alloc->ssa_temp_index());
}
@@ -8440,7 +8440,7 @@
Definition* alloc = candidates_[i];
if (!alloc->Identity().IsAllocationSinkingCandidate()) {
if (FLAG_trace_optimization) {
- ISL_Print("allocation v%" Pd " can't be eliminated\n",
+ THR_Print("allocation v%" Pd " can't be eliminated\n",
alloc->ssa_temp_index());
}
diff --git a/runtime/vm/flow_graph_range_analysis.cc b/runtime/vm/flow_graph_range_analysis.cc
index cd45479..9016d1c 100644
--- a/runtime/vm/flow_graph_range_analysis.cc
+++ b/runtime/vm/flow_graph_range_analysis.cc
@@ -184,7 +184,7 @@
InductionVariableInfo* info = DetectSimpleInductionVariable(current);
if (info != NULL) {
if (FLAG_trace_range_analysis) {
- ISL_Print("Simple loop variable: %s bound <%s>\n",
+ THR_Print("Simple loop variable: %s bound <%s>\n",
current->ToCString(),
info->limit() != NULL ?
info->limit()->ToCString() : "?");
@@ -694,7 +694,7 @@
if (!range.Equals(defn->range())) {
if (FLAG_trace_range_analysis) {
- ISL_Print("%c [%" Pd "] %s: %s => %s\n",
+ THR_Print("%c [%" Pd "] %s: %s => %s\n",
OpPrefix(op),
iteration,
defn->ToCString(),
@@ -997,7 +997,7 @@
if (upper_bound == UnwrapConstraint(check->index()->definition())) {
// Unable to construct upper bound for the index.
if (FLAG_trace_range_analysis) {
- ISL_Print("Failed to construct upper bound for %s index\n",
+ THR_Print("Failed to construct upper bound for %s index\n",
check->ToCString());
}
return;
@@ -1008,7 +1008,7 @@
// upper bound through scheduler.
if (!Simplify(&upper_bound, NULL)) {
if (FLAG_trace_range_analysis) {
- ISL_Print("Failed to simplify upper bound for %s index\n",
+ THR_Print("Failed to simplify upper bound for %s index\n",
check->ToCString());
}
return;
@@ -1023,7 +1023,7 @@
GrowableArray<Definition*> non_positive_symbols;
if (!FindNonPositiveSymbols(&non_positive_symbols, upper_bound)) {
if (FLAG_trace_range_analysis) {
- ISL_Print("Failed to generalize %s index to %s"
+ THR_Print("Failed to generalize %s index to %s"
" (can't ensure positivity)\n",
check->ToCString(),
IndexBoundToCString(upper_bound));
@@ -1057,7 +1057,7 @@
// Can't prove that lower bound is positive even with additional checks
// against potentially non-positive symbols. Give up.
if (FLAG_trace_range_analysis) {
- ISL_Print("Failed to generalize %s index to %s"
+ THR_Print("Failed to generalize %s index to %s"
" (lower bound is not positive)\n",
check->ToCString(),
IndexBoundToCString(upper_bound));
@@ -1066,7 +1066,7 @@
}
if (FLAG_trace_range_analysis) {
- ISL_Print("For %s computed index bounds [%s, %s]\n",
+ THR_Print("For %s computed index bounds [%s, %s]\n",
check->ToCString(),
IndexBoundToCString(lower_bound),
IndexBoundToCString(upper_bound));
@@ -1087,7 +1087,7 @@
precondition = scheduler_.Emit(precondition, check);
if (precondition == NULL) {
if (FLAG_trace_range_analysis) {
- ISL_Print(" => failed to insert positivity constraint\n");
+ THR_Print(" => failed to insert positivity constraint\n");
}
scheduler_.Rollback();
return;
@@ -1101,7 +1101,7 @@
new_check->mark_generalized();
if (new_check->IsRedundant(array_length)) {
if (FLAG_trace_range_analysis) {
- ISL_Print(" => generalized check is redundant\n");
+ THR_Print(" => generalized check is redundant\n");
}
RemoveGeneralizedCheck(check);
return;
@@ -1110,13 +1110,13 @@
new_check = scheduler_.Emit(new_check, check);
if (new_check != NULL) {
if (FLAG_trace_range_analysis) {
- ISL_Print(" => generalized check was hoisted into B%" Pd "\n",
+ THR_Print(" => generalized check was hoisted into B%" Pd "\n",
new_check->GetBlock()->block_id());
}
RemoveGeneralizedCheck(check);
} else {
if (FLAG_trace_range_analysis) {
- ISL_Print(" => generalized check can't be hoisted\n");
+ THR_Print(" => generalized check can't be hoisted\n");
}
scheduler_.Rollback();
}
@@ -1566,7 +1566,7 @@
if (target == branch->true_successor()) {
// True unreachable.
if (FLAG_trace_constant_propagation) {
- ISL_Print("Range analysis: True unreachable (B%" Pd ")\n",
+ THR_Print("Range analysis: True unreachable (B%" Pd ")\n",
branch->true_successor()->block_id());
}
branch->set_constant_target(branch->false_successor());
@@ -1574,7 +1574,7 @@
ASSERT(target == branch->false_successor());
// False unreachable.
if (FLAG_trace_constant_propagation) {
- ISL_Print("Range analysis: False unreachable (B%" Pd ")\n",
+ THR_Print("Range analysis: False unreachable (B%" Pd ")\n",
branch->false_successor()->block_id());
}
branch->set_constant_target(branch->true_successor());
@@ -1662,14 +1662,14 @@
void IntegerInstructionSelector::Select() {
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("---- starting integer ir selection -------\n");
+ THR_Print("---- starting integer ir selection -------\n");
}
FindPotentialUint32Definitions();
FindUint32NarrowingDefinitions();
Propagate();
ReplaceInstructions();
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("---- after integer ir selection -------\n");
+ THR_Print("---- after integer ir selection -------\n");
FlowGraphPrinter printer(*flow_graph_);
printer.PrintBlocks();
}
@@ -1690,7 +1690,7 @@
void IntegerInstructionSelector::FindPotentialUint32Definitions() {
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("++++ Finding potential Uint32 definitions:\n");
+ THR_Print("++++ Finding potential Uint32 definitions:\n");
}
for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
@@ -1706,7 +1706,7 @@
if ((defn != NULL) && defn->HasSSATemp()) {
if (IsPotentialUint32Definition(defn)) {
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("Adding %s\n", current->ToCString());
+ THR_Print("Adding %s\n", current->ToCString());
}
potential_uint32_defs_.Add(defn);
}
@@ -1740,14 +1740,14 @@
void IntegerInstructionSelector::FindUint32NarrowingDefinitions() {
ASSERT(selected_uint32_defs_ != NULL);
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("++++ Selecting Uint32 definitions:\n");
- ISL_Print("++++ Initial set:\n");
+ THR_Print("++++ Selecting Uint32 definitions:\n");
+ THR_Print("++++ Initial set:\n");
}
for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) {
Definition* defn = potential_uint32_defs_[i];
if (IsUint32NarrowingDefinition(defn)) {
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("Adding %s\n", defn->ToCString());
+ THR_Print("Adding %s\n", defn->ToCString());
}
selected_uint32_defs_->Add(defn->ssa_temp_index());
}
@@ -1807,7 +1807,7 @@
intptr_t iteration = 0;
while (changed) {
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("+++ Iteration: %" Pd "\n", iteration++);
+ THR_Print("+++ Iteration: %" Pd "\n", iteration++);
}
changed = false;
for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) {
@@ -1822,7 +1822,7 @@
}
if (CanBecomeUint32(defn)) {
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("Adding %s\n", defn->ToCString());
+ THR_Print("Adding %s\n", defn->ToCString());
}
// Found a new candidate.
selected_uint32_defs_->Add(defn->ssa_temp_index());
@@ -1832,7 +1832,7 @@
}
}
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("Reached fixed point\n");
+ THR_Print("Reached fixed point\n");
}
}
@@ -1879,7 +1879,7 @@
void IntegerInstructionSelector::ReplaceInstructions() {
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("++++ Replacing instructions:\n");
+ THR_Print("++++ Replacing instructions:\n");
}
for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) {
Definition* defn = potential_uint32_defs_[i];
@@ -1890,7 +1890,7 @@
Definition* replacement = ConstructReplacementFor(defn);
ASSERT(replacement != NULL);
if (FLAG_trace_integer_ir_selection) {
- ISL_Print("Replacing %s with %s\n", defn->ToCString(),
+ THR_Print("Replacing %s with %s\n", defn->ToCString(),
replacement->ToCString());
}
if (!Range::IsUnknown(defn->range())) {
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index c80005d..3448fd0 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -74,13 +74,13 @@
while (!worklist_.is_empty()) {
Definition* def = RemoveLastFromWorklist();
if (FLAG_trace_type_propagation) {
- ISL_Print("recomputing type of v%" Pd ": %s\n",
+ THR_Print("recomputing type of v%" Pd ": %s\n",
def->ssa_temp_index(),
def->Type()->ToCString());
}
if (def->RecomputeType()) {
if (FLAG_trace_type_propagation) {
- ISL_Print(" ... new type %s\n", def->Type()->ToCString());
+ THR_Print(" ... new type %s\n", def->Type()->ToCString());
}
for (Value::Iterator it(def->input_use_list());
!it.Done();
@@ -267,7 +267,7 @@
value->SetReachingType(type);
if (FLAG_trace_type_propagation) {
- ISL_Print("reaching type to v%" Pd " for v%" Pd " is %s\n",
+ THR_Print("reaching type to v%" Pd " for v%" Pd " is %s\n",
value->instruction()->IsDefinition() ?
value->instruction()->AsDefinition()->ssa_temp_index() : -1,
value->definition()->ssa_temp_index(),
@@ -552,7 +552,7 @@
cid_ = type_class.id();
} else if (FLAG_use_cha_deopt) {
if (FLAG_trace_cha) {
- ISL_Print(" **(CHA) Compile type not subclassed: %s\n",
+ THR_Print(" **(CHA) Compile type not subclassed: %s\n",
type_class.ToCString());
}
cha->AddToLeafClasses(type_class);
@@ -698,7 +698,7 @@
CompileType result = CompileType::None();
for (intptr_t i = 0; i < InputCount(); i++) {
if (FLAG_trace_type_propagation) {
- ISL_Print(" phi %" Pd " input %" Pd ": v%" Pd " has reaching type %s\n",
+ THR_Print(" phi %" Pd " input %" Pd ": v%" Pd " has reaching type %s\n",
ssa_temp_index(),
i,
InputAt(i)->definition()->ssa_temp_index(),
@@ -795,7 +795,7 @@
} else {
if (FLAG_use_cha_deopt) {
if (FLAG_trace_cha) {
- ISL_Print(" **(CHA) Computing exact type of parameters, "
+ THR_Print(" **(CHA) Computing exact type of parameters, "
"no subclasses: %s\n",
type_class.ToCString());
}
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index 42a08bd..1d151d0 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -110,7 +110,7 @@
// helper functions to the raw object interface.
String name;
name = func->ptr()->name_;
- ISL_Print("Detaching code: %s\n", name.ToCString());
+ THR_Print("Detaching code: %s\n", name.ToCString());
current_code_count++;
}
}
@@ -127,8 +127,8 @@
}
}
if (FLAG_log_code_drop) {
- ISL_Print(" total detached current: %" Pd "\n", current_code_count);
- ISL_Print(" total detached unoptimized: %" Pd "\n",
+ THR_Print(" total detached current: %" Pd "\n", current_code_count);
+ THR_Print(" total detached unoptimized: %" Pd "\n",
unoptimized_code_count);
}
// Clean up.
@@ -700,11 +700,9 @@
MarkingWeakVisitor mark_weak;
IterateWeakRoots(isolate, &mark_weak,
!visit_prologue_weak_persistent_handles);
- // TODO(koda): Move this into Phase 3 after making ISL_Print thread-safe
- // (used in SkippedCodeFunctions::DetachCode).
- FinalizeResultsFrom(&mark);
MainSync(num_tasks);
// Phase 3: Finalize results from all markers (detach code, etc.).
+ FinalizeResultsFrom(&mark);
MainSync(num_tasks);
// Finalization complete and all tasks exited.
}
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 9e0b653..c691b85 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -83,11 +83,11 @@
void FlowGraphPrinter::PrintGraph(const char* phase, FlowGraph* flow_graph) {
- LogBlock lb(Isolate::Current());
- ISL_Print("*** BEGIN CFG\n%s\n", phase);
+ LogBlock lb;
+ THR_Print("*** BEGIN CFG\n%s\n", phase);
FlowGraphPrinter printer(*flow_graph);
printer.PrintBlocks();
- ISL_Print("*** END CFG\n");
+ THR_Print("*** END CFG\n");
fflush(stdout);
}
@@ -96,19 +96,19 @@
bool print_locations) {
// Print the block entry.
PrintOneInstruction(block, print_locations);
- ISL_Print("\n");
+ THR_Print("\n");
// And all the successors in the block.
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
Instruction* current = it.Current();
PrintOneInstruction(current, print_locations);
- ISL_Print("\n");
+ THR_Print("\n");
}
}
void FlowGraphPrinter::PrintBlocks() {
if (!function_.IsNull()) {
- ISL_Print("==== %s\n", function_.ToFullyQualifiedCString());
+ THR_Print("==== %s\n", function_.ToFullyQualifiedCString());
}
for (intptr_t i = 0; i < block_order_.length(); ++i) {
@@ -134,12 +134,12 @@
instr->locs()->PrintTo(&f);
}
if (instr->lifetime_position() != -1) {
- ISL_Print("%3" Pd ": ", instr->lifetime_position());
+ THR_Print("%3" Pd ": ", instr->lifetime_position());
}
- if (!instr->IsBlockEntry()) ISL_Print(" ");
- ISL_Print("%s", str);
+ if (!instr->IsBlockEntry()) THR_Print(" ");
+ THR_Print("%s", str);
if (FLAG_trace_inlining_intervals) {
- ISL_Print(" iid: %" Pd "", instr->inlining_id());
+ THR_Print(" iid: %" Pd "", instr->inlining_id());
}
}
@@ -154,7 +154,7 @@
if (value != NULL && value->reaching_type_ != NULL) {
compile_type_name = value->reaching_type_->ToCString();
}
- ISL_Print("%s type check: compile type %s is %s specific than "
+ THR_Print("%s type check: compile type %s is %s specific than "
"type '%s' of '%s'.\n",
eliminated ? "Eliminated" : "Generated",
compile_type_name,
@@ -228,9 +228,9 @@
char buffer[1024];
BufferFormatter f(buffer, sizeof(buffer));
PrintICDataHelper(&f, ic_data);
- ISL_Print("%s ", buffer);
+ THR_Print("%s ", buffer);
const Array& a = Array::Handle(ic_data.arguments_descriptor());
- ISL_Print(" arg-desc %" Pd "\n", a.Length());
+ THR_Print(" arg-desc %" Pd "\n", a.Length());
}
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 8754ecf..b8db54d 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -37,6 +37,8 @@
"Generate special IC stubs for two args Smi operations");
DEFINE_FLAG(bool, unbox_numeric_fields, true,
"Support unboxed double and float32x4 fields.");
+DEFINE_FLAG(bool, fields_may_be_reset, false,
+ "Don't optimize away static field initialization");
DECLARE_FLAG(bool, eliminate_type_checks);
DECLARE_FLAG(bool, trace_optimization);
DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
@@ -385,7 +387,11 @@
const bool is_initialized =
(field_.StaticValue() != Object::sentinel().raw()) &&
(field_.StaticValue() != Object::transition_sentinel().raw());
- return is_initialized ? NULL : this;
+ // When precompiling, the fact that a field is currently initialized does not
+ // make it safe to omit code that checks if the field needs initialization
+ // because the field will be reset so it starts uninitialized in the process
+ // running the precompiled code. We must be prepared to reinitialize fields.
+ return is_initialized && !FLAG_fields_may_be_reset ? NULL : this;
}
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index bc4ba3c..45ec027 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -24,6 +24,7 @@
namespace dart {
+DECLARE_FLAG(bool, allow_absolute_addresses);
DECLARE_FLAG(bool, emit_edge_counters);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, use_osr);
@@ -947,7 +948,7 @@
entry = reinterpret_cast<uword>(&NativeEntry::LinkNativeCall);
#if defined(USING_SIMULATOR)
entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+ entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
#endif
} else {
entry = reinterpret_cast<uword>(native_c_function());
@@ -955,7 +956,7 @@
stub_entry = StubCode::CallBootstrapCFunction_entry();
#if defined(USING_SIMULATOR)
entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+ entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
#endif
} else {
// In the case of non bootstrap native methods the CallNativeCFunction
@@ -965,14 +966,14 @@
#if defined(USING_SIMULATOR)
if (!function().IsNativeAutoSetupScope()) {
entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+ entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
}
#endif
}
}
__ LoadImmediate(R1, argc_tag);
ExternalLabel label(entry);
- __ LoadExternalLabel(R5, &label, link_lazily() ? kPatchable : kNotPatchable);
+ __ LoadNativeEntry(R5, &label, link_lazily() ? kPatchable : kNotPatchable);
compiler->GenerateCall(token_pos(),
*stub_entry,
RawPcDescriptors::kOther,
@@ -1703,8 +1704,7 @@
if (field_cid != kSmiCid) {
__ CompareImmediate(value_cid_reg, kNullCid);
} else {
- __ CompareImmediate(value_reg,
- reinterpret_cast<intptr_t>(Object::null()));
+ __ CompareObject(value_reg, Object::null_object());
}
}
__ b(fail, NE);
@@ -2034,8 +2034,7 @@
Register temp) {
Label done;
__ ldr(box_reg, FieldAddress(instance_reg, offset));
- __ CompareImmediate(box_reg,
- reinterpret_cast<intptr_t>(Object::null()));
+ __ CompareObject(box_reg, Object::null_object());
__ b(&done, NE);
BoxAllocationSlowPath::Allocate(
@@ -2352,7 +2351,7 @@
// R6: null
if (num_elements > 0) {
const intptr_t array_size = instance_size - sizeof(RawArray);
- __ LoadImmediate(R6, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R6, Object::null_object());
if (num_elements >= 2) {
__ mov(R7, Operand(R6));
} else {
@@ -2621,7 +2620,7 @@
Label type_arguments_instantiated;
const intptr_t len = type_arguments().Length();
if (type_arguments().IsRawInstantiatedRaw(len)) {
- __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(IP, Object::null_object());
__ cmp(instantiator_reg, Operand(IP));
__ b(&type_arguments_instantiated, EQ);
}
@@ -2886,6 +2885,7 @@
const Register value = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
+ ASSERT(FLAG_allow_absolute_addresses);
__ LoadImmediate(IP, flags_address);
__ LoadImmediate(value, Isolate::kOsrRequest);
__ str(value, Address(IP));
@@ -2930,7 +2930,7 @@
CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
compiler->AddSlowPathCode(slow_path);
- if (compiler->is_optimizing()) {
+ if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
__ LoadImmediate(IP, Isolate::Current()->stack_limit_address());
__ ldr(IP, Address(IP));
} else {
@@ -3757,7 +3757,7 @@
if ((value()->Type()->ToNullableCid() == box_cid) &&
value()->Type()->is_nullable()) {
- __ CompareImmediate(box, reinterpret_cast<intptr_t>(Object::null()));
+ __ CompareObject(box, Object::null_object());
__ b(deopt, EQ);
} else {
__ tst(box, Operand(kSmiTagMask));
@@ -5916,8 +5916,7 @@
ICData::kDeoptCheckClass,
licm_hoisted_ ? ICData::kHoisted : 0);
if (IsNullCheck()) {
- __ CompareImmediate(locs()->in(0).reg(),
- reinterpret_cast<intptr_t>(Object::null()));
+ __ CompareObject(locs()->in(0).reg(), Object::null_object());
ASSERT(DeoptIfNull() || DeoptIfNotNull());
Condition cond = DeoptIfNull() ? EQ : NE;
__ b(deopt, cond);
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 8c87b54..7ae62c0 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -23,6 +23,7 @@
namespace dart {
+DECLARE_FLAG(bool, allow_absolute_addresses);
DECLARE_FLAG(bool, emit_edge_counters);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, use_osr);
@@ -800,7 +801,7 @@
entry = reinterpret_cast<uword>(&NativeEntry::LinkNativeCall);
#if defined(USING_SIMULATOR)
entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+ entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
#endif
} else {
entry = reinterpret_cast<uword>(native_c_function());
@@ -808,7 +809,7 @@
stub_entry = StubCode::CallBootstrapCFunction_entry();
#if defined(USING_SIMULATOR)
entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+ entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
#endif
} else {
// In the case of non bootstrap native methods the CallNativeCFunction
@@ -818,14 +819,14 @@
#if defined(USING_SIMULATOR)
if (!function().IsNativeAutoSetupScope()) {
entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+ entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
}
#endif
}
}
__ LoadImmediate(R1, argc_tag);
ExternalLabel label(entry);
- __ LoadExternalLabel(R5, &label);
+ __ LoadNativeEntry(R5, &label);
compiler->GenerateCall(token_pos(),
*stub_entry,
RawPcDescriptors::kOther,
@@ -2598,6 +2599,7 @@
const Register value = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
+ ASSERT(FLAG_allow_absolute_addresses);
__ LoadImmediate(TMP, flags_address);
__ LoadImmediate(value, Isolate::kOsrRequest);
__ str(value, Address(TMP));
@@ -2642,7 +2644,7 @@
CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
compiler->AddSlowPathCode(slow_path);
- if (compiler->is_optimizing()) {
+ if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
__ LoadImmediate(TMP, Isolate::Current()->stack_limit_address());
__ ldr(TMP, Address(TMP));
} else {
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index eb7d932..fe30067 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -23,6 +23,7 @@
namespace dart {
+DECLARE_FLAG(bool, allow_absolute_addresses);
DECLARE_FLAG(bool, emit_edge_counters);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, use_osr);
@@ -998,7 +999,7 @@
entry = reinterpret_cast<uword>(&NativeEntry::LinkNativeCall);
#if defined(USING_SIMULATOR)
entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+ entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
#endif
} else {
entry = reinterpret_cast<uword>(native_c_function());
@@ -1006,7 +1007,7 @@
stub_entry = StubCode::CallBootstrapCFunction_entry();
#if defined(USING_SIMULATOR)
entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+ entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
#endif
} else {
// In the case of non bootstrap native methods the CallNativeCFunction
@@ -1016,14 +1017,14 @@
#if defined(USING_SIMULATOR)
if (!function().IsNativeAutoSetupScope()) {
entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, function().NumParameters());
+ entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
}
#endif
}
}
__ LoadImmediate(A1, argc_tag);
ExternalLabel label(entry);
- __ LoadExternalLabel(T5, &label, kNotPatchable);
+ __ LoadNativeEntry(T5, &label, kNotPatchable);
compiler->GenerateCall(token_pos(),
*stub_entry,
RawPcDescriptors::kOther,
@@ -1737,7 +1738,7 @@
__ LoadImmediate(TMP, kNullCid);
__ subu(CMPRES1, value_cid_reg, TMP);
} else {
- __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ subu(CMPRES1, value_reg, TMP);
}
}
@@ -2204,7 +2205,7 @@
// T7: null.
if (num_elements > 0) {
const intptr_t array_size = instance_size - sizeof(RawArray);
- __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(T7, Object::null_object());
__ AddImmediate(T2, V0, sizeof(RawArray) - kHeapObjectTag);
if (array_size < (kInlineArraySize * kWordSize)) {
intptr_t current_offset = 0;
@@ -2715,6 +2716,7 @@
Register value = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
+ ASSERT(FLAG_allow_absolute_addresses);
__ LoadImmediate(TMP, flags_address);
__ LoadImmediate(value, Isolate::kOsrRequest);
__ sw(value, Address(TMP));
@@ -2760,7 +2762,7 @@
CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
compiler->AddSlowPathCode(slow_path);
- if (compiler->is_optimizing()) {
+ if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
__ LoadImmediate(TMP, Isolate::Current()->stack_limit_address());
__ lw(CMPRES1, Address(TMP));
} else {
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 4955df6..19fc8b3 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -22,6 +22,7 @@
namespace dart {
+DECLARE_FLAG(bool, allow_absolute_addresses);
DECLARE_FLAG(bool, emit_edge_counters);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
@@ -785,14 +786,14 @@
const StubEntry* stub_entry;
if (link_lazily()) {
stub_entry = StubCode::CallBootstrapCFunction_entry();
- __ LoadExternalLabel(
+ __ LoadNativeEntry(
RBX, &NativeEntry::LinkNativeCallLabel(), kPatchable);
} else {
stub_entry = (is_bootstrap_native() || is_leaf_call)
? StubCode::CallBootstrapCFunction_entry()
: StubCode::CallNativeCFunction_entry();
const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
- __ LoadExternalLabel(RBX, &label, kNotPatchable);
+ __ LoadNativeEntry(RBX, &label, kNotPatchable);
}
compiler->GenerateCall(token_pos(),
*stub_entry,
@@ -2600,6 +2601,7 @@
Register temp = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
+ ASSERT(FLAG_allow_absolute_addresses);
__ LoadImmediate(temp, Immediate(flags_address));
__ movq(Address(temp, 0), Immediate(Isolate::kOsrRequest));
}
@@ -2646,7 +2648,7 @@
Register temp = locs()->temp(0).reg();
// Generate stack overflow check.
- if (compiler->is_optimizing()) {
+ if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
__ LoadImmediate(
temp, Immediate(Isolate::Current()->stack_limit_address()));
__ cmpq(RSP, Address(temp, 0));
@@ -3405,9 +3407,7 @@
if ((value()->Type()->ToNullableCid() == box_cid) &&
value()->Type()->is_nullable()) {
- const Immediate& raw_null =
- Immediate(reinterpret_cast<intptr_t>(Object::null()));
- __ cmpq(box, raw_null);
+ __ CompareObject(box, Object::null_object());
__ j(EQUAL, deopt);
} else {
__ testq(box, Immediate(kSmiTagMask));
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index ffeda36..5e24dd3 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -155,7 +155,7 @@
}
if (FLAG_print_flow_graph && FlowGraphPrinter::ShouldPrint(function)) {
- ISL_Print("Intrinsic graph before\n");
+ THR_Print("Intrinsic graph before\n");
FlowGraphPrinter printer(*graph);
printer.PrintBlocks();
}
@@ -165,7 +165,7 @@
allocator.AllocateRegisters();
if (FLAG_print_flow_graph && FlowGraphPrinter::ShouldPrint(function)) {
- ISL_Print("Intrinsic graph after\n");
+ THR_Print("Intrinsic graph after\n");
FlowGraphPrinter printer(*graph);
printer.PrintBlocks();
}
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 2618ef9..7d3421d 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -56,19 +56,18 @@
const intptr_t type_args_field_offset =
ComputeObjectArrayTypeArgumentsOffset();
// Inline simple tests (Smi, null), fallthrough if not positive.
- const int32_t raw_null = reinterpret_cast<intptr_t>(Object::null());
Label checked_ok;
__ ldr(R2, Address(SP, 0 * kWordSize)); // Value.
// Null value is valid for any type.
- __ CompareImmediate(R2, raw_null);
+ __ CompareObject(R2, Object::null_object());
__ b(&checked_ok, EQ);
__ ldr(R1, Address(SP, 2 * kWordSize)); // Array.
__ ldr(R1, FieldAddress(R1, type_args_field_offset));
// R1: Type arguments of array.
- __ CompareImmediate(R1, raw_null);
+ __ CompareObject(R1, Object::null_object());
__ b(&checked_ok, EQ);
// Check if it's dynamic.
@@ -179,8 +178,7 @@
ASSERT(kSmiTagShift == 1);
__ add(R1, R2, Operand(R1, LSL, 1));
__ StoreIntoObject(R2, FieldAddress(R1, Array::data_offset()), R0);
- const int32_t raw_null = reinterpret_cast<int32_t>(Object::null());
- __ LoadImmediate(R0, raw_null);
+ __ LoadObject(R0, Object::null_object());
__ Ret();
__ Bind(&fall_through);
}
@@ -1587,7 +1585,7 @@
__ LoadClassById(R2, R1);
// R2: class of instance (R0).
__ ldr(R3, FieldAddress(R2, Class::signature_function_offset()));
- __ CompareImmediate(R3, reinterpret_cast<int32_t>(Object::null()));
+ __ CompareObject(R3, Object::null_object());
__ b(&fall_through, NE);
__ ldrh(R3, FieldAddress(R2, Class::num_type_arguments_offset()));
@@ -1595,7 +1593,7 @@
__ b(&fall_through, NE);
__ ldr(R0, FieldAddress(R2, Class::canonical_types_offset()));
- __ CompareImmediate(R0, reinterpret_cast<int32_t>(Object::null()));
+ __ CompareObject(R0, Object::null_object());
__ b(&fall_through, EQ);
__ Ret();
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index d5df533..95783b6 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -58,7 +58,7 @@
__ lw(T2, Address(SP, 0 * kWordSize)); // Value.
// Null value is valid for any type.
- __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(T7, Object::null_object());
__ beq(T2, T7, &checked_ok);
__ lw(T1, Address(SP, 2 * kWordSize)); // Array.
@@ -169,7 +169,7 @@
__ StoreIntoObject(T2,
FieldAddress(T1, Array::data_offset()),
T0);
- __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(T7, Object::null_object());
__ Ret();
__ delay_slot()->mov(V0, T7);
__ Bind(&fall_through);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 06dfad2..87ab7eb 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -5,11 +5,13 @@
#include "vm/isolate.h"
#include "include/dart_api.h"
+#include "include/dart_native_api.h"
#include "platform/assert.h"
#include "platform/json.h"
#include "vm/code_observers.h"
#include "vm/compiler_stats.h"
#include "vm/coverage.h"
+#include "vm/dart_api_message.h"
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
@@ -38,6 +40,7 @@
#include "vm/thread_interrupter.h"
#include "vm/thread_registry.h"
#include "vm/timeline.h"
+#include "vm/timeline_analysis.h"
#include "vm/timer.h"
#include "vm/visitor.h"
@@ -45,6 +48,7 @@
namespace dart {
DECLARE_FLAG(bool, print_metrics);
+DECLARE_FLAG(bool, timing);
DECLARE_FLAG(bool, trace_service);
DEFINE_FLAG(bool, trace_isolates, false,
@@ -56,9 +60,6 @@
DEFINE_FLAG(bool, break_at_isolate_spawn, false,
"Insert a one-time breakpoint at the entrypoint for all spawned "
"isolates");
-DEFINE_FLAG(charp, isolate_log_filter, NULL,
- "Log isolates whose name include the filter. "
- "Default: service isolate log messages are suppressed.");
DEFINE_FLAG(int, new_gen_semi_max_size, (kWordSize <= 4) ? 16 : 32,
"Max size of new gen semi space in MB");
@@ -166,7 +167,6 @@
bool IsCurrentIsolate() const;
virtual Isolate* isolate() const { return isolate_; }
- private:
// Keep both these enums in sync with isolate_patch.dart.
// The different Isolate API message types.
enum {
@@ -187,6 +187,7 @@
kAsEventAction = 2
};
+ private:
// A result of false indicates that the isolate should terminate the
// processing of further events.
bool HandleLibMessage(const Array& message);
@@ -656,6 +657,7 @@
Isolate::Isolate(const Dart_IsolateFlags& api_flags)
: vm_tag_(0),
store_buffer_(new StoreBuffer()),
+ heap_(NULL),
thread_registry_(new ThreadRegistry()),
message_notify_callback_(NULL),
name_(NULL),
@@ -666,7 +668,6 @@
pause_capability_(0),
terminate_capability_(0),
errors_fatal_(true),
- heap_(NULL),
object_store_(NULL),
top_exit_frame_info_(0),
init_callback_data_(NULL),
@@ -699,7 +700,6 @@
edge_counter_increment_size_(-1),
compiler_stats_(NULL),
is_service_isolate_(false),
- log_(new class Log()),
stacktrace_(NULL),
stack_frame_index_(-1),
last_allocationprofile_accumulator_reset_timestamp_(0),
@@ -747,8 +747,6 @@
message_handler_ = NULL; // Fail fast if we send messages to a dead isolate.
ASSERT(deopt_context_ == NULL); // No deopt in progress when isolate deleted.
delete spawn_state_;
- delete log_;
- log_ = NULL;
delete object_id_ring_;
object_id_ring_ = NULL;
delete pause_loop_monitor_;
@@ -772,6 +770,7 @@
create_callback_ = NULL;
isolates_list_monitor_ = new Monitor();
ASSERT(isolates_list_monitor_ != NULL);
+ EnableIsolateCreation();
}
@@ -850,8 +849,14 @@
result->compiler_stats_ = new CompilerStats(result);
}
ObjectIdRing::Init(result);
- // Add to isolate list.
- AddIsolateTolist(result);
+
+ // Add to isolate list. Shutdown and delete the isolate on failure.
+ if (!AddIsolateToList(result)) {
+ result->LowLevelShutdown();
+ Thread::ExitIsolate();
+ delete result;
+ return NULL;
+ }
return result;
}
@@ -900,27 +905,7 @@
name_ = strdup(name_prefix);
return;
}
- const char* kFormat = "%s-%lld";
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, name_prefix, main_port()) + 1;
- name_ = reinterpret_cast<char*>(malloc(len));
- OS::SNPrint(name_, len, kFormat, name_prefix, main_port());
-}
-
-
-Log* Isolate::Log() const {
- if (FLAG_isolate_log_filter == NULL) {
- if (is_service_isolate_) {
- // By default, do not log for the service isolate.
- return Log::NoOpLog();
- }
- return log_;
- }
- ASSERT(name_ != NULL);
- if (strstr(name_, FLAG_isolate_log_filter) == NULL) {
- // Filter does not match, do not log for this isolate.
- return Log::NoOpLog();
- }
- return log_;
+ name_ = OS::SCreate(NULL, "%s-%" Pd64 "", name_prefix, main_port());
}
@@ -1486,6 +1471,70 @@
};
+void Isolate::LowLevelShutdown() {
+ // Ensure we have a zone and handle scope so that we can call VM functions,
+ // but we no longer allocate new heap objects.
+ Thread* thread = Thread::Current();
+ StackZone stack_zone(thread);
+ HandleScope handle_scope(thread);
+ NoSafepointScope no_safepoint_scope;
+
+ if (compiler_stats_ != NULL) {
+ OS::Print("%s", compiler_stats()->PrintToZone());
+ }
+
+ // Notify exit listeners that this isolate is shutting down.
+ if (object_store() != NULL) {
+ NotifyExitListeners();
+ }
+
+ // Clean up debugger resources.
+ debugger()->Shutdown();
+
+ // Close all the ports owned by this isolate.
+ PortMap::ClosePorts(message_handler());
+
+ // Fail fast if anybody tries to post any more messsages to this isolate.
+ delete message_handler();
+ set_message_handler(NULL);
+
+ // Dump all accumulated timer data for the isolate.
+ timer_list_.ReportTimers();
+
+ // Before analyzing the isolate's timeline blocks- close all of them.
+ CloseAllTimelineBlocks();
+
+ // Dump all timing data for the isolate.
+ if (FLAG_timing) {
+ TimelinePauseTrace tpt;
+ tpt.Print();
+ }
+
+ // Finalize any weak persistent handles with a non-null referent.
+ FinalizeWeakPersistentHandlesVisitor visitor;
+ api_state()->weak_persistent_handles().VisitHandles(&visitor);
+ api_state()->prologue_weak_persistent_handles().VisitHandles(&visitor);
+
+ if (FLAG_trace_isolates) {
+ heap()->PrintSizes();
+ MegamorphicCacheTable::PrintSizes(this);
+ Symbols::DumpStats();
+ OS::Print("[-] Stopping isolate:\n"
+ "\tisolate: %s\n", name());
+ }
+ if (FLAG_print_metrics) {
+ LogBlock lb;
+ THR_Print("Printing metrics for %s\n", name());
+#define ISOLATE_METRIC_PRINT(type, variable, name, unit) \
+ THR_Print("%s\n", metric_##variable##_.ToString());
+
+ ISOLATE_METRIC_LIST(ISOLATE_METRIC_PRINT);
+#undef ISOLATE_METRIC_PRINT
+ THR_Print("\n");
+ }
+}
+
+
void Isolate::Shutdown() {
ASSERT(this == Isolate::Current());
ASSERT(top_resource() == NULL);
@@ -1505,7 +1554,10 @@
HandleScope handle_scope(thread);
// Write out the coverage data if collection has been enabled.
- CodeCoverage::Write(this);
+ if ((this != Dart::vm_isolate()) &&
+ !ServiceIsolate::IsServiceIsolateDescendant(this)) {
+ CodeCoverage::Write(this);
+ }
}
// Remove this isolate from the list *before* we start tearing it down, to
@@ -1523,57 +1575,7 @@
}
// Then, proceed with low-level teardown.
- {
- // Ensure we have a zone and handle scope so that we can call VM functions,
- // but we no longer allocate new heap objects.
- StackZone stack_zone(thread);
- HandleScope handle_scope(thread);
- NoSafepointScope no_safepoint_scope;
-
- if (compiler_stats_ != NULL) {
- OS::Print("%s", compiler_stats()->PrintToZone());
- }
-
- // Notify exit listeners that this isolate is shutting down.
- if (object_store() != NULL) {
- NotifyExitListeners();
- }
-
- // Clean up debugger resources.
- debugger()->Shutdown();
-
- // Close all the ports owned by this isolate.
- PortMap::ClosePorts(message_handler());
-
- // Fail fast if anybody tries to post any more messsages to this isolate.
- delete message_handler();
- set_message_handler(NULL);
-
- // Dump all accumulated timer data for the isolate.
- timer_list_.ReportTimers();
-
- // Finalize any weak persistent handles with a non-null referent.
- FinalizeWeakPersistentHandlesVisitor visitor;
- api_state()->weak_persistent_handles().VisitHandles(&visitor);
- api_state()->prologue_weak_persistent_handles().VisitHandles(&visitor);
-
- if (FLAG_trace_isolates) {
- heap()->PrintSizes();
- megamorphic_cache_table()->PrintSizes();
- Symbols::DumpStats();
- OS::Print("[-] Stopping isolate:\n"
- "\tisolate: %s\n", name());
- }
- if (FLAG_print_metrics) {
- LogBlock lb(this);
- ISL_Print("Printing metrics for %s\n", name());
-#define ISOLATE_METRIC_PRINT(type, variable, name, unit) \
- ISL_Print("%s\n", metric_##variable##_.ToString());
- ISOLATE_METRIC_LIST(ISOLATE_METRIC_PRINT);
-#undef ISOLATE_METRIC_PRINT
- ISL_Print("\n");
- }
- }
+ LowLevelShutdown();
#if defined(DEBUG)
// No concurrent sweeper tasks should be running at this point.
@@ -1593,6 +1595,17 @@
}
+void Isolate::CloseAllTimelineBlocks() {
+ // Close all blocks
+ thread_registry_->CloseAllTimelineBlocks();
+ TimelineEventRecorder* recorder = Timeline::recorder();
+ if (recorder != NULL) {
+ MutexLocker ml(&recorder->lock_);
+ Thread::Current()->CloseTimelineBlock();
+ }
+}
+
+
Dart_IsolateCreateCallback Isolate::create_callback_ = NULL;
Dart_IsolateInterruptCallback Isolate::interrupt_callback_ = NULL;
Dart_IsolateUnhandledExceptionCallback
@@ -1606,7 +1619,7 @@
Monitor* Isolate::isolates_list_monitor_ = NULL;
Isolate* Isolate::isolates_list_head_ = NULL;
-
+bool Isolate::creation_enabled_ = false;
void Isolate::IterateObjectPointers(ObjectPointerVisitor* visitor,
bool visit_prologue_weak_handles,
@@ -1627,9 +1640,6 @@
// Visit objects in the class table.
class_table()->VisitObjectPointers(visitor);
- // Visit objects in the megamorphic cache.
- megamorphic_cache_table()->VisitObjectPointers(visitor);
-
// Visit objects in per isolate stubs.
StubCode::VisitObjectPointers(visitor);
@@ -2119,12 +2129,16 @@
}
-void Isolate::AddIsolateTolist(Isolate* isolate) {
+bool Isolate::AddIsolateToList(Isolate* isolate) {
MonitorLocker ml(isolates_list_monitor_);
+ if (!creation_enabled_) {
+ return false;
+ }
ASSERT(isolate != NULL);
ASSERT(isolate->next_ == NULL);
isolate->next_ = isolates_list_head_;
isolates_list_head_ = isolate;
+ return true;
}
@@ -2133,6 +2147,9 @@
ASSERT(isolate != NULL);
if (isolate == isolates_list_head_) {
isolates_list_head_ = isolate->next_;
+ if (!creation_enabled_) {
+ ml.Notify();
+ }
return;
}
Isolate* previous = NULL;
@@ -2141,12 +2158,28 @@
if (current == isolate) {
ASSERT(previous != NULL);
previous->next_ = current->next_;
+ if (!creation_enabled_) {
+ ml.Notify();
+ }
return;
}
previous = current;
current = current->next_;
}
- UNREACHABLE();
+ // If we are shutting down the VM, the isolate may not be in the list.
+ ASSERT(!creation_enabled_);
+}
+
+
+void Isolate::DisableIsolateCreation() {
+ MonitorLocker ml(isolates_list_monitor_);
+ creation_enabled_ = false;
+}
+
+
+void Isolate::EnableIsolateCreation() {
+ MonitorLocker ml(isolates_list_monitor_);
+ creation_enabled_ = true;
}
@@ -2158,6 +2191,93 @@
}
+void Isolate::KillLocked() {
+ Dart_CObject kill_msg;
+ Dart_CObject* list_values[4];
+ kill_msg.type = Dart_CObject_kArray;
+ kill_msg.value.as_array.length = 4;
+ kill_msg.value.as_array.values = list_values;
+
+ Dart_CObject oob;
+ oob.type = Dart_CObject_kInt32;
+ oob.value.as_int32 = Message::kIsolateLibOOBMsg;
+ list_values[0] = &oob;
+
+ Dart_CObject kill;
+ kill.type = Dart_CObject_kInt32;
+ kill.value.as_int32 = IsolateMessageHandler::kKillMsg;
+ list_values[1] = &kill;
+
+ Dart_CObject cap;
+ cap.type = Dart_CObject_kCapability;
+ cap.value.as_capability.id = terminate_capability();
+ list_values[2] = ∩
+
+ Dart_CObject imm;
+ imm.type = Dart_CObject_kInt32;
+ imm.value.as_int32 = IsolateMessageHandler::kImmediateAction;
+ list_values[3] = &imm;
+
+ {
+ uint8_t* buffer = NULL;
+ ApiMessageWriter writer(&buffer, allocator);
+ bool success = writer.WriteCMessage(&kill_msg);
+ ASSERT(success);
+
+ // Post the message at the given port.
+ success = PortMap::PostMessage(new Message(main_port(),
+ buffer,
+ writer.BytesWritten(),
+ Message::kOOBPriority));
+ ASSERT(success);
+ }
+}
+
+
+class IsolateKillerVisitor : public IsolateVisitor {
+ public:
+ IsolateKillerVisitor() : target_(NULL) {}
+
+ explicit IsolateKillerVisitor(Isolate* isolate)
+ : target_(isolate) {
+ ASSERT(isolate != Dart::vm_isolate());
+ }
+
+ virtual ~IsolateKillerVisitor() {}
+
+ void VisitIsolate(Isolate* isolate) {
+ ASSERT(isolate != NULL);
+ if (ShouldKill(isolate)) {
+ isolate->KillLocked();
+ }
+ }
+
+ private:
+ bool ShouldKill(Isolate* isolate) {
+ // If a target_ is specified, then only kill the target_.
+ // Otherwise, don't kill the service isolate or vm isolate.
+ return (((target_ != NULL) && (isolate == target_)) ||
+ ((target_ == NULL) &&
+ !ServiceIsolate::IsServiceIsolateDescendant(isolate) &&
+ (isolate != Dart::vm_isolate())));
+ }
+
+ Isolate* target_;
+};
+
+
+void Isolate::KillAllIsolates() {
+ IsolateKillerVisitor visitor;
+ VisitIsolates(&visitor);
+}
+
+
+void Isolate::KillIfExists(Isolate* isolate) {
+ IsolateKillerVisitor visitor(isolate);
+ VisitIsolates(&visitor);
+}
+
+
static RawInstance* DeserializeObject(Thread* thread,
uint8_t* obj_data,
intptr_t obj_len) {
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index b8e7a4c..5c75c94 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -145,10 +145,6 @@
return OFFSET_OF(Isolate, class_table_);
}
- MegamorphicCacheTable* megamorphic_cache_table() {
- return &megamorphic_cache_table_;
- }
-
Dart_MessageNotifyCallback message_notify_callback() const {
return message_notify_callback_;
}
@@ -170,9 +166,6 @@
const char* debugger_name() const { return debugger_name_; }
void set_debugger_name(const char* name);
- // TODO(koda): Move to Thread.
- class Log* Log() const;
-
int64_t start_time() const { return start_time_; }
Dart_Port main_port() const { return main_port_; }
@@ -759,8 +752,17 @@
mutator_thread_->set_zone(zone);
}
+ bool is_service_isolate() const { return is_service_isolate_; }
+
+ static void KillAllIsolates();
+ static void KillIfExists(Isolate* isolate);
+
+ static void DisableIsolateCreation();
+ static void EnableIsolateCreation();
+
private:
friend class Dart; // Init, InitOnce, Shutdown.
+ friend class IsolateKillerVisitor; // Kill().
explicit Isolate(const Dart_IsolateFlags& api_flags);
@@ -768,7 +770,14 @@
static Isolate* Init(const char* name_prefix,
const Dart_IsolateFlags& api_flags,
bool is_vm_isolate = false);
+
+ // The isolates_list_monitor_ should be held when calling Kill().
+ void KillLocked();
+
+ void LowLevelShutdown();
void Shutdown();
+ // Assumes mutator is the only thread still in the isolate.
+ void CloseAllTimelineBlocks();
void BuildName(const char* name_prefix);
void PrintInvokedFunctions();
@@ -812,9 +821,9 @@
uword vm_tag_;
StoreBuffer* store_buffer_;
+ Heap* heap_;
ThreadRegistry* thread_registry_;
ClassTable class_table_;
- MegamorphicCacheTable megamorphic_cache_table_;
Dart_MessageNotifyCallback message_notify_callback_;
char* name_;
char* debugger_name_;
@@ -824,7 +833,6 @@
uint64_t pause_capability_;
uint64_t terminate_capability_;
bool errors_fatal_;
- Heap* heap_;
ObjectStore* object_store_;
uword top_exit_frame_info_;
void* init_callback_data_;
@@ -858,9 +866,7 @@
CompilerStats* compiler_stats_;
- // Log.
bool is_service_isolate_;
- class Log* log_;
// Status support.
char* stacktrace_;
@@ -962,11 +968,13 @@
static void WakePauseEventHandler(Dart_Isolate isolate);
// Manage list of existing isolates.
- static void AddIsolateTolist(Isolate* isolate);
+ static bool AddIsolateToList(Isolate* isolate);
static void RemoveIsolateFromList(Isolate* isolate);
- static Monitor* isolates_list_monitor_; // Protects isolates_list_head_
+ // This monitor protects isolates_list_head_, and creation_enabled_.
+ static Monitor* isolates_list_monitor_;
static Isolate* isolates_list_head_;
+ static bool creation_enabled_;
#define REUSABLE_FRIEND_DECLARATION(name) \
friend class Reusable##name##HandleScope;
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index e0ee6b7..f6a255d 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -686,7 +686,7 @@
void JSONObject::AddLocation(const Script& script,
intptr_t token_pos,
- intptr_t end_token_pos) {
+ intptr_t end_token_pos) const {
JSONObject location(this, "location");
location.AddProperty("type", "SourceLocation");
location.AddProperty("script", script);
@@ -697,6 +697,49 @@
}
+void JSONObject::AddLocation(const BreakpointLocation* bpt_loc) const {
+ ASSERT(bpt_loc->IsResolved());
+
+ Isolate* isolate = Isolate::Current();
+ Library& library = Library::Handle(isolate);
+ Script& script = Script::Handle(isolate);
+ intptr_t token_pos;
+ bpt_loc->GetCodeLocation(&library, &script, &token_pos);
+ AddLocation(script, token_pos);
+}
+
+
+void JSONObject::AddUnresolvedLocation(
+ const BreakpointLocation* bpt_loc) const {
+ ASSERT(!bpt_loc->IsResolved());
+
+ Isolate* isolate = Isolate::Current();
+ Library& library = Library::Handle(isolate);
+ Script& script = Script::Handle(isolate);
+ intptr_t token_pos;
+ bpt_loc->GetCodeLocation(&library, &script, &token_pos);
+
+ JSONObject location(this, "location");
+ location.AddProperty("type", "UnresolvedSourceLocation");
+ if (!script.IsNull()) {
+ location.AddProperty("script", script);
+ } else {
+ const String& scriptUri = String::Handle(isolate, bpt_loc->url());
+ location.AddPropertyStr("scriptUri", scriptUri);
+ }
+ if (bpt_loc->requested_line_number() >= 0) {
+ // This unresolved breakpoint was specified at a particular line.
+ location.AddProperty("line", bpt_loc->requested_line_number());
+ if (bpt_loc->requested_column_number() >= 0) {
+ location.AddProperty("column",
+ bpt_loc->requested_column_number());
+ }
+ } else {
+ // This unresolved breakpoint was requested at some function entry.
+ location.AddProperty("tokenPos", token_pos);
+ }
+}
+
void JSONObject::AddPropertyF(const char* name,
const char* format, ...) const {
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index cdc5c4e..f835edc 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -15,6 +15,7 @@
class Array;
class Breakpoint;
+class BreakpointLocation;
class Field;
class GrowableObjectArray;
class Instance;
@@ -209,7 +210,11 @@
void AddLocation(const Script& script,
intptr_t token_pos,
- intptr_t end_token_pos = -1);
+ intptr_t end_token_pos = -1) const;
+
+ void AddLocation(const BreakpointLocation* bpt_loc) const;
+
+ void AddUnresolvedLocation(const BreakpointLocation* bpt_loc) const;
void AddProperty(const char* name, bool b) const {
stream_->PrintPropertyBool(name, b);
diff --git a/runtime/vm/json_test.cc b/runtime/vm/json_test.cc
index 5bce0d39..6ca6760 100644
--- a/runtime/vm/json_test.cc
+++ b/runtime/vm/json_test.cc
@@ -299,8 +299,12 @@
JSONObject jsobj(&jsarr);
jsobj.AddProperty("object_key", Object::Handle(Object::null()));
}
+ char buffer[1024];
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
EXPECT_STREQ("[{\"type\":\"@Instance\","
"\"_vmType\":\"null\","
+ "\"class\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"Null\"},"
"\"kind\":\"Null\","
"\"fixedId\":true,"
"\"id\":\"objects\\/null\","
@@ -308,11 +312,13 @@
"{\"object_key\":"
"{\"type\":\"@Instance\","
"\"_vmType\":\"null\","
+ "\"class\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"Null\"},"
"\"kind\":\"Null\","
"\"fixedId\":true,"
"\"id\":\"objects\\/null\","
"\"valueAsString\":\"null\"}}]",
- js.ToCString());
+ buffer);
}
TEST_CASE(JSON_JSONStream_EscapedString) {
diff --git a/runtime/vm/locations.cc b/runtime/vm/locations.cc
index 525855a..e460a2d 100644
--- a/runtime/vm/locations.cc
+++ b/runtime/vm/locations.cc
@@ -225,9 +225,9 @@
void Location::Print() const {
if (kind() == kStackSlot) {
- ISL_Print("S%+" Pd "", stack_index());
+ THR_Print("S%+" Pd "", stack_index());
} else {
- ISL_Print("%s", Name());
+ THR_Print("%s", Name());
}
}
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index 48fbd6f..5e92c16 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -519,7 +519,7 @@
for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
Register r = static_cast<Register>(i);
if (ContainsRegister(r)) {
- ISL_Print("%s %s\n", Assembler::RegisterName(r),
+ THR_Print("%s %s\n", Assembler::RegisterName(r),
IsTagged(r) ? "tagged" : "untagged");
}
}
@@ -527,7 +527,7 @@
for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
FpuRegister r = static_cast<FpuRegister>(i);
if (ContainsFpuRegister(r)) {
- ISL_Print("%s\n", Assembler::FpuRegisterName(r));
+ THR_Print("%s\n", Assembler::FpuRegisterName(r));
}
}
}
diff --git a/runtime/vm/log.cc b/runtime/vm/log.cc
index 5bb9842..e29432f 100644
--- a/runtime/vm/log.cc
+++ b/runtime/vm/log.cc
@@ -11,6 +11,10 @@
DEFINE_FLAG(bool, force_log_flush, false, "Always flush log messages.");
+DEFINE_FLAG(charp, isolate_log_filter, NULL,
+ "Log isolates whose name include the filter. "
+ "Default: service isolate log messages are suppressed.");
+
Log::Log(LogPrinter printer)
: printer_(printer),
manual_flush_(0),
@@ -18,6 +22,23 @@
}
+Log::~Log() {
+ // Did someone enable manual flushing and then forgot to Flush?
+ ASSERT(cursor() == 0);
+}
+
+
+Log* Log::Current() {
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
+ if (isolate != NULL && Log::ShouldLogForIsolate(isolate)) {
+ return thread->log();
+ } else {
+ return Log::NoOpLog();
+ }
+}
+
+
void Log::Print(const char* format, ...) {
if (this == NoOpLog()) {
return;
@@ -92,6 +113,24 @@
}
+bool Log::ShouldLogForIsolate(const Isolate* isolate) {
+ if (FLAG_isolate_log_filter == NULL) {
+ if (isolate->is_service_isolate()) {
+ // By default, do not log for the service isolate.
+ return false;
+ }
+ return true;
+ }
+ const char* name = isolate->name();
+ ASSERT(name != NULL);
+ if (strstr(name, FLAG_isolate_log_filter) == NULL) {
+ // Filter does not match, do not log for this isolate.
+ return false;
+ }
+ return true;
+}
+
+
Log Log::noop_log_;
Log* Log::NoOpLog() {
return &noop_log_;
@@ -117,25 +156,14 @@
}
-LogBlock::LogBlock(Thread* thread, Log* log)
- : StackResource(thread),
- log_(log), cursor_(log->cursor()) {
- CommonConstructor();
+void LogBlock::Initialize() {
+ log_->EnableManualFlush();
}
-LogBlock::LogBlock(Isolate* isolate)
- : StackResource(isolate),
- log_(isolate->Log()), cursor_(isolate->Log()->cursor()) {
- CommonConstructor();
-}
-
-
-LogBlock::LogBlock(Thread* thread)
- : StackResource(thread),
- log_(thread->isolate()->Log()),
- cursor_(thread->isolate()->Log()->cursor()) {
- CommonConstructor();
+LogBlock::~LogBlock() {
+ log_->Flush(cursor_);
+ log_->DisableManualFlush();
}
} // namespace dart
diff --git a/runtime/vm/log.h b/runtime/vm/log.h
index f4c58e9..a2f18fa 100644
--- a/runtime/vm/log.h
+++ b/runtime/vm/log.h
@@ -11,26 +11,28 @@
namespace dart {
-class Isolate;
class LogBlock;
class Thread;
#if defined(_MSC_VER)
-#define ISL_Print(format, ...) \
- Isolate::Current()->Log()->Print(format, __VA_ARGS__)
+#define THR_Print(format, ...) \
+ Log::Current()->Print(format, __VA_ARGS__)
#else
-#define ISL_Print(format, ...) \
- Isolate::Current()->Log()->Print(format, ##__VA_ARGS__)
+#define THR_Print(format, ...) \
+ Log::Current()->Print(format, ##__VA_ARGS__)
#endif
-#define ISL_VPrint(format, args) \
- Isolate::Current()->Log()->VPrint(format, args)
+#define THR_VPrint(format, args) \
+ Log::Current()->VPrint(format, args)
typedef void (*LogPrinter)(const char* str, ...);
class Log {
public:
explicit Log(LogPrinter printer = OS::Print);
+ ~Log();
+
+ static Log* Current();
// Append a formatted string to the log.
void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
@@ -55,6 +57,9 @@
void EnableManualFlush();
void DisableManualFlush();
+ // Returns false if we should drop log messages related to 'isolate'.
+ static bool ShouldLogForIsolate(const Isolate* isolate);
+
static Log noop_log_;
LogPrinter printer_;
intptr_t manual_flush_;
@@ -70,31 +75,24 @@
// Can be nested.
class LogBlock : public StackResource {
public:
- LogBlock(Isolate* isolate, Log* log)
- : StackResource(isolate),
- log_(log), cursor_(log->cursor()) {
- CommonConstructor();
+ LogBlock(Thread* thread, Log* log)
+ : StackResource(thread), log_(log), cursor_(log->cursor()) {
+ Initialize();
}
- explicit LogBlock(Isolate* isolate);
- explicit LogBlock(Thread* thread);
-
- LogBlock(Thread* thread, Log* log);
-
- ~LogBlock() {
- CommonDestructor();
+ LogBlock()
+ : StackResource(Thread::Current()),
+ log_(Log::Current()),
+ cursor_(Log::Current()->cursor()) {
+ Initialize();
}
+ ~LogBlock();
+
private:
- void CommonConstructor() {
- log_->EnableManualFlush();
- }
+ void Initialize();
- void CommonDestructor() {
- log_->Flush(cursor_);
- log_->DisableManualFlush();
- }
- Log* log_;
+ Log* const log_;
const intptr_t cursor_;
};
diff --git a/runtime/vm/log_test.cc b/runtime/vm/log_test.cc
index 370fefc..84ef855 100644
--- a/runtime/vm/log_test.cc
+++ b/runtime/vm/log_test.cc
@@ -47,13 +47,12 @@
TEST_CASE(Log_Macro) {
test_output_ = NULL;
- Isolate* isolate = Isolate::Current();
- Log* log = isolate->Log();
+ Log* log = Log::Current();
LogTestHelper::SetPrinter(log, TestPrinter);
- ISL_Print("Hello %s", "World");
+ THR_Print("Hello %s", "World");
EXPECT_STREQ("Hello World", test_output_);
- ISL_Print("SingleArgument");
+ THR_Print("SingleArgument");
EXPECT_STREQ("SingleArgument", test_output_);
}
@@ -72,15 +71,13 @@
test_output_ = NULL;
Log* log = new Log(TestPrinter);
- Isolate* isolate = Isolate::Current();
-
EXPECT_EQ(reinterpret_cast<const char*>(NULL), test_output_);
{
- LogBlock ba(isolate, log);
+ LogBlock ba(thread, log);
log->Print("APPLE");
EXPECT_EQ(reinterpret_cast<const char*>(NULL), test_output_);
{
- LogBlock ba(isolate, log);
+ LogBlock ba(thread, log);
log->Print("BANANA");
EXPECT_EQ(reinterpret_cast<const char*>(NULL), test_output_);
}
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index 3bbc529..c87be96 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -6,50 +6,52 @@
#include <stdlib.h>
#include "vm/object.h"
+#include "vm/object_store.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
namespace dart {
-MegamorphicCacheTable::MegamorphicCacheTable()
- : miss_handler_function_(NULL),
- miss_handler_code_(NULL),
- capacity_(0),
- length_(0),
- table_(NULL) {
-}
-
-
-MegamorphicCacheTable::~MegamorphicCacheTable() {
- free(table_);
-}
-
-
-RawMegamorphicCache* MegamorphicCacheTable::Lookup(const String& name,
+RawMegamorphicCache* MegamorphicCacheTable::Lookup(Isolate* isolate,
+ const String& name,
const Array& descriptor) {
- for (intptr_t i = 0; i < length_; ++i) {
- if ((table_[i].name == name.raw()) &&
- (table_[i].descriptor == descriptor.raw())) {
- return table_[i].cache;
+ ASSERT(name.IsSymbol());
+ // TODO(rmacnak): ASSERT(descriptor.IsCanonical());
+
+ // TODO(rmacnak): Make a proper hashtable a la symbol table.
+ GrowableObjectArray& table = GrowableObjectArray::Handle(
+ isolate->object_store()->megamorphic_cache_table());
+ if (table.IsNull()) {
+ table = GrowableObjectArray::New();
+ ASSERT((table.Length() % kEntrySize) == 0);
+ isolate->object_store()->set_megamorphic_cache_table(table);
+ } else {
+ for (intptr_t i = 0; i < table.Length(); i += kEntrySize) {
+ if ((table.At(i + kEntryNameOffset) == name.raw()) &&
+ (table.At(i + kEntryDescriptorOffset) == descriptor.raw())) {
+ return MegamorphicCache::RawCast(table.At(i + kEntryCacheOffset));
+ }
}
}
- if (length_ == capacity_) {
- capacity_ += kCapacityIncrement;
- table_ =
- reinterpret_cast<Entry*>(realloc(table_, capacity_ * sizeof(*table_)));
- }
-
- ASSERT(length_ < capacity_);
const MegamorphicCache& cache =
MegamorphicCache::Handle(MegamorphicCache::New());
- Entry entry = { name.raw(), descriptor.raw(), cache.raw() };
- table_[length_++] = entry;
+ table.Add(name);
+ table.Add(descriptor);
+ table.Add(cache);
+ ASSERT((table.Length() % kEntrySize) == 0);
return cache.raw();
}
-void MegamorphicCacheTable::InitMissHandler() {
+RawFunction* MegamorphicCacheTable::miss_handler(Isolate* isolate) {
+ ASSERT(isolate->object_store()->megamorphic_miss_function() !=
+ Function::null());
+ return isolate->object_store()->megamorphic_miss_function();
+}
+
+
+void MegamorphicCacheTable::InitMissHandler(Isolate* isolate) {
// The miss handler for a class ID not found in the table is invoked as a
// normal Dart function.
const Code& code =
@@ -69,37 +71,27 @@
0)); // No token position.
function.set_is_debuggable(false);
function.set_is_visible(false);
- miss_handler_code_ = code.raw();
- miss_handler_function_ = function.raw();
function.AttachCode(code);
+
+ isolate->object_store()->SetMegamorphicMissHandler(code, function);
}
-void MegamorphicCacheTable::VisitObjectPointers(ObjectPointerVisitor* v) {
- ASSERT(v != NULL);
- v->VisitPointer(reinterpret_cast<RawObject**>(&miss_handler_code_));
- v->VisitPointer(reinterpret_cast<RawObject**>(&miss_handler_function_));
- for (intptr_t i = 0; i < length_; ++i) {
- v->VisitPointer(reinterpret_cast<RawObject**>(&table_[i].name));
- v->VisitPointer(reinterpret_cast<RawObject**>(&table_[i].descriptor));
- v->VisitPointer(reinterpret_cast<RawObject**>(&table_[i].cache));
- }
-}
-
-
-void MegamorphicCacheTable::PrintSizes() {
+void MegamorphicCacheTable::PrintSizes(Isolate* isolate) {
StackZone zone(Thread::Current());
intptr_t size = 0;
MegamorphicCache& cache = MegamorphicCache::Handle();
Array& buckets = Array::Handle();
- for (intptr_t i = 0; i < length_; ++i) {
- cache = table_[i].cache;
+ const GrowableObjectArray& table = GrowableObjectArray::Handle(
+ isolate->object_store()->megamorphic_cache_table());
+ for (intptr_t i = 0; i < table.Length(); i += kEntrySize) {
+ cache ^= table.At(i + kEntryCacheOffset);
buckets = cache.buckets();
size += MegamorphicCache::InstanceSize();
size += Array::InstanceSize(buckets.Length());
}
OS::Print("%" Pd " megamorphic caches using %" Pd "KB.\n",
- length_, size / 1024);
+ table.Length() / kEntrySize, size / 1024);
}
} // namespace dart
diff --git a/runtime/vm/megamorphic_cache_table.h b/runtime/vm/megamorphic_cache_table.h
index eafb35b..c47d4d8 100644
--- a/runtime/vm/megamorphic_cache_table.h
+++ b/runtime/vm/megamorphic_cache_table.h
@@ -11,6 +11,7 @@
class Array;
class Function;
+class Isolate;
class ObjectPointerVisitor;
class RawArray;
class RawFunction;
@@ -19,36 +20,24 @@
class RawString;
class String;
-class MegamorphicCacheTable {
+class MegamorphicCacheTable : public AllStatic {
public:
- MegamorphicCacheTable();
- ~MegamorphicCacheTable();
+ static RawFunction* miss_handler(Isolate* isolate);
+ static void InitMissHandler(Isolate* isolate);
- RawFunction* miss_handler() const { return miss_handler_function_; }
- void InitMissHandler();
+ static RawMegamorphicCache* Lookup(Isolate* isolate,
+ const String& name,
+ const Array& descriptor);
- RawMegamorphicCache* Lookup(const String& name, const Array& descriptor);
-
- void VisitObjectPointers(ObjectPointerVisitor* visitor);
-
- void PrintSizes();
+ static void PrintSizes(Isolate* isolate);
private:
- struct Entry {
- RawString* name;
- RawArray* descriptor;
- RawMegamorphicCache* cache;
+ enum {
+ kEntryNameOffset = 0,
+ kEntryDescriptorOffset,
+ kEntryCacheOffset,
+ kEntrySize
};
-
- static const int kCapacityIncrement = 128;
-
- RawFunction* miss_handler_function_;
- RawCode* miss_handler_code_;
- intptr_t capacity_;
- intptr_t length_;
- Entry* table_;
-
- DISALLOW_COPY_AND_ASSIGN(MegamorphicCacheTable);
};
} // namespace dart
diff --git a/runtime/vm/message_handler.cc b/runtime/vm/message_handler.cc
index f832cbc..ef8a71e 100644
--- a/runtime/vm/message_handler.cc
+++ b/runtime/vm/message_handler.cc
@@ -24,6 +24,7 @@
}
virtual void Run() {
+ ASSERT(handler_ != NULL);
handler_->TaskCallback();
}
@@ -82,6 +83,7 @@
StartCallback start_callback,
EndCallback end_callback,
CallbackData data) {
+ bool task_running;
MonitorLocker ml(&monitor_);
if (FLAG_trace_isolates) {
OS::Print("[+] Starting message handler:\n"
@@ -94,12 +96,14 @@
end_callback_ = end_callback;
callback_data_ = data;
task_ = new MessageHandlerTask(this);
- pool_->Run(task_);
+ task_running = pool_->Run(task_);
+ ASSERT(task_running);
}
void MessageHandler::PostMessage(Message* message, bool before_events) {
Message::Priority saved_priority;
+ bool task_running = true;
{
MonitorLocker ml(&monitor_);
if (FLAG_trace_isolates) {
@@ -124,11 +128,13 @@
}
message = NULL; // Do not access message. May have been deleted.
- if (pool_ != NULL && task_ == NULL) {
+ if ((pool_ != NULL) && (task_ == NULL)) {
task_ = new MessageHandlerTask(this);
- pool_->Run(task_);
+ task_running = pool_->Run(task_);
}
}
+ ASSERT(task_running);
+
// Invoke any custom message notification.
MessageNotify(saved_priority);
}
@@ -149,7 +155,7 @@
// If isolate() returns NULL StartIsolateScope does nothing.
StartIsolateScope start_isolate(isolate());
- // ThreadInterrupter may have gone to sleep waiting while waiting for
+ // ThreadInterrupter may have gone to sleep while waiting for
// an isolate to start handling messages.
ThreadInterrupter::WakeUp();
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index ad351c8..5f373df 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -184,7 +184,6 @@
bool call_through_wrapper = false;
#ifdef USING_SIMULATOR
bool is_native_auto_setup_scope = false;
- intptr_t num_parameters = -1;
#endif
{
@@ -197,7 +196,6 @@
const Function& func = Function::Handle(code.function());
#ifdef USING_SIMULATOR
is_native_auto_setup_scope = func.IsNativeAutoSetupScope();
- num_parameters = func.NumParameters();
#endif
if (FLAG_trace_natives) {
@@ -225,7 +223,7 @@
Simulator::RedirectExternalReference(
reinterpret_cast<uword>(LinkNativeCall),
Simulator::kBootstrapNativeCall,
- func.NumParameters())));
+ NativeEntry::kNumArguments)));
#endif
ASSERT(current_trampoline ==
StubCode::CallBootstrapCFunction_entry()->EntryPoint());
@@ -248,7 +246,7 @@
patch_target_function = reinterpret_cast<NativeFunction>(
Simulator::RedirectExternalReference(
reinterpret_cast<uword>(patch_target_function),
- Simulator::kBootstrapNativeCall, num_parameters));
+ Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments));
}
#endif
diff --git a/runtime/vm/native_entry.h b/runtime/vm/native_entry.h
index cacf42d..4dd655d 100644
--- a/runtime/vm/native_entry.h
+++ b/runtime/vm/native_entry.h
@@ -102,6 +102,7 @@
// Helper class for resolving and handling native functions.
class NativeEntry : public AllStatic {
public:
+ static const intptr_t kNumArguments = 1;
static const intptr_t kNumCallWrapperArguments = 2;
// Resolve specified dart native function to the actual native entrypoint.
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 107ad5d..d95e73d 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1640,7 +1640,7 @@
void Object::Print() const {
- ISL_Print("%s\n", ToCString());
+ THR_Print("%s\n", ToCString());
}
@@ -1667,7 +1667,7 @@
if (!same_type) {
jsobj->AddProperty("_vmType", vm_type);
}
- if (!ref || IsInstance()) {
+ if (!ref || IsInstance() || IsNull()) {
// TODO(turnidge): Provide the type arguments here too?
const Class& cls = Class::Handle(this->clazz());
jsobj->AddProperty("class", cls);
@@ -2731,7 +2731,7 @@
virtual void ReportDeoptimization(const Code& code) {
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
Function& function = Function::Handle(code.function());
- ISL_Print("Deoptimizing %s because CHA optimized (%s).\n",
+ THR_Print("Deoptimizing %s because CHA optimized (%s).\n",
function.ToFullyQualifiedCString(),
cls_.ToCString());
}
@@ -2740,7 +2740,7 @@
virtual void ReportSwitchingCode(const Code& code) {
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
Function& function = Function::Handle(code.function());
- ISL_Print("Switching %s to unoptimized code because CHA invalid"
+ THR_Print("Switching %s to unoptimized code because CHA invalid"
" (%s)\n",
function.ToFullyQualifiedCString(),
cls_.ToCString());
@@ -2755,7 +2755,7 @@
void Class::RegisterCHACode(const Code& code) {
if (FLAG_trace_cha) {
- ISL_Print("RegisterCHACode %s class %s\n",
+ THR_Print("RegisterCHACode %s class %s\n",
Function::Handle(code.function()).ToQualifiedCString(), ToCString());
}
ASSERT(code.is_optimized());
@@ -4238,16 +4238,12 @@
const char* Class::ToCString() const {
- const char* format = "%s %sClass: %s";
const Library& lib = Library::Handle(library());
const char* library_name = lib.IsNull() ? "" : lib.ToCString();
const char* patch_prefix = is_patch() ? "Patch " : "";
const char* class_name = String::Handle(Name()).ToCString();
- intptr_t len =
- OS::SNPrint(NULL, 0, format, library_name, patch_prefix, class_name) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, library_name, patch_prefix, class_name);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "%s %sClass: %s", library_name, patch_prefix, class_name);
}
@@ -4415,12 +4411,9 @@
const char* UnresolvedClass::ToCString() const {
- const char* format = "unresolved class '%s'";
const char* cname = String::Handle(Name()).ToCString();
- intptr_t len = OS::SNPrint(NULL, 0, format, cname) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, cname);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "unresolved class '%s'", cname);
}
@@ -5167,14 +5160,12 @@
if (IsNull()) {
return "NULL TypeArguments";
}
- const char* format = "%s [%s]";
const char* prev_cstr = "TypeArguments:";
for (int i = 0; i < Length(); i++) {
const AbstractType& type_at = AbstractType::Handle(TypeAt(i));
const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString();
- intptr_t len = OS::SNPrint(NULL, 0, format, prev_cstr, type_cstr) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, prev_cstr, type_cstr);
+ char* chars = OS::SCreate(Thread::Current()->zone(),
+ "%s [%s]", prev_cstr, type_cstr);
prev_cstr = chars;
}
return prev_cstr;
@@ -5182,13 +5173,10 @@
const char* PatchClass::ToCString() const {
- const char* kFormat = "PatchClass for %s";
const Class& cls = Class::Handle(patched_class());
const char* cls_name = cls.ToCString();
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, cls_name) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, cls_name);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "PatchClass for %s", cls_name);
}
@@ -5257,7 +5245,7 @@
void Function::ClearCode() const {
- ASSERT(ic_data_array() == Array::null());
+ ASSERT((usage_counter() != 0) || (ic_data_array() == Array::null()));
StorePointer(&raw_ptr()->unoptimized_code_, Code::null());
SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code()));
}
@@ -5271,7 +5259,7 @@
const Code& current_code = Code::Handle(zone, CurrentCode());
if (FLAG_trace_deoptimization_verbose) {
- ISL_Print("Disabling optimized code: '%s' entry: %#" Px "\n",
+ THR_Print("Disabling optimized code: '%s' entry: %#" Px "\n",
ToFullyQualifiedCString(),
current_code.EntryPoint());
}
@@ -6965,10 +6953,10 @@
// to replace the old values.
// sed -i .bak -f /tmp/newkeys runtime/vm/method_recognizer.h
// sed -i .bak -f /tmp/newkeys runtime/vm/flow_graph_builder.h
- ISL_Print("s/V(%s, %d)/V(%s, %d)/\n",
+ THR_Print("s/V(%s, %d)/V(%s, %d)/\n",
prefix, fp, prefix, SourceFingerprint());
} else {
- ISL_Print("FP mismatch while recognizing method %s:"
+ THR_Print("FP mismatch while recognizing method %s:"
" expecting %d found %d\n",
ToFullyQualifiedCString(),
fp,
@@ -7022,14 +7010,10 @@
default:
UNREACHABLE();
}
- const char* kFormat = "Function '%s':%s%s%s%s.";
const char* function_name = String::Handle(name()).ToCString();
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name,
- static_str, abstract_str, kind_str, const_str) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, function_name,
- static_str, abstract_str, kind_str, const_str);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "Function '%s':%s%s%s%s.",
+ function_name, static_str, abstract_str, kind_str, const_str);
}
@@ -7409,15 +7393,11 @@
const char* kF0 = is_static() ? " static" : "";
const char* kF1 = is_final() ? " final" : "";
const char* kF2 = is_const() ? " const" : "";
- const char* kFormat = "Field <%s.%s>:%s%s%s";
const char* field_name = String::Handle(name()).ToCString();
const Class& cls = Class::Handle(owner());
const char* cls_name = String::Handle(cls.Name()).ToCString();
- intptr_t len =
- OS::SNPrint(NULL, 0, kFormat, cls_name, field_name, kF0, kF1, kF2) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, cls_name, field_name, kF0, kF1, kF2);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "Field <%s.%s>:%s%s%s", cls_name, field_name, kF0, kF1, kF2);
}
void Field::PrintJSONImpl(JSONStream* stream, bool ref) const {
@@ -7569,7 +7549,7 @@
virtual void ReportDeoptimization(const Code& code) {
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
Function& function = Function::Handle(code.function());
- ISL_Print("Deoptimizing %s because guard on field %s failed.\n",
+ THR_Print("Deoptimizing %s because guard on field %s failed.\n",
function.ToFullyQualifiedCString(), field_.ToCString());
}
}
@@ -7577,7 +7557,7 @@
virtual void ReportSwitchingCode(const Code& code) {
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
Function& function = Function::Handle(code.function());
- ISL_Print("Switching %s to unoptimized code because guard"
+ THR_Print("Switching %s to unoptimized code because guard"
" on field %s was violated.\n",
function.ToFullyQualifiedCString(),
field_.ToCString());
@@ -7616,11 +7596,13 @@
bool Field::HasPrecompiledInitializer() const {
- return raw_ptr()->initializer_.precompiled_->IsFunction();
+ return raw_ptr()->initializer_.precompiled_->IsHeapObject() &&
+ raw_ptr()->initializer_.precompiled_->IsFunction();
}
void Field::SetSavedInitialStaticValue(const Instance& value) const {
+ ASSERT(!HasPrecompiledInitializer());
StorePointer(&raw_ptr()->initializer_.saved_value_, value.raw());
}
@@ -7637,7 +7619,7 @@
}
ASSERT(value.IsNull() || value.IsInstance());
SetStaticValue(value.IsNull() ? Instance::null_instance()
- : Instance::Cast(value));
+ : Instance::Cast(value));
return;
} else if (StaticValue() == Object::transition_sentinel().raw()) {
SetStaticValue(Object::null_instance());
@@ -7755,7 +7737,7 @@
}
if (FLAG_trace_field_guards) {
- ISL_Print(" => %s\n", GuardedPropertiesAsCString());
+ THR_Print(" => %s\n", GuardedPropertiesAsCString());
}
return false;
@@ -7810,7 +7792,7 @@
}
if (FLAG_trace_field_guards) {
- ISL_Print("Store %s %s <- %s\n",
+ THR_Print("Store %s %s <- %s\n",
ToCString(),
GuardedPropertiesAsCString(),
value.ToCString());
@@ -7818,7 +7800,7 @@
if (UpdateGuardedCidAndLength(value)) {
if (FLAG_trace_field_guards) {
- ISL_Print(" => %s\n", GuardedPropertiesAsCString());
+ THR_Print(" => %s\n", GuardedPropertiesAsCString());
}
DeoptimizeDependentCode();
@@ -8620,7 +8602,8 @@
void Script::GetTokenLocation(intptr_t token_pos,
intptr_t* line,
- intptr_t* column) const {
+ intptr_t* column,
+ intptr_t* token_len) const {
ASSERT(line != NULL);
const TokenStream& tkns = TokenStream::Handle(tokens());
if (column == NULL) {
@@ -8642,6 +8625,13 @@
intptr_t relative_line = scanner.CurrentPosition().line;
*line = relative_line + line_offset();
*column = scanner.CurrentPosition().column;
+ if (token_len != NULL) {
+ if (scanner.current_token().literal != NULL) {
+ *token_len = scanner.current_token().literal->Length();
+ } else {
+ *token_len = 1;
+ }
+ }
// On the first line of the script we must add the column offset.
if (relative_line == 1) {
*column += col_offset();
@@ -10198,12 +10188,9 @@
const char* Library::ToCString() const {
- const char* kFormat = "Library:'%s'";
const String& name = String::Handle(url());
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, name.ToCString()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, name.ToCString());
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "Library:'%s'", name.ToCString());
}
@@ -10536,7 +10523,7 @@
virtual void ReportSwitchingCode(const Code& code) {
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
- ISL_Print("Prefix '%s': disabling %s code for %s function '%s'\n",
+ THR_Print("Prefix '%s': disabling %s code for %s function '%s'\n",
String::Handle(prefix_.name()).ToCString(),
code.is_optimized() ? "optimized" : "unoptimized",
CodePatcher::IsEntryPatched(code) ? "patched" : "unpatched",
@@ -10614,12 +10601,9 @@
const char* LibraryPrefix::ToCString() const {
- const char* kFormat = "LibraryPrefix:'%s'";
const String& prefix = String::Handle(name());
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, prefix.ToCString()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, prefix.ToCString());
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "LibraryPrefix:'%s'", prefix.ToCString());
}
@@ -10670,12 +10654,9 @@
const char* Namespace::ToCString() const {
- const char* kFormat = "Namespace for library '%s'";
const Library& lib = Library::Handle(library());
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, lib.ToCString()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, lib.ToCString());
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "Namespace for library '%s'", lib.ToCString());
}
@@ -11053,6 +11034,7 @@
jsarr.AddValue64(imm);
break;
case ObjectPool::kExternalLabel:
+ case ObjectPool::kNativeEntry:
imm = RawValueAt(i);
jsarr.AddValueF("0x%" Px, imm);
break;
@@ -11070,38 +11052,31 @@
return stub_name;
}
- RuntimeFunctionId rt_id = RuntimeEntry::RuntimeFunctionIdFromAddress(addr);
- if (rt_id != kNoRuntimeFunctionId) {
- return "runtime entry";
- }
-
- if (addr == NativeEntry::LinkNativeCallLabel().address()) {
- return "link native";
- }
-
return "UNKNOWN";
}
void ObjectPool::DebugPrint() const {
- ISL_Print("Object Pool: {\n");
+ THR_Print("Object Pool: {\n");
for (intptr_t i = 0; i < Length(); i++) {
intptr_t offset = OffsetFromIndex(i);
- ISL_Print(" %" Pd " PP+0x%" Px ": ", i, offset);
+ THR_Print(" %" Pd " PP+0x%" Px ": ", i, offset);
if (InfoAt(i) == kTaggedObject) {
RawObject* obj = ObjectAt(i);
- ISL_Print("0x%" Px " %s (obj)\n",
+ THR_Print("0x%" Px " %s (obj)\n",
reinterpret_cast<uword>(obj),
Object::Handle(obj).ToCString());
} else if (InfoAt(i) == kExternalLabel) {
uword addr = RawValueAt(i);
- ISL_Print("0x%" Px " (external label: %s)\n",
+ THR_Print("0x%" Px " (external label: %s)\n",
addr, DescribeExternalLabel(addr));
+ } else if (InfoAt(i) == kNativeEntry) {
+ THR_Print("0x%" Px " (native entry)\n", RawValueAt(i));
} else {
- ISL_Print("0x%" Px " (raw)\n", RawValueAt(i));
+ THR_Print("0x%" Px " (raw)\n", RawValueAt(i));
}
}
- ISL_Print("}\n");
+ THR_Print("}\n");
}
@@ -11183,27 +11158,26 @@
const int addr_width = (kBitsPerWord / 4) + 2;
// "*" in a printf format specifier tells it to read the field width from
// the printf argument list.
- ISL_Print("%-*s\tkind \tdeopt-id\ttok-ix\ttry-ix\n",
+ THR_Print("%-*s\tkind \tdeopt-id\ttok-ix\ttry-ix\n",
addr_width, "pc");
}
const char* PcDescriptors::ToCString() const {
+ // "*" in a printf format specifier tells it to read the field width from
+ // the printf argument list.
+#define FORMAT "%#-*" Px "\t%s\t%" Pd "\t\t%" Pd "\t%" Pd "\n"
if (Length() == 0) {
return "empty PcDescriptors\n";
}
// 4 bits per hex digit.
const int addr_width = kBitsPerWord / 4;
- // "*" in a printf format specifier tells it to read the field width from
- // the printf argument list.
- const char* kFormat =
- "%#-*" Px "\t%s\t%" Pd "\t\t%" Pd "\t%" Pd "\n";
// First compute the buffer size required.
intptr_t len = 1; // Trailing '\0'.
{
Iterator iter(*this, RawPcDescriptors::kAnyKind);
while (iter.MoveNext()) {
- len += OS::SNPrint(NULL, 0, kFormat, addr_width,
+ len += OS::SNPrint(NULL, 0, FORMAT, addr_width,
iter.PcOffset(),
KindAsStr(iter.Kind()),
iter.DeoptId(),
@@ -11217,7 +11191,7 @@
intptr_t index = 0;
Iterator iter(*this, RawPcDescriptors::kAnyKind);
while (iter.MoveNext()) {
- index += OS::SNPrint((buffer + index), (len - index), kFormat, addr_width,
+ index += OS::SNPrint((buffer + index), (len - index), FORMAT, addr_width,
iter.PcOffset(),
KindAsStr(iter.Kind()),
iter.DeoptId(),
@@ -11225,6 +11199,7 @@
iter.TryIndex());
}
return buffer;
+#undef FORMAT
}
@@ -11395,11 +11370,11 @@
const char* Stackmap::ToCString() const {
+#define FORMAT "%#x: "
if (IsNull()) {
return "{null}";
} else {
- const char* kFormat = "%#" Px ": ";
- intptr_t fixed_length = OS::SNPrint(NULL, 0, kFormat, PcOffset()) + 1;
+ intptr_t fixed_length = OS::SNPrint(NULL, 0, FORMAT, PcOffset()) + 1;
Thread* thread = Thread::Current();
// Guard against integer overflow in the computation of alloc_size.
//
@@ -11410,13 +11385,14 @@
}
intptr_t alloc_size = fixed_length + Length();
char* chars = thread->zone()->Alloc<char>(alloc_size);
- intptr_t index = OS::SNPrint(chars, alloc_size, kFormat, PcOffset());
+ intptr_t index = OS::SNPrint(chars, alloc_size, FORMAT, PcOffset());
for (intptr_t i = 0; i < Length(); i++) {
chars[index++] = IsObject(i) ? '1' : '0';
}
chars[index] = '\0';
return chars;
}
+#undef FORMAT
}
@@ -11747,6 +11723,8 @@
const char* ExceptionHandlers::ToCString() const {
+#define FORMAT1 "%" Pd " => %#x (%" Pd " types) (outer %d)\n"
+#define FORMAT2 " %d. %s\n"
if (num_entries() == 0) {
return "empty ExceptionHandlers\n";
}
@@ -11754,16 +11732,13 @@
Type& type = Type::Handle();
RawExceptionHandlers::HandlerInfo info;
// First compute the buffer size required.
- const char* kFormat = "%" Pd " => %#" Px " (%" Pd
- " types) (outer %" Pd ")\n";
- const char* kFormat2 = " %d. %s\n";
intptr_t len = 1; // Trailing '\0'.
for (intptr_t i = 0; i < num_entries(); i++) {
GetHandlerInfo(i, &info);
handled_types = GetHandledTypes(i);
const intptr_t num_types =
handled_types.IsNull() ? 0 : handled_types.Length();
- len += OS::SNPrint(NULL, 0, kFormat,
+ len += OS::SNPrint(NULL, 0, FORMAT1,
i,
info.handler_pc_offset,
num_types,
@@ -11771,7 +11746,7 @@
for (int k = 0; k < num_types; k++) {
type ^= handled_types.At(k);
ASSERT(!type.IsNull());
- len += OS::SNPrint(NULL, 0, kFormat2, k, type.ToCString());
+ len += OS::SNPrint(NULL, 0, FORMAT2, k, type.ToCString());
}
}
// Allocate the buffer.
@@ -11785,7 +11760,7 @@
handled_types.IsNull() ? 0 : handled_types.Length();
num_chars += OS::SNPrint((buffer + num_chars),
(len - num_chars),
- kFormat,
+ FORMAT1,
i,
info.handler_pc_offset,
num_types,
@@ -11794,10 +11769,12 @@
type ^= handled_types.At(k);
num_chars += OS::SNPrint((buffer + num_chars),
(len - num_chars),
- kFormat2, k, type.ToCString());
+ FORMAT2, k, type.ToCString());
}
}
return buffer;
+#undef FORMAT1
+#undef FORMAT2
}
@@ -11874,13 +11851,14 @@
const char* DeoptInfo::ToCString(const Array& deopt_table,
const TypedData& packed) {
+#define FORMAT "[%s]"
GrowableArray<DeoptInstr*> deopt_instrs;
Unpack(deopt_table, packed, &deopt_instrs);
// Compute the buffer size required.
intptr_t len = 1; // Trailing '\0'.
for (intptr_t i = 0; i < deopt_instrs.length(); i++) {
- len += OS::SNPrint(NULL, 0, "[%s]", deopt_instrs[i]->ToCString());
+ len += OS::SNPrint(NULL, 0, FORMAT, deopt_instrs[i]->ToCString());
}
// Allocate the buffer.
@@ -11891,11 +11869,12 @@
for (intptr_t i = 0; i < deopt_instrs.length(); i++) {
index += OS::SNPrint((buffer + index),
(len - index),
- "[%s]",
+ FORMAT,
deopt_instrs[i]->ToCString());
}
return buffer;
+#undef FORMAT
}
@@ -11914,16 +11893,12 @@
const char* ICData::ToCString() const {
- const char* kFormat = "ICData target:'%s' num-args: %" Pd
- " num-checks: %" Pd "";
const String& name = String::Handle(target_name());
const intptr_t num_args = NumArgsTested();
const intptr_t num_checks = NumberOfChecks();
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, name.ToCString(),
- num_args, num_checks) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, name.ToCString(), num_args, num_checks);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "ICData target:'%s' num-args: %" Pd " num-checks: %" Pd "",
+ name.ToCString(), num_args, num_checks);
}
@@ -13491,8 +13466,8 @@
void Code::DumpInlinedIntervals() const {
- LogBlock lb(Isolate::Current());
- ISL_Print("Inlined intervals:\n");
+ LogBlock lb;
+ THR_Print("Inlined intervals:\n");
const Array& intervals = Array::Handle(GetInlinedIntervals());
if (intervals.IsNull() || (intervals.Length() == 0)) return;
Smi& start = Smi::Handle();
@@ -13504,38 +13479,38 @@
ASSERT(!start.IsNull());
if (start.IsNull()) continue;
inlining_id ^= intervals.At(i + Code::kInlIntInliningId);
- ISL_Print(" %" Px " iid: %" Pd " ; ", start.Value(), inlining_id.Value());
+ THR_Print(" %" Px " iid: %" Pd " ; ", start.Value(), inlining_id.Value());
inlined_functions.Clear();
- ISL_Print("inlined: ");
+ THR_Print("inlined: ");
GetInlinedFunctionsAt(start.Value(), &inlined_functions);
for (intptr_t j = 0; j < inlined_functions.length(); j++) {
const char* name = inlined_functions[j]->ToQualifiedCString();
- ISL_Print(" %s <-", name);
+ THR_Print(" %s <-", name);
}
if (inlined_functions[inlined_functions.length() - 1]->raw() !=
inliner.raw()) {
- ISL_Print(" (ERROR, missing inliner)\n");
+ THR_Print(" (ERROR, missing inliner)\n");
} else {
- ISL_Print("\n");
+ THR_Print("\n");
}
}
- ISL_Print("Inlined ids:\n");
+ THR_Print("Inlined ids:\n");
const Array& id_map = Array::Handle(GetInlinedIdToFunction());
Function& function = Function::Handle();
for (intptr_t i = 0; i < id_map.Length(); i++) {
function ^= id_map.At(i);
if (!function.IsNull()) {
- ISL_Print(" %" Pd ": %s\n", i, function.ToQualifiedCString());
+ THR_Print(" %" Pd ": %s\n", i, function.ToQualifiedCString());
}
}
- ISL_Print("Caller Inlining Ids:\n");
+ THR_Print("Caller Inlining Ids:\n");
const Array& caller_map = Array::Handle(GetInlinedCallerIdMap());
Smi& smi = Smi::Handle();
for (intptr_t i = 0; i < caller_map.Length(); i++) {
smi ^= caller_map.At(i);
- ISL_Print(" iid: %" Pd " caller iid: %" Pd "\n", i, smi.Value());
+ THR_Print(" iid: %" Pd " caller iid: %" Pd "\n", i, smi.Value());
}
}
@@ -13582,7 +13557,7 @@
static void IndentN(int count) {
for (int i = 0; i < count; i++) {
- ISL_Print(" ");
+ THR_Print(" ");
}
}
@@ -13590,17 +13565,17 @@
void Context::Dump(int indent) const {
if (IsNull()) {
IndentN(indent);
- ISL_Print("Context@null\n");
+ THR_Print("Context@null\n");
return;
}
IndentN(indent);
- ISL_Print("Context@%p vars(%" Pd ") {\n", this->raw(), num_variables());
+ THR_Print("Context@%p vars(%" Pd ") {\n", this->raw(), num_variables());
Object& obj = Object::Handle();
for (intptr_t i = 0; i < num_variables(); i++) {
IndentN(indent + 2);
obj = At(i);
- ISL_Print("[%" Pd "] = %s\n", i, obj.ToCString());
+ THR_Print("[%" Pd "] = %s\n", i, obj.ToCString());
}
const Context& parent_ctx = Context::Handle(parent());
@@ -13608,7 +13583,7 @@
parent_ctx.Dump(indent + 2);
}
IndentN(indent);
- ISL_Print("}\n");
+ THR_Print("}\n");
}
@@ -13756,8 +13731,6 @@
const char* ContextScope::ToCString() const {
- const char* format =
- "%s\nvar %s token-pos %" Pd " ctx lvl %" Pd " index %" Pd "";
const char* prev_cstr = "ContextScope:";
String& name = String::Handle();
for (int i = 0; i < num_variables(); i++) {
@@ -13766,10 +13739,9 @@
intptr_t pos = TokenIndexAt(i);
intptr_t idx = ContextIndexAt(i);
intptr_t lvl = ContextLevelAt(i);
- intptr_t len =
- OS::SNPrint(NULL, 0, format, prev_cstr, cname, pos, lvl, idx) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, prev_cstr, cname, pos, lvl, idx);
+ char* chars = OS::SCreate(Thread::Current()->zone(),
+ "%s\nvar %s token-pos %" Pd " ctx lvl %" Pd " index %" Pd "",
+ prev_cstr, cname, pos, lvl, idx);
prev_cstr = chars;
}
return prev_cstr;
@@ -13825,9 +13797,8 @@
const intptr_t capacity = kInitialCapacity;
const Array& buckets = Array::Handle(
Array::New(kEntryLength * capacity, Heap::kOld));
- ASSERT(Isolate::Current()->megamorphic_cache_table()->miss_handler() != NULL);
const Function& handler = Function::Handle(
- Isolate::Current()->megamorphic_cache_table()->miss_handler());
+ MegamorphicCacheTable::miss_handler(Isolate::Current()));
for (intptr_t i = 0; i < capacity; ++i) {
SetEntry(buckets, i, smi_illegal_cid(), handler);
}
@@ -13848,7 +13819,7 @@
Array::Handle(Array::New(kEntryLength * new_capacity));
Function& target = Function::Handle(
- Isolate::Current()->megamorphic_cache_table()->miss_handler());
+ MegamorphicCacheTable::miss_handler(Isolate::Current()));
for (intptr_t i = 0; i < new_capacity; ++i) {
SetEntry(new_buckets, i, smi_illegal_cid(), target);
}
@@ -13890,7 +13861,7 @@
const char* MegamorphicCache::ToCString() const {
- return "";
+ return "MegamorphicCache";
}
@@ -14251,11 +14222,8 @@
if (!strtmp.IsError()) {
stack_str = strtmp.ToCString();
}
- const char* format = "Unhandled exception:\n%s\n%s";
- intptr_t len = OS::SNPrint(NULL, 0, format, exc_str, stack_str);
- char* chars = thread->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, exc_str, stack_str);
- return chars;
+ return OS::SCreate(thread->zone(),
+ "Unhandled exception:\n%s\n%s", exc_str, stack_str);
}
@@ -14416,11 +14384,8 @@
this->SetFieldAtOffset(field_offset, obj);
} else {
ASSERT(error_str != NULL);
- const char* kFormat = "field: %s\n";
- const intptr_t len =
- OS::SNPrint(NULL, 0, kFormat, obj.ToCString()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, obj.ToCString());
+ char* chars = OS::SCreate(Thread::Current()->zone(),
+ "field: %s\n", obj.ToCString());
*error_str = chars;
return false;
}
@@ -14744,7 +14709,6 @@
if (IsClosure()) {
return Closure::ToCString(*this);
}
- const char* kFormat = "Instance of '%s'";
const Class& cls = Class::Handle(clazz());
TypeArguments& type_arguments = TypeArguments::Handle();
const intptr_t num_type_arguments = cls.NumTypeArguments();
@@ -14754,11 +14718,8 @@
const Type& type =
Type::Handle(Type::New(cls, type_arguments, Scanner::kNoSourcePos));
const String& type_name = String::Handle(type.UserVisibleName());
- // Calculate the size of the string.
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, type_name.ToCString()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, type_name.ToCString());
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "Instance of '%s'", type_name.ToCString());
}
}
@@ -15930,29 +15891,18 @@
class_name = UnresolvedClass::Handle(unresolved_class()).ToCString();
}
if (type_arguments.IsNull()) {
- const char* format = "%sType: class '%s'";
- const intptr_t len =
- OS::SNPrint(NULL, 0, format, unresolved, class_name) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, unresolved, class_name);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "%sType: class '%s'", unresolved, class_name);
} else if (IsResolved() && IsFinalized() && IsRecursive()) {
- const char* format = "Type: (@%" Px " H%" Px ") class '%s', args:[%s]";
const intptr_t hash = Hash();
const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
- const intptr_t len =
- OS::SNPrint(NULL, 0, format, raw(), hash, class_name, args_cstr) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, raw(), hash, class_name, args_cstr);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "Type: (@%p H%" Px ") class '%s', args:[%s]",
+ raw(), hash, class_name, args_cstr);
} else {
- const char* format = "%sType: class '%s', args:[%s]";
const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
- const intptr_t len =
- OS::SNPrint(NULL, 0, format, unresolved, class_name, args_cstr) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, unresolved, class_name, args_cstr);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "%sType: class '%s', args:[%s]", unresolved, class_name, args_cstr);
}
}
@@ -16134,19 +16084,12 @@
type_class()).Name()).ToCString();
AbstractType& ref_type = AbstractType::Handle(type());
if (ref_type.IsFinalized()) {
- const char* format = "TypeRef: %s<...> (@%" Px " H%" Px ")";
const intptr_t hash = ref_type.Hash();
- const intptr_t len =
- OS::SNPrint(NULL, 0, format, type_cstr, ref_type.raw(), hash) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, type_cstr, ref_type.raw(), hash);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "TypeRef: %s<...> (@%p H%" Px ")", type_cstr, ref_type.raw(), hash);
} else {
- const char* format = "TypeRef: %s<...>";
- const intptr_t len = OS::SNPrint(NULL, 0, format, type_cstr) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, type_cstr);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "TypeRef: %s<...>", type_cstr);
}
}
@@ -17136,12 +17079,7 @@
const char* Smi::ToCString() const {
- const char* kFormat = "%ld";
- // Calculate the size of the string.
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, Value()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, Value());
- return chars;
+ return OS::SCreate(Thread::Current()->zone(), "%" Pd "", Value());
}
@@ -17267,12 +17205,7 @@
const char* Mint::ToCString() const {
- const char* kFormat = "%lld";
- // Calculate the size of the string.
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, value()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, value());
- return chars;
+ return OS::SCreate(Thread::Current()->zone(), "%" Pd64 "", value());
}
@@ -20120,11 +20053,8 @@
this->SetAt(i, obj);
} else {
ASSERT(error_str != NULL);
- const char* kFormat = "element at index %" Pd ": %s\n";
- const intptr_t len =
- OS::SNPrint(NULL, 0, kFormat, i, obj.ToCString()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, i, obj.ToCString());
+ char* chars = OS::SCreate(Thread::Current()->zone(),
+ "element at index %" Pd ": %s\n", i, obj.ToCString());
*error_str = chars;
return false;
}
@@ -20248,11 +20178,8 @@
if (IsNull()) {
return "_GrowableList NULL";
}
- const char* format = "Instance(length:%" Pd ") of '_GrowableList'";
- intptr_t len = OS::SNPrint(NULL, 0, format, Length()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, Length());
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "Instance(length:%" Pd ") of '_GrowableList'", Length());
}
@@ -20474,16 +20401,12 @@
const char* Float32x4::ToCString() const {
- const char* kFormat = "[%f, %f, %f, %f]";
float _x = x();
float _y = y();
float _z = z();
float _w = w();
- // Calculate the size of the string.
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, _x, _y, _z, _w) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, _x, _y, _z, _w);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "[%f, %f, %f, %f]", _x, _y, _z, _w);
}
@@ -20583,16 +20506,12 @@
const char* Int32x4::ToCString() const {
- const char* kFormat = "[%08x, %08x, %08x, %08x]";
int32_t _x = x();
int32_t _y = y();
int32_t _z = z();
int32_t _w = w();
- // Calculate the size of the string.
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, _x, _y, _z, _w) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, _x, _y, _z, _w);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "[%08x, %08x, %08x, %08x]", _x, _y, _z, _w);
}
@@ -20669,14 +20588,9 @@
const char* Float64x2::ToCString() const {
- const char* kFormat = "[%f, %f]";
double _x = x();
double _y = y();
- // Calculate the size of the string.
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, _x, _y) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, _x, _y);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(), "[%f, %f]", _x, _y);
}
@@ -20946,11 +20860,8 @@
const char* fun_sig = String::Handle(fun.UserVisibleSignature()).ToCString();
const char* from = is_implicit_closure ? " from " : "";
const char* fun_desc = is_implicit_closure ? fun.ToCString() : "";
- const char* format = "Closure: %s%s%s";
- intptr_t len = OS::SNPrint(NULL, 0, format, fun_sig, from, fun_desc) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, fun_sig, from, fun_desc);
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "Closure: %s%s%s", fun_sig, from, fun_desc);
}
@@ -21069,9 +20980,6 @@
const Function& function,
const Code& code,
intptr_t frame_index) {
- const char* kFormatWithCol = "#%-6d %s (%s:%d:%d)\n";
- const char* kFormatNoCol = "#%-6d %s (%s:%d)\n";
- const char* kFormatNoLine = "#%-6d %s (%s)\n";
const intptr_t token_pos = code.GetTokenIndexOfPC(pc);
const Script& script = Script::Handle(zone, function.script());
const String& function_name =
@@ -21086,36 +20994,22 @@
script.GetTokenLocation(token_pos, &line, NULL);
}
}
- intptr_t len = 0;
char* chars = NULL;
if (column >= 0) {
- len = OS::SNPrint(NULL, 0, kFormatWithCol,
- frame_index, function_name.ToCString(),
- url.ToCString(), line, column);
- chars = zone->Alloc<char>(len + 1);
- OS::SNPrint(chars, (len + 1), kFormatWithCol,
- frame_index,
- function_name.ToCString(),
- url.ToCString(), line, column);
+ chars = OS::SCreate(zone,
+ "#%-6" Pd " %s (%s:%" Pd ":%" Pd ")\n",
+ frame_index, function_name.ToCString(), url.ToCString(), line, column);
} else if (line >= 0) {
- len = OS::SNPrint(NULL, 0, kFormatNoCol,
- frame_index, function_name.ToCString(),
- url.ToCString(), line);
- chars = zone->Alloc<char>(len + 1);
- OS::SNPrint(chars, (len + 1), kFormatNoCol,
- frame_index, function_name.ToCString(),
- url.ToCString(), line);
+ chars = OS::SCreate(zone,
+ "#%-6" Pd " %s (%s:%" Pd ")\n",
+ frame_index, function_name.ToCString(), url.ToCString(), line);
} else {
- len = OS::SNPrint(NULL, 0, kFormatNoLine,
- frame_index, function_name.ToCString(),
- url.ToCString());
- chars = zone->Alloc<char>(len + 1);
- OS::SNPrint(chars, (len + 1), kFormatNoLine,
- frame_index, function_name.ToCString(),
- url.ToCString());
+ chars = OS::SCreate(zone,
+ "#%-6" Pd " %s (%s)\n",
+ frame_index, function_name.ToCString(), url.ToCString());
}
frame_strings->Add(chars);
- return len;
+ return strlen(chars);
}
@@ -21282,11 +21176,8 @@
const char* JSRegExp::ToCString() const {
const String& str = String::Handle(pattern());
- const char* format = "JSRegExp: pattern=%s flags=%s";
- intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags());
- char* chars = Thread::Current()->zone()->Alloc<char>(len + 1);
- OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags());
- return chars;
+ return OS::SCreate(Thread::Current()->zone(),
+ "JSRegExp: pattern=%s flags=%s", str.ToCString(), Flags());
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 9d1326e..75ec1f4 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1751,6 +1751,10 @@
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(RawPatchClass));
}
+ static bool IsInFullSnapshot(RawPatchClass* cls) {
+ NoSafepointScope no_safepoint;
+ return Class::IsInFullSnapshot(cls->ptr()->patched_class_);
+ }
static RawPatchClass* New(const Class& patched_class,
const Class& source_class);
@@ -3222,7 +3226,9 @@
void SetLocationOffset(intptr_t line_offset, intptr_t col_offset) const;
void GetTokenLocation(intptr_t token_pos,
- intptr_t* line, intptr_t* column) const;
+ intptr_t* line,
+ intptr_t* column,
+ intptr_t* token_len = NULL) const;
// Returns index of first and last token on the given line. Returns both
// indices < 0 if no token exists on or after the line. If a token exists
@@ -3604,6 +3610,7 @@
kTaggedObject,
kImmediate,
kExternalLabel,
+ kNativeEntry,
};
struct Entry {
@@ -8033,6 +8040,7 @@
ASSERT(is_static()); // Valid only for static dart fields.
StorePointer(&raw_ptr()->value_.static_value_, value.raw());
if (save_initial_value) {
+ ASSERT(!HasPrecompiledInitializer());
StorePointer(&raw_ptr()->initializer_.saved_value_, value.raw());
}
}
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 25469da..8c32a4a 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -88,7 +88,10 @@
empty_uint32_array_(TypedData::null()),
handle_message_function_(Function::null()),
library_load_error_table_(Array::null()),
- compile_time_constants_(Array::null()) {
+ compile_time_constants_(Array::null()),
+ megamorphic_cache_table_(GrowableObjectArray::null()),
+ megamorphic_miss_code_(Code::null()),
+ megamorphic_miss_function_(Function::null()) {
for (RawObject** current = from(); current <= to(); current++) {
ASSERT(*current == Object::null());
}
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index e22a096..fda986d 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -433,6 +433,21 @@
compile_time_constants_ = value.raw();
}
+ RawGrowableObjectArray* megamorphic_cache_table() const {
+ return megamorphic_cache_table_;
+ }
+ void set_megamorphic_cache_table(const GrowableObjectArray& value) {
+ megamorphic_cache_table_ = value.raw();
+ }
+ RawFunction* megamorphic_miss_function() const {
+ return megamorphic_miss_function_;
+ }
+ void SetMegamorphicMissHandler(const Code& code, const Function& func) {
+ // Hold onto the code so it is traced and not detached from the function.
+ megamorphic_miss_code_ = code.raw();
+ megamorphic_miss_function_ = func.raw();
+ }
+
// Visit all object pointers.
void VisitObjectPointers(ObjectPointerVisitor* visitor);
@@ -523,10 +538,17 @@
RawFunction* handle_message_function_;
RawArray* library_load_error_table_;
RawArray* compile_time_constants_;
- RawObject** to() {
+ RawObject** to_snapshot() {
return reinterpret_cast<RawObject**>(&compile_time_constants_);
}
+ RawGrowableObjectArray* megamorphic_cache_table_;
+ RawCode* megamorphic_miss_code_;
+ RawFunction* megamorphic_miss_function_;
+ RawObject** to() {
+ return reinterpret_cast<RawObject**>(&megamorphic_miss_function_);
+ }
+ friend class FullSnapshotWriter;
friend class SnapshotReader;
friend class VmIsolateSnapshotReader;
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 692a03b..c7ddd97 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -4229,40 +4229,6 @@
}
-// Elide a substring which starts with some prefix and ends with a ".
-//
-// This is used to remove non-deterministic or fragile substrings from
-// JSON output.
-//
-// For example:
-//
-// prefix = "classes"
-// in = "\"id\":\"classes/46\""
-//
-// Yields:
-//
-// out = "\"id\":\"\""
-//
-static void elideSubstring(const char* prefix, const char* in, char* out) {
- const char* pos = strstr(in, prefix);
- while (pos != NULL) {
- // Copy up to pos into the output buffer.
- while (in < pos) {
- *out++ = *in++;
- }
-
- // Skip to the close quote.
- in += strcspn(in, "\"");
- pos = strstr(in, prefix);
- }
- // Copy the remainder of in to out.
- while (*in != '\0') {
- *out++ = *in++;
- }
- *out = '\0';
-}
-
-
TEST_CASE(PrintJSONPrimitives) {
char buffer[1024];
Isolate* isolate = Isolate::Current();
@@ -4272,7 +4238,7 @@
JSONStream js;
Class& cls = Class::Handle(isolate->object_store()->bool_class());
cls.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
EXPECT_STREQ(
"{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"bool\"}",
buffer);
@@ -4285,7 +4251,7 @@
Function& func = Function::Handle(cls.LookupFunction(func_name));
ASSERT(!func.IsNull());
func.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
EXPECT_STREQ(
"{\"type\":\"@Function\",\"fixedId\":true,"
"\"id\":\"\",\"name\":\"toString\","
@@ -4300,7 +4266,7 @@
JSONStream js;
Library& lib = Library::Handle(isolate->object_store()->core_library());
lib.PrintJSON(&js, true);
- elideSubstring("libraries", js.ToCString(), buffer);
+ ElideJSONSubstring("libraries", js.ToCString(), buffer);
EXPECT_STREQ(
"{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
"\"name\":\"dart.core\",\"uri\":\"dart:core\"}",
@@ -4310,7 +4276,7 @@
{
JSONStream js;
Bool::True().PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"Bool\","
@@ -4326,8 +4292,8 @@
JSONStream js;
const Integer& smi = Integer::Handle(Integer::New(7));
smi.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
- elideSubstring("_Smi@", buffer, buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("_Smi@", buffer, buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"Smi\","
@@ -4344,9 +4310,9 @@
JSONStream js;
const Integer& smi = Integer::Handle(Integer::New(Mint::kMinValue));
smi.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
- elideSubstring("objects", buffer, buffer);
- elideSubstring("_Mint@", buffer, buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("objects", buffer, buffer);
+ ElideJSONSubstring("_Mint@", buffer, buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"Mint\","
@@ -4363,9 +4329,9 @@
String::Handle(String::New("44444444444444444444444444444444"));
const Integer& bigint = Integer::Handle(Integer::New(bigint_str));
bigint.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
- elideSubstring("objects", buffer, buffer);
- elideSubstring("_Bigint@", buffer, buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("objects", buffer, buffer);
+ ElideJSONSubstring("_Bigint@", buffer, buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"Bigint\","
@@ -4380,9 +4346,9 @@
JSONStream js;
const Double& dub = Double::Handle(Double::New(0.1234));
dub.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
- elideSubstring("objects", buffer, buffer);
- elideSubstring("_Double@", buffer, buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("objects", buffer, buffer);
+ ElideJSONSubstring("_Double@", buffer, buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"Double\","
@@ -4397,9 +4363,9 @@
JSONStream js;
const String& str = String::Handle(String::New("dw"));
str.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
- elideSubstring("objects", buffer, buffer);
- elideSubstring("_OneByteString@", buffer, buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("objects", buffer, buffer);
+ ElideJSONSubstring("_OneByteString@", buffer, buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"String\","
@@ -4414,9 +4380,9 @@
JSONStream js;
const Array& array = Array::Handle(Array::New(0));
array.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
- elideSubstring("objects", buffer, buffer);
- elideSubstring("_List@", buffer, buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("objects", buffer, buffer);
+ ElideJSONSubstring("_List@", buffer, buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"Array\","
@@ -4432,9 +4398,9 @@
const GrowableObjectArray& array =
GrowableObjectArray::Handle(GrowableObjectArray::New());
array.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
- elideSubstring("objects", buffer, buffer);
- elideSubstring("_GrowableList@", buffer, buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("objects", buffer, buffer);
+ ElideJSONSubstring("_GrowableList@", buffer, buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"GrowableObjectArray\","
@@ -4451,9 +4417,9 @@
const LinkedHashMap& array =
LinkedHashMap::Handle(LinkedHashMap::NewDefault());
array.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
- elideSubstring("objects", buffer, buffer);
- elideSubstring("_InternalLinkedHashMap@", buffer, buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("objects", buffer, buffer);
+ ElideJSONSubstring("_InternalLinkedHashMap@", buffer, buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"LinkedHashMap\","
@@ -4469,9 +4435,9 @@
JSONStream js;
Instance& tag = Instance::Handle(isolate->default_tag());
tag.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
- elideSubstring("objects", buffer, buffer);
- elideSubstring("_UserTag@", buffer, buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("objects", buffer, buffer);
+ ElideJSONSubstring("_UserTag@", buffer, buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"UserTag\","
@@ -4487,9 +4453,9 @@
JSONStream js;
Instance& type = Instance::Handle(isolate->object_store()->bool_type());
type.PrintJSON(&js, true);
- elideSubstring("classes", js.ToCString(), buffer);
- elideSubstring("objects", buffer, buffer);
- elideSubstring("_Type@", buffer, buffer);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("objects", buffer, buffer);
+ ElideJSONSubstring("_Type@", buffer, buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"Type\","
@@ -4505,14 +4471,17 @@
{
JSONStream js;
Object::null_object().PrintJSON(&js, true);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
EXPECT_STREQ(
"{\"type\":\"@Instance\","
"\"_vmType\":\"null\","
+ "\"class\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"Null\"},"
"\"kind\":\"Null\","
"\"fixedId\":true,"
"\"id\":\"objects\\/null\","
"\"valueAsString\":\"null\"}",
- js.ToCString());
+ buffer);
}
// Sentinel reference
{
@@ -4541,7 +4510,7 @@
JSONStream js;
LiteralToken& tok = LiteralToken::Handle(LiteralToken::New());
tok.PrintJSON(&js, true);
- elideSubstring("objects", js.ToCString(), buffer);
+ ElideJSONSubstring("objects", js.ToCString(), buffer);
EXPECT_STREQ(
"{\"type\":\"@Object\",\"_vmType\":\"LiteralToken\",\"id\":\"\"}",
buffer);
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index 60456e4..871b23e 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -14,6 +14,7 @@
// Forward declarations.
class Isolate;
+class Zone;
// Interface to the underlying OS platform.
class OS {
@@ -120,6 +121,13 @@
const char* format,
va_list args);
+ // Allocate a string and print formatted output into the buffer.
+ // Uses the zone for allocation if one if provided, and otherwise uses
+ // malloc.
+ static char* SCreate(Zone* zone, const char* format, ...)
+ PRINTF_ATTRIBUTE(2, 3);
+ static char* VSCreate(Zone* zone, const char* format, va_list args);
+
// Converts a C string which represents a valid dart integer into a 64 bit
// value.
// Returns false if it is unable to convert the string to a 64 bit value,
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 676e278..0966a52 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -44,12 +44,10 @@
if (file_open == NULL) {
return;
}
- const char* format = "/tmp/perf-%ld.map";
intptr_t pid = getpid();
- intptr_t len = OS::SNPrint(NULL, 0, format, pid);
- char* filename = new char[len + 1];
- OS::SNPrint(filename, len + 1, format, pid);
+ char* filename = OS::SCreate(NULL, "/tmp/perf-%" Pd ".map", pid);
out_file_ = (*file_open)(filename, true);
+ free(filename);
}
~PerfCodeObserver() {
@@ -73,12 +71,10 @@
if ((file_write == NULL) || (out_file_ == NULL)) {
return;
}
- const char* format = "%" Px " %" Px " %s%s\n";
const char* marker = optimized ? "*" : "";
- intptr_t len = OS::SNPrint(NULL, 0, format, base, size, marker, name);
- char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
- OS::SNPrint(buffer, len + 1, format, base, size, marker, name);
- (*file_write)(buffer, len, out_file_);
+ char* buffer = OS::SCreate(Thread::Current()->zone(),
+ "%" Px " %" Px " %s%s\n", base, size, marker, name);
+ (*file_write)(buffer, strlen(buffer), out_file_);
}
private:
@@ -107,10 +103,8 @@
// the prologue sequence is not the first instruction:
// <name>_entry is used for code preceding the prologue sequence.
// <name> for rest of the code (first instruction is prologue sequence).
- const char* kFormat = "%s_%s";
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, name, "entry");
- char* pname = Thread::Current()->zone()->Alloc<char>(len + 1);
- OS::SNPrint(pname, (len + 1), kFormat, name, "entry");
+ char* pname = OS::SCreate(Thread::Current()->zone(),
+ "%s_%s", name, "entry");
DebugInfo::RegisterSection(pname, base, size);
DebugInfo::RegisterSection(name,
(base + prologue_offset),
@@ -354,6 +348,39 @@
}
+char* OS::SCreate(Zone* zone, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ char* buffer = VSCreate(zone, format, args);
+ va_end(args);
+ return buffer;
+}
+
+
+char* OS::VSCreate(Zone* zone, const char* format, va_list args) {
+ // Measure.
+ va_list measure_args;
+ va_copy(measure_args, args);
+ intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+ va_end(measure_args);
+
+ char* buffer;
+ if (zone) {
+ buffer = zone->Alloc<char>(len + 1);
+ } else {
+ buffer = reinterpret_cast<char*>(malloc(len + 1));
+ }
+ ASSERT(buffer != NULL);
+
+ // Print.
+ va_list print_args;
+ va_copy(print_args, args);
+ VSNPrint(buffer, len + 1, format, print_args);
+ va_end(print_args);
+ return buffer;
+}
+
+
bool OS::StringToInt64(const char* str, int64_t* value) {
ASSERT(str != NULL && strlen(str) > 0 && value != NULL);
int32_t base = 10;
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 288db46..73fc0ea 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -49,13 +49,10 @@
if (file_open == NULL) {
return;
}
- const char* format = "/tmp/perf-%" Pd ".map";
intptr_t pid = getpid();
- intptr_t len = OS::SNPrint(NULL, 0, format, pid);
- char* filename = new char[len + 1];
- OS::SNPrint(filename, len + 1, format, pid);
+ char* filename = OS::SCreate(NULL, "/tmp/perf-%" Pd ".map", pid);
out_file_ = (*file_open)(filename, true);
- delete[] filename;
+ free(filename);
}
~PerfCodeObserver() {
@@ -79,14 +76,12 @@
if ((file_write == NULL) || (out_file_ == NULL)) {
return;
}
- const char* format = "%" Px " %" Px " %s%s\n";
const char* marker = optimized ? "*" : "";
- intptr_t len = OS::SNPrint(NULL, 0, format, base, size, marker, name);
- char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
- OS::SNPrint(buffer, len + 1, format, base, size, marker, name);
+ char* buffer = OS::SCreate(Thread::Current()->zone(),
+ "%" Px " %" Px " %s%s\n", base, size, marker, name);
{
MutexLocker ml(CodeObservers::mutex());
- (*file_write)(buffer, len, out_file_);
+ (*file_write)(buffer, strlen(buffer), out_file_);
}
}
@@ -116,10 +111,8 @@
// the prologue sequence is not the first instruction:
// <name>_entry is used for code preceding the prologue sequence.
// <name> for rest of the code (first instruction is prologue sequence).
- const char* kFormat = "%s_%s";
- intptr_t len = OS::SNPrint(NULL, 0, kFormat, name, "entry");
- char* pname = Thread::Current()->zone()->Alloc<char>(len + 1);
- OS::SNPrint(pname, (len + 1), kFormat, name, "entry");
+ char* pname = OS::SCreate(Thread::Current()->zone(),
+ "%s_%s", name, "entry");
DebugInfo::RegisterSection(pname, base, size);
DebugInfo::RegisterSection(name,
(base + prologue_offset),
@@ -245,12 +238,8 @@
};
const char* GenerateCodeName(const char* name, bool optimized) {
- const char* format = "%s%s";
const char* marker = optimized ? "*" : "";
- intptr_t len = OS::SNPrint(NULL, 0, format, marker, name);
- char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
- OS::SNPrint(buffer, len + 1, format, marker, name);
- return buffer;
+ return OS::SCreate(Thread::Current()->zone(), "%s%s", marker, name);
}
uint32_t GetElfMach() {
@@ -549,6 +538,39 @@
}
+char* OS::SCreate(Zone* zone, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ char* buffer = VSCreate(zone, format, args);
+ va_end(args);
+ return buffer;
+}
+
+
+char* OS::VSCreate(Zone* zone, const char* format, va_list args) {
+ // Measure.
+ va_list measure_args;
+ va_copy(measure_args, args);
+ intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+ va_end(measure_args);
+
+ char* buffer;
+ if (zone) {
+ buffer = zone->Alloc<char>(len + 1);
+ } else {
+ buffer = reinterpret_cast<char*>(malloc(len + 1));
+ }
+ ASSERT(buffer != NULL);
+
+ // Print.
+ va_list print_args;
+ va_copy(print_args, args);
+ VSNPrint(buffer, len + 1, format, print_args);
+ va_end(print_args);
+ return buffer;
+}
+
+
bool OS::StringToInt64(const char* str, int64_t* value) {
ASSERT(str != NULL && strlen(str) > 0 && value != NULL);
int32_t base = 10;
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index efdcd2b..ce4003e 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -18,6 +18,7 @@
#include "platform/utils.h"
#include "vm/isolate.h"
+#include "vm/zone.h"
namespace dart {
@@ -214,6 +215,39 @@
}
+char* OS::SCreate(Zone* zone, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ char* buffer = VSCreate(zone, format, args);
+ va_end(args);
+ return buffer;
+}
+
+
+char* OS::VSCreate(Zone* zone, const char* format, va_list args) {
+ // Measure.
+ va_list measure_args;
+ va_copy(measure_args, args);
+ intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+ va_end(measure_args);
+
+ char* buffer;
+ if (zone) {
+ buffer = zone->Alloc<char>(len + 1);
+ } else {
+ buffer = reinterpret_cast<char*>(malloc(len + 1));
+ }
+ ASSERT(buffer != NULL);
+
+ // Print.
+ va_list print_args;
+ va_copy(print_args, args);
+ VSNPrint(buffer, len + 1, format, print_args);
+ va_end(print_args);
+ return buffer;
+}
+
+
bool OS::StringToInt64(const char* str, int64_t* value) {
ASSERT(str != NULL && strlen(str) > 0 && value != NULL);
int32_t base = 10;
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index 36436aa..5d6a21e 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -29,6 +29,7 @@
public:
static ThreadLocalKey kUnsetThreadLocalKey;
static ThreadId kInvalidThreadId;
+ static ThreadJoinId kInvalidThreadJoinId;
typedef void (*ThreadStartFunction) (uword parameter);
typedef void (*ThreadDestructor) (void* parameter);
@@ -47,7 +48,11 @@
static void SetThreadLocal(ThreadLocalKey key, uword value);
static intptr_t GetMaxStackSize();
static ThreadId GetCurrentThreadId();
- static bool Join(ThreadId id);
+ static intptr_t CurrentCurrentThreadIdAsIntPtr() {
+ return ThreadIdToIntPtr(GetCurrentThreadId());
+ }
+ static ThreadJoinId GetCurrentThreadJoinId();
+ static void Join(ThreadJoinId id);
static intptr_t ThreadIdToIntPtr(ThreadId id);
static ThreadId ThreadIdFromIntPtr(intptr_t id);
static bool Compare(ThreadId a, ThreadId b);
diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc
index 377fd94..1f8de35 100644
--- a/runtime/vm/os_thread_android.cc
+++ b/runtime/vm/os_thread_android.cc
@@ -101,9 +101,6 @@
int result = pthread_attr_init(&attr);
RETURN_ON_PTHREAD_FAILURE(result);
- result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- RETURN_ON_PTHREAD_FAILURE(result);
-
result = pthread_attr_setstacksize(&attr, OSThread::GetMaxStackSize());
RETURN_ON_PTHREAD_FAILURE(result);
@@ -123,6 +120,7 @@
ThreadLocalKey OSThread::kUnsetThreadLocalKey =
static_cast<pthread_key_t>(-1);
ThreadId OSThread::kInvalidThreadId = static_cast<ThreadId>(0);
+ThreadJoinId OSThread::kInvalidThreadJoinId = static_cast<ThreadJoinId>(0);
ThreadLocalKey OSThread::CreateThreadLocal(ThreadDestructor destructor) {
pthread_key_t key = kUnsetThreadLocalKey;
@@ -158,8 +156,13 @@
}
-bool OSThread::Join(ThreadId id) {
- return false;
+ThreadJoinId OSThread::GetCurrentThreadJoinId() {
+ return pthread_self();
+}
+
+
+void OSThread::Join(ThreadJoinId id) {
+ ASSERT(pthread_join(id, NULL) == 0);
}
diff --git a/runtime/vm/os_thread_android.h b/runtime/vm/os_thread_android.h
index 5ac0f81..061066e 100644
--- a/runtime/vm/os_thread_android.h
+++ b/runtime/vm/os_thread_android.h
@@ -17,7 +17,8 @@
namespace dart {
typedef pthread_key_t ThreadLocalKey;
-typedef pthread_t ThreadId;
+typedef pid_t ThreadId;
+typedef pthread_t ThreadJoinId;
class ThreadInlineImpl {
private:
diff --git a/runtime/vm/os_thread_linux.cc b/runtime/vm/os_thread_linux.cc
index c99189b..f9bb9b5 100644
--- a/runtime/vm/os_thread_linux.cc
+++ b/runtime/vm/os_thread_linux.cc
@@ -102,9 +102,6 @@
int result = pthread_attr_init(&attr);
RETURN_ON_PTHREAD_FAILURE(result);
- result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- RETURN_ON_PTHREAD_FAILURE(result);
-
result = pthread_attr_setstacksize(&attr, OSThread::GetMaxStackSize());
RETURN_ON_PTHREAD_FAILURE(result);
@@ -124,6 +121,7 @@
ThreadLocalKey OSThread::kUnsetThreadLocalKey =
static_cast<pthread_key_t>(-1);
ThreadId OSThread::kInvalidThreadId = static_cast<ThreadId>(0);
+ThreadJoinId OSThread::kInvalidThreadJoinId = static_cast<ThreadJoinId>(0);
ThreadLocalKey OSThread::CreateThreadLocal(ThreadDestructor destructor) {
pthread_key_t key = kUnsetThreadLocalKey;
@@ -159,8 +157,13 @@
}
-bool OSThread::Join(ThreadId id) {
- return false;
+ThreadJoinId OSThread::GetCurrentThreadJoinId() {
+ return pthread_self();
+}
+
+
+void OSThread::Join(ThreadJoinId id) {
+ ASSERT(pthread_join(id, NULL) == 0);
}
diff --git a/runtime/vm/os_thread_linux.h b/runtime/vm/os_thread_linux.h
index 840b36e..5901214 100644
--- a/runtime/vm/os_thread_linux.h
+++ b/runtime/vm/os_thread_linux.h
@@ -18,6 +18,7 @@
typedef pthread_key_t ThreadLocalKey;
typedef pthread_t ThreadId;
+typedef pthread_t ThreadJoinId;
class ThreadInlineImpl {
private:
diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc
index bcac828..ffb94e9 100644
--- a/runtime/vm/os_thread_macos.cc
+++ b/runtime/vm/os_thread_macos.cc
@@ -94,9 +94,6 @@
int result = pthread_attr_init(&attr);
RETURN_ON_PTHREAD_FAILURE(result);
- result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- RETURN_ON_PTHREAD_FAILURE(result);
-
result = pthread_attr_setstacksize(&attr, OSThread::GetMaxStackSize());
RETURN_ON_PTHREAD_FAILURE(result);
@@ -116,6 +113,8 @@
ThreadLocalKey OSThread::kUnsetThreadLocalKey =
static_cast<pthread_key_t>(-1);
ThreadId OSThread::kInvalidThreadId = reinterpret_cast<ThreadId>(NULL);
+ThreadJoinId OSThread::kInvalidThreadJoinId =
+ reinterpret_cast<ThreadJoinId>(NULL);
ThreadLocalKey OSThread::CreateThreadLocal(ThreadDestructor destructor) {
pthread_key_t key = kUnsetThreadLocalKey;
@@ -151,8 +150,13 @@
}
-bool OSThread::Join(ThreadId id) {
- return false;
+ThreadJoinId OSThread::GetCurrentThreadJoinId() {
+ return pthread_self();
+}
+
+
+void OSThread::Join(ThreadJoinId id) {
+ ASSERT(pthread_join(id, NULL) == 0);
}
diff --git a/runtime/vm/os_thread_macos.h b/runtime/vm/os_thread_macos.h
index d2b9143..63b4f02 100644
--- a/runtime/vm/os_thread_macos.h
+++ b/runtime/vm/os_thread_macos.h
@@ -18,6 +18,7 @@
typedef pthread_key_t ThreadLocalKey;
typedef pthread_t ThreadId;
+typedef pthread_t ThreadJoinId;
class ThreadInlineImpl {
private:
diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc
index 12659491..7af1ce4 100644
--- a/runtime/vm/os_thread_win.cc
+++ b/runtime/vm/os_thread_win.cc
@@ -71,6 +71,7 @@
ThreadLocalKey OSThread::kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES;
ThreadId OSThread::kInvalidThreadId = 0;
+ThreadJoinId OSThread::kInvalidThreadJoinId = 0;
ThreadLocalKey OSThread::CreateThreadLocal(ThreadDestructor unused) {
ThreadLocalKey key = TlsAlloc();
@@ -101,14 +102,29 @@
}
-bool OSThread::Join(ThreadId id) {
+ThreadJoinId OSThread::GetCurrentThreadJoinId() {
+ return ::GetCurrentThreadId();
+}
+
+
+void OSThread::Join(ThreadJoinId id) {
HANDLE handle = OpenThread(SYNCHRONIZE, false, id);
- if (handle == INVALID_HANDLE_VALUE) {
- return false;
+
+ // TODO(zra): OSThread::Start() closes the handle to the thread. Thus, by the
+ // time we try to join the thread, its resources may have already been
+ // reclaimed, and joining will fail. This can be avoided in a couple of ways.
+ // First, GetCurrentThreadJoinId could call OpenThread and return a handle.
+ // This is bad, because each of those handles would have to be closed.
+ // Second OSThread could be refactored to no longer be AllStatic. Then the
+ // handle could be cached in the object by the Start method.
+ if (handle == NULL) {
+ ASSERT(GetLastError() == ERROR_INVALID_PARAMETER);
+ return;
}
+
DWORD res = WaitForSingleObject(handle, INFINITE);
CloseHandle(handle);
- return res == WAIT_OBJECT_0;
+ ASSERT(res == WAIT_OBJECT_0);
}
diff --git a/runtime/vm/os_thread_win.h b/runtime/vm/os_thread_win.h
index 27a5b14..5dc9b18 100644
--- a/runtime/vm/os_thread_win.h
+++ b/runtime/vm/os_thread_win.h
@@ -16,7 +16,7 @@
typedef DWORD ThreadLocalKey;
typedef DWORD ThreadId;
-
+typedef DWORD ThreadJoinId;
class ThreadInlineImpl {
private:
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index 1f66ad4..8513341 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -15,6 +15,7 @@
#include "platform/assert.h"
#include "vm/os_thread.h"
#include "vm/vtune.h"
+#include "vm/zone.h"
namespace dart {
@@ -271,6 +272,39 @@
}
+char* OS::SCreate(Zone* zone, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ char* buffer = VSCreate(zone, format, args);
+ va_end(args);
+ return buffer;
+}
+
+
+char* OS::VSCreate(Zone* zone, const char* format, va_list args) {
+ // Measure.
+ va_list measure_args;
+ va_copy(measure_args, args);
+ intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+ va_end(measure_args);
+
+ char* buffer;
+ if (zone) {
+ buffer = zone->Alloc<char>(len + 1);
+ } else {
+ buffer = reinterpret_cast<char*>(malloc(len + 1));
+ }
+ ASSERT(buffer != NULL);
+
+ // Print.
+ va_list print_args;
+ va_copy(print_args, args);
+ VSNPrint(buffer, len + 1, format, print_args);
+ va_end(print_args);
+ return buffer;
+}
+
+
bool OS::StringToInt64(const char* str, int64_t* value) {
ASSERT(str != NULL && strlen(str) > 0 && value != NULL);
int32_t base = 10;
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index d837830..23c45fd 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -9091,7 +9091,7 @@
ConsumeToken(); // Consume assert keyword.
ExpectToken(Token::kLPAREN);
const intptr_t condition_pos = TokenPos();
- if (!I->flags().asserts() && !I->flags().type_checks()) {
+ if (!I->flags().asserts()) {
SkipExpr();
ExpectToken(Token::kRPAREN);
return NULL;
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index c49e68c..426aa88 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -62,7 +62,7 @@
void Precompiler::DoCompileAll() {
- LogBlock lb(thread_);
+ LogBlock lb;
// Drop all existing code so we can use the presence of code as an indicator
// that we have already looked for the function's callees.
@@ -81,7 +81,7 @@
CleanUp();
if (FLAG_trace_precompiler) {
- ISL_Print("Precompiled %" Pd " functions, %" Pd " dynamic types,"
+ THR_Print("Precompiled %" Pd " functions, %" Pd " dynamic types,"
" %" Pd " dynamic selectors.\n Dropped %" Pd " functions.\n",
function_count_,
class_count_,
@@ -276,7 +276,7 @@
lib = Library::LookupLibrary(library_name);
if (lib.IsNull()) {
if (FLAG_trace_precompiler) {
- ISL_Print("WARNING: Missing %s\n", kExternallyCalled[i].library_);
+ THR_Print("WARNING: Missing %s\n", kExternallyCalled[i].library_);
}
continue;
}
@@ -287,7 +287,7 @@
cls = lib.LookupClassAllowPrivate(class_name);
if (cls.IsNull()) {
if (FLAG_trace_precompiler) {
- ISL_Print("WARNING: Missing %s %s\n",
+ THR_Print("WARNING: Missing %s %s\n",
kExternallyCalled[i].library_,
kExternallyCalled[i].class_);
}
@@ -300,7 +300,7 @@
if (func.IsNull()) {
if (FLAG_trace_precompiler) {
- ISL_Print("WARNING: Missing %s %s %s\n",
+ THR_Print("WARNING: Missing %s %s %s\n",
kExternallyCalled[i].library_,
kExternallyCalled[i].class_,
kExternallyCalled[i].function_);
@@ -350,7 +350,7 @@
function_count_++;
if (FLAG_trace_precompiler) {
- ISL_Print("Precompiling %" Pd " %s (%" Pd ", %s)\n",
+ THR_Print("Precompiling %" Pd " %s (%" Pd ", %s)\n",
function_count_,
function.ToLibNamePrefixedQualifiedCString(),
function.token_pos(),
@@ -439,11 +439,13 @@
AddClass(cls);
if (field.has_initializer()) {
- if (field.PrecompiledInitializer() != Function::null()) return;
+ if (field.HasPrecompiledInitializer()) return;
if (FLAG_trace_precompiler) {
- ISL_Print("Precompiling initializer for %s\n", field.ToCString());
+ THR_Print("Precompiling initializer for %s\n", field.ToCString());
}
+ ASSERT(Object::instructions_snapshot_buffer() == NULL);
+ field.SetStaticValue(Instance::Handle(field.SavedInitialStaticValue()));
Compiler::CompileStaticInitializer(field);
const Function& function =
@@ -474,7 +476,7 @@
changed_ = true;
if (FLAG_trace_precompiler) {
- ISL_Print("Enqueueing selector %" Pd " %s\n",
+ THR_Print("Enqueueing selector %" Pd " %s\n",
selector_count_,
selector.ToCString());
}
@@ -497,7 +499,7 @@
changed_ = true;
if (FLAG_trace_precompiler) {
- ISL_Print("Allocation %" Pd " %s\n", class_count_, cls.ToCString());
+ THR_Print("Allocation %" Pd " %s\n", class_count_, cls.ToCString());
}
const Class& superclass = Class::Handle(cls.SuperClass());
@@ -614,7 +616,7 @@
} else {
dropped_function_count_++;
if (FLAG_trace_precompiler) {
- ISL_Print("Precompilation dropping %s\n",
+ THR_Print("Precompilation dropping %s\n",
function.ToLibNamePrefixedQualifiedCString());
}
}
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index bacbfe8..2110436 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -763,8 +763,10 @@
RawObject** to_snapshot() {
return reinterpret_cast<RawObject**>(&ptr()->data_);
}
- // Fields below are not part of the snapshot.
RawArray* ic_data_array_; // ICData of unoptimized code.
+ RawObject** to_optimized_snapshot() {
+ return reinterpret_cast<RawObject**>(&ptr()->ic_data_array_);
+ }
RawObject** to_no_code() {
return reinterpret_cast<RawObject**>(&ptr()->ic_data_array_);
}
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 13791de..051855f 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/snapshot.h"
@@ -504,10 +505,7 @@
// Set all the object fields.
READ_OBJECT_FIELDS(cls, cls.raw()->from(), cls.raw()->to(), kAsReference);
- ASSERT(((kind == Snapshot::kScript) &&
- !Class::IsInFullSnapshot(cls.source_class())) ||
- (kind == Snapshot::kFull));
-
+ ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));
return cls.raw();
}
@@ -631,37 +629,45 @@
ASSERT(reader != NULL);
ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));
- // Allocate function object.
- Function& func = Function::ZoneHandle(
- reader->zone(), NEW_OBJECT(Function));
- reader->AddBackRef(object_id, &func, kIsDeserialized);
+ bool is_in_fullsnapshot = reader->Read<bool>();
+ if ((kind == Snapshot::kFull) || !is_in_fullsnapshot) {
+ // Allocate function object.
+ Function& func = Function::ZoneHandle(
+ reader->zone(), NEW_OBJECT(Function));
+ reader->AddBackRef(object_id, &func, kIsDeserialized);
- // Set all the non object fields.
- func.set_token_pos(reader->Read<int32_t>());
- func.set_end_token_pos(reader->Read<int32_t>());
- func.set_usage_counter(reader->Read<int32_t>());
- func.set_num_fixed_parameters(reader->Read<int16_t>());
- func.set_num_optional_parameters(reader->Read<int16_t>());
- func.set_deoptimization_counter(reader->Read<int16_t>());
- func.set_kind_tag(reader->Read<uint32_t>());
- func.set_optimized_instruction_count(reader->Read<uint16_t>());
- func.set_optimized_call_site_count(reader->Read<uint16_t>());
+ // Set all the non object fields.
+ func.set_token_pos(reader->Read<int32_t>());
+ func.set_end_token_pos(reader->Read<int32_t>());
+ func.set_usage_counter(reader->Read<int32_t>());
+ func.set_num_fixed_parameters(reader->Read<int16_t>());
+ func.set_num_optional_parameters(reader->Read<int16_t>());
+ func.set_deoptimization_counter(reader->Read<int16_t>());
+ func.set_kind_tag(reader->Read<uint32_t>());
+ func.set_optimized_instruction_count(reader->Read<uint16_t>());
+ func.set_optimized_call_site_count(reader->Read<uint16_t>());
- // Set all the object fields.
- READ_OBJECT_FIELDS(func,
- func.raw()->from(),
- reader->snapshot_code() ? func.raw()->to()
- : func.raw()->to_snapshot(),
- kAsReference);
-
- if (!reader->snapshot_code()) {
- // Initialize all fields that are not part of the snapshot.
- func.ClearICDataArray();
- func.ClearCode();
+ // Set all the object fields.
+ bool is_optimized = func.usage_counter() != 0;
+ RawObject** toobj = reader->snapshot_code() ? func.raw()->to() :
+ (is_optimized ? func.raw()->to_optimized_snapshot() :
+ func.raw()->to_snapshot());
+ READ_OBJECT_FIELDS(func,
+ func.raw()->from(), toobj,
+ kAsReference);
+ if (!reader->snapshot_code()) {
+ // Initialize all fields that are not part of the snapshot.
+ if (!is_optimized) {
+ func.ClearICDataArray();
+ }
+ func.ClearCode();
+ } else {
+ // TODO(rmacnak): Fix entry_point_.
+ }
+ return func.raw();
} else {
- // TODO(rmacnak): Fix entry_point_.
+ return reader->ReadFunctionId(object_id);
}
- return func.raw();
}
@@ -670,6 +676,17 @@
Snapshot::Kind kind) {
ASSERT(writer != NULL);
ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));
+ bool is_in_fullsnapshot = false;
+ bool owner_is_class = false;
+ if (kind == Snapshot::kScript) {
+ intptr_t tags = writer->GetObjectTags(ptr()->owner_);
+ intptr_t cid = ClassIdTag::decode(tags);
+ owner_is_class = (cid == kClassCid);
+ is_in_fullsnapshot = owner_is_class ?
+ Class::IsInFullSnapshot(reinterpret_cast<RawClass*>(ptr()->owner_)) :
+ PatchClass::IsInFullSnapshot(
+ reinterpret_cast<RawPatchClass*>(ptr()->owner_));
+ }
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
@@ -678,25 +695,38 @@
writer->WriteVMIsolateObject(kFunctionCid);
writer->WriteTags(writer->GetObjectTags(this));
- // Write out all the non object fields.
- writer->Write<int32_t>(ptr()->token_pos_);
- writer->Write<int32_t>(ptr()->end_token_pos_);
- if (Code::IsOptimized(ptr()->instructions_->ptr()->code_)) {
- writer->Write<int32_t>(FLAG_optimization_counter_threshold);
- } else {
- writer->Write<int32_t>(0);
- }
- writer->Write<int16_t>(ptr()->num_fixed_parameters_);
- writer->Write<int16_t>(ptr()->num_optional_parameters_);
- writer->Write<int16_t>(ptr()->deoptimization_counter_);
- writer->Write<uint32_t>(ptr()->kind_tag_);
- writer->Write<uint16_t>(ptr()->optimized_instruction_count_);
- writer->Write<uint16_t>(ptr()->optimized_call_site_count_);
+ // Write out the boolean is_in_fullsnapshot first as this will
+ // help the reader decide how the rest of the information needs
+ // to be interpreted.
+ writer->Write<bool>(is_in_fullsnapshot);
- // Write out all the object pointer fields.
- SnapshotWriterVisitor visitor(writer);
- visitor.VisitPointers(from(), writer->snapshot_code() ? to()
- : to_snapshot());
+ if (kind == Snapshot::kFull || !is_in_fullsnapshot) {
+ bool is_optimized = Code::IsOptimized(ptr()->instructions_->ptr()->code_);
+
+ // Write out all the non object fields.
+ writer->Write<int32_t>(ptr()->token_pos_);
+ writer->Write<int32_t>(ptr()->end_token_pos_);
+ if (is_optimized) {
+ writer->Write<int32_t>(FLAG_optimization_counter_threshold);
+ } else {
+ writer->Write<int32_t>(0);
+ }
+ writer->Write<int16_t>(ptr()->num_fixed_parameters_);
+ writer->Write<int16_t>(ptr()->num_optional_parameters_);
+ writer->Write<int16_t>(ptr()->deoptimization_counter_);
+ writer->Write<uint32_t>(ptr()->kind_tag_);
+ writer->Write<uint16_t>(ptr()->optimized_instruction_count_);
+ writer->Write<uint16_t>(ptr()->optimized_call_site_count_);
+
+ // Write out all the object pointer fields.
+ RawObject** toobj =
+ writer->snapshot_code() ? to() :
+ (is_optimized ? to_optimized_snapshot() : to_snapshot());
+ SnapshotWriterVisitor visitor(writer);
+ visitor.VisitPointers(from(), toobj);
+ } else {
+ writer->WriteFunctionId(this, owner_is_class);
+ }
}
@@ -755,15 +785,25 @@
writer->WriteObjectImpl(ptr()->type_, kAsReference);
// Write out the initial static value or field offset.
if (Field::StaticBit::decode(ptr()->kind_bits_)) {
- // For static field we write out the initial static value.
- writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference);
+ if (writer->snapshot_code()) {
+ // For precompiled static fields, the value was already reset and
+ // initializer_ now contains a Function.
+ writer->WriteObjectImpl(ptr()->value_.static_value_, kAsReference);
+ } else {
+ // Otherwise, for static fields we write out the initial static value.
+ writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference);
+ }
} else {
writer->WriteObjectImpl(ptr()->value_.offset_, kAsReference);
}
// Write out the dependent code.
writer->WriteObjectImpl(ptr()->dependent_code_, kAsReference);
- // Write out the initializer value.
- writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference);
+ // Write out the initializer function or saved initial value.
+ if (writer->snapshot_code()) {
+ writer->WriteObjectImpl(ptr()->initializer_.precompiled_, kAsReference);
+ } else {
+ writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference);
+ }
// Write out the guarded list length.
writer->WriteObjectImpl(ptr()->guarded_list_length_, kAsReference);
}
@@ -1296,6 +1336,16 @@
result.SetRawValueAt(i, raw_value);
break;
}
+ case ObjectPool::kNativeEntry: {
+ // Read nothing. Initialize with the lazy link entry.
+ uword entry = reinterpret_cast<uword>(&NativeEntry::LinkNativeCall);
+#if defined(USING_SIMULATOR)
+ entry = Simulator::RedirectExternalReference(
+ entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
+#endif
+ result.SetRawValueAt(i, entry);
+ break;
+ }
default:
UNREACHABLE();
}
@@ -1339,6 +1389,9 @@
// TODO(rmacnak): Write symbolically.
writer->Write<intptr_t>(entry.raw_value_);
break;
+ case ObjectPool::kNativeEntry:
+ // Write nothing. Will initialize with the lazy link entry.
+ break;
default:
UNREACHABLE();
}
@@ -1665,8 +1718,7 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- ASSERT(reader->snapshot_code());
- ASSERT(kind == Snapshot::kFull);
+ ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));
ICData& result = ICData::ZoneHandle(reader->zone(), NEW_OBJECT(ICData));
reader->AddBackRef(object_id, &result, kIsDeserialized);
@@ -1686,8 +1738,7 @@
void RawICData::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
- ASSERT(writer->snapshot_code());
- ASSERT(kind == Snapshot::kFull);
+ ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index c0959e3..4cb379e 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -1354,6 +1354,29 @@
}
+static RawObject* LookupHeapObjectMessage(Isolate* isolate,
+ char** parts, int num_parts) {
+ if (num_parts != 2) {
+ return Object::sentinel().raw();
+ }
+ uword message_id = 0;
+ if (!GetUnsignedIntegerId(parts[1], &message_id, 16)) {
+ return Object::sentinel().raw();
+ }
+ MessageHandler::AcquiredQueues aq;
+ isolate->message_handler()->AcquireQueues(&aq);
+ Message* message = aq.queue()->FindMessageById(message_id);
+ if (message == NULL) {
+ // The user may try to load an expired message.
+ return Object::sentinel().raw();
+ }
+ MessageSnapshotReader reader(message->data(),
+ message->len(),
+ Thread::Current());
+ return reader.ReadObject();
+}
+
+
static RawObject* LookupHeapObject(Isolate* isolate,
const char* id_original,
ObjectIdRing::LookupResult* result) {
@@ -1406,6 +1429,8 @@
return LookupHeapObjectTypeArguments(isolate, parts, num_parts);
} else if (strcmp(parts[0], "code") == 0) {
return LookupHeapObjectCode(isolate, parts, num_parts);
+ } else if (strcmp(parts[0], "messages") == 0) {
+ return LookupHeapObjectMessage(isolate, parts, num_parts);
}
// Not found.
@@ -1443,7 +1468,10 @@
}
-static Breakpoint* LookupBreakpoint(Isolate* isolate, const char* id) {
+static Breakpoint* LookupBreakpoint(Isolate* isolate,
+ const char* id,
+ ObjectIdRing::LookupResult* result) {
+ *result = ObjectIdRing::kInvalid;
size_t end_pos = strcspn(id, "/");
if (end_pos == strlen(id)) {
return NULL;
@@ -1454,46 +1482,20 @@
Breakpoint* bpt = NULL;
if (GetIntegerId(rest, &bpt_id)) {
bpt = isolate->debugger()->GetBreakpointById(bpt_id);
+ if (bpt) {
+ *result = ObjectIdRing::kValid;
+ return bpt;
+ }
+ if (bpt_id < isolate->debugger()->limitBreakpointId()) {
+ *result = ObjectIdRing::kCollected;
+ return NULL;
+ }
}
- return bpt;
}
return NULL;
}
-// Scans |isolate|'s message queue looking for a message with |id|.
-// If found, the message is printed to |js| and true is returned.
-// If not found, false is returned.
-static bool PrintMessage(JSONStream* js, Isolate* isolate, const char* id) {
- size_t end_pos = strcspn(id, "/");
- if (end_pos == strlen(id)) {
- return false;
- }
- const char* rest = id + end_pos + 1; // +1 for '/'.
- if (strncmp("messages", id, end_pos) == 0) {
- uword message_id = 0;
- if (GetUnsignedIntegerId(rest, &message_id, 16)) {
- MessageHandler::AcquiredQueues aq;
- isolate->message_handler()->AcquireQueues(&aq);
- Message* message = aq.queue()->FindMessageById(message_id);
- if (message == NULL) {
- // The user may try to load an expired message, so we treat
- // unrecognized ids as if they are expired.
- PrintSentinel(js, kExpiredSentinel);
- return true;
- }
- MessageSnapshotReader reader(message->data(),
- message->len(),
- Thread::Current());
- const Object& msg_obj = Object::Handle(reader.ReadObject());
- msg_obj.PrintJSON(js);
- return true;
- }
- }
- return false;
-}
-
-
static bool PrintInboundReferences(Isolate* isolate,
Object* target,
intptr_t limit,
@@ -2041,8 +2043,10 @@
static const MethodParameter* add_breakpoint_params[] = {
ISOLATE_PARAMETER,
- new IdParameter("scriptId", true),
+ new IdParameter("scriptId", false),
+ new IdParameter("scriptUri", false),
new UIntParameter("line", true),
+ new UIntParameter("column", false),
NULL,
};
@@ -2050,16 +2054,41 @@
static bool AddBreakpoint(Isolate* isolate, JSONStream* js) {
const char* line_param = js->LookupParam("line");
intptr_t line = UIntParameter::Parse(line_param);
- const char* script_id = js->LookupParam("scriptId");
- Object& obj = Object::Handle(LookupHeapObject(isolate, script_id, NULL));
- if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
- PrintInvalidParamError(js, "scriptId");
+ const char* col_param = js->LookupParam("column");
+ intptr_t col = -1;
+ if (col_param != NULL) {
+ col = UIntParameter::Parse(col_param);
+ if (col == 0) {
+ // Column number is 1-based.
+ PrintInvalidParamError(js, "column");
+ return true;
+ }
+ }
+ const char* script_id_param = js->LookupParam("scriptId");
+ const char* script_uri_param = js->LookupParam("scriptUri");
+ if (script_id_param == NULL && script_uri_param == NULL) {
+ js->PrintError(kInvalidParams,
+ "%s expects the 'scriptId' or the 'scriptUri' parameter",
+ js->method());
return true;
}
- const Script& script = Script::Cast(obj);
- const String& script_url = String::Handle(script.url());
- Breakpoint* bpt =
- isolate->debugger()->SetBreakpointAtLine(script_url, line);
+ String& script_uri = String::Handle(isolate);
+ if (script_id_param != NULL) {
+ Object& obj =
+ Object::Handle(LookupHeapObject(isolate, script_id_param, NULL));
+ if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
+ PrintInvalidParamError(js, "scriptId");
+ return true;
+ }
+ const Script& script = Script::Cast(obj);
+ script_uri = script.url();
+ }
+ if (script_uri_param != NULL) {
+ script_uri = String::New(script_uri_param);
+ }
+ ASSERT(!script_uri.IsNull());
+ Breakpoint* bpt = NULL;
+ bpt = isolate->debugger()->SetBreakpointAtLineCol(script_uri, line, col);
if (bpt == NULL) {
js->PrintError(kCannotAddBreakpoint,
"%s: Cannot add breakpoint at line '%s'",
@@ -2139,7 +2168,10 @@
return true;
}
const char* bpt_id = js->LookupParam("breakpointId");
- Breakpoint* bpt = LookupBreakpoint(isolate, bpt_id);
+ ObjectIdRing::LookupResult lookup_result;
+ Breakpoint* bpt = LookupBreakpoint(isolate, bpt_id, &lookup_result);
+ // TODO(turnidge): Should we return a different error for bpts whic
+ // have been already removed?
if (bpt == NULL) {
PrintInvalidParamError(js, "breakpointId");
return true;
@@ -2794,13 +2826,12 @@
}
// Handle non-heap objects.
- Breakpoint* bpt = LookupBreakpoint(isolate, id);
+ Breakpoint* bpt = LookupBreakpoint(isolate, id, &lookup_result);
if (bpt != NULL) {
bpt->PrintJSON(js);
return true;
- }
-
- if (PrintMessage(js, isolate, id)) {
+ } else if (lookup_result == ObjectIdRing::kCollected) {
+ PrintSentinel(js, kCollectedSentinel);
return true;
}
@@ -2866,8 +2897,8 @@
static bool GetVersion(Isolate* isolate, JSONStream* js) {
JSONObject jsobj(js);
jsobj.AddProperty("type", "Version");
- jsobj.AddProperty("major", static_cast<intptr_t>(2));
- jsobj.AddProperty("minor", static_cast<intptr_t>(1));
+ jsobj.AddProperty("major", static_cast<intptr_t>(3));
+ jsobj.AddProperty("minor", static_cast<intptr_t>(0));
jsobj.AddProperty("_privateMajor", static_cast<intptr_t>(0));
jsobj.AddProperty("_privateMinor", static_cast<intptr_t>(0));
return true;
diff --git a/runtime/vm/service/client.dart b/runtime/vm/service/client.dart
index 1ac2a23..279b424 100644
--- a/runtime/vm/service/client.dart
+++ b/runtime/vm/service/client.dart
@@ -15,6 +15,9 @@
service._addClient(this);
}
+ // Disconnects the client.
+ disconnect();
+
/// When implementing, call [close] when the network connection closes.
void close() {
service._removeClient(this);
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index c18f390..b390460 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 2.0
+# Dart VM Service Protocol 3.0
> Please post feedback to the [observatory-discuss group][discuss-list]
-This document describes of _version 2.0_ of the Dart VM Service Protocol. This
+This document describes of _version 3.0_ of the Dart VM Service Protocol. This
protocol is used to communicate with a running Dart Virtual Machine.
To use the Service Protocol, start the VM with the *--observe* flag.
@@ -68,6 +68,7 @@
- [Message](#message)
- [Null](#null)
- [Object](#object)
+ - [Response](#response)
- [Sentinel](#sentinel)
- [SentinelKind](#sentinelkind)
- [Script](#script)
@@ -76,7 +77,7 @@
- [StepOption](#stepoption)
- [Success](#success)
- [TypeArguments](#typearguments)
- - [Response](#response)
+ - [UresolvedSourceLocation](#unresolvedsourcelocation)
- [Version](#version)
- [VM](#vm)
- [Revision History](#revision-history)
@@ -109,7 +110,7 @@
"jsonrpc": "2.0",
"result": {
"type": "Version",
- "major": 2,
+ "major": 3,
"minor": 0
}
"id": "1"
@@ -299,7 +300,7 @@
```
"result": {
"type": "Version",
- "major": 2,
+ "major": 3,
"minor": 0
}
```
@@ -371,13 +372,29 @@
```
Breakpoint addBreakpoint(string isolateId,
- string scriptId,
- int line)
+ string scriptId [optional],
+ string scriptUri [optional],
+ int line,
+ int column [optional])
```
The _addBreakpoint_ RPC is used to add a breakpoint at a specific line
of some script.
+The _scriptId_ or _scriptUri_ parameter is used to specify the target
+script. One of these two parameters must always be provided.
+
+The _line_ parameter is used to specify the target line for the
+breakpoint. If there are multiple possible breakpoints on the target
+line, then the VM will place the breakpoint at the location which
+would execute soonest. If it is not possible to set a breakpoint at
+the target line, the breakpoint will be added at the next possible
+breakpoint location within the same function.
+
+The _column_ parameter may be optionally specified. This is useful
+for targeting a specific breakpoint on a line with multiple possible
+breakpoints.
+
If no breakpoint is possible at that line, the _102_ (Cannot add
breakpoint) error code is returned.
@@ -481,10 +498,13 @@
If _objectId_ is a temporary id which has expired, then then _Expired_
[Sentinel](#sentinel) is returned.
-If _objectId_ refers to an object which has been collected by the VM's
+If _objectId_ refers to a heap object which has been collected by the VM's
garbage collector, then the _Collected_ [Sentinel](#sentinel) is
returned.
+If _objectId_ refers to a non-heap object which has been deleted, then
+the _Collected_ [Sentinel](#sentinel) is returned.
+
If the object handle has not expired and the object has not been
collected, then an [Object](#object) will be returned.
@@ -757,14 +777,25 @@
```
class Breakpoint extends Object {
+ // A number identifying this breakpoint to the user.
int breakpointNumber;
+
+ // Has this breakpoint been assigned to a specific program location?
bool resolved;
- SourceLocation location;
+
+ // SourceLocation when breakpoint is resolved, UnresolvedSourceLocation
+ // when a breakpoint is not resolved.
+ SourceLocation|UnresolvedSourceLocation location;
}
```
A _Breakpoint_ describes a debugger breakpoint.
+A breakpoint is _resolved_ when it has been assigned to a specific
+program location. A breakpoint my remain unresolved when it is in
+code which has not yet been compiled or in a library which has not
+been loaded (i.e. a deferred library).
+
### Class
```
@@ -868,14 +899,14 @@
### Context
```
-class @Context {
+class @Context extends @Object {
// The number of variables in this context.
int length;
}
```
```
-class Context {
+class Context extends Object {
// The number of variables in this context.
int length;
@@ -887,6 +918,9 @@
}
```
+A _Context_ is a data structure which holds the captured variables for
+some closure.
+
### ContextElement
```
@@ -1293,9 +1327,11 @@
// The pattern of a RegExp instance.
//
+ // The pattern is always an instance of kind String.
+ //
// Provided for instance kinds:
// RegExp
- String pattern [optional];
+ @Instance pattern [optional];
}
```
@@ -1378,6 +1414,8 @@
// The bytes of a TypedData instance.
//
+ // The data is provided as a Base64 encoded string.
+ //
// Provided for instance kinds:
// Uint8ClampedList
// Uint8List
@@ -1393,7 +1431,7 @@
// Int32x4List
// Float32x4List
// Float64x2List
- int[] bytes [optional];
+ string bytes [optional];
// The function associated with a Closure instance.
//
@@ -1405,7 +1443,7 @@
//
// Provided for instance kinds:
// Closure
- @Function closureContext [optional];
+ @Context closureContext [optional];
// The referent of a MirrorReference instance.
//
@@ -1715,15 +1753,32 @@
```
class Message extends Response {
+ // The index in the isolate's message queue. The 0th message being the next
+ // message to be processed.
int index;
+
+ // An advisory name describing this message.
string name;
+
+ // An instance id for the decoded message. This id can be passed to other
+ // RPCs, for example, getObject or evaluate.
string messageObjectId;
+
+ // The size (bytes) of the encoded message.
int size;
+
+ // A reference to the function that will be invoked to handle this message.
@Function handler [optional];
+
+ // The source location of handler.
SourceLocation location [optional];
}
```
+A _Message_ provides information about a pending isolate message and the
+function that will be invoked to handle it.
+
+
### Null
```
@@ -1787,6 +1842,21 @@
An _Object_ is a persistent object that is owned by some isolate.
+### Response
+
+```
+class Response {
+ // Every response returned by the VM Service has the
+ // type property. This allows the client distinguish
+ // between different kinds of responses.
+ string type;
+}
+```
+
+Every non-error response returned by the Service Protocol extends _Response_.
+By using the _type_ property, the client can determine which [type](#types)
+of response has been provided.
+
### Sentinel
```
@@ -1955,20 +2025,42 @@
A _TypeArguments_ object represents the type argument vector for some
instantiated generic type.
-### Response
+### UnresolvedSourceLocation
```
-class Response {
- // Every response returned by the VM Service has the
- // type property. This allows the client distinguish
- // between different kinds of responses.
- string type;
+class UnresolvedSourceLocation extends Response {
+ // The script containing the source location if the script has been loaded.
+ @Script script [optional];
+
+ // The uri of the script containing the source location if the script
+ // has yet to be loaded.
+ string scriptUri [optional];
+
+ // An approximate token position for the source location. This may
+ // change when the location is resolved.
+ int tokenPos [optional];
+
+ // An approximate line number for the source location. This may
+ // change when the location is resolved.
+ int line [optional];
+
+ // An approximate column number for the source location. This may
+ // change when the location is resolved.
+ int column [optional];
+
}
```
-Every non-error response returned by the Service Protocol extends _Response_.
-By using the _type_ property, the client can determine which [type](#types)
-of response has been provided.
+The _UnresolvedSourceLocation_ class is used to refer to an unresolved
+breakpoint location. As such, it is meant to approximate the final
+location of the breakpoint but it is not exact.
+
+Either the _script_ or the _scriptUri_ field will be present.
+
+Either the _tokenPos_ or the _line_ field will be present.
+
+The _column_ field will only be present when the breakpoint was
+specified with a specific column number.
### Version
@@ -2020,6 +2112,8 @@
version | comments
------- | --------
1.0 draft 1 | initial revision
+1.1 | Describe protocol version 2.0.
+1.2 | Describe protocol version 3.0. Added UnresolvedSourceLocation.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service/vmservice.dart b/runtime/vm/service/vmservice.dart
index 4c12cdb..f2210c5 100644
--- a/runtime/vm/service/vmservice.dart
+++ b/runtime/vm/service/vmservice.dart
@@ -106,10 +106,11 @@
void _exit() {
isolateLifecyclePort.close();
scriptLoadPort.close();
- // Create a copy of the set as a list because client.close() alters the set.
+ // Create a copy of the set as a list because client.disconnect() will
+ // alter the connected clients set.
var clientsList = clients.toList();
for (var client in clientsList) {
- client.close();
+ client.disconnect();
}
// Call embedder shutdown hook after the internal shutdown.
if (onShutdown != null) {
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index 2068e40..29a71ce 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -675,6 +675,8 @@
static void ShutdownIsolate(uword parameter) {
Isolate* I = reinterpret_cast<Isolate*>(parameter);
ASSERT(ServiceIsolate::IsServiceIsolate(I));
+ ServiceIsolate::SetServiceIsolate(NULL);
+ ServiceIsolate::SetServicePort(ILLEGAL_PORT);
{
// Print the error if there is one. This may execute dart code to
// print the exception object, so we need to use a StartIsolateScope.
@@ -695,8 +697,6 @@
SwitchIsolateScope switch_scope(I);
Dart::ShutdownIsolate();
}
- ServiceIsolate::SetServiceIsolate(NULL);
- ServiceIsolate::SetServicePort(ILLEGAL_PORT);
if (FLAG_trace_service) {
OS::Print("vm-service: Shutdown.\n");
}
@@ -762,8 +762,30 @@
}
+void ServiceIsolate::KillServiceIsolate() {
+ {
+ MonitorLocker ml(monitor_);
+ shutting_down_ = true;
+ }
+ Isolate::KillIfExists(isolate_);
+ {
+ MonitorLocker ml(monitor_);
+ while (shutting_down_) {
+ ml.Wait();
+ }
+ }
+}
+
+
void ServiceIsolate::Shutdown() {
if (!IsRunning()) {
+ if (isolate_ != NULL) {
+ // TODO(johnmccutchan,turnidge) When it is possible to properly create
+ // the VMService object and set up its shutdown handler in the service
+ // isolate's main() function, this case will no longer be possible and
+ // can be removed.
+ KillServiceIsolate();
+ }
return;
}
{
diff --git a/runtime/vm/service_isolate.h b/runtime/vm/service_isolate.h
index fbcd136..86433c9 100644
--- a/runtime/vm/service_isolate.h
+++ b/runtime/vm/service_isolate.h
@@ -32,6 +32,9 @@
static void SendServiceExitMessage();
static void Shutdown();
+ private:
+ static void KillServiceIsolate();
+
protected:
static void SetServicePort(Dart_Port port);
static void SetServiceIsolate(Isolate* isolate);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 45ae49a..4b3fb8a 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -1578,6 +1578,7 @@
set_register(R1, r1);
}
} else if (redirection->call_kind() == kBootstrapNativeCall) {
+ ASSERT(redirection->argument_count() == 1);
NativeArguments* arguments;
arguments = reinterpret_cast<NativeArguments*>(get_register(R0));
SimulatorBootstrapNativeCall target =
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 9663fdc..3c7b99d 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -1626,6 +1626,7 @@
set_vregisterd(V0, 0, bit_cast<int64_t, double>(res));
set_vregisterd(V0, 1, 0);
} else if (redirection->call_kind() == kBootstrapNativeCall) {
+ ASSERT(redirection->argument_count() == 1);
NativeArguments* arguments;
arguments = reinterpret_cast<NativeArguments*>(get_register(R0));
SimulatorBootstrapNativeCall target =
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index fdcdcf2..f8da783 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -1268,6 +1268,7 @@
d0 = target(d6, d7);
set_fregister_double(F0, d0);
} else if (redirection->call_kind() == kBootstrapNativeCall) {
+ ASSERT(redirection->argument_count() == 1);
NativeArguments* arguments;
arguments = reinterpret_cast<NativeArguments*>(get_register(A0));
SimulatorBootstrapNativeCall target =
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index b336512..decc5a7 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -198,6 +198,8 @@
data_(ExternalTypedData::Handle(zone_)),
typed_data_(TypedData::Handle(zone_)),
code_(Code::Handle(zone_)),
+ function_(Function::Handle(zone_)),
+ megamorphic_cache_(MegamorphicCache::Handle(zone_)),
error_(UnhandledException::Handle(zone_)),
max_vm_isolate_object_id_(
(kind == Snapshot::kFull) ?
@@ -262,6 +264,43 @@
}
+RawFunction* SnapshotReader::ReadFunctionId(intptr_t object_id) {
+ ASSERT(kind_ == Snapshot::kScript);
+ // Read the function header information and lookup the function.
+ intptr_t func_header = Read<int32_t>();
+ ASSERT((func_header & kSmiTagMask) != kSmiTag);
+ ASSERT(!IsVMIsolateObject(func_header) ||
+ !IsSingletonClassId(GetVMIsolateObjectId(func_header)));
+ ASSERT((SerializedHeaderTag::decode(func_header) != kObjectId) ||
+ !IsObjectStoreClassId(SerializedHeaderData::decode(func_header)));
+ Function& func = Function::ZoneHandle(zone(), Function::null());
+ AddBackRef(object_id, &func, kIsDeserialized);
+ // Read the library/class/function information and lookup the function.
+ str_ ^= ReadObjectImpl(func_header, kAsInlinedObject, kInvalidPatchIndex, 0);
+ library_ = Library::LookupLibrary(str_);
+ if (library_.IsNull() || !library_.Loaded()) {
+ SetReadException("Expected a library name, but found an invalid name.");
+ }
+ str_ ^= ReadObjectImpl(kAsInlinedObject);
+ if (str_.Equals(Symbols::TopLevel(), 0, Symbols::TopLevel().Length())) {
+ str_ ^= ReadObjectImpl(kAsInlinedObject);
+ func ^= library_.LookupLocalFunction(str_);
+ } else {
+ cls_ = library_.LookupClass(str_);
+ if (cls_.IsNull()) {
+ SetReadException("Expected a class name, but found an invalid name.");
+ }
+ cls_.EnsureIsFinalized(isolate());
+ str_ ^= ReadObjectImpl(kAsInlinedObject);
+ func ^= cls_.LookupFunctionAllowPrivate(str_);
+ }
+ if (func.IsNull()) {
+ SetReadException("Expected a function name, but found an invalid name.");
+ }
+ return func.raw();
+}
+
+
RawObject* SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id,
intptr_t class_header) {
ASSERT(kind_ != Snapshot::kFull);
@@ -660,7 +699,9 @@
HeapLocker hl(isolate, old_space());
// Read in all the objects stored in the object store.
- intptr_t num_flds = (object_store->to() - object_store->from());
+ RawObject** toobj = snapshot_code() ? object_store->to()
+ : object_store->to_snapshot();
+ intptr_t num_flds = (toobj - object_store->from());
for (intptr_t i = 0; i <= num_flds; i++) {
*(object_store->from() + i) = ReadObjectImpl(kAsInlinedObject);
}
@@ -1307,58 +1348,59 @@
}
+#define READ_VM_SINGLETON_OBJ(id, obj) \
+ if (object_id == id) { \
+ return obj; \
+ } \
+
RawObject* SnapshotReader::ReadVMIsolateObject(intptr_t header_value) {
intptr_t object_id = GetVMIsolateObjectId(header_value);
- if (object_id == kNullObject) {
- // This is a singleton null object, return it.
- return Object::null();
- }
- if (object_id == kSentinelObject) {
- return Object::sentinel().raw();
- }
- if (object_id == kTransitionSentinelObject) {
- return Object::transition_sentinel().raw();
- }
- if (object_id == kEmptyArrayObject) {
- return Object::empty_array().raw();
- }
- if (object_id == kZeroArrayObject) {
- return Object::zero_array().raw();
- }
- if (object_id == kDynamicType) {
- return Object::dynamic_type();
- }
- if (object_id == kVoidType) {
- return Object::void_type();
- }
- if (object_id == kTrueValue) {
- return Bool::True().raw();
- }
- if (object_id == kFalseValue) {
- return Bool::False().raw();
- }
- if (object_id == kExtractorParameterTypes) {
- return Object::extractor_parameter_types().raw();
- }
- if (object_id == kExtractorParameterNames) {
- return Object::extractor_parameter_names().raw();
- }
- if (object_id == kEmptyContextScopeObject) {
- return Object::empty_context_scope().raw();
- }
+
+ // First check if it is one of the singleton objects.
+ READ_VM_SINGLETON_OBJ(kNullObject, Object::null());
+ READ_VM_SINGLETON_OBJ(kSentinelObject, Object::sentinel().raw());
+ READ_VM_SINGLETON_OBJ(kTransitionSentinelObject,
+ Object::transition_sentinel().raw());
+ READ_VM_SINGLETON_OBJ(kEmptyArrayObject, Object::empty_array().raw());
+ READ_VM_SINGLETON_OBJ(kZeroArrayObject, Object::zero_array().raw());
+ READ_VM_SINGLETON_OBJ(kDynamicType, Object::dynamic_type());
+ READ_VM_SINGLETON_OBJ(kVoidType, Object::void_type());
+ READ_VM_SINGLETON_OBJ(kTrueValue, Bool::True().raw());
+ READ_VM_SINGLETON_OBJ(kFalseValue, Bool::False().raw());
+ READ_VM_SINGLETON_OBJ(kExtractorParameterTypes,
+ Object::extractor_parameter_types().raw());
+ READ_VM_SINGLETON_OBJ(kExtractorParameterNames,
+ Object::extractor_parameter_names().raw());
+ READ_VM_SINGLETON_OBJ(kEmptyContextScopeObject,
+ Object::empty_context_scope().raw());
+ READ_VM_SINGLETON_OBJ(kEmptyObjectPool, Object::empty_object_pool().raw());
+ READ_VM_SINGLETON_OBJ(kEmptyDescriptors, Object::empty_descriptors().raw());
+ READ_VM_SINGLETON_OBJ(kEmptyVarDescriptors,
+ Object::empty_var_descriptors().raw());
+ READ_VM_SINGLETON_OBJ(kEmptyExceptionHandlers,
+ Object::empty_exception_handlers().raw());
+
+ // Check if it is a double.
if (object_id == kDoubleObject) {
ASSERT(kind_ == Snapshot::kMessage);
return Double::New(ReadDouble());
}
+
+ // Check it is a singleton class object.
intptr_t class_id = ClassIdFromObjectId(object_id);
if (IsSingletonClassId(class_id)) {
return isolate()->class_table()->At(class_id); // get singleton class.
- } else {
- ASSERT(Symbols::IsVMSymbolId(object_id));
- return Symbols::GetVMSymbol(object_id); // return VM symbol.
}
- UNREACHABLE();
- return Object::null();
+
+ // Check if it is a singleton Argument descriptor object.
+ for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
+ if (object_id == (kCachedArgumentsDescriptor0 + i)) {
+ return ArgumentsDescriptor::cached_args_descriptors_[i];
+ }
+ }
+
+ ASSERT(Symbols::IsVMSymbolId(object_id));
+ return Symbols::GetVMSymbol(object_id); // return VM symbol.
}
@@ -1525,27 +1567,8 @@
// only memory.
*(ArrayHandle()) ^= ReadObject();
-
if (snapshot_code()) {
- for (intptr_t i = 0;
- i < ArgumentsDescriptor::kCachedDescriptorCount;
- i++) {
- *(ArrayHandle()) ^= ReadObject();
- // TODO(rmacnak):
- // ArgumentsDescriptor::InitOnceFromSnapshot(i, *(ArrayHandle()));
- }
-
- ObjectPool::CheckedHandle(ReadObject()); // empty pool
- PcDescriptors::CheckedHandle(ReadObject()); // empty pc desc
- LocalVarDescriptors::CheckedHandle(ReadObject()); // empty var desc
- ExceptionHandlers::CheckedHandle(ReadObject()); // empty exc handlers
-
-#define READ_STUB(name) \
- *(CodeHandle()) ^= ReadObject();
- // TODO(rmacnak):
- // StubCode::name##_entry()->InitOnceFromSnapshot(CodeHandle())
- VM_STUB_CODE_LIST(READ_STUB);
-#undef READ_STUB
+ StubCode::ReadFrom(this);
}
// Validate the class table.
@@ -1569,6 +1592,7 @@
new ZoneGrowableArray<BackRefNode>(
kNumInitialReferencesInFullSnapshot),
thread) {
+ isolate()->set_compilation_allowed(instructions_buffer_ == NULL);
}
@@ -1657,78 +1681,36 @@
return true; \
} \
+#define WRITE_VM_SINGLETON_OBJ(obj, id) \
+ if (rawobj == obj) { \
+ WriteVMIsolateObject(id); \
+ return true; \
+ } \
+
bool SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
- // Check if it is a singleton null object.
- if (rawobj == Object::null()) {
- WriteVMIsolateObject(kNullObject);
- return true;
- }
-
- // Check if it is a singleton sentinel object.
- if (rawobj == Object::sentinel().raw()) {
- WriteVMIsolateObject(kSentinelObject);
- return true;
- }
-
- // Check if it is a singleton sentinel object.
- if (rawobj == Object::transition_sentinel().raw()) {
- WriteVMIsolateObject(kTransitionSentinelObject);
- return true;
- }
-
- // Check if it is a singleton empty array object.
- if (rawobj == Object::empty_array().raw()) {
- WriteVMIsolateObject(kEmptyArrayObject);
- return true;
- }
-
- // Check if it is a singleton zero array object.
- if (rawobj == Object::zero_array().raw()) {
- WriteVMIsolateObject(kZeroArrayObject);
- return true;
- }
-
- // Check if it is a singleton dyanmic Type object.
- if (rawobj == Object::dynamic_type()) {
- WriteVMIsolateObject(kDynamicType);
- return true;
- }
-
- // Check if it is a singleton void Type object.
- if (rawobj == Object::void_type()) {
- WriteVMIsolateObject(kVoidType);
- return true;
- }
-
- // Check if it is a singleton boolean true object.
- if (rawobj == Bool::True().raw()) {
- WriteVMIsolateObject(kTrueValue);
- return true;
- }
-
- // Check if it is a singleton boolean false object.
- if (rawobj == Bool::False().raw()) {
- WriteVMIsolateObject(kFalseValue);
- return true;
- }
-
- // Check if it is a singleton extractor parameter types array.
- if (rawobj == Object::extractor_parameter_types().raw()) {
- WriteVMIsolateObject(kExtractorParameterTypes);
- return true;
- }
-
- // Check if it is a singleton extractor parameter names array.
- if (rawobj == Object::extractor_parameter_names().raw()) {
- WriteVMIsolateObject(kExtractorParameterNames);
- return true;
- }
-
- // Check if it is a singleton empty context scope object.
- if (rawobj == Object::empty_context_scope().raw()) {
- WriteVMIsolateObject(kEmptyContextScopeObject);
- return true;
- }
+ // Check if it is one of the singleton VM objects.
+ WRITE_VM_SINGLETON_OBJ(Object::null(), kNullObject);
+ WRITE_VM_SINGLETON_OBJ(Object::sentinel().raw(), kSentinelObject);
+ WRITE_VM_SINGLETON_OBJ(Object::transition_sentinel().raw(),
+ kTransitionSentinelObject);
+ WRITE_VM_SINGLETON_OBJ(Object::empty_array().raw(), kEmptyArrayObject);
+ WRITE_VM_SINGLETON_OBJ(Object::zero_array().raw(), kZeroArrayObject);
+ WRITE_VM_SINGLETON_OBJ(Object::dynamic_type(), kDynamicType);
+ WRITE_VM_SINGLETON_OBJ(Object::void_type(), kVoidType);
+ WRITE_VM_SINGLETON_OBJ(Bool::True().raw(), kTrueValue);
+ WRITE_VM_SINGLETON_OBJ(Bool::False().raw(), kFalseValue);
+ WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_types().raw(),
+ kExtractorParameterTypes);
+ WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_names().raw(),
+ kExtractorParameterNames);
+ WRITE_VM_SINGLETON_OBJ(Object::empty_context_scope().raw(),
+ kEmptyContextScopeObject);
+ WRITE_VM_SINGLETON_OBJ(Object::empty_object_pool().raw(), kEmptyObjectPool);
+ WRITE_VM_SINGLETON_OBJ(Object::empty_descriptors().raw(), kEmptyDescriptors);
+ WRITE_VM_SINGLETON_OBJ(Object::empty_var_descriptors().raw(),
+ kEmptyVarDescriptors);
+ WRITE_VM_SINGLETON_OBJ(Object::empty_exception_handlers().raw(),
+ kEmptyExceptionHandlers);
// Check if it is a singleton class object which is shared by
// all isolates.
@@ -1743,6 +1725,14 @@
}
}
+ // Check if it is a singleton Argument descriptor object.
+ for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
+ if (rawobj == ArgumentsDescriptor::cached_args_descriptors_[i]) {
+ WriteVMIsolateObject(kCachedArgumentsDescriptor0 + i);
+ return true;
+ }
+ }
+
if (kind() == Snapshot::kFull) {
// Check it is a predefined symbol in the VM isolate.
id = Symbols::LookupVMSymbol(rawobj);
@@ -1937,22 +1927,7 @@
if (snapshot_code_) {
ASSERT(!vm_isolate_is_symbolic_);
-
- for (intptr_t i = 0;
- i < ArgumentsDescriptor::kCachedDescriptorCount;
- i++) {
- writer.WriteObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
- }
-
- writer.WriteObject(Object::empty_object_pool().raw());
- writer.WriteObject(Object::empty_descriptors().raw());
- writer.WriteObject(Object::empty_var_descriptors().raw());
- writer.WriteObject(Object::empty_exception_handlers().raw());
-
-#define WRITE_STUB(name) \
- writer.WriteObject(StubCode::name##_entry()->code());
- VM_STUB_CODE_LIST(WRITE_STUB);
-#undef WRITE_STUB
+ StubCode::WriteTo(&writer);
}
@@ -1994,7 +1969,9 @@
// Write out all the objects in the object store of the isolate which
// is the root set for all dart allocated objects at this point.
SnapshotWriterVisitor visitor(&writer, false);
- object_store->VisitObjectPointers(&visitor);
+ visitor.VisitPointers(object_store->from(),
+ snapshot_code_ ? object_store->to()
+ : object_store->to_snapshot());
// Write out all forwarded objects.
writer.WriteForwardedObjects();
@@ -2441,6 +2418,22 @@
}
+void SnapshotWriter::WriteFunctionId(RawFunction* func, bool owner_is_class) {
+ ASSERT(kind_ == Snapshot::kScript);
+ RawClass* cls = (owner_is_class) ?
+ reinterpret_cast<RawClass*>(func->ptr()->owner_) :
+ reinterpret_cast<RawPatchClass*>(
+ func->ptr()->owner_)->ptr()->patched_class_;
+
+ // Write out the library url and class name.
+ RawLibrary* library = cls->ptr()->library_;
+ ASSERT(library != Library::null());
+ WriteObjectImpl(library->ptr()->url_, kAsInlinedObject);
+ WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject);
+ WriteObjectImpl(func->ptr()->name_, kAsInlinedObject);
+}
+
+
void SnapshotWriter::WriteStaticImplicitClosure(intptr_t object_id,
RawFunction* func,
intptr_t tags) {
@@ -2515,13 +2508,10 @@
ASSERT(!errorFunc.IsNull());
// All other closures are errors.
- const char* format = "Illegal argument in isolate message"
- " : (object is a closure - %s %s)";
UnmarkAll(); // Unmark objects now as we are about to print stuff.
- intptr_t len = OS::SNPrint(NULL, 0, format,
- clazz.ToCString(), errorFunc.ToCString()) + 1;
- char* chars = thread()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, clazz.ToCString(), errorFunc.ToCString());
+ char* chars = OS::SCreate(thread()->zone(),
+ "Illegal argument in isolate message : (object is a closure - %s %s)",
+ clazz.ToCString(), errorFunc.ToCString());
SetWriteException(Exceptions::kArgument, chars);
}
return Function::null();
@@ -2544,13 +2534,12 @@
if (cls->ptr()->num_native_fields_ != 0) {
// We do not allow objects with native fields in an isolate message.
HANDLESCOPE(thread());
- const char* format = "Illegal argument in isolate message"
- " : (object extends NativeWrapper - %s)";
UnmarkAll(); // Unmark objects now as we are about to print stuff.
const Class& clazz = Class::Handle(isolate(), cls);
- intptr_t len = OS::SNPrint(NULL, 0, format, clazz.ToCString()) + 1;
- char* chars = thread()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, clazz.ToCString());
+ char* chars = OS::SCreate(thread()->zone(),
+ "Illegal argument in isolate message"
+ " : (object extends NativeWrapper - %s)",
+ clazz.ToCString());
SetWriteException(Exceptions::kArgument, chars);
}
}
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index f612073..a23e692 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -32,6 +32,7 @@
class Object;
class PassiveObject;
class ObjectStore;
+class MegamorphicCache;
class PageSpace;
class RawApiError;
class RawArray;
@@ -339,6 +340,8 @@
ExternalTypedData* DataHandle() { return &data_; }
TypedData* TypedDataHandle() { return &typed_data_; }
Code* CodeHandle() { return &code_; }
+ Function* FunctionHandle() { return &function_; }
+ MegamorphicCache* MegamorphicCacheHandle() { return &megamorphic_cache_; }
Snapshot::Kind kind() const { return kind_; }
bool snapshot_code() const { return snapshot_code_; }
@@ -442,6 +445,7 @@
RawObject* AllocateUninitialized(intptr_t class_id, intptr_t size);
RawClass* ReadClassId(intptr_t object_id);
+ RawFunction* ReadFunctionId(intptr_t object_id);
RawObject* ReadStaticImplicitClosure(intptr_t object_id, intptr_t cls_header);
// Implementation to read an object.
@@ -521,6 +525,8 @@
ExternalTypedData& data_; // Temporary stream data handle.
TypedData& typed_data_; // Temporary typed data handle.
Code& code_; // Temporary code handle.
+ Function& function_; // Temporary function handle.
+ MegamorphicCache& megamorphic_cache_; // Temporary megamorphic cache handle.
UnhandledException& error_; // Error handle.
intptr_t max_vm_isolate_object_id_;
ZoneGrowableArray<BackRefNode>* backward_references_;
@@ -876,6 +882,8 @@
return instructions_writer_->SetInstructionsCode(instructions, code);
}
+ void WriteFunctionId(RawFunction* func, bool owner_is_class);
+
protected:
void UnmarkAll() {
if (!unmarked_objects_ && forward_list_ != NULL) {
diff --git a/runtime/vm/snapshot_ids.h b/runtime/vm/snapshot_ids.h
index a65df69..856887d 100644
--- a/runtime/vm/snapshot_ids.h
+++ b/runtime/vm/snapshot_ids.h
@@ -6,6 +6,7 @@
#define VM_SNAPSHOT_IDS_H_
#include "vm/raw_object.h"
+#include "vm/dart_entry.h"
namespace dart {
@@ -46,6 +47,13 @@
kExtractorParameterNames,
kEmptyContextScopeObject,
kImplicitClosureScopeObject,
+ kEmptyObjectPool,
+ kEmptyDescriptors,
+ kEmptyVarDescriptors,
+ kEmptyExceptionHandlers,
+ kCachedArgumentsDescriptor0,
+ kCachedArgumentsDescriptorN = (kCachedArgumentsDescriptor0 +
+ ArgumentsDescriptor::kCachedDescriptorCount - 1),
kInstanceObjectId,
kStaticImplicitClosureObjectId,
diff --git a/runtime/vm/stack_frame_test.cc b/runtime/vm/stack_frame_test.cc
index 426ede7..c5f280a 100644
--- a/runtime/vm/stack_frame_test.cc
+++ b/runtime/vm/stack_frame_test.cc
@@ -101,10 +101,8 @@
const Library& lib = Library::Handle(Library::LookupLibrary(url));
ASSERT(!lib.IsNull());
const char* lib_name = String::Handle(lib.url()).ToCString();
- intptr_t length = OS::SNPrint(NULL, 0, "%s_%s", lib_name, expected_name);
- char* full_name = Thread::Current()->zone()->Alloc<char>(length + 1);
- ASSERT(full_name != NULL);
- OS::SNPrint(full_name, (length + 1), "%s_%s", lib_name, expected_name);
+ char* full_name = OS::SCreate(Thread::Current()->zone(),
+ "%s_%s", lib_name, expected_name);
if (strcmp(full_name, name) != 0) {
FATAL("StackFrame_validateFrame fails, incorrect frame.\n");
}
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 486531a..65a4966 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -10,6 +10,7 @@
#include "vm/disassembler.h"
#include "vm/flags.h"
#include "vm/object_store.h"
+#include "vm/snapshot.h"
#include "vm/virtual_memory.h"
#include "vm/visitor.h"
@@ -53,6 +54,24 @@
#undef STUB_CODE_GENERATE
+void StubCode::ReadFrom(SnapshotReader* reader) {
+#define READ_STUB(name) \
+ *(reader->CodeHandle()) ^= reader->ReadObject(); \
+ name##_entry_ = new StubEntry(*(reader->CodeHandle()));
+ VM_STUB_CODE_LIST(READ_STUB);
+#undef READ_STUB
+}
+
+void StubCode::WriteTo(SnapshotWriter* writer) {
+ // TODO(rmacnak): Consider writing only the instructions to avoid
+ // vm_isolate_is_symbolic.
+#define WRITE_STUB(name) \
+ writer->WriteObject(StubCode::name##_entry()->code());
+ VM_STUB_CODE_LIST(WRITE_STUB);
+#undef WRITE_STUB
+}
+
+
void StubCode::Init(Isolate* isolate) { }
@@ -93,11 +112,11 @@
stub.set_owner(cls);
cls.set_allocation_stub(stub);
if (FLAG_disassemble_stubs) {
- LogBlock lb(Isolate::Current());
- ISL_Print("Code for allocation stub '%s': {\n", name);
+ LogBlock lb;
+ THR_Print("Code for allocation stub '%s': {\n", name);
DisassembleToStdout formatter;
stub.Disassemble(&formatter);
- ISL_Print("}\n");
+ THR_Print("}\n");
const ObjectPool& object_pool = ObjectPool::Handle(
Instructions::Handle(stub.instructions()).object_pool());
object_pool.DebugPrint();
@@ -131,11 +150,11 @@
GenerateStub(&assembler);
const Code& code = Code::Handle(Code::FinalizeCode(name, &assembler));
if (FLAG_disassemble_stubs) {
- LogBlock lb(Isolate::Current());
- ISL_Print("Code for stub '%s': {\n", name);
+ LogBlock lb;
+ THR_Print("Code for stub '%s': {\n", name);
DisassembleToStdout formatter;
code.Disassemble(&formatter);
- ISL_Print("}\n");
+ THR_Print("}\n");
const ObjectPool& object_pool = ObjectPool::Handle(
Instructions::Handle(code.instructions()).object_pool());
object_pool.DebugPrint();
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 3a5ffc1..3d3c016 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -15,6 +15,8 @@
class Isolate;
class ObjectPointerVisitor;
class RawCode;
+class SnapshotReader;
+class SnapshotWriter;
// List of stubs created in the VM isolate, these stubs are shared by different
@@ -98,6 +100,9 @@
// only once and the stub code resides in the vm_isolate heap.
static void InitOnce();
+ static void ReadFrom(SnapshotReader* reader);
+ static void WriteTo(SnapshotWriter* writer);
+
// Generate all stubs which are generated on a per isolate basis as they
// have embedded objects which are isolate specific.
static void Init(Isolate* isolate);
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index ab56734..9d2883b 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -303,7 +303,7 @@
// calling into the runtime.
__ EnterStubFrame();
// Setup space on stack for return value and preserve arguments descriptor.
- __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R0, Object::null_object());
__ PushList((1 << R0) | (1 << R4));
__ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
// Get Code object result and restore arguments descriptor array.
@@ -324,7 +324,7 @@
// calling into the runtime.
__ EnterStubFrame();
// Setup space on stack for return value and preserve arguments descriptor.
- __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R0, Object::null_object());
__ PushList((1 << R0) | (1 << R4));
__ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
// Get Code object result and restore arguments descriptor array.
@@ -342,7 +342,7 @@
void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
__ EnterStubFrame();
// Setup space on stack for return value.
- __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R0, Object::null_object());
__ Push(R0);
__ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
// Get Code object result.
@@ -360,7 +360,7 @@
// FP[kParamEndSlotFromFp + 1]: last argument.
static void PushArgumentsArray(Assembler* assembler) {
// Allocate array to store arguments of caller.
- __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R1, Object::null_object());
// R1: null element type for raw Array.
// R2: smi-tagged argument count, may be zero.
__ BranchLink(*StubCode::AllocateArray_entry());
@@ -563,7 +563,7 @@
// Push the receiver.
// Push IC data object.
// Push arguments descriptor array.
- __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(IP, Object::null_object());
__ PushList((1 << R4) | (1 << R5) | (1 << R6) | (1 << IP));
__ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
// Remove arguments.
@@ -688,7 +688,7 @@
// R7: new object end address.
// R9: allocation size.
- __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R4, Object::null_object());
__ mov(R5, Operand(R4));
__ AddImmediate(R6, R0, sizeof(RawArray) - kHeapObjectTag);
__ InitializeFieldsNoBarrier(R0, R6, R7, R4, R5);
@@ -701,7 +701,7 @@
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
__ EnterStubFrame();
- __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(IP, Object::null_object());
// Setup space on stack for return value.
// Push array length as Smi and element type.
__ PushList((1 << R1) | (1 << R2) | (1 << IP));
@@ -914,7 +914,7 @@
// R2: object size.
// R3: next object start.
// R6: allocation stats address.
- __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R4, Object::null_object());
__ InitializeFieldNoBarrier(R0, FieldAddress(R0, Context::parent_offset()),
R4);
@@ -940,7 +940,7 @@
// calling into the runtime.
__ EnterStubFrame();
// Setup space on stack for return value.
- __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R2, Object::null_object());
__ SmiTag(R1);
__ PushList((1 << R1) | (1 << R2));
__ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context.
@@ -1086,7 +1086,7 @@
__ add(R0, R0, Operand(kHeapObjectTag));
// Initialize the remaining words of the object.
- __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R2, Object::null_object());
// R2: raw null.
// R0: new object (tagged).
@@ -1144,7 +1144,7 @@
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
__ EnterStubFrame(); // Uses pool pointer to pass cls to runtime.
- __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R2, Object::null_object());
__ Push(R2); // Setup space on stack for return value.
__ PushObject(cls); // Push class of object to be allocated.
if (is_cls_parameterized) {
@@ -1184,7 +1184,7 @@
// Push space for the return value.
// Push the receiver.
// Push arguments descriptor array.
- __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(IP, Object::null_object());
__ PushList((1 << R4) | (1 << R6) | (1 << IP));
// R2: Smi-tagged arguments array length.
@@ -1424,7 +1424,7 @@
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
__ EnterStubFrame();
- __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R0, Object::null_object());
// Preserve IC data object and arguments descriptor array and
// setup space on stack for result (target code object).
__ PushList((1 << R0) | (1 << R4) | (1 << R5));
@@ -1699,7 +1699,7 @@
// R5: Contains an ICData.
void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
__ EnterStubFrame();
- __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R0, Object::null_object());
// Preserve arguments descriptor and make room for result.
__ PushList((1 << R0) | (1 << R5));
__ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
@@ -1711,7 +1711,7 @@
void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
__ EnterStubFrame();
- __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R0, Object::null_object());
// Make room for result.
__ PushList((1 << R0));
__ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
@@ -1754,7 +1754,7 @@
__ LoadClass(R3, R0, R4);
// Compute instance type arguments into R4.
Label has_no_type_arguments;
- __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R4, Object::null_object());
__ ldr(R5, FieldAddress(R3,
Class::type_arguments_field_offset_in_words_offset()));
__ CompareImmediate(R5, Class::kNoTypeArguments);
@@ -1779,7 +1779,7 @@
__ SmiTag(R3);
__ Bind(&loop);
__ ldr(R5, Address(R2, kWordSize * SubtypeTestCache::kInstanceClassId));
- __ CompareImmediate(R5, reinterpret_cast<intptr_t>(Object::null()));
+ __ CompareObject(R5, Object::null_object());
__ b(¬_found, EQ);
__ cmp(R5, Operand(R3));
if (n == 1) {
@@ -1804,7 +1804,7 @@
__ b(&loop);
// Fall through to not found.
__ Bind(¬_found);
- __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R1, Object::null_object());
__ Ret();
__ Bind(&found);
@@ -1889,7 +1889,7 @@
void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
__ EnterStubFrame();
__ Push(R4);
- __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(IP, Object::null_object());
__ Push(IP); // Setup space on stack for return value.
__ Push(R6);
__ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 44498fc..d6b55f8 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -316,7 +316,7 @@
__ addiu(SP, SP, Immediate(-2 * kWordSize));
__ sw(S4, Address(SP, 1 * kWordSize));
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 0 * kWordSize));
__ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
@@ -345,7 +345,7 @@
// Setup space on stack for return value and preserve arguments descriptor.
__ addiu(SP, SP, Immediate(-2 * kWordSize));
__ sw(S4, Address(SP, 1 * kWordSize));
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 0 * kWordSize));
__ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
// Get Code object result and restore arguments descriptor array.
@@ -368,7 +368,7 @@
__ EnterStubFrame();
// Setup space on stack for return value.
__ addiu(SP, SP, Immediate(-1 * kWordSize));
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 0 * kWordSize));
__ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
// Get Code object result.
@@ -389,7 +389,7 @@
static void PushArgumentsArray(Assembler* assembler) {
__ Comment("PushArgumentsArray");
// Allocate array to store arguments of caller.
- __ LoadImmediate(A0, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(A0, Object::null_object());
// A0: Null element type for raw Array.
// A1: Smi-tagged argument count, may be zero.
__ BranchLink(*StubCode::AllocateArray_entry());
@@ -568,7 +568,7 @@
// Push arguments descriptor array.
// Push original arguments array.
__ addiu(SP, SP, Immediate(-4 * kWordSize));
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 3 * kWordSize));
__ sw(T6, Address(SP, 2 * kWordSize));
__ sw(S5, Address(SP, 1 * kWordSize));
@@ -602,7 +602,7 @@
// Push the receiver.
// Push IC data object.
// Push arguments descriptor array.
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 3 * kWordSize));
__ sw(T6, Address(SP, 2 * kWordSize));
__ sw(S5, Address(SP, 1 * kWordSize));
@@ -731,7 +731,7 @@
FieldAddress(T0, Array::length_offset()),
A1);
- __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
+ __ LoadObject(T7, Object::null_object());
// Initialize all array elements to raw_null.
// T0: new object start as a tagged pointer.
// T1: new object end address.
@@ -761,7 +761,7 @@
// Setup space on stack for return value.
// Push array length as Smi and element type.
__ addiu(SP, SP, Immediate(-3 * kWordSize));
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 2 * kWordSize));
__ sw(A1, Address(SP, 1 * kWordSize));
__ sw(A0, Address(SP, 0 * kWordSize));
@@ -995,7 +995,7 @@
// T1: number of context variables as integer value (not object).
__ sw(T1, FieldAddress(V0, Context::num_variables_offset()));
- __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(T7, Object::null_object());
// Initialize the context variables.
// V0: new object.
@@ -1025,7 +1025,7 @@
// Setup space on stack for return value.
__ SmiTag(T1);
__ addiu(SP, SP, Immediate(-2 * kWordSize));
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 1 * kWordSize)); // Store null.
__ sw(T1, Address(SP, 0 * kWordSize));
__ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context.
@@ -1167,7 +1167,7 @@
__ LoadImmediate(T0, tags);
__ sw(T0, Address(T2, Instance::tags_offset()));
- __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(T7, Object::null_object());
// Initialize the remaining words of the object.
// T2: new object start.
@@ -1218,7 +1218,7 @@
__ addiu(SP, SP, Immediate(-3 * kWordSize));
// Space on stack for return value.
- __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(T7, Object::null_object());
__ sw(T7, Address(SP, 2 * kWordSize));
__ sw(TMP, Address(SP, 1 * kWordSize)); // Class of object to be allocated.
@@ -1263,7 +1263,7 @@
// Push arguments descriptor array.
const intptr_t kNumArgs = 3;
__ addiu(SP, SP, Immediate(-kNumArgs * kWordSize));
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 2 * kWordSize));
__ sw(T6, Address(SP, 1 * kWordSize));
__ sw(S4, Address(SP, 0 * kWordSize));
@@ -1539,7 +1539,7 @@
__ addiu(SP, SP, Immediate(-num_slots * kWordSize));
__ sw(S5, Address(SP, (num_slots - 1) * kWordSize));
__ sw(S4, Address(SP, (num_slots - 2) * kWordSize));
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, (num_slots - 3) * kWordSize));
// Push call arguments.
for (intptr_t i = 0; i < num_args; i++) {
@@ -1838,7 +1838,7 @@
__ EnterStubFrame();
__ addiu(SP, SP, Immediate(-2 * kWordSize));
__ sw(S5, Address(SP, 1 * kWordSize));
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 0 * kWordSize));
__ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
@@ -1855,7 +1855,7 @@
__ Comment("RuntimeCallBreakpoint stub");
__ EnterStubFrame();
__ addiu(SP, SP, Immediate(-1 * kWordSize));
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 0 * kWordSize));
__ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
@@ -1906,7 +1906,7 @@
__ LoadClass(T0, A0);
// Compute instance type arguments into T1.
Label has_no_type_arguments;
- __ LoadImmediate(T1, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(T1, Object::null_object());
__ lw(T2, FieldAddress(T0,
Class::type_arguments_field_offset_in_words_offset()));
__ BranchEqual(
@@ -1925,7 +1925,7 @@
__ lw(T2, FieldAddress(A2, SubtypeTestCache::cache_offset()));
__ AddImmediate(T2, Array::data_offset() - kHeapObjectTag);
- __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(T7, Object::null_object());
Label loop, found, not_found, next_iteration;
// T0: instance class id.
@@ -2048,7 +2048,7 @@
__ addiu(SP, SP, Immediate(-3 * kWordSize));
__ sw(S4, Address(SP, 2 * kWordSize));
// Setup space on stack for return value.
- __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(TMP, Object::null_object());
__ sw(TMP, Address(SP, 1 * kWordSize));
__ sw(T0, Address(SP, 0 * kWordSize));
__ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 9d389c1..0dd4640 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -493,16 +493,14 @@
__ Comment("NoSuchMethodDispatch");
// When lazily generated invocation dispatchers are disabled, the
// miss-handler may return null.
- const Immediate& raw_null =
- Immediate(reinterpret_cast<intptr_t>(Object::null()));
- __ cmpq(RAX, raw_null);
+ __ CompareObject(RAX, Object::null_object());
__ j(NOT_EQUAL, call_target_function);
__ EnterStubFrame();
// Load the receiver.
__ movq(RDI, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
__ movq(RAX, Address(
RBP, RDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize));
- __ pushq(raw_null); // Setup space on stack for result.
+ __ PushObject(Object::null_object()); // Setup space on stack for result.
__ pushq(RAX); // Receiver.
__ pushq(RBX);
__ pushq(R10); // Arguments descriptor array.
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 7d817d3..ceba83f 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -7,6 +7,7 @@
#include "vm/growable_array.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
+#include "vm/log.h"
#include "vm/object.h"
#include "vm/os_thread.h"
#include "vm/profiler.h"
@@ -52,6 +53,8 @@
// Clear |this| from all isolate's thread registry.
ThreadPruner pruner(this);
Isolate::VisitIsolates(&pruner);
+ delete log_;
+ log_ = NULL;
}
@@ -108,7 +111,8 @@
thread_interrupt_data_(NULL),
isolate_(NULL),
heap_(NULL),
- store_buffer_block_(NULL) {
+ store_buffer_block_(NULL),
+ log_(new class Log()) {
ClearState();
#define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \
@@ -307,6 +311,11 @@
}
+Log* Thread::log() const {
+ return log_;
+}
+
+
void Thread::SetThreadInterrupter(ThreadInterruptCallback callback,
void* data) {
ASSERT(Thread::Current() == this);
@@ -333,6 +342,14 @@
}
+void Thread::CloseTimelineBlock() {
+ if (timeline_block() != NULL) {
+ timeline_block()->Finish();
+ set_timeline_block(NULL);
+ }
+}
+
+
bool Thread::CanLoadFromThread(const Object& object) {
#define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \
if (object.raw() == expr) return true;
@@ -352,6 +369,7 @@
return -1;
}
+
intptr_t Thread::OffsetFromThread(const RuntimeEntry* runtime_entry) {
#define COMPUTE_OFFSET(name) \
if (runtime_entry->function() == k##name##RuntimeEntry.function()) { \
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 16eade4..5e14a8f 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -16,6 +16,7 @@
class HandleScope;
class Heap;
class Isolate;
+class Log;
class LongJumpScope;
class Object;
class RawBool;
@@ -256,6 +257,9 @@
state_.timeline_block = block;
}
+ void CloseTimelineBlock();
+ class Log* log() const;
+
LongJumpScope* long_jump_base() const { return state_.long_jump_base; }
void set_long_jump_base(LongJumpScope* value) {
state_.long_jump_base = value;
@@ -281,6 +285,7 @@
Heap* heap_;
State state_;
StoreBufferBlock* store_buffer_block_;
+ class Log* log_;
#define DECLARE_MEMBERS(type_name, member_name, expr, default_init_value) \
type_name member_name;
CACHED_CONSTANTS_LIST(DECLARE_MEMBERS)
diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc
index 0cf7c38..58c94be 100644
--- a/runtime/vm/thread_interrupter.cc
+++ b/runtime/vm/thread_interrupter.cc
@@ -51,8 +51,8 @@
bool ThreadInterrupter::initialized_ = false;
bool ThreadInterrupter::shutdown_ = false;
bool ThreadInterrupter::thread_running_ = false;
-ThreadId ThreadInterrupter::interrupter_thread_id_ =
- OSThread::kInvalidThreadId;
+ThreadJoinId ThreadInterrupter::interrupter_thread_id_ =
+ OSThread::kInvalidThreadJoinId;
Monitor* ThreadInterrupter::monitor_ = NULL;
intptr_t ThreadInterrupter::interrupt_period_ = 1000;
intptr_t ThreadInterrupter::current_wait_time_ = Monitor::kNoTimeout;
@@ -71,7 +71,7 @@
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter starting up.\n");
}
- ASSERT(interrupter_thread_id_ == OSThread::kInvalidThreadId);
+ ASSERT(interrupter_thread_id_ == OSThread::kInvalidThreadJoinId);
{
MonitorLocker startup_ml(monitor_);
OSThread::Start(ThreadMain, 0);
@@ -79,7 +79,7 @@
startup_ml.Wait();
}
}
- ASSERT(interrupter_thread_id_ != OSThread::kInvalidThreadId);
+ ASSERT(interrupter_thread_id_ != OSThread::kInvalidThreadJoinId);
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter running.\n");
}
@@ -101,24 +101,12 @@
OS::Print("ThreadInterrupter shutting down.\n");
}
}
-#if defined(TARGET_OS_WINDOWS)
- // On Windows, a thread's exit-code can leak into the process's exit-code,
- // if exiting 'at same time' as the process ends. By joining with the thread
- // here, we avoid this race condition.
- ASSERT(interrupter_thread_id_ != OSThread::kInvalidThreadId);
+
+ // Join the thread.
+ ASSERT(interrupter_thread_id_ != OSThread::kInvalidThreadJoinId);
OSThread::Join(interrupter_thread_id_);
- interrupter_thread_id_ = OSThread::kInvalidThreadId;
-#else
- // On non-Windows platforms, just wait for the thread interrupter to signal
- // that it has exited the loop.
- {
- MonitorLocker shutdown_ml(monitor_);
- while (thread_running_) {
- // Wait for thread to exit.
- shutdown_ml.Wait();
- }
- }
-#endif
+ interrupter_thread_id_ = OSThread::kInvalidThreadJoinId;
+
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter shut down.\n");
}
@@ -187,7 +175,7 @@
{
// Signal to main thread we are ready.
MonitorLocker startup_ml(monitor_);
- interrupter_thread_id_ = OSThread::GetCurrentThreadId();
+ interrupter_thread_id_ = OSThread::GetCurrentThreadJoinId();
thread_running_ = true;
startup_ml.Notify();
}
@@ -198,6 +186,10 @@
while (!shutdown_) {
intptr_t r = wait_ml.WaitMicros(current_wait_time_);
+ if ((r == Monitor::kNotified) && shutdown_) {
+ break;
+ }
+
if ((r == Monitor::kNotified) && InDeepSleep()) {
// Woken up from deep sleep.
ASSERT(visitor.profiled_thread_count() == 0);
diff --git a/runtime/vm/thread_interrupter.h b/runtime/vm/thread_interrupter.h
index 0fa00e1..9d3ccab 100644
--- a/runtime/vm/thread_interrupter.h
+++ b/runtime/vm/thread_interrupter.h
@@ -40,7 +40,7 @@
static bool initialized_;
static bool shutdown_;
static bool thread_running_;
- static ThreadId interrupter_thread_id_;
+ static ThreadJoinId interrupter_thread_id_;
static Monitor* monitor_;
static intptr_t interrupt_period_;
static intptr_t current_wait_time_;
diff --git a/runtime/vm/thread_pool.cc b/runtime/vm/thread_pool.cc
index 5b3a713..e4453d8 100644
--- a/runtime/vm/thread_pool.cc
+++ b/runtime/vm/thread_pool.cc
@@ -12,9 +12,6 @@
DEFINE_FLAG(int, worker_timeout_millis, 5000,
"Free workers when they have been idle for this amount of time.");
-Monitor* ThreadPool::exit_monitor_ = NULL;
-int* ThreadPool::exit_count_ = NULL;
-
ThreadPool::ThreadPool()
: shutting_down_(false),
all_workers_(NULL),
@@ -22,7 +19,9 @@
count_started_(0),
count_stopped_(0),
count_running_(0),
- count_idle_(0) {
+ count_idle_(0),
+ shutting_down_workers_(NULL),
+ join_list_(NULL) {
}
@@ -31,7 +30,7 @@
}
-void ThreadPool::Run(Task* task) {
+bool ThreadPool::Run(Task* task) {
Worker* worker = NULL;
bool new_worker = false;
{
@@ -39,7 +38,7 @@
// ThreadPool state.
MutexLocker ml(&mutex_);
if (shutting_down_) {
- return;
+ return false;
}
if (idle_workers_ == NULL) {
worker = new Worker(this);
@@ -51,15 +50,17 @@
worker->all_next_ = all_workers_;
all_workers_ = worker;
worker->owned_ = true;
+ count_running_++;
} else {
// Get the first worker from the idle worker list.
worker = idle_workers_;
idle_workers_ = worker->idle_next_;
worker->idle_next_ = NULL;
count_idle_--;
+ count_running_++;
}
- count_running_++;
}
+
// Release ThreadPool::mutex_ before calling Worker functions.
ASSERT(worker != NULL);
worker->SetTask(task);
@@ -67,6 +68,7 @@
// Call StartThread after we've assigned the first task.
worker->StartThread();
}
+ return true;
}
@@ -94,15 +96,48 @@
}
// Release ThreadPool::mutex_ before calling Worker functions.
- Worker* current = saved;
- while (current != NULL) {
- // We may access all_next_ without holding ThreadPool::mutex_ here
- // because the worker is no longer owned by the ThreadPool.
- Worker* next = current->all_next_;
- current->all_next_ = NULL;
- current->Shutdown();
- current = next;
+ {
+ MonitorLocker eml(&exit_monitor_);
+
+ // First tell all the workers to shut down.
+ Worker* current = saved;
+ ThreadId id = OSThread::GetCurrentThreadId();
+ while (current != NULL) {
+ Worker* next = current->all_next_;
+ ThreadId currentId = current->id();
+ if (currentId != id) {
+ AddWorkerToShutdownList(current);
+ }
+ current->Shutdown();
+ current = next;
+ }
+ saved = NULL;
+
+ // Wait until all workers will exit.
+ while (shutting_down_workers_ != NULL) {
+ // Here, we are waiting for workers to exit. When a worker exits we will
+ // be notified.
+ eml.Wait();
+ }
}
+
+ // Extract the join list, and join on the threads.
+ JoinList* list = NULL;
+ {
+ MutexLocker ml(&mutex_);
+ list = join_list_;
+ join_list_ = NULL;
+ }
+
+ // Join non-idle threads.
+ JoinList::Join(&list);
+
+#if defined(DEBUG)
+ {
+ MutexLocker ml(&mutex_);
+ ASSERT(join_list_ == NULL);
+ }
+#endif
}
@@ -156,7 +191,7 @@
all_workers_ = worker->all_next_;
worker->all_next_ = NULL;
worker->owned_ = false;
- worker->pool_ = NULL;
+ worker->done_ = true;
return true;
}
@@ -174,16 +209,24 @@
}
-void ThreadPool::SetIdle(Worker* worker) {
- MutexLocker ml(&mutex_);
- if (shutting_down_) {
- return;
+void ThreadPool::SetIdleAndReapExited(Worker* worker) {
+ JoinList* list = NULL;
+ {
+ MutexLocker ml(&mutex_);
+ if (shutting_down_) {
+ return;
+ }
+ ASSERT(worker->owned_ && !IsIdle(worker));
+ worker->idle_next_ = idle_workers_;
+ idle_workers_ = worker;
+ count_idle_++;
+ count_running_--;
+
+ // While we have the lock, opportunistically grab and clear the join_list_.
+ list = join_list_;
+ join_list_ = NULL;
}
- ASSERT(worker->owned_ && !IsIdle(worker));
- worker->idle_next_ = idle_workers_;
- idle_workers_ = worker;
- count_idle_++;
- count_running_--;
+ JoinList::Join(&list);
}
@@ -200,12 +243,62 @@
bool found = RemoveWorkerFromAllList(worker);
ASSERT(found);
+ // The thread for worker will exit. Add its ThreadId to the join_list_
+ // so that we can join on it at the next opportunity.
+ JoinList::AddLocked(OSThread::GetCurrentThreadJoinId(), &join_list_);
count_stopped_++;
count_idle_--;
return true;
}
+// Only call while holding the exit_monitor_
+void ThreadPool::AddWorkerToShutdownList(Worker* worker) {
+ worker->shutdown_next_ = shutting_down_workers_;
+ shutting_down_workers_ = worker;
+}
+
+
+// Only call while holding the exit_monitor_
+bool ThreadPool::RemoveWorkerFromShutdownList(Worker* worker) {
+ ASSERT(worker != NULL);
+ ASSERT(shutting_down_workers_ != NULL);
+
+ // Special case head of list.
+ if (shutting_down_workers_ == worker) {
+ shutting_down_workers_ = worker->shutdown_next_;
+ worker->shutdown_next_ = NULL;
+ return true;
+ }
+
+ for (Worker* current = shutting_down_workers_;
+ current->shutdown_next_ != NULL;
+ current = current->shutdown_next_) {
+ if (current->shutdown_next_ == worker) {
+ current->shutdown_next_ = worker->shutdown_next_;
+ worker->shutdown_next_ = NULL;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void ThreadPool::JoinList::AddLocked(ThreadJoinId id, JoinList** list) {
+ *list = new JoinList(id, *list);
+}
+
+
+void ThreadPool::JoinList::Join(JoinList** list) {
+ while (*list != NULL) {
+ JoinList* current = *list;
+ *list = current->next();
+ OSThread::Join(current->id());
+ delete current;
+ }
+}
+
+
ThreadPool::Task::Task() {
}
@@ -217,9 +310,18 @@
ThreadPool::Worker::Worker(ThreadPool* pool)
: pool_(pool),
task_(NULL),
+ id_(OSThread::kInvalidThreadId),
+ done_(false),
owned_(false),
all_next_(NULL),
- idle_next_(NULL) {
+ idle_next_(NULL),
+ shutdown_next_(NULL) {
+}
+
+
+ThreadId ThreadPool::Worker::id() {
+ MonitorLocker ml(&monitor_);
+ return id_;
}
@@ -264,7 +366,7 @@
}
-void ThreadPool::Worker::Loop() {
+bool ThreadPool::Worker::Loop() {
MonitorLocker ml(&monitor_);
int64_t idle_start;
while (true) {
@@ -281,10 +383,10 @@
ASSERT(task_ == NULL);
if (IsDone()) {
- return;
+ return false;
}
- ASSERT(pool_ != NULL);
- pool_->SetIdle(this);
+ ASSERT(!done_);
+ pool_->SetIdleAndReapExited(this);
idle_start = OS::GetCurrentTimeMillis();
while (true) {
Monitor::WaitResult result = ml.Wait(ComputeTimeout(idle_start));
@@ -294,21 +396,21 @@
break;
}
if (IsDone()) {
- return;
+ return false;
}
- if (result == Monitor::kTimedOut &&
- pool_->ReleaseIdleWorker(this)) {
- return;
+ if ((result == Monitor::kTimedOut) && pool_->ReleaseIdleWorker(this)) {
+ return true;
}
}
}
UNREACHABLE();
+ return false;
}
void ThreadPool::Worker::Shutdown() {
MonitorLocker ml(&monitor_);
- pool_ = NULL; // Fail fast if someone tries to access pool_.
+ done_ = true;
ml.Notify();
}
@@ -317,20 +419,58 @@
void ThreadPool::Worker::Main(uword args) {
Thread::EnsureInit();
Worker* worker = reinterpret_cast<Worker*>(args);
- worker->Loop();
+ ThreadId id = OSThread::GetCurrentThreadId();
+ ThreadJoinId join_id = OSThread::GetCurrentThreadJoinId();
+ ThreadPool* pool;
+
+ {
+ MonitorLocker ml(&worker->monitor_);
+ ASSERT(worker->task_);
+ worker->id_ = id;
+ pool = worker->pool_;
+ }
+
+ bool released = worker->Loop();
// It should be okay to access these unlocked here in this assert.
- ASSERT(!worker->owned_ &&
- worker->all_next_ == NULL &&
- worker->idle_next_ == NULL);
+ // worker->all_next_ is retained by the pool for shutdown monitoring.
+ ASSERT(!worker->owned_ && (worker->idle_next_ == NULL));
- // The exit monitor is only used during testing.
- if (ThreadPool::exit_monitor_) {
- MonitorLocker ml(ThreadPool::exit_monitor_);
- (*ThreadPool::exit_count_)++;
- ml.Notify();
+ if (!released) {
+ // This worker is exiting because the thread pool is being shut down.
+ // Inform the thread pool that we are exiting. We remove this worker from
+ // shutting_down_workers_ list because there will be no need for the
+ // ThreadPool to take action for this worker.
+ {
+ MutexLocker ml(&pool->mutex_);
+ JoinList::AddLocked(join_id, &pool->join_list_);
+ }
+
+ // worker->id_ should never be read again, so set to invalid in debug mode
+ // for asserts.
+#if defined(DEBUG)
+ {
+ MonitorLocker ml(&worker->monitor_);
+ worker->id_ = OSThread::kInvalidThreadId;
+ }
+#endif
+
+ // Remove from the shutdown list, delete, and notify the thread pool.
+ {
+ MonitorLocker eml(&pool->exit_monitor_);
+ pool->RemoveWorkerFromShutdownList(worker);
+ delete worker;
+ eml.Notify();
+ }
+ } else {
+ // This worker is going down because it was idle for too long. This case
+ // is not due to a ThreadPool Shutdown. Thus, we simply delete the worker.
+ // The worker's id is added to the thread pool's join list by
+ // ReleaseIdleWorker, so in the case that the thread pool begins shutting
+ // down immediately after returning from worker->Loop() above, we still
+ // wait for the thread to exit by joining on it in Shutdown().
+ delete worker;
}
- delete worker;
#if defined(TARGET_OS_WINDOWS)
Thread::CleanUp();
#endif
diff --git a/runtime/vm/thread_pool.h b/runtime/vm/thread_pool.h
index 792aef7..1713781 100644
--- a/runtime/vm/thread_pool.h
+++ b/runtime/vm/thread_pool.h
@@ -5,6 +5,7 @@
#ifndef VM_THREAD_POOL_H_
#define VM_THREAD_POOL_H_
+#include "vm/allocation.h"
#include "vm/globals.h"
#include "vm/os_thread.h"
@@ -29,12 +30,12 @@
ThreadPool();
- // Shuts down this thread pool. Causes workers to terminate
+ // Shuts down this thread pool. Causes workers to terminate
// themselves when they are active again.
~ThreadPool();
// Runs a task on the thread pool.
- void Run(Task* task);
+ bool Run(Task* task);
// Some simple stats.
uint64_t workers_running() const { return count_running_; }
@@ -43,8 +44,6 @@
uint64_t workers_stopped() const { return count_stopped_; }
private:
- friend class ThreadPoolTestPeer;
-
class Worker {
public:
explicit Worker(ThreadPool* pool);
@@ -56,24 +55,30 @@
// after a task has been set by the initial call to SetTask().
void StartThread();
- // Main loop for a worker.
- void Loop();
+ // Main loop for a worker. Returns true if worker is removed from thread
+ // lists, false otherwise.
+ bool Loop();
// Causes worker to terminate eventually.
void Shutdown();
+ // Get the Worker's thread id.
+ ThreadId id();
+
private:
friend class ThreadPool;
// The main entry point for new worker threads.
static void Main(uword args);
- bool IsDone() const { return pool_ == NULL; }
+ bool IsDone() const { return done_; }
// Fields owned by Worker.
Monitor monitor_;
ThreadPool* pool_;
Task* task_;
+ ThreadId id_;
+ bool done_;
// Fields owned by ThreadPool. Workers should not look at these
// directly. It's like looking at the sun.
@@ -81,9 +86,31 @@
Worker* all_next_; // Protected by ThreadPool::mutex_
Worker* idle_next_; // Protected by ThreadPool::mutex_
+ Worker* shutdown_next_; // Protected by ThreadPool::exit_monitor
+
DISALLOW_COPY_AND_ASSIGN(Worker);
};
+ class JoinList {
+ public:
+ explicit JoinList(ThreadJoinId id, JoinList* next) : id_(id), next_(next) {
+ }
+
+ // The thread pool's mutex_ must be held when calling this.
+ static void AddLocked(ThreadJoinId id, JoinList** list);
+
+ static void Join(JoinList** list);
+
+ ThreadJoinId id() const { return id_; }
+ JoinList* next() const { return next_; }
+
+ private:
+ ThreadJoinId id_;
+ JoinList* next_;
+
+ DISALLOW_COPY_AND_ASSIGN(JoinList);
+ };
+
void Shutdown();
// Expensive. Use only in assertions.
@@ -92,8 +119,13 @@
bool RemoveWorkerFromIdleList(Worker* worker);
bool RemoveWorkerFromAllList(Worker* worker);
+ void AddWorkerToShutdownList(Worker* worker);
+ bool RemoveWorkerFromShutdownList(Worker* worker);
+
+ void ReapExitedIdleThreads();
+
// Worker operations.
- void SetIdle(Worker* worker);
+ void SetIdleAndReapExited(Worker* worker);
bool ReleaseIdleWorker(Worker* worker);
Mutex mutex_;
@@ -105,8 +137,9 @@
uint64_t count_running_;
uint64_t count_idle_;
- static Monitor* exit_monitor_; // Used only in testing.
- static int* exit_count_; // Used only in testing.
+ Monitor exit_monitor_;
+ Worker* shutting_down_workers_;
+ JoinList* join_list_;
DISALLOW_COPY_AND_ASSIGN(ThreadPool);
};
diff --git a/runtime/vm/thread_pool_test.cc b/runtime/vm/thread_pool_test.cc
index 35a6127..48d2125 100644
--- a/runtime/vm/thread_pool_test.cc
+++ b/runtime/vm/thread_pool_test.cc
@@ -12,18 +12,6 @@
DECLARE_FLAG(int, worker_timeout_millis);
-class ThreadPoolTestPeer {
- public:
- // When the pool has an exit monitor, workers notify a monitor just
- // before they exit. This is only used in tests to make sure that
- // Shutdown works.
- static void SetExitMonitor(Monitor* exit_monitor, int* exit_count) {
- ThreadPool::exit_monitor_ = exit_monitor;
- ThreadPool::exit_count_ = exit_count;
- }
-};
-
-
UNIT_TEST_CASE(ThreadPool_Create) {
ThreadPool thread_pool;
}
@@ -88,40 +76,73 @@
class SleepTask : public ThreadPool::Task {
public:
- explicit SleepTask(int millis)
- : millis_(millis) {
+ SleepTask(Monitor* sync, int* started_count, int* slept_count, int millis)
+ : sync_(sync),
+ started_count_(started_count),
+ slept_count_(slept_count),
+ millis_(millis) {
}
virtual void Run() {
+ {
+ MonitorLocker ml(sync_);
+ *started_count_ = *started_count_ + 1;
+ ml.Notify();
+ }
+ // Sleep so we can be sure the ThreadPool destructor blocks until we're
+ // done.
OS::Sleep(millis_);
+ {
+ MonitorLocker ml(sync_);
+ *slept_count_ = *slept_count_ + 1;
+ // No notification here. The main thread is blocked in ThreadPool
+ // shutdown waiting for this thread to finish.
+ }
}
private:
+ Monitor* sync_;
+ int* started_count_;
+ int* slept_count_;
int millis_;
};
UNIT_TEST_CASE(ThreadPool_WorkerShutdown) {
- Monitor exit_sync;
- int exit_count = 0;
- MonitorLocker ml(&exit_sync);
+ const int kTaskCount = 10;
+ Monitor sync;
+ int slept_count = 0;
+ int started_count = 0;
// Set up the ThreadPool so that workers notify before they exit.
ThreadPool* thread_pool = new ThreadPool();
- ThreadPoolTestPeer::SetExitMonitor(&exit_sync, &exit_count);
// Run a single task.
- thread_pool->Run(new SleepTask(2));
+ for (int i = 0; i < kTaskCount; i++) {
+ thread_pool->Run(new SleepTask(&sync, &started_count, &slept_count, 2));
+ }
- // Kill the thread pool.
+ {
+ // Wait for everybody to start.
+ MonitorLocker ml(&sync);
+ while (started_count < kTaskCount) {
+ ml.Wait();
+ }
+ }
+
+ // Kill the thread pool while the workers are sleeping.
delete thread_pool;
thread_pool = NULL;
- // Wait for the workers to terminate.
- while (exit_count == 0) {
- ml.Wait();
+ int final_count = 0;
+ {
+ MonitorLocker ml(&sync);
+ final_count = slept_count;
}
- EXPECT_EQ(1, exit_count);
+
+ // We should have waited for all the workers to finish, so they all should
+ // have had a chance to increment slept_count.
+ EXPECT_EQ(kTaskCount, final_count);
}
@@ -172,12 +193,11 @@
// Spawn 0-2 children.
if (todo_ > 0) {
- pool_->Run(
- new SpawnTask(pool_, sync_, todo_ - child_todo, total_, done_));
+ pool_->Run(new SpawnTask(
+ pool_, sync_, todo_ - child_todo, total_, done_));
}
if (todo_ > 1) {
- pool_->Run(
- new SpawnTask(pool_, sync_, child_todo, total_, done_));
+ pool_->Run(new SpawnTask(pool_, sync_, child_todo, total_, done_));
}
{
@@ -214,5 +234,4 @@
EXPECT_EQ(kTotalTasks, done);
}
-
} // namespace dart
diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc
index d4ef68d..3648bff 100644
--- a/runtime/vm/thread_registry.cc
+++ b/runtime/vm/thread_registry.cc
@@ -10,23 +10,7 @@
namespace dart {
ThreadRegistry::~ThreadRegistry() {
- {
- // Each thread that is scheduled in this isolate may have a cached timeline
- // block. Mark these timeline blocks as finished.
- MonitorLocker ml(monitor_);
- TimelineEventRecorder* recorder = Timeline::recorder();
- if (recorder != NULL) {
- MutexLocker recorder_lock(&recorder->lock_);
- for (intptr_t i = 0; i < entries_.length(); i++) {
- // NOTE: It is only safe to access |entry.state| here.
- const Entry& entry = entries_.At(i);
- if (entry.state.timeline_block != NULL) {
- entry.state.timeline_block->Finish();
- }
- }
- }
- }
-
+ CloseAllTimelineBlocks();
// Delete monitor.
delete monitor_;
}
@@ -83,6 +67,15 @@
if (found_index < 0) {
return;
}
+ {
+ TimelineEventRecorder* recorder = Timeline::recorder();
+ if (recorder != NULL) {
+ MutexLocker recorder_lock(&recorder->lock_);
+ // Cleanup entry.
+ Entry& entry_to_remove = entries_[found_index];
+ CloseTimelineBlockLocked(&entry_to_remove);
+ }
+ }
if (found_index != (length - 1)) {
// Swap with last entry.
entries_.Swap(found_index, length - 1);
@@ -91,6 +84,31 @@
}
+void ThreadRegistry::CloseAllTimelineBlocks() {
+ // Each thread that is scheduled in this isolate may have a cached timeline
+ // block. Mark these timeline blocks as finished.
+ MonitorLocker ml(monitor_);
+ TimelineEventRecorder* recorder = Timeline::recorder();
+ if (recorder != NULL) {
+ MutexLocker recorder_lock(&recorder->lock_);
+ for (intptr_t i = 0; i < entries_.length(); i++) {
+ // NOTE: It is only safe to access |entry.state| here.
+ Entry& entry = entries_[i];
+ CloseTimelineBlockLocked(&entry);
+ }
+ }
+}
+
+
+void ThreadRegistry::CloseTimelineBlockLocked(Entry* entry) {
+ if ((entry != NULL) && !entry->scheduled &&
+ (entry->state.timeline_block != NULL)) {
+ entry->state.timeline_block->Finish();
+ entry->state.timeline_block = NULL;
+ }
+}
+
+
ThreadRegistry::EntryIterator::EntryIterator(ThreadRegistry* registry)
: index_(0),
registry_(NULL) {
diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h
index cb10626..01f52a3 100644
--- a/runtime/vm/thread_registry.h
+++ b/runtime/vm/thread_registry.h
@@ -142,6 +142,8 @@
void PruneThread(Thread* thread);
+ void CloseAllTimelineBlocks();
+
struct Entry {
// NOTE: |thread| is deleted automatically when the thread exits.
// In other words, it is not safe to dereference |thread| unless you are on
@@ -182,6 +184,11 @@
return NULL;
}
+ // Close the timeline block cache inside entry.
+ // NOTE: Lock should be taken before this function is called.
+ // NOTE: Recorder lock should be taken before this function is called.
+ void CloseTimelineBlockLocked(Entry* entry);
+
// Note: Lock should be taken before this function is called.
void CheckSafepointLocked();
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index ecdd085..d510d5e 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -8,15 +8,20 @@
#include "vm/isolate.h"
#include "vm/json_stream.h"
#include "vm/lockers.h"
+#include "vm/log.h"
#include "vm/object.h"
#include "vm/thread.h"
#include "vm/timeline.h"
namespace dart {
-DEFINE_FLAG(bool, trace_timeline, false, "Trace timeline backend");
DEFINE_FLAG(bool, complete_timeline, false, "Record the complete timeline");
-
+DEFINE_FLAG(bool, trace_timeline, false,
+ "Trace timeline backend");
+DEFINE_FLAG(bool, trace_timeline_analysis, false,
+ "Trace timeline analysis backend");
+DEFINE_FLAG(bool, timing, false,
+ "Dump isolate timing information from timeline.");
DEFINE_FLAG(charp, timeline_dir, NULL,
"Enable all timeline trace streams and output VM global trace "
"into specified directory.");
@@ -26,7 +31,8 @@
// Default to ring recorder being enabled.
const bool use_ring_recorder = true;
// Some flags require that we use the endless recorder.
- const bool use_endless_recorder = (FLAG_timeline_dir != NULL);
+ const bool use_endless_recorder =
+ (FLAG_timeline_dir != NULL) || FLAG_timing;
if (use_endless_recorder) {
recorder_ = new TimelineEventEndlessRecorder();
} else if (use_ring_recorder) {
@@ -56,7 +62,7 @@
bool Timeline::EnableStreamByDefault(const char* stream_name) {
// TODO(johnmccutchan): Allow for command line control over streams.
- return FLAG_timeline_dir != NULL;
+ return (FLAG_timeline_dir != NULL) || FLAG_timing;
}
@@ -410,6 +416,10 @@
TimelineEvent* TimelineEventRecorder::GlobalBlockStartEvent() {
MutexLocker ml(&lock_);
+ if (FLAG_trace_timeline) {
+ OS::Print("GlobalBlockStartEvent in block %p for thread %" Px "\n",
+ global_block_, OSThread::CurrentCurrentThreadIdAsIntPtr());
+ }
if ((global_block_ != NULL) && global_block_->IsFull()) {
// Global block is full.
global_block_->Finish();
@@ -418,6 +428,7 @@
if (global_block_ == NULL) {
// Allocate a new block.
global_block_ = GetNewBlockLocked(NULL);
+ ASSERT(global_block_ != NULL);
}
if (global_block_ != NULL) {
ASSERT(!global_block_->IsFull());
@@ -441,11 +452,9 @@
TimelineEventFilter filter;
PrintJSON(&js, &filter);
- const char* format = "%s/dart-timeline-%" Pd ".json";
intptr_t pid = OS::ProcessId();
- intptr_t len = OS::SNPrint(NULL, 0, format, directory, pid);
- char* filename = reinterpret_cast<char*>(malloc(len + 1));
- OS::SNPrint(filename, len + 1, format, directory, pid);
+ char* filename = OS::SCreate(NULL,
+ "%s/dart-timeline-%" Pd ".json", directory, pid);
void* file = (*file_open)(filename, true);
if (file == NULL) {
OS::Print("Failed to write timeline file: %s\n", filename);
@@ -632,7 +641,6 @@
TimelineEventEndlessRecorder::TimelineEventEndlessRecorder()
: head_(NULL),
block_index_(0) {
- GetNewBlock();
}
@@ -670,6 +678,14 @@
block->set_next(head_);
block->Open(isolate);
head_ = block;
+ if (FLAG_trace_timeline) {
+ if (isolate != NULL) {
+ OS::Print("Created new isolate block %p for %s\n",
+ block, isolate->name());
+ } else {
+ OS::Print("Created new global block %p\n", block);
+ }
+ }
return head_;
}
@@ -725,6 +741,10 @@
TimelineEvent* TimelineEventBlock::StartEvent() {
ASSERT(!IsFull());
+ if (FLAG_trace_timeline) {
+ OS::Print("StartEvent in block %p for thread %" Px "\n",
+ this, OSThread::CurrentCurrentThreadIdAsIntPtr());
+ }
return &events_[length_++];
}
@@ -785,6 +805,9 @@
void TimelineEventBlock::Finish() {
+ if (FLAG_trace_timeline) {
+ OS::Print("Finish block %p\n", this);
+ }
open_ = false;
}
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 983d3fc..3c771292 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -396,6 +396,7 @@
void Open(Isolate* isolate);
void Finish();
+ friend class Thread;
friend class ThreadRegistry;
friend class TimelineEventRecorder;
friend class TimelineEventRingRecorder;
diff --git a/runtime/vm/timeline_analysis.cc b/runtime/vm/timeline_analysis.cc
index 08deb77..1ca8442 100644
--- a/runtime/vm/timeline_analysis.cc
+++ b/runtime/vm/timeline_analysis.cc
@@ -10,7 +10,8 @@
namespace dart {
-DEFINE_FLAG(bool, trace_timeline_analysis, false, "Trace timeline analysis");
+DECLARE_FLAG(bool, trace_timeline_analysis);
+DECLARE_FLAG(bool, timing);
TimelineAnalysisThread::TimelineAnalysisThread(ThreadId id)
: id_(id) {
@@ -39,7 +40,7 @@
void TimelineAnalysisThread::Finalize() {
blocks_.Sort(CompareBlocksLowerTimeBound);
if (FLAG_trace_timeline_analysis) {
- ISL_Print("Thread %" Px " has %" Pd " blocks\n",
+ THR_Print("Thread %" Px " has %" Pd " blocks\n",
OSThread::ThreadIdToIntPtr(id_),
blocks_.length());
}
@@ -161,9 +162,13 @@
// Skip empty blocks.
continue;
}
+ if (block->isolate() != isolate_) {
+ // Skip blocks for other isolates.
+ continue;
+ }
if (!block->CheckBlock()) {
if (FLAG_trace_timeline_analysis) {
- ISL_Print("DiscoverThreads block %" Pd " "
+ THR_Print("DiscoverThreads block %" Pd " "
"violates invariants.\n", block->block_index());
}
SetError("Block %" Pd " violates invariants. See "
@@ -226,6 +231,20 @@
}
+void TimelineLabelPauseInfo::Aggregate(
+ const TimelineLabelPauseInfo* thread_pause_info) {
+ ASSERT(thread_pause_info != NULL);
+ inclusive_micros_ += thread_pause_info->inclusive_micros_;
+ exclusive_micros_ += thread_pause_info->exclusive_micros_;
+ if (max_inclusive_micros_ < thread_pause_info->max_inclusive_micros_) {
+ max_inclusive_micros_ = thread_pause_info->max_inclusive_micros_;
+ }
+ if (max_exclusive_micros_ < thread_pause_info->max_exclusive_micros_) {
+ max_exclusive_micros_ = thread_pause_info->max_exclusive_micros_;
+ }
+}
+
+
TimelinePauses::TimelinePauses(Zone* zone,
Isolate* isolate,
TimelineEventRecorder* recorder)
@@ -300,7 +319,7 @@
TimelineAnalysisThreadEventIterator it(thread);
if (FLAG_trace_timeline_analysis) {
- ISL_Print(">>> TimelinePauses::ProcessThread %" Px "\n",
+ THR_Print(">>> TimelinePauses::ProcessThread %" Px "\n",
OSThread::ThreadIdToIntPtr(thread->id()));
}
intptr_t event_count = 0;
@@ -322,7 +341,7 @@
// Pop remaining stack.
PopFinished(kMaxInt64);
if (FLAG_trace_timeline_analysis) {
- ISL_Print("<<< TimelinePauses::ProcessThread %" Px " had %" Pd " events\n",
+ THR_Print("<<< TimelinePauses::ProcessThread %" Px " had %" Pd " events\n",
OSThread::ThreadIdToIntPtr(thread->id()),
event_count);
}
@@ -350,7 +369,7 @@
// Top of stack completes before |start|.
stack_.RemoveLast();
if (FLAG_trace_timeline_analysis) {
- ISL_Print("Popping %s (%" Pd64 " <= %" Pd64 ")\n",
+ THR_Print("Popping %s (%" Pd64 " <= %" Pd64 ")\n",
top.event->label(),
top.event->TimeEnd(),
start);
@@ -367,7 +386,7 @@
ASSERT(pause_info != NULL);
// |pause_info| will be running for |event->TimeDuration()|.
if (FLAG_trace_timeline_analysis) {
- ISL_Print("Pushing %s %" Pd64 " us\n",
+ THR_Print("Pushing %s %" Pd64 " us\n",
pause_info->name(),
event->TimeDuration());
}
@@ -386,7 +405,7 @@
}
-bool TimelinePauses::IsLabelOnStack(const char* label) {
+bool TimelinePauses::IsLabelOnStack(const char* label) const {
ASSERT(label != NULL);
for (intptr_t i = 0; i < stack_.length(); i++) {
const StackItem& slot = stack_.At(i);
@@ -422,4 +441,95 @@
return pause_info;
}
+
+TimelinePauseTrace::TimelinePauseTrace() {
+}
+
+
+TimelinePauseTrace::~TimelinePauseTrace() {
+}
+
+
+void TimelinePauseTrace::Print() {
+ Thread* thread = Thread::Current();
+ ASSERT(thread != NULL);
+ Isolate* isolate = thread->isolate();
+ ASSERT(isolate != NULL);
+ Zone* zone = thread->zone();
+ ASSERT(zone != NULL);
+ TimelineEventRecorder* recorder = Timeline::recorder();
+ ASSERT(recorder != NULL);
+ TimelinePauses pauses(zone, isolate, recorder);
+ pauses.Setup();
+
+ THR_Print("Timing for isolate %s (from %" Pd " threads)\n",
+ isolate->name(),
+ pauses.NumThreads());
+ THR_Print("\n");
+ for (intptr_t t_idx = 0; t_idx < pauses.NumThreads(); t_idx++) {
+ TimelineAnalysisThread* tat = pauses.At(t_idx);
+ ASSERT(tat != NULL);
+ pauses.CalculatePauseTimesForThread(tat->id());
+ THR_Print("Thread %" Pd " (%" Px "):\n",
+ t_idx,
+ OSThread::ThreadIdToIntPtr(tat->id()));
+ for (intptr_t j = 0; j < pauses.NumPauseInfos(); j++) {
+ const TimelineLabelPauseInfo* pause_info = pauses.PauseInfoAt(j);
+ ASSERT(pause_info != NULL);
+ Aggregate(pause_info);
+ PrintPauseInfo(pause_info);
+ }
+ THR_Print("\n");
+ }
+ THR_Print("Totals:\n");
+ for (intptr_t i = 0; i < isolate_labels_.length(); i++) {
+ TimelineLabelPauseInfo* pause_info = isolate_labels_.At(i);
+ ASSERT(pause_info != NULL);
+ PrintPauseInfo(pause_info);
+ }
+ THR_Print("\n");
+}
+
+
+TimelineLabelPauseInfo* TimelinePauseTrace::GetOrAddLabelPauseInfo(
+ const char* name) {
+ ASSERT(name != NULL);
+ // Linear lookup because we expect N (# of labels in an isolate) to be small.
+ for (intptr_t i = 0; i < isolate_labels_.length(); i++) {
+ TimelineLabelPauseInfo* label = isolate_labels_.At(i);
+ if (strcmp(label->name(), name) == 0) {
+ return label;
+ }
+ }
+ // New label.
+ TimelineLabelPauseInfo* pause_info = new TimelineLabelPauseInfo(name);
+ isolate_labels_.Add(pause_info);
+ return pause_info;
+}
+
+
+void TimelinePauseTrace::Aggregate(
+ const TimelineLabelPauseInfo* thread_pause_info) {
+ ASSERT(thread_pause_info != NULL);
+ TimelineLabelPauseInfo* isolate_pause_info =
+ GetOrAddLabelPauseInfo(thread_pause_info->name());
+ ASSERT(isolate_pause_info != NULL);
+ isolate_pause_info->Aggregate(thread_pause_info);
+}
+
+
+void TimelinePauseTrace::PrintPauseInfo(
+ const TimelineLabelPauseInfo* pause_info) {
+ ASSERT(pause_info != NULL);
+ THR_Print("%s : ", pause_info->name());
+ THR_Print("%.3f ms total on stack; ",
+ MicrosecondsToMilliseconds(pause_info->inclusive_micros()));
+ THR_Print("%.3f ms total executing; ",
+ MicrosecondsToMilliseconds(pause_info->exclusive_micros()));
+ THR_Print("%.3f ms max on stack; ",
+ MicrosecondsToMilliseconds(pause_info->max_inclusive_micros()));
+ THR_Print("%.3f ms max executing.\n",
+ MicrosecondsToMilliseconds(pause_info->max_exclusive_micros()));
+}
+
} // namespace dart
diff --git a/runtime/vm/timeline_analysis.h b/runtime/vm/timeline_analysis.h
index 5f5049b..b49d821 100644
--- a/runtime/vm/timeline_analysis.h
+++ b/runtime/vm/timeline_analysis.h
@@ -150,6 +150,8 @@
ASSERT(exclusive_micros_ >= 0);
}
+ void Aggregate(const TimelineLabelPauseInfo* thread_pause_info);
+
const char* name_;
int64_t inclusive_micros_;
int64_t exclusive_micros_;
@@ -157,6 +159,7 @@
int64_t max_exclusive_micros_;
friend class TimelinePauses;
+ friend class TimelinePauseTrace;
};
@@ -177,6 +180,14 @@
int64_t MaxInclusiveTime(const char* name) const;
int64_t MaxExclusiveTime(const char* name) const;
+ intptr_t NumPauseInfos() const {
+ return labels_.length();
+ }
+
+ const TimelineLabelPauseInfo* PauseInfoAt(intptr_t i) const {
+ return labels_.At(i);
+ }
+
private:
struct StackItem {
TimelineEvent* event;
@@ -188,7 +199,7 @@
bool CheckStack(TimelineEvent* event);
void PopFinished(int64_t start);
void Push(TimelineEvent* event);
- bool IsLabelOnStack(const char* label);
+ bool IsLabelOnStack(const char* label) const;
intptr_t StackDepth() const;
StackItem& GetStackTop();
TimelineLabelPauseInfo* GetOrAddLabelPauseInfo(const char* name);
@@ -197,6 +208,22 @@
ZoneGrowableArray<TimelineLabelPauseInfo*> labels_;
};
+
+class TimelinePauseTrace : public ValueObject {
+ public:
+ TimelinePauseTrace();
+ ~TimelinePauseTrace();
+
+ void Print();
+
+ private:
+ TimelineLabelPauseInfo* GetOrAddLabelPauseInfo(const char* name);
+ void Aggregate(const TimelineLabelPauseInfo* thread_pause_info);
+ void PrintPauseInfo(const TimelineLabelPauseInfo* pause_info);
+
+ ZoneGrowableArray<TimelineLabelPauseInfo*> isolate_labels_;
+};
+
} // namespace dart
#endif // VM_TIMELINE_ANALYSIS_H_
diff --git a/runtime/vm/unicode.cc b/runtime/vm/unicode.cc
index 615e87b..8e1649e 100644
--- a/runtime/vm/unicode.cc
+++ b/runtime/vm/unicode.cc
@@ -102,8 +102,7 @@
if (!((is_malformed == false) &&
(j == num_trail_bytes) &&
!Utf::IsOutOfRange(ch) &&
- !IsNonShortestForm(ch, j) &&
- !Utf16::IsSurrogate(ch))) {
+ !IsNonShortestForm(ch, j))) {
return false;
}
}
@@ -201,8 +200,7 @@
if (!((is_malformed == false) &&
(i == num_trail_bytes) &&
!Utf::IsOutOfRange(ch) &&
- !IsNonShortestForm(ch, i) &&
- !Utf16::IsSurrogate(ch))) {
+ !IsNonShortestForm(ch, i))) {
*dst = -1;
return 0;
}
diff --git a/runtime/vm/unicode_test.cc b/runtime/vm/unicode_test.cc
index 582a2a6..36fdf85 100644
--- a/runtime/vm/unicode_test.cc
+++ b/runtime/vm/unicode_test.cc
@@ -832,6 +832,8 @@
}
// 5.1 - Single UTF-16 surrogates
+ // UTF-8 suggests single surrogates are invalid, but both JS and
+ // Dart allow them and make use of them.
// 5.1.1 - U+D800 = ed a0 80 = "\xED\xA0\x80"
{
@@ -840,8 +842,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.1.2 - U+DB7F = ed ad bf = "\xED\xAD\xBF"
@@ -851,8 +853,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.1.3 - U+DB80 = ed ae 80 = "\xED\xAE\x80"
@@ -862,8 +864,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.1.4 - U+DBFF = ed af bf = "\xED\xAF\xBF"
@@ -873,8 +875,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.1.5 - U+DC00 = ed b0 80 = "\xED\xB0\x80"
@@ -884,8 +886,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.1.6 - U+DF80 = ed be 80 = "\xED\xBE\x80"
@@ -895,8 +897,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.1.7 - U+DFFF = ed bf bf = "\xED\xBF\xBF"
@@ -906,11 +908,16 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.2 Paired UTF-16 surrogates
+ // Also not a valid string, but accepted in Dart, even if it doesn't make
+ // sense. e.g.
+ // var s = new String.fromCharCodes([0xd800, 0xDC00]);
+ // print(s.runes); // (65536) (0x10000)
+ // print(s.codeUnits); // [55296, 56320]
// 5.2.1 - U+D800 U+DC00 = ed a0 80 ed b0 80 = "\xED\xA0\x80\xED\xB0\x80"
{
@@ -919,8 +926,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.2.2 - U+D800 U+DFFF = ed a0 80 ed bf bf = "\xED\xA0\x80\xED\xBF\xBF"
@@ -930,8 +937,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.2.3 - U+DB7F U+DC00 = ed a0 80 ed bf bf = "\xED\xAD\xBF\xED\xB0\x80"
@@ -941,8 +948,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.2.4 - U+DB7F U+DFFF = ed ad bf ed bf bf = "\xED\xAD\xBF\xED\xBF\xBF"
@@ -952,8 +959,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.2.5 - U+DB80 U+DC00 = ed ae 80 ed b0 80 = "\xED\xAE\x80\xED\xB0\x80"
@@ -963,8 +970,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.2.6 - U+DB80 U+DFFF = ed ae 80 ed bf bf = "\xED\xAE\x80\xED\xBF\xBF"
@@ -974,8 +981,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.2.7 - U+DBFF U+DC00 = ed af bf ed b0 80 = "\xED\xAF\xBF\xED\xB0\x80"
@@ -985,8 +992,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.2.8 - U+DBFF U+DFFF = ed af bf ed bf bf = "\xED\xAF\xBF\xED\xBF\xBF"
@@ -996,8 +1003,8 @@
int32_t dst[ARRAY_SIZE(expected)];
memset(dst, 0, sizeof(dst));
bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
- EXPECT(!is_valid);
- EXPECT(memcmp(expected, dst, sizeof(expected)));
+ EXPECT(is_valid);
+ EXPECT(!memcmp(expected, dst, sizeof(expected)));
}
// 5.3 - Other illegal code positions
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 421bbdc..9694527 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -282,4 +282,24 @@
}
+void ElideJSONSubstring(const char* prefix, const char* in, char* out) {
+ const char* pos = strstr(in, prefix);
+ while (pos != NULL) {
+ // Copy up to pos into the output buffer.
+ while (in < pos) {
+ *out++ = *in++;
+ }
+
+ // Skip to the close quote.
+ in += strcspn(in, "\"");
+ pos = strstr(in, prefix);
+ }
+ // Copy the remainder of in to out.
+ while (*in != '\0') {
+ *out++ = *in++;
+ }
+ *out = '\0';
+}
+
+
} // namespace dart
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 1edeb15..d4853e4 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -521,6 +521,24 @@
} \
} while (0)
+
+// Elide a substring which starts with some prefix and ends with a ".
+//
+// This is used to remove non-deterministic or fragile substrings from
+// JSON output.
+//
+// For example:
+//
+// prefix = "classes"
+// in = "\"id\":\"classes/46\""
+//
+// Yields:
+//
+// out = "\"id\":\"\""
+//
+void ElideJSONSubstring(const char* prefix, const char* in, char* out);
+
+
} // namespace dart
#endif // VM_UNIT_TEST_H_
diff --git a/runtime/vm/verified_memory_test.cc b/runtime/vm/verified_memory_test.cc
index 6d97216..21978e7 100644
--- a/runtime/vm/verified_memory_test.cc
+++ b/runtime/vm/verified_memory_test.cc
@@ -15,12 +15,22 @@
}
+void Shutdown() {
+#if defined(DEBUG)
+ // We must reset this to false to avoid checking some assumptions in
+ // VM shutdown that are left violated by these tests.
+ FLAG_verified_mem = false;
+#endif
+}
+
+
UNIT_TEST_CASE(VerifiedMemoryReserve) {
Init();
const intptr_t kReservationSize = 64 * KB;
VirtualMemory* vm = VerifiedMemory::Reserve(kReservationSize);
EXPECT_EQ(kReservationSize, vm->size());
delete vm;
+ Shutdown();
}
@@ -31,6 +41,7 @@
EXPECT_EQ(kReservationSize, vm->size());
vm->Commit(false);
delete vm;
+ Shutdown();
}
@@ -53,6 +64,7 @@
*unverified = 123;
VerifiedMemory::Verify(reinterpret_cast<uword>(addr), 3 * sizeof(double));
delete vm;
+ Shutdown();
}
@@ -72,6 +84,7 @@
VerifiedMemory::Accept(reinterpret_cast<uword>(addr), 2 * sizeof(double));
VerifiedMemory::Verify(reinterpret_cast<uword>(addr), 3 * sizeof(double));
delete vm;
+ Shutdown();
}
@@ -86,6 +99,7 @@
double* addr = reinterpret_cast<double*>(vm->address());
addr[0] = 0.5; // Forget to use Write.
VerifiedMemory::Write(&addr[0], 1.5);
+ Shutdown();
}
@@ -101,6 +115,7 @@
addr[1] = 3.5; // Forget to use Write.
VerifiedMemory::Write(&addr[2], 2.5);
VerifiedMemory::Verify(reinterpret_cast<uword>(addr), 3 * sizeof(double));
+ Shutdown();
}
} // namespace dart
diff --git a/runtime/vm/version_in.cc b/runtime/vm/version_in.cc
index 34d7fc6..d196310 100644
--- a/runtime/vm/version_in.cc
+++ b/runtime/vm/version_in.cc
@@ -14,14 +14,9 @@
const char* Version::String() {
if (formatted_version == NULL) {
- const char* format = "%s on \"%s_%s\"";
const char* os = OS::Name();
const char* arch = CPU::Id();
-
- intptr_t len = OS::SNPrint(NULL, 0, format, str_, os, arch);
- char* buffer = reinterpret_cast<char*>(malloc(len + 1));
- OS::SNPrint(buffer, (len + 1), format, str_, os, arch);
- formatted_version = buffer;
+ formatted_version = OS::SCreate(NULL, "%s on \"%s_%s\"", str_, os, arch);
}
return formatted_version;
}
diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc
index c271991..ea42f49 100644
--- a/runtime/vm/zone.cc
+++ b/runtime/vm/zone.cc
@@ -203,24 +203,14 @@
char* Zone::PrintToString(const char* format, ...) {
va_list args;
va_start(args, format);
- return VPrint(format, args);
+ char* buffer = OS::VSCreate(this, format, args);
+ va_end(args);
+ return buffer;
}
char* Zone::VPrint(const char* format, va_list args) {
- // Measure.
- va_list measure_args;
- va_copy(measure_args, args);
- intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
- va_end(measure_args);
-
- // Print.
- char* buffer = Alloc<char>(len + 1);
- va_list print_args;
- va_copy(print_args, args);
- OS::VSNPrint(buffer, (len + 1), format, print_args);
- va_end(print_args);
- return buffer;
+ return OS::VSCreate(this, format, args);
}
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index 4850e5e..361e6e2 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -46,9 +46,12 @@
// Make a copy of the string in the zone allocated area.
char* MakeCopyOfString(const char* str);
+ // TODO(zra): Remove these calls and replace them with calls to OS::SCreate
+ // and OS::VSCreate.
+ // These calls are deprecated. Do not add further calls to these functions.
+ // instead use OS::SCreate and OS::VSCreate.
// Make a zone-allocated string based on printf format and args.
char* PrintToString(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
-
char* VPrint(const char* format, va_list args);
// Compute the total size of this zone. This includes wasted space that is
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 3c639dc..7d6ad7c 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -18,7 +18,8 @@
stringJoinUnchecked,
objectHashCode,
Closure,
- readHttp;
+ readHttp,
+ JsLinkedHashMap;
import 'dart:_foreign_helper' show JS;
@@ -311,6 +312,9 @@
class Map<K, V> {
@patch
factory Map.unmodifiable(Map other) = ConstantMap<K, V>.from;
+
+ @patch
+ factory Map() = JsLinkedHashMap<K, V>.es6;
}
@patch
diff --git a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
index 15cafa8..8349d14 100644
--- a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
@@ -4,7 +4,7 @@
// Patch file for dart:developer library.
-import 'dart:_js_helper' show patch;
+import 'dart:_js_helper' show patch, ForceInline;
import 'dart:_foreign_helper' show JS;
@patch
diff --git a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
index eb68107..70eda5b 100644
--- a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
@@ -62,9 +62,15 @@
@patch
static Future<Isolate> spawnUri(
Uri uri, List<String> args, var message,
- {bool paused: false, bool checked, Uri packageRoot, bool errorsAreFatal,
- SendPort onExit, SendPort onError}) {
+ {bool paused: false,
+ bool checked,
+ Uri packageRoot,
+ Map<String, Uri> packages,
+ bool errorsAreFatal,
+ SendPort onExit,
+ SendPort onError}) {
if (packageRoot != null) throw new UnimplementedError("packageRoot");
+ if (packages != null) throw new UnimplementedError("packages");
bool forcePause = (errorsAreFatal != null) ||
(onExit != null) ||
(onError != null);
@@ -78,6 +84,7 @@
} else if (args != null) {
throw new ArgumentError("Args must be a list of Strings $args");
}
+ // TODO: Handle [packageRoot]/[packages] somehow, possibly by throwing.
// TODO: Consider passing the errorsAreFatal/onExit/onError values
// as arguments to the internal spawnUri instead of setting
// them after the isolate has been created.
diff --git a/sdk/lib/_internal/js_runtime/lib/js_array.dart b/sdk/lib/_internal/js_runtime/lib/js_array.dart
index 51a8fb4..5495a6c 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_array.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_array.dart
@@ -150,7 +150,7 @@
E removeLast() {
checkGrowable('removeLast');
- if (length == 0) throw new RangeError.value(-1);
+ if (length == 0) throw diagnoseIndexError(this, -1);
return JS('var', r'#.pop()', this);
}
@@ -351,14 +351,14 @@
checkNull(start); // TODO(ahe): This is not specified but co19 tests it.
if (start is !int) throw argumentErrorValue(start);
if (start < 0 || start > length) {
- throw new RangeError.range(start, 0, length);
+ throw new RangeError.range(start, 0, length, "start");
}
if (end == null) {
end = length;
} else {
if (end is !int) throw argumentErrorValue(end);
if (end < start || end > length) {
- throw new RangeError.range(end, start, length);
+ throw new RangeError.range(end, start, length, "end");
}
}
if (start == end) return <E>[];
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 91049cd..b4ab91c 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -1566,7 +1566,7 @@
*/
@NoInline()
Error diagnoseIndexError(indexable, index) {
- if (index is !int) return new ArgumentError.value(index, 'index');
+ if (index is! int) return new ArgumentError.value(index, 'index');
int length = indexable.length;
// The following returns the same error that would be thrown by calling
// [RangeError.checkValidIndex] with no optional parameters provided.
@@ -1577,6 +1577,29 @@
return new RangeError.value(index, 'index');
}
+/**
+ * Diagnoses a range error. Returns the ArgumentError or RangeError that
+ * describes the problem.
+ */
+@NoInline()
+Error diagnoseRangeError(start, end, length) {
+ if (start is! int) {
+ return new ArgumentError.value(start, 'start');
+ }
+ if (start < 0 || start > length) {
+ return new RangeError.range(start, 0, length, 'start');
+ }
+ if (end != null) {
+ if (end is! int) {
+ return new ArgumentError.value(end, 'end');
+ }
+ if (end < start || end > length) {
+ return new RangeError.range(end, start, length, 'end');
+ }
+ }
+ // The above should always match, but if it does not, use the following.
+ return new ArgumentError.value(end, "end");
+}
stringLastIndexOfUnchecked(receiver, element, start)
=> JS('int', r'#.lastIndexOf(#, #)', receiver, element, start);
diff --git a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
index d134c6d..ec50a86 100644
--- a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
+++ b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
@@ -13,7 +13,7 @@
import 'dart:_interceptors' show JSIndexable, JSUInt32, JSUInt31;
import 'dart:_js_helper' show
Creates, JavaScriptIndexingBehavior, JSName, Native, Null, Returns,
- diagnoseIndexError;
+ diagnoseIndexError, diagnoseRangeError;
import 'dart:_foreign_helper' show JS;
import 'dart:math' as Math;
@@ -148,39 +148,10 @@
int get elementSizeInBytes => Float32x4List.BYTES_PER_ELEMENT;
- void _invalidIndex(int index, int length) {
- if (index < 0 || index >= length) {
- if (length == this.length) {
- throw new RangeError.index(index, this);
- }
- throw new RangeError.range(index, 0, length - 1);
- } else {
- throw new ArgumentError('Invalid list index $index');
- }
- }
-
- void _checkIndex(int index, int length) {
- if (JS('bool', '(# >>> 0 != #)', index, index) || index >= length) {
- _invalidIndex(index, length);
- }
- }
-
- int _checkSublistArguments(int start, int end, int length) {
- // For `sublist` the [start] and [end] indices are allowed to be equal to
- // [length]. However, [_checkIndex] only allows indices in the range
- // 0 .. length - 1. We therefore increment the [length] argument by one
- // for the [_checkIndex] checks.
- _checkIndex(start, length + 1);
- if (end == null) return length;
- _checkIndex(end, length + 1);
- if (start > end) throw new RangeError.range(start, 0, end);
- return end;
- }
-
int get length => _storage.length ~/ 4;
Float32x4 operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
double _x = _storage[(index * 4) + 0];
double _y = _storage[(index * 4) + 1];
double _z = _storage[(index * 4) + 2];
@@ -189,7 +160,7 @@
}
void operator[]=(int index, Float32x4 value) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
_storage[(index * 4) + 0] = value.x;
_storage[(index * 4) + 1] = value.y;
_storage[(index * 4) + 2] = value.z;
@@ -197,7 +168,7 @@
}
List<Float32x4> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
return new NativeFloat32x4List._externalStorage(
_storage.sublist(start * 4, end * 4));
}
@@ -257,40 +228,10 @@
int get elementSizeInBytes => Int32x4List.BYTES_PER_ELEMENT;
- void _invalidIndex(int index, int length) {
- if (index < 0 || index >= length) {
- if (length == this.length) {
- throw new RangeError.index(index, this);
- }
- throw new RangeError.range(index, 0, length - 1);
- } else {
- throw new ArgumentError('Invalid list index $index');
- }
- }
-
- void _checkIndex(int index, int length) {
- if (JS('bool', '(# >>> 0 != #)', index, index)
- || JS('bool', '# >= #', index, length)) {
- _invalidIndex(index, length);
- }
- }
-
- int _checkSublistArguments(int start, int end, int length) {
- // For `sublist` the [start] and [end] indices are allowed to be equal to
- // [length]. However, [_checkIndex] only allows indices in the range
- // 0 .. length - 1. We therefore increment the [length] argument by one
- // for the [_checkIndex] checks.
- _checkIndex(start, length + 1);
- if (end == null) return length;
- _checkIndex(end, length + 1);
- if (start > end) throw new RangeError.range(start, 0, end);
- return end;
- }
-
int get length => _storage.length ~/ 4;
Int32x4 operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
int _x = _storage[(index * 4) + 0];
int _y = _storage[(index * 4) + 1];
int _z = _storage[(index * 4) + 2];
@@ -299,7 +240,7 @@
}
void operator[]=(int index, Int32x4 value) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
_storage[(index * 4) + 0] = value.x;
_storage[(index * 4) + 1] = value.y;
_storage[(index * 4) + 2] = value.z;
@@ -307,7 +248,7 @@
}
List<Int32x4> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
return new NativeInt32x4List._externalStorage(
_storage.sublist(start * 4, end * 4));
}
@@ -366,52 +307,23 @@
int get elementSizeInBytes => Float64x2List.BYTES_PER_ELEMENT;
- void _invalidIndex(int index, int length) {
- if (index < 0 || index >= length) {
- if (length == this.length) {
- throw new RangeError.index(index, this);
- }
- throw new RangeError.range(index, 0, length - 1);
- } else {
- throw new ArgumentError('Invalid list index $index');
- }
- }
-
- void _checkIndex(int index, int length) {
- if (JS('bool', '(# >>> 0 != #)', index, index) || index >= length) {
- _invalidIndex(index, length);
- }
- }
-
- int _checkSublistArguments(int start, int end, int length) {
- // For `sublist` the [start] and [end] indices are allowed to be equal to
- // [length]. However, [_checkIndex] only allows indices in the range
- // 0 .. length - 1. We therefore increment the [length] argument by one
- // for the [_checkIndex] checks.
- _checkIndex(start, length + 1);
- if (end == null) return length;
- _checkIndex(end, length + 1);
- if (start > end) throw new RangeError.range(start, 0, end);
- return end;
- }
-
int get length => _storage.length ~/ 2;
Float64x2 operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
double _x = _storage[(index * 2) + 0];
double _y = _storage[(index * 2) + 1];
return new Float64x2(_x, _y);
}
void operator[]=(int index, Float64x2 value) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
_storage[(index * 2) + 0] = value.x;
_storage[(index * 2) + 1] = value.y;
}
List<Float64x2> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
return new NativeFloat64x2List._externalStorage(
_storage.sublist(start * 2, end * 2));
}
@@ -446,37 +358,20 @@
@JSName('BYTES_PER_ELEMENT')
final int elementSizeInBytes;
- void _checkIndex(int index, int length) {
- if (JS('bool', '(# >>> 0) !== #', index, index) ||
- JS('int', '#', index) >= length) { // 'int' guaranteed by above test.
- throw diagnoseIndexError(this, index);
- }
- }
-
- void _invalidPosition(int position, int length) {
+ void _invalidPosition(int position, int length, String name) {
if (position is !int) {
- throw new ArgumentError.value(position, null, 'Invalid list position');
+ throw new ArgumentError.value(position, name, 'Invalid list position');
} else {
- throw new RangeError.range(position, 0, length);
+ throw new RangeError.range(position, 0, length, name);
}
}
- void _checkPosition(int position, int length) {
+ void _checkPosition(int position, int length, String name) {
if (JS('bool', '(# >>> 0) !== #', position, position) ||
JS('int', '#', position) > length) { // 'int' guaranteed by above test.
- _invalidPosition(position, length);
+ _invalidPosition(position, length, name);
}
}
-
- int _checkSublistArguments(int start, int end, int length) {
- // For `sublist` the [start] and [end] indices are allowed to be equal to
- // [length].
- _checkPosition(start, length);
- if (end == null) return length;
- _checkPosition(end, length);
- if (start > end) throw new RangeError.range(start, 0, end);
- return end;
- }
}
@@ -862,8 +757,8 @@
void _setRangeFast(int start, int end,
NativeTypedArray source, int skipCount) {
int targetLength = this.length;
- _checkPosition(start, targetLength);
- _checkPosition(end, targetLength);
+ _checkPosition(start, targetLength, "start");
+ _checkPosition(end, targetLength, "end");
if (start > end) throw new RangeError.range(start, 0, end);
int count = end - start;
@@ -888,12 +783,12 @@
with ListMixin<double>, FixedLengthListMixin<double> {
num operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
return JS('num', '#[#]', this, index);
}
void operator[]=(int index, num value) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
JS('void', '#[#] = #', this, index, value);
}
@@ -916,7 +811,7 @@
// types
void operator[]=(int index, int value) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
JS('void', '#[#] = #', this, index, value);
}
@@ -952,7 +847,7 @@
Type get runtimeType => Float32List;
List<double> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
var source = JS('NativeFloat32List', '#.subarray(#, #)', this, start, end);
return _create1(source);
}
@@ -989,7 +884,7 @@
Type get runtimeType => Float64List;
List<double> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
var source = JS('NativeFloat64List', '#.subarray(#, #)', this, start, end);
return _create1(source);
}
@@ -1026,12 +921,12 @@
Type get runtimeType => Int16List;
int operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
return JS('int', '#[#]', this, index);
}
List<int> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
var source = JS('NativeInt16List', '#.subarray(#, #)', this, start, end);
return _create1(source);
}
@@ -1066,12 +961,12 @@
Type get runtimeType => Int32List;
int operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
return JS('int', '#[#]', this, index);
}
List<int> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
var source = JS('NativeInt32List', '#.subarray(#, #)', this, start, end);
return _create1(source);
}
@@ -1106,12 +1001,12 @@
Type get runtimeType => Int8List;
int operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
return JS('int', '#[#]', this, index);
}
List<int> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
var source = JS('NativeInt8List', '#.subarray(#, #)', this, start, end);
return _create1(source);
}
@@ -1146,12 +1041,12 @@
Type get runtimeType => Uint16List;
int operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
return JS('JSUInt31', '#[#]', this, index);
}
List<int> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
var source = JS('NativeUint16List', '#.subarray(#, #)', this, start, end);
return _create1(source);
}
@@ -1186,12 +1081,12 @@
Type get runtimeType => Uint32List;
int operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
return JS('JSUInt32', '#[#]', this, index);
}
List<int> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
var source = JS('NativeUint32List', '#.subarray(#, #)', this, start, end);
return _create1(source);
}
@@ -1230,12 +1125,12 @@
int get length => JS('JSUInt32', '#.length', this);
int operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
return JS('JSUInt31', '#[#]', this, index);
}
List<int> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
var source = JS('NativeUint8ClampedList', '#.subarray(#, #)',
this, start, end);
return _create1(source);
@@ -1278,12 +1173,12 @@
int get length => JS('JSUInt32', '#.length', this);
int operator[](int index) {
- _checkIndex(index, length);
+ _checkValidIndex(index, this, this.length);
return JS('JSUInt31', '#[#]', this, index);
}
List<int> sublist(int start, [int end]) {
- end = _checkSublistArguments(start, end, length);
+ end = _checkValidRange(start, end, this.length);
var source = JS('NativeUint8List', '#.subarray(#, #)', this, start, end);
return _create1(source);
}
@@ -2006,3 +1901,37 @@
return new NativeFloat64x2._doubles(Math.sqrt(x), Math.sqrt(y));
}
}
+
+/// Checks that the value is a Uint32. If not, it's not valid as an array
+/// index or offset. Also ensures that the value is non-negative.
+bool _isInvalidArrayIndex(int index) {
+ return (JS('bool', '(# >>> 0 !== #)', index, index));
+}
+
+/// Checks that [index] is a valid index into [list] which has length [length].
+///
+/// That is, [index] is an insteger in the range `0..length - 1`.
+void _checkValidIndex(int index, List list, int length) {
+ if (_isInvalidArrayIndex(index) || JS('int', '#', index) >= length) {
+ throw diagnoseIndexError(list, index);
+ }
+}
+
+/// Checks that [start] and [end] form a range of a list of length [length].
+///
+/// That is: `start` and `end` are integers with `0 <= start <= end <= length`.
+/// If `end` is `null` in which case it is considered to be `length`
+///
+/// Returns the actual value of `end`, which is `length` if `end` is `null`, and
+/// the original value of `end` otherwise.
+int _checkValidRange(int start, int end, int length) {
+ if (_isInvalidArrayIndex(start) || // Ensures start is non-negative int.
+ ((end == null) ? start > length
+ : (_isInvalidArrayIndex(end) ||
+ start > end ||
+ end > length))) {
+ throw diagnoseRangeError(start, end, length);
+ }
+ if (end == null) return length;
+ return end;
+}
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index 6fb73a5..5a22dc0 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.dart
@@ -27,7 +27,7 @@
*
* Iterating the map's keys, values or entries (through [forEach])
* may happen in any order.
- * The itearation order only changes when the map is modified.
+ * The iteration order only changes when the map is modified.
* Values are iterated in the same order as their associated keys,
* so iterating the [keys] and [values] in parallel
* will give matching key and value pairs.
diff --git a/sdk/lib/convert/utf.dart b/sdk/lib/convert/utf.dart
index 9128e61..8b1a1e0 100644
--- a/sdk/lib/convert/utf.dart
+++ b/sdk/lib/convert/utf.dart
@@ -66,7 +66,7 @@
return new Utf8Decoder(allowMalformed: allowMalformed).convert(codeUnits);
}
- Utf8Encoder get encoder => new Utf8Encoder();
+ Utf8Encoder get encoder => const Utf8Encoder();
Utf8Decoder get decoder {
return new Utf8Decoder(allowMalformed: _allowMalformed);
}
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index 0e99b0b..3053807 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -392,12 +392,13 @@
String get _errorName => "RangeError";
String get _errorExplanation {
assert(_hasValue);
- String target = Error.safeToString(indexable);
- var explanation = ": index should be less than $length";
if (invalidValue < 0) {
- explanation = ": index must not be negative";
+ return ": index must not be negative";
}
- return explanation;
+ if (length == 0) {
+ return ": no indices are valid";
+ }
+ return ": index should be less than $length";
}
}
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index d19d108..e92c780 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -35,7 +35,7 @@
* `operator==` and `hashCode`, and it allows null as a key.
* It iterates in key insertion order.
*/
- factory Map() = LinkedHashMap<K, V>;
+ external factory Map();
/**
* Creates a [LinkedHashMap] instance that contains all key-value pairs of
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 2164bc9..6b0dc96 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -632,8 +632,7 @@
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "readByte failed", path);
}
- _resourceInfo.readCount++;
- _resourceInfo.totalRead++;
+ _resourceInfo.addRead(1);
return response;
});
}
@@ -646,8 +645,7 @@
if (result is OSError) {
throw new FileSystemException("readByte failed", path, result);
}
- _resourceInfo.readCount++;
- _resourceInfo.totalRead++;
+ _resourceInfo.addRead(1);
return result;
}
@@ -659,8 +657,7 @@
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "read failed", path);
}
- _resourceInfo.readCount++;
- _resourceInfo.totalRead += response[1].length;
+ _resourceInfo.addRead(response[1].length);
return response[1];
});
}
@@ -676,8 +673,7 @@
if (result is OSError) {
throw new FileSystemException("readSync failed", path, result);
}
- _resourceInfo.readCount++;
- _resourceInfo.totalRead += result.length;
+ _resourceInfo.addRead(result.length);
return result;
}
@@ -697,8 +693,7 @@
var read = response[1];
var data = response[2];
buffer.setRange(start, start + read, data);
- _resourceInfo.readCount++;
- _resourceInfo.totalRead += read;
+ _resourceInfo.addRead(read);
return read;
});
}
@@ -718,8 +713,7 @@
if (result is OSError) {
throw new FileSystemException("readInto failed", path, result);
}
- _resourceInfo.readCount++;
- _resourceInfo.totalRead += result;
+ _resourceInfo.addRead(result);
return result;
}
@@ -731,8 +725,7 @@
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "writeByte failed", path);
}
- _resourceInfo.writeCount++;
- _resourceInfo.totalWritten++;
+ _resourceInfo.addWrite(1);
return this;
});
}
@@ -748,8 +741,7 @@
if (result is OSError) {
throw new FileSystemException("writeByte failed", path, result);
}
- _resourceInfo.writeCount++;
- _resourceInfo.totalWritten++;
+ _resourceInfo.addWrite(1);
return result;
}
@@ -778,8 +770,7 @@
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "writeFrom failed", path);
}
- _resourceInfo.writeCount++;
- _resourceInfo.totalWritten += end - (start - result.start);
+ _resourceInfo.addWrite(end - (start - result.start));
return this;
});
}
@@ -804,8 +795,7 @@
if (result is OSError) {
throw new FileSystemException("writeFrom failed", path, result);
}
- _resourceInfo.writeCount++;
- _resourceInfo.totalWritten += end - (start - bufferAndStart.start);
+ _resourceInfo.addWrite(end - (start - bufferAndStart.start));
}
Future<RandomAccessFile> writeString(String string,
diff --git a/sdk/lib/io/io_resource_info.dart b/sdk/lib/io/io_resource_info.dart
index 8c30c64..1a18fc9 100644
--- a/sdk/lib/io/io_resource_info.dart
+++ b/sdk/lib/io/io_resource_info.dart
@@ -10,9 +10,12 @@
String get name;
static int _count = 0;
- _IOResourceInfo(this.type) : id = _IOResourceInfo.getNextID();
+ static final Stopwatch _sw = new Stopwatch()..start();
+ static final _startTime = new DateTime.now().millisecondsSinceEpoch;
- String toJSON();
+ static double get timestamp => _startTime + _sw.elapsedMicroseconds/1000;
+
+ _IOResourceInfo(this.type) : id = _IOResourceInfo.getNextID();
/// Get the full set of values for a specific implementation. This is normally
/// looked up based on an id from a referenceValueMap.
@@ -31,9 +34,6 @@
static int getNextID() => _count++;
}
-// TODO(ricow): Move stopwatch into this class and use it for both files
-// and sockets (by using setters on totalRead/totalWritten). Also, consider
-// setting readCount and writeCount in those setters.
abstract class _ReadWriteResourceInfo extends _IOResourceInfo {
int totalRead;
int totalWritten;
@@ -42,6 +42,26 @@
double lastRead;
double lastWrite;
+ // Not all call sites use this. In some cases, e.g., a socket, a read does
+ // not always mean that we actually read some bytes (we may do a read to see
+ // if there are some bytes available).
+ void addRead(int bytes) {
+ totalRead += bytes;
+ readCount++;
+ lastRead = _IOResourceInfo.timestamp;
+ }
+
+ // In cases where we read but did not neccesarily get any bytes, use this to
+ // update the readCount and timestamp. Manually update totalRead if any bytes
+ // where acutally read.
+ void didRead() => addRead(0);
+
+ void addWrite(int bytes) {
+ totalWritten += bytes;
+ writeCount++;
+ lastWrite = _IOResourceInfo.timestamp;
+ }
+
_ReadWriteResourceInfo(String type) :
totalRead = 0,
totalWritten = 0,
@@ -56,17 +76,13 @@
'type': type,
'id': id,
'name': name,
- 'total_read': totalRead,
- 'total_written': totalWritten,
- 'read_count': readCount,
- 'write_count': writeCount,
- 'last_read': lastRead,
- 'last_write': lastWrite
+ 'totalRead': totalRead,
+ 'totalWritten': totalWritten,
+ 'readCount': readCount,
+ 'writeCount': writeCount,
+ 'lastRead': lastRead,
+ 'lastWrite': lastWrite
};
-
- String toJSON() {
- return JSON.encode(fullValueMap);
- }
}
class _FileResourceInfo extends _ReadWriteResourceInfo {
@@ -121,6 +137,68 @@
}
}
+class _ProcessResourceInfo extends _IOResourceInfo{
+ static const String TYPE = '_process';
+ final process;
+ final double startedAt;
+
+ static Map<int, _ProcessResourceInfo> startedProcesses =
+ new Map<int, _ProcessResourceInfo>();
+
+ _ProcessResourceInfo(this.process) :
+ startedAt = _IOResourceInfo.timestamp,
+ super(TYPE) {
+ ProcessStarted(this);
+ }
+
+ String get name => process._path;
+
+ void stopped() => ProcessStopped(this);
+
+ Map<String, String> get fullValueMap =>
+ {
+ 'type': type,
+ 'id': id,
+ 'name': name,
+ 'pid': process.pid,
+ 'startedAt': startedAt,
+ 'arguments': process._arguments,
+ 'workingDirectory':
+ process._workingDirectory == null ? '.' : process._workingDirectory,
+ };
+
+ static ProcessStarted(_ProcessResourceInfo info) {
+ assert(!startedProcesses.containsKey(info.id));
+ startedProcesses[info.id] = info;
+ }
+
+ static ProcessStopped(_ProcessResourceInfo info) {
+ assert(startedProcesses.containsKey(info.id));
+ startedProcesses.remove(info.id);
+ }
+
+ static Iterable<Map<String, String>> getStartedProcessesList() =>
+ new List.from(startedProcesses.values.map((e) => e.referenceValueMap));
+
+ static Future<ServiceExtensionResponse> getStartedProcesses(
+ String function, Map<String, String> params) {
+ assert(function == '__getProcesses');
+ var data = {'type': '_startedprocesses', 'data': getStartedProcessesList()};
+ var json = JSON.encode(data);
+ return new Future.value(new ServiceExtensionResponse.result(json));
+ }
+
+ static Future<ServiceExtensionResponse> getProcessInfoMapById(
+ String function, Map<String, String> params) {
+ var id = int.parse(params['id']);
+ var result = startedProcesses.containsKey(id)
+ ? startedProcesses[id].fullValueMap
+ : {};
+ var json = JSON.encode(result);
+ return new Future.value(new ServiceExtensionResponse.result(json));
+ }
+}
+
class _SocketResourceInfo extends _ReadWriteResourceInfo {
static const String TCP_STRING = 'TCP';
static const String UDP_STRING = 'UDP';
@@ -154,24 +232,24 @@
Map<String, String> getSocketInfoMap() {
var result = fullValueMap;
- result['socket_type'] = socket.isTcp ? TCP_STRING : UDP_STRING;
+ result['socketType'] = socket.isTcp ? TCP_STRING : UDP_STRING;
result['listening'] = socket.isListening;
result['host'] = socket.address.host;
result['port'] = socket.port;
if (!socket.isListening) {
try {
- result['remote_host'] = socket.remoteAddress.host;
- result['remote_port'] = socket.remotePort;
+ result['remoteHost'] = socket.remoteAddress.host;
+ result['remotePort'] = socket.remotePort;
} catch (e) {
// UDP.
- result['remote_port'] = 'NA';
- result['remote_host'] = 'NA';
+ result['remotePort'] = 'NA';
+ result['remoteHost'] = 'NA';
}
} else {
- result['remote_port'] = 'NA';
- result['remote_host'] = 'NA';
+ result['remotePort'] = 'NA';
+ result['remoteHost'] = 'NA';
}
- result['address_type'] = socket.address.type.name;
+ result['addressType'] = socket.address.type.name;
return result;
}
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index d239ef2..d5534ba 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -212,20 +212,30 @@
*
* WARNING: The [checked] parameter is not implemented on all platforms yet.
*
- * If the [packageRoot] parameter is provided, it is used to find the location
- * of packages imports in the spawned isolate.
+ * If either the [packageRoot] or the [packages] parameter is provided,
+ * it is used to find the location of package sources in the spawned isolate.
+ *
* The `packageRoot` URI must be a "file" or "http"/"https" URI that specifies
* a directory. If it doesn't end in a slash, one will be added before
* using the URI, and any query or fragment parts are ignored.
- * Package imports (like "package:foo/bar.dart") in the new isolate are
+ * Package imports (like `"package:foo/bar.dart"`) in the new isolate are
* resolved against this location, as by
* `packageRoot.resolve("foo/bar.dart")`.
- * This includes the main entry [uri] if it happens to be a package-URL.
- * If [packageRoot] is omitted, it defaults to the same URI that
- * the current isolate is using.
*
- * WARNING: The [packageRoot] parameter is not implemented on all
- * platforms yet.
+ * The `packages` map maps package names to URIs with the same requirements
+ * as `packageRoot`. Package imports (like `"package:foo/bar/baz.dart"`) in
+ * the new isolate are resolved against the URI for that package (if any),
+ * as by `packages["foo"].resolve("bar/baz.dart")
+ *
+ * This resolution also applies to the main entry [uri]
+ * if that happens to be a package-URI.
+ *
+ * If both [packageRoot] and [packages] are omitted, the new isolate uses
+ * the same package resolution as the current isolate.
+ * It's not allowed to provide both a `packageRoot` and a `package` parameter.
+ *
+ * WARNING: The [packageRoot] and [packages] parameters are not implemented
+ * on all platforms yet.
*
* Returns a future that will complete with an [Isolate] instance if the
* spawning succeeded. It will complete with an error otherwise.
@@ -237,6 +247,7 @@
{bool paused: false,
bool checked,
Uri packageRoot,
+ Map<String, Uri> packages,
bool errorsAreFatal,
SendPort onExit,
SendPort onError});
diff --git a/site/try/poi/scope_information_visitor.dart b/site/try/poi/scope_information_visitor.dart
index c9d2af0..5ae18ee 100644
--- a/site/try/poi/scope_information_visitor.dart
+++ b/site/try/poi/scope_information_visitor.dart
@@ -74,7 +74,7 @@
// TODO(ahe): We omit the import scope if there is no current
// class. That's wrong.
omitEnclosing: ignoreImports || currentClass == null,
- name: e.getLibraryName(),
+ name: e.libraryName,
serializeEnclosing: () {
// The enclosing scope of a library is a scope which contains all the
// imported names.
diff --git a/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart b/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart
index ac72614..98555ea 100644
--- a/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart
+++ b/tests/compiler/dart2js/analyze_dart2js_helpers_test.dart
@@ -11,6 +11,7 @@
Diagnostic;
import 'package:compiler/src/apiimpl.dart' show
Compiler;
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/constants/expressions.dart' show
ConstructedConstantExpression;
import 'package:compiler/src/dart_types.dart' show
@@ -36,11 +37,11 @@
bool verbose = arguments.contains('-v');
List<String> options = <String>[
- '--analyze-only',
- '--analyze-main',
+ Flags.analyzeOnly,
+ Flags.analyzeMain,
'--categories=Client,Server'];
if (verbose) {
- options.add('--verbose');
+ options.add(Flags.verbose);
}
asyncTest(() async {
Compiler compiler = compilerFor(
diff --git a/tests/compiler/dart2js/analyze_dart2js_test.dart b/tests/compiler/dart2js/analyze_dart2js_test.dart
index 602f904..f5fc77c 100644
--- a/tests/compiler/dart2js/analyze_dart2js_test.dart
+++ b/tests/compiler/dart2js/analyze_dart2js_test.dart
@@ -4,9 +4,11 @@
library analyze_dart2js;
+import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/filenames.dart';
+import 'package:compiler/src/compiler.dart';
import 'analyze_helper.dart';
-import "package:async_helper/async_helper.dart";
+import 'related_types.dart';
/**
* Map of whitelisted warnings and errors.
@@ -24,5 +26,11 @@
void main() {
var uri = currentDirectory.resolve('pkg/compiler/lib/src/dart2js.dart');
- asyncTest(() => analyze([uri], WHITE_LIST));
+ asyncTest(() => analyze([uri], WHITE_LIST, checkResults: checkResults));
}
+
+bool checkResults(Compiler compiler,
+ CollectingDiagnosticHandler handler) {
+ checkRelatedTypes(compiler);
+ return !handler.hasHint;
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/analyze_helper.dart b/tests/compiler/dart2js/analyze_helper.dart
index ccd9b3b..a916133 100644
--- a/tests/compiler/dart2js/analyze_helper.dart
+++ b/tests/compiler/dart2js/analyze_helper.dart
@@ -8,6 +8,7 @@
import 'dart:io';
import 'package:compiler/compiler.dart' as api;
import 'package:compiler/src/apiimpl.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/diagnostics/messages.dart' show
Message;
import 'package:compiler/src/filenames.dart';
@@ -155,9 +156,9 @@
currentDirectory.resolveUri(new Uri.file('${Platform.packageRoot}/'));
var provider = new CompilerSourceFileProvider();
var handler = new CollectingDiagnosticHandler(whiteList, provider);
- var options = <String>['--analyze-only', '--categories=Client,Server',
- '--show-package-warnings'];
- if (analyzeAll) options.add('--analyze-all');
+ var options = <String>[Flags.analyzeOnly, '--categories=Client,Server',
+ Flags.showPackageWarnings];
+ if (analyzeAll) options.add(Flags.analyzeAll);
var compiler = new Compiler(
provider,
null,
diff --git a/tests/compiler/dart2js/analyze_only_test.dart b/tests/compiler/dart2js/analyze_only_test.dart
index bb42728..08100a6 100644
--- a/tests/compiler/dart2js/analyze_only_test.dart
+++ b/tests/compiler/dart2js/analyze_only_test.dart
@@ -11,7 +11,7 @@
import '../../utils/dummy_compiler_test.dart' as dummy;
import 'package:compiler/compiler.dart';
-
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/diagnostics/messages.dart' show
MessageKind, MessageTemplate;
@@ -64,7 +64,7 @@
main() {
runCompiler(
"",
- ['--generate-code-with-compile-time-errors'],
+ [Flags.generateCodeWithCompileTimeErrors],
(String code, List errors, List warnings) {
Expect.isNotNull(code);
Expect.isTrue(errors.isEmpty, 'errors is not empty: $errors');
@@ -77,7 +77,7 @@
runCompiler(
"main() {}",
- ['--generate-code-with-compile-time-errors'],
+ [Flags.generateCodeWithCompileTimeErrors],
(String code, List errors, List warnings) {
Expect.isNotNull(code);
Expect.isTrue(errors.isEmpty);
@@ -86,7 +86,7 @@
runCompiler(
"",
- ['--analyze-only'],
+ [Flags.analyzeOnly],
(String code, List errors, List warnings) {
Expect.isNull(code);
Expect.isTrue(errors.isEmpty, 'errors is not empty: $errors');
@@ -99,7 +99,7 @@
runCompiler(
"main() {}",
- ['--analyze-only'],
+ [Flags.analyzeOnly],
(String code, List errors, List warnings) {
Expect.isNull(code);
Expect.isTrue(errors.isEmpty);
@@ -108,7 +108,7 @@
runCompiler(
"Foo foo; // Unresolved but not analyzed.",
- ['--analyze-only'],
+ [Flags.analyzeOnly],
(String code, List errors, List warnings) {
Expect.isNull(code);
Expect.isTrue(errors.isEmpty, 'errors is not empty: $errors');
@@ -123,7 +123,7 @@
"""main() {
Foo foo; // Unresolved and analyzed.
}""",
- ['--analyze-only'],
+ [Flags.analyzeOnly],
(String code, List errors, List warnings) {
Expect.isNull(code);
Expect.isTrue(errors.isEmpty);
@@ -136,7 +136,7 @@
"""main() {
Foo foo; // Unresolved and analyzed.
}""",
- ['--analyze-only', '--analyze-signatures-only'],
+ [Flags.analyzeOnly, Flags.analyzeSignaturesOnly],
(String code, List errors, List warnings) {
Expect.isNull(code);
Expect.isTrue(errors.isEmpty);
@@ -145,7 +145,7 @@
runCompiler(
"Foo foo; // Unresolved and analyzed.",
- ['--analyze-only', '--analyze-all'],
+ [Flags.analyzeOnly, Flags.analyzeAll],
(String code, List errors, List warnings) {
Expect.isNull(code);
Expect.isTrue(errors.isEmpty);
@@ -156,7 +156,7 @@
runCompiler(
"""Foo foo; // Unresolved and analyzed.
main() {}""",
- ['--analyze-only', '--analyze-all'],
+ [Flags.analyzeOnly, Flags.analyzeAll],
(String code, List errors, List warnings) {
Expect.isNull(code);
Expect.isTrue(errors.isEmpty, 'Unexpected errors: $errors.');
@@ -167,7 +167,7 @@
runCompiler(
"",
- ['--analyze-only', '--analyze-all'],
+ [Flags.analyzeOnly, Flags.analyzeAll],
(String code, List errors, List warnings) {
Expect.isNull(code);
Expect.isTrue(errors.isEmpty);
@@ -177,7 +177,7 @@
// --analyze-signatures-only implies --analyze-only
runCompiler(
"",
- ['--analyze-signatures-only', '--analyze-all'],
+ [Flags.analyzeSignaturesOnly, Flags.analyzeAll],
(String code, List errors, List warnings) {
Expect.isNull(code);
Expect.isTrue(errors.isEmpty);
diff --git a/tests/compiler/dart2js/arithmetic_simplification_test.dart b/tests/compiler/dart2js/arithmetic_simplification_test.dart
index 8b69d50..039a844 100644
--- a/tests/compiler/dart2js/arithmetic_simplification_test.dart
+++ b/tests/compiler/dart2js/arithmetic_simplification_test.dart
@@ -81,7 +81,8 @@
asyncTest(() => Future.wait([
compileAndDoNotMatch(INT_PLUS_ZERO, 'main', plusZero),
compileAndDoNotMatch(ZERO_PLUS_INT, 'main', zeroPlus),
- compileAndMatch(NUM_PLUS_ZERO, 'main', plusZero),
+ // TODO(johnniwinther): Find out why this doesn't work without [useMock].
+ compileAndMatch(NUM_PLUS_ZERO, 'main', plusZero, useMock: true),
compileAndMatch(ZERO_PLUS_NUM, 'main', zeroPlus),
compileAndDoNotMatch(INT_TIMES_ONE, 'main', timesOne),
compileAndDoNotMatch(ONE_TIMES_INT, 'main', oneTimes),
diff --git a/tests/compiler/dart2js/array_tracing_mirror_test.dart b/tests/compiler/dart2js/array_tracing_mirror_test.dart
index 2c4c9aa..6a083ca 100644
--- a/tests/compiler/dart2js/array_tracing_mirror_test.dart
+++ b/tests/compiler/dart2js/array_tracing_mirror_test.dart
@@ -34,9 +34,10 @@
asyncTest(() async {
var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
var compiler = result.compiler;
- var element = compiler.mainApp.findExported('main');
- var code = compiler.backend.assembleCode(element);
- Expect.isTrue(code.contains('return 2'));
+ var element = compiler.mainFunction;
+ var code = compiler.backend.getGeneratedCode(element);
+ Expect.isTrue(code.contains('return 2'),
+ "Unexpected code:\n$code");
});
}
diff --git a/tests/compiler/dart2js/bad_loop_test.dart b/tests/compiler/dart2js/bad_loop_test.dart
index 82d8607..bd1053c 100644
--- a/tests/compiler/dart2js/bad_loop_test.dart
+++ b/tests/compiler/dart2js/bad_loop_test.dart
@@ -8,6 +8,7 @@
import 'package:compiler/compiler.dart'
show Diagnostic;
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/old_to_new_api.dart';
main() {
@@ -38,7 +39,7 @@
new LegacyCompilerDiagnostics(diagnosticHandler),
libraryRoot,
packageRoot,
- ['--analyze-only'],
+ [Flags.analyzeOnly],
{});
asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
Expect.isTrue(compiler.compilationFailed);
diff --git a/tests/compiler/dart2js/class_set_test.dart b/tests/compiler/dart2js/class_set_test.dart
index 2e12cdbf..c3ee031 100644
--- a/tests/compiler/dart2js/class_set_test.dart
+++ b/tests/compiler/dart2js/class_set_test.dart
@@ -55,7 +55,7 @@
void checkClass(ClassElement cls,
{bool directlyInstantiated: false,
bool indirectlyInstantiated: false}) {
- ClassHierarchyNode node = world.classHierarchyNode(cls);
+ ClassHierarchyNode node = world.getClassHierarchyNode(cls);
Expect.isNotNull(node, "Expected ClassHierarchyNode for $cls.");
Expect.equals(
directlyInstantiated || indirectlyInstantiated,
@@ -131,7 +131,7 @@
}
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(G)).iterator;
+ world.getClassHierarchyNode(G)).iterator;
checkState(G, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isTrue(iterator.moveNext());
@@ -142,7 +142,8 @@
Expect.isNull(iterator.current);
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(G), includeRoot: false).iterator;
+ world.getClassHierarchyNode(G),
+ includeRoot: false).iterator;
checkState(G, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isFalse(iterator.moveNext());
@@ -150,7 +151,7 @@
Expect.isNull(iterator.current);
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(C)).iterator;
+ world.getClassHierarchyNode(C)).iterator;
checkState(C, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isTrue(iterator.moveNext());
@@ -170,7 +171,7 @@
Expect.isNull(iterator.current);
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(D)).iterator;
+ world.getClassHierarchyNode(D)).iterator;
checkState(D, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isTrue(iterator.moveNext());
@@ -181,7 +182,7 @@
Expect.isNull(iterator.current);
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(B)).iterator;
+ world.getClassHierarchyNode(B)).iterator;
checkState(B, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isTrue(iterator.moveNext());
@@ -195,7 +196,8 @@
Expect.isNull(iterator.current);
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(B), includeRoot: false).iterator;
+ world.getClassHierarchyNode(B),
+ includeRoot: false).iterator;
checkState(B, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isTrue(iterator.moveNext());
@@ -206,7 +208,8 @@
Expect.isNull(iterator.current);
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(B), directlyInstantiatedOnly: true).iterator;
+ world.getClassHierarchyNode(B),
+ includeIndirectlyInstantiated: false).iterator;
checkState(B, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isTrue(iterator.moveNext());
@@ -217,7 +220,7 @@
Expect.isNull(iterator.current);
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(A)).iterator;
+ world.getClassHierarchyNode(A)).iterator;
checkState(A, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isTrue(iterator.moveNext());
@@ -246,7 +249,8 @@
Expect.isNull(iterator.current);
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(A), includeRoot: false).iterator;
+ world.getClassHierarchyNode(A),
+ includeRoot: false).iterator;
checkState(A, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isTrue(iterator.moveNext());
@@ -272,7 +276,8 @@
Expect.isNull(iterator.current);
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(A), directlyInstantiatedOnly: true).iterator;
+ world.getClassHierarchyNode(A),
+ includeIndirectlyInstantiated: false).iterator;
checkState(A, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isTrue(iterator.moveNext());
@@ -298,8 +303,9 @@
Expect.isNull(iterator.current);
iterator = new ClassHierarchyNodeIterable(
- world.classHierarchyNode(A),
- includeRoot: false, directlyInstantiatedOnly: true).iterator;
+ world.getClassHierarchyNode(A),
+ includeRoot: false,
+ includeIndirectlyInstantiated: false).iterator;
checkState(A, currentNode: null, stack: null);
Expect.isNull(iterator.current);
Expect.isTrue(iterator.moveNext());
diff --git a/tests/compiler/dart2js/codegen_helper.dart b/tests/compiler/dart2js/codegen_helper.dart
index 1512442..36fadff 100644
--- a/tests/compiler/dart2js/codegen_helper.dart
+++ b/tests/compiler/dart2js/codegen_helper.dart
@@ -31,7 +31,7 @@
for (var element in backend.generatedCode.keys) {
if (element.compilationUnit.script.readableUri != uri) continue;
var name = element.name;
- var code = backend.assembleCode(element);
+ var code = backend.getGeneratedCode(element);
result[name] = code;
}
return result;
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index 9c84a8c..d3ac2ac 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -7,8 +7,6 @@
import 'dart:async';
import "package:expect/expect.dart";
-import 'package:compiler/compiler.dart' as api;
-
import 'package:compiler/src/elements/elements.dart'
as lego;
export 'package:compiler/src/elements/elements.dart';
@@ -16,6 +14,7 @@
import 'package:compiler/src/js_backend/js_backend.dart'
as js;
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/common/codegen.dart';
import 'package:compiler/src/common/resolution.dart';
@@ -39,24 +38,35 @@
import 'mock_compiler.dart';
export 'mock_compiler.dart';
+import 'memory_compiler.dart' hide compilerFor;
+
import 'output_collector.dart';
export 'output_collector.dart';
+/// Compile [code] and returns the code for [entry].
+///
+/// If [check] is provided, it is executed on the code for [entry] before
+/// returning. If [useMock] is `true` the [MockCompiler] is used for
+/// compilation, otherwise the memory compiler is used.
Future<String> compile(String code,
{String entry: 'main',
bool enableTypeAssertions: false,
bool minify: false,
bool analyzeAll: false,
bool disableInlining: true,
- void check(String generated)}) {
- MockCompiler compiler = new MockCompiler.internal(
- enableTypeAssertions: enableTypeAssertions,
- // Type inference does not run when manually
- // compiling a method.
- disableTypeInference: true,
- enableMinification: minify,
- disableInlining: disableInlining);
- return compiler.init().then((_) {
+ bool useMock: false,
+ void check(String generated)}) async {
+ if (useMock) {
+ // TODO(johnniwinther): Remove this when no longer needed by
+ // `arithmetic_simplication_test.dart`.
+ MockCompiler compiler = new MockCompiler.internal(
+ enableTypeAssertions: enableTypeAssertions,
+ // Type inference does not run when manually
+ // compiling a method.
+ disableTypeInference: true,
+ enableMinification: minify,
+ disableInlining: disableInlining);
+ await compiler.init();
compiler.parseScript(code);
lego.Element element = compiler.mainApp.find(entry);
if (element == null) return null;
@@ -75,40 +85,49 @@
compiler.phase = Compiler.PHASE_COMPILING;
work.run(compiler, compiler.enqueuer.codegen);
js.JavaScriptBackend backend = compiler.backend;
- String generated = backend.assembleCode(element);
+ String generated = backend.getGeneratedCode(element);
if (check != null) {
check(generated);
}
return generated;
- });
-}
+ } else {
+ List<String> options = <String>[
+ Flags.disableTypeInference];
+ if (enableTypeAssertions) {
+ options.add(Flags.enableCheckedMode);
+ }
+ if (minify) {
+ options.add(Flags.minify);
+ }
+ if (analyzeAll) {
+ options.add(Flags.analyzeAll);
+ }
-// TODO(herhut): Disallow warnings and errors during compilation by default.
-MockCompiler compilerFor(String code, Uri uri,
- {bool analyzeAll: false,
- bool analyzeOnly: false,
- Map<String, String> coreSource,
- bool disableInlining: true,
- bool minify: false,
- bool trustTypeAnnotations: false,
- bool enableTypeAssertions: false,
- int expectedErrors,
- int expectedWarnings,
- api.CompilerOutputProvider outputProvider}) {
- MockCompiler compiler = new MockCompiler.internal(
- analyzeAll: analyzeAll,
- analyzeOnly: analyzeOnly,
- coreSource: coreSource,
- disableInlining: disableInlining,
- enableMinification: minify,
- trustTypeAnnotations: trustTypeAnnotations,
- enableTypeAssertions: enableTypeAssertions,
- expectedErrors: expectedErrors,
- expectedWarnings: expectedWarnings,
- outputProvider: outputProvider);
- compiler.registerSource(uri, code);
- compiler.diagnosticHandler = createHandler(compiler, code);
- return compiler;
+ Map<String, String> source;
+ if (entry != 'main') {
+ source = {'main.dart': "$code\n\nmain() => $entry;" };
+ } else {
+ source = {'main.dart': code};
+ }
+
+ CompilationResult result = await runCompiler(
+ memorySourceFiles: source,
+ options: options,
+ beforeRun: (compiler) {
+ if (disableInlining) {
+ compiler.disableInlining = true;
+ }
+ });
+ Expect.isTrue(result.isSuccess);
+ Compiler compiler = result.compiler;
+ lego.Element element = compiler.mainApp.find(entry);
+ js.JavaScriptBackend backend = compiler.backend;
+ String generated = backend.getGeneratedCode(element);
+ if (check != null) {
+ check(generated);
+ }
+ return generated;
+ }
}
Future<String> compileAll(String code,
@@ -225,8 +244,11 @@
Expect.isFalse(hasNext, "Found more than $nb matches");
}
-Future compileAndMatch(String code, String entry, RegExp regexp) {
- return compile(code, entry: entry, check: (String generated) {
+Future compileAndMatch(String code, String entry, RegExp regexp,
+ {bool useMock: false}) {
+ return compile(code, entry: entry,
+ useMock: useMock,
+ check: (String generated) {
Expect.isTrue(regexp.hasMatch(generated),
'"$generated" does not match /$regexp/');
});
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 3518280..0ae992d 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -69,6 +69,7 @@
check_elements_invariants_test: Slow, Pass
import_mirrors_test: Slow, Pass
exit_code_test: Pass, Slow
+value_range_test: Pass, Slow
[ $mode == debug ]
check_elements_invariants_test: Skip # Slow and only needs to be run in one
diff --git a/tests/compiler/dart2js/dictionary_types_test.dart b/tests/compiler/dart2js/dictionary_types_test.dart
index 11734e1..f173c23 100644
--- a/tests/compiler/dart2js/dictionary_types_test.dart
+++ b/tests/compiler/dart2js/dictionary_types_test.dart
@@ -147,7 +147,7 @@
checker(typesTask, getType, compiler);
} else {
var element = compiler.mainFunction;
- var code = compiler.backend.assembleCode(element);
+ var code = compiler.backend.getGeneratedCode(element);
checker(code);
}
}
diff --git a/tests/compiler/dart2js/duplicate_library_test.dart b/tests/compiler/dart2js/duplicate_library_test.dart
index 0164981..80aa6fe 100644
--- a/tests/compiler/dart2js/duplicate_library_test.dart
+++ b/tests/compiler/dart2js/duplicate_library_test.dart
@@ -8,6 +8,7 @@
import 'dart:async';
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/diagnostics/messages.dart' show MessageKind;
import 'memory_compiler.dart';
@@ -30,7 +31,7 @@
memorySourceFiles: source,
diagnosticHandler: collector,
showDiagnostics: true,
- options: ['--analyze-only', '--analyze-all'],
+ options: [Flags.analyzeOnly, Flags.analyzeAll],
packageRoot: Uri.parse('memory:pkg/'));
Expect.isTrue(collector.errors.isEmpty);
diff --git a/tests/compiler/dart2js/frontend_checker.dart b/tests/compiler/dart2js/frontend_checker.dart
index 67b88d3..8624cfe 100644
--- a/tests/compiler/dart2js/frontend_checker.dart
+++ b/tests/compiler/dart2js/frontend_checker.dart
@@ -9,6 +9,7 @@
import 'dart:io';
import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/util/uri_extras.dart'
show relativize;
import 'memory_compiler.dart';
@@ -49,7 +50,7 @@
entryPoint: Uri.parse('memory:$testFileName'),
memorySourceFiles: {testFileName: testSources[testName]},
diagnosticHandler: collector,
- options: ['--analyze-only']..addAll(options),
+ options: [Flags.analyzeOnly]..addAll(options),
showDiagnostics: verbose,
cachedCompiler: cachedCompiler);
var compiler = result.compiler;
diff --git a/tests/compiler/dart2js/in_user_code_test.dart b/tests/compiler/dart2js/in_user_code_test.dart
index 9870491..0a6e13f 100644
--- a/tests/compiler/dart2js/in_user_code_test.dart
+++ b/tests/compiler/dart2js/in_user_code_test.dart
@@ -7,6 +7,7 @@
import 'dart:async';
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart' show Compiler;
import 'memory_compiler.dart';
@@ -47,7 +48,7 @@
CompilationResult result = await runCompiler(
entryPoints: entryPoints,
memorySourceFiles: SOURCE,
- options: ['--analyze-only', '--analyze-all'],
+ options: [Flags.analyzeOnly, Flags.analyzeAll],
packageRoot: Uri.parse('memory:pkg/'));
Compiler compiler = result.compiler;
expectedResults.forEach((String uri, bool expectedResult) {
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
index 1665195..877b371 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
@@ -11,7 +11,8 @@
const List<TestEntry> tests = const [
const TestEntry("main() { return true ? 42 : 'foo'; }"),
const TestEntry("""
-foo() => foo();
+var x = 1;
+foo() => ++x > 10;
main() {
print(foo() ? "hello world" : "bad bad");
}""","""
@@ -19,16 +20,17 @@
P.print(V.foo() ? "hello world" : "bad bad");
}"""),
const TestEntry("""
-foo() { print('foo'); }
+var x = 1;
+foo() => ++x > 10;
main() {
print(foo() ? "hello world" : "bad bad");
}""","""
function() {
- V.foo();
- P.print("bad bad");
+ P.print(V.foo() ? "hello world" : "bad bad");
}"""),
const TestEntry("""
-get foo => foo;
+var x = 1;
+get foo => ++x > 10;
main() {
print(foo ? "hello world" : "bad bad");
}""","""
@@ -36,19 +38,28 @@
P.print(V.foo() ? "hello world" : "bad bad");
}"""),
const TestEntry("""
-get foo => foo;
+var x = 1;
+get foo => ++x > 10;
main() { print(foo && foo); }
""", """
function() {
P.print(V.foo() ? !!V.foo() : false);
}"""),
const TestEntry("""
-get foo => foo;
+var x = 1;
+get foo => ++x > 10;
main() { print(foo || foo); }
""","""
function() {
P.print(V.foo() ? true : !!V.foo());
}"""),
+const TestEntry("""
+get foo => foo;
+main() { print(foo || foo); }
+""","""
+function() {
+ V.foo();
+}"""),
// Needs interceptor calling convention
//const TestEntry("""
diff --git a/tests/compiler/dart2js/js_spec_optimization_test.dart b/tests/compiler/dart2js/js_spec_optimization_test.dart
index 078104f..8c83b3b 100644
--- a/tests/compiler/dart2js/js_spec_optimization_test.dart
+++ b/tests/compiler/dart2js/js_spec_optimization_test.dart
@@ -70,7 +70,7 @@
return compiler.runCompiler(uri).then((_) {
var element = findElement(compiler, 'main');
var backend = compiler.backend;
- String generated = backend.assembleCode(element);
+ String generated = backend.getGeneratedCode(element);
for (Match match in directivePattern.allMatches(test)) {
String directive = match.group(1);
diff --git a/tests/compiler/dart2js/memory_compiler.dart b/tests/compiler/dart2js/memory_compiler.dart
index 06e73144..49664b7 100644
--- a/tests/compiler/dart2js/memory_compiler.dart
+++ b/tests/compiler/dart2js/memory_compiler.dart
@@ -81,6 +81,10 @@
bool get hasRegularMessages {
return messages.any((m) => m.kind != Diagnostic.VERBOSE_INFO);
}
+
+ void clear() {
+ messages.clear();
+ }
}
class MultiDiagnostics implements CompilerDiagnostics {
diff --git a/tests/compiler/dart2js/message_kind_helper.dart b/tests/compiler/dart2js/message_kind_helper.dart
index af32b58..12089cf 100644
--- a/tests/compiler/dart2js/message_kind_helper.dart
+++ b/tests/compiler/dart2js/message_kind_helper.dart
@@ -7,6 +7,7 @@
import 'package:expect/expect.dart';
import 'dart:async';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart' show
Compiler;
import 'package:compiler/src/dart_backend/dart_backend.dart' show
@@ -84,8 +85,8 @@
Compiler compiler = compilerFor(
memorySourceFiles: example,
diagnosticHandler: new LegacyCompilerDiagnostics(collect),
- options: ['--analyze-only',
- '--enable-experimental-mirrors']..addAll(template.options),
+ options: [Flags.analyzeOnly,
+ Flags.enableExperimentalMirrors]..addAll(template.options),
cachedCompiler:
// TODO(johnniwinther): Remove this restriction when constant
// values can be computed directly from the expressions.
diff --git a/tests/compiler/dart2js/message_kind_test.dart b/tests/compiler/dart2js/message_kind_test.dart
index efaecc8..3ed7010 100644
--- a/tests/compiler/dart2js/message_kind_test.dart
+++ b/tests/compiler/dart2js/message_kind_test.dart
@@ -26,7 +26,8 @@
|| name == 'COMPILER_CRASHED'
|| name == 'PLEASE_REPORT_THE_CRASH'
// We cannot provide examples for patch errors.
- || name.startsWith('PATCH_')) continue;
+ || name.startsWith('PATCH_')
+ || name == 'LIBRARY_NOT_SUPPORTED') continue;
if (template.examples != null) {
examples.add(template);
} else {
diff --git a/tests/compiler/dart2js/metadata_test.dart b/tests/compiler/dart2js/metadata_test.dart
index b304b4f..205c897 100644
--- a/tests/compiler/dart2js/metadata_test.dart
+++ b/tests/compiler/dart2js/metadata_test.dart
@@ -33,9 +33,9 @@
compileAndCheck(source1, name, (compiler, element) {
compiler.enqueuer.resolution.queueIsClosed = false;
- Expect.equals(1, length(element.metadata),
+ Expect.equals(1, element.metadata.length,
'Unexpected metadata count on $element.');
- PartialMetadataAnnotation annotation = element.metadata.head;
+ PartialMetadataAnnotation annotation = element.metadata.first;
annotation.ensureResolved(compiler);
PrimitiveConstantValue value =
compiler.constants.getConstantValue(annotation.constant);
@@ -53,9 +53,9 @@
compileAndCheck(source2, name, (compiler, element) {
compiler.enqueuer.resolution.queueIsClosed = false;
- Expect.equals(2, length(element.metadata));
- PartialMetadataAnnotation annotation1 = element.metadata.head;
- PartialMetadataAnnotation annotation2 = element.metadata.tail.head;
+ Expect.equals(2, element.metadata.length);
+ PartialMetadataAnnotation annotation1 = element.metadata.elementAt(0);
+ PartialMetadataAnnotation annotation2 = element.metadata.elementAt(1);
annotation1.ensureResolved(compiler);
annotation2.ensureResolved(compiler);
Expect.isFalse(identical(annotation1, annotation2),
@@ -86,12 +86,12 @@
compileAndCheck(source3, 'Foo', (compiler, element) {
compiler.enqueuer.resolution.queueIsClosed = false;
- Expect.equals(0, length(element.metadata));
+ Expect.equals(0, element.metadata.length);
element.ensureResolved(compiler);
- Expect.equals(0, length(element.metadata));
+ Expect.equals(0, element.metadata.length);
element = element.lookupLocalMember(name);
- Expect.equals(1, length(element.metadata));
- PartialMetadataAnnotation annotation = element.metadata.head;
+ Expect.equals(1, element.metadata.length);
+ PartialMetadataAnnotation annotation = element.metadata.first;
annotation.ensureResolved(compiler);
PrimitiveConstantValue value =
compiler.constants.getConstantValue(annotation.constant);
@@ -111,13 +111,13 @@
compileAndCheck(source4, 'Foo', (compiler, element) {
compiler.enqueuer.resolution.queueIsClosed = false;
- Expect.equals(0, length(element.metadata));
+ Expect.equals(0, element.metadata.length);
element.ensureResolved(compiler);
- Expect.equals(0, length(element.metadata));
+ Expect.equals(0, element.metadata.length);
element = element.lookupLocalMember(name);
- Expect.equals(2, length(element.metadata));
- PartialMetadataAnnotation annotation1 = element.metadata.head;
- PartialMetadataAnnotation annotation2 = element.metadata.tail.head;
+ Expect.equals(2, element.metadata.length);
+ PartialMetadataAnnotation annotation1 = element.metadata.elementAt(0);
+ PartialMetadataAnnotation annotation2 = element.metadata.elementAt(1);
annotation1.ensureResolved(compiler);
annotation2.ensureResolved(compiler);
Expect.isFalse(identical(annotation1, annotation2),
@@ -152,7 +152,7 @@
void testLibraryTags() {
void compileAndCheckLibrary(
String source,
- Link<MetadataAnnotation> extractMetadata(LibraryElement element)) {
+ List<MetadataAnnotation> extractMetadata(LibraryElement element)) {
Uri partUri = new Uri(scheme: 'source', path: 'part.dart');
String partSource = '@native part of foo;';
@@ -170,10 +170,10 @@
LibraryElement element = compiler.libraryLoader.lookupLibrary(uri);
Expect.isNotNull(element, 'Cannot find $uri');
- Link<MetadataAnnotation> metadata = extractMetadata(element);
- Expect.equals(1, length(metadata));
+ List<MetadataAnnotation> metadata = extractMetadata(element);
+ Expect.equals(1, metadata.length);
- PartialMetadataAnnotation annotation = metadata.head;
+ PartialMetadataAnnotation annotation = metadata.first;
annotation.ensureResolved(compiler);
PrimitiveConstantValue value =
compiler.constants.getConstantValue(annotation.constant);
diff --git a/tests/compiler/dart2js/minimal_resolution_test.dart b/tests/compiler/dart2js/minimal_resolution_test.dart
new file mode 100644
index 0000000..ca61f80
--- /dev/null
+++ b/tests/compiler/dart2js/minimal_resolution_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that elements are not needlessly required by dart2js.
+
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:expect/expect.dart';
+import 'memory_compiler.dart';
+
+main() {
+ asyncTest(() async {
+ await analyze('main() {}');
+ await analyze('main() => proxy;', proxyConstant: true);
+ });
+}
+
+analyze(String code,
+ {bool proxyConstant: false}) async {
+ CompilationResult result = await runCompiler(
+ memorySourceFiles: {'main.dart': code},
+ options: ['--analyze-only']);
+ Expect.isTrue(result.isSuccess);
+ Compiler compiler = result.compiler;
+ Expect.equals(proxyConstant, compiler.proxyConstant != null);
+}
diff --git a/tests/compiler/dart2js/mirrors_test.dart b/tests/compiler/dart2js/mirrors_test.dart
index 2c7b09f..7d3c48c 100644
--- a/tests/compiler/dart2js/mirrors_test.dart
+++ b/tests/compiler/dart2js/mirrors_test.dart
@@ -183,7 +183,8 @@
Expect.isTrue(metadata is InstanceMirror);
Expect.isFalse(metadata.hasReflectee);
Expect.throws(() => metadata.reflectee, (_) => true);
- Expect.isTrue(metadata is CommentInstanceMirror);
+ Expect.isTrue(metadata is CommentInstanceMirror,
+ "Unexpected metadata: $metadata");
Expect.equals(commentType.originalDeclaration, metadata.type);
Expect.isTrue(metadata.isDocComment);
Expect.stringEquals(
diff --git a/tests/compiler/dart2js/missing_file_test.dart b/tests/compiler/dart2js/missing_file_test.dart
index efbc43f..457a4f0 100644
--- a/tests/compiler/dart2js/missing_file_test.dart
+++ b/tests/compiler/dart2js/missing_file_test.dart
@@ -14,35 +14,73 @@
const MEMORY_SOURCE_FILES = const {
'main.dart': '''
-
import 'foo.dart';
+main() {}
+''',
+'bar.dart': '''
+import 'dart:foo';
+main() {}
+''',
+
+'baz.dart': '''
+import 'dart:io';
main() {}
''',
};
-Future runTest(Uri main, MessageKind expectedMessageKind) async {
- print("\n\n\n");
+Future runTest(Uri main,
+ {MessageKind error,
+ MessageKind info}) async {
+ print("----\nentry-point: $main\n");
DiagnosticCollector diagnostics = new DiagnosticCollector();
OutputCollector output = new OutputCollector();
await runCompiler(
+ entryPoint: main,
memorySourceFiles: MEMORY_SOURCE_FILES,
diagnosticHandler: diagnostics,
outputProvider: output);
Expect.isFalse(output.hasExtraOutput);
- Expect.equals(1, diagnostics.errors.length);
- Expect.equals(expectedMessageKind, diagnostics.errors.first.message.kind);
+ Expect.equals(error != null ? 1 : 0, diagnostics.errors.length);
+ if (error != null) {
+ Expect.equals(error, diagnostics.errors.first.message.kind);
+ }
+ Expect.equals(info != null ? 1 : 0, diagnostics.infos.length);
+ if (info != null) {
+ Expect.equals(info, diagnostics.infos.first.message.kind);
+ }
+ Expect.equals(0, diagnostics.warnings.length);
+ Expect.equals(0, diagnostics.hints.length);
}
void main() {
asyncTest(() async {
await runTest(
- Uri.parse('memory:main.dart'), MessageKind.READ_SCRIPT_ERROR);
+ Uri.parse('memory:main.dart'),
+ error: MessageKind.READ_SCRIPT_ERROR);
+
await runTest(
- Uri.parse('memory:foo.dart'), MessageKind.READ_SCRIPT_ERROR);
+ Uri.parse('memory:foo.dart'),
+ error: MessageKind.READ_SELF_ERROR);
+
await runTest(
- Uri.parse('dart:foo'), MessageKind.READ_SCRIPT_ERROR);
+ Uri.parse('dart:foo'),
+ error: MessageKind.LIBRARY_NOT_FOUND);
+
+ await runTest(
+ Uri.parse('dart:io'),
+ error: MessageKind.LIBRARY_NOT_SUPPORTED,
+ info: MessageKind.DISALLOWED_LIBRARY_IMPORT);
+
+ await runTest(
+ Uri.parse('memory:bar.dart'),
+ error: MessageKind.LIBRARY_NOT_FOUND);
+
+ await runTest(
+ Uri.parse('memory:baz.dart'),
+ error: MessageKind.LIBRARY_NOT_SUPPORTED,
+ info: MessageKind.DISALLOWED_LIBRARY_IMPORT);
});
}
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index cda5aa6..b52951c 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -279,7 +279,7 @@
}
Uri translateResolvedUri(LibraryElement importingLibrary,
- Uri resolvedUri, Node node) => resolvedUri;
+ Uri resolvedUri, Spannable spannable) => resolvedUri;
// The mock library doesn't need any patches.
Uri resolvePatchUri(String dartLibraryName) {
@@ -370,7 +370,8 @@
}
if (foundIterator.hasNext) {
do {
- print('Additional $kind "${foundIterator.next()}"');
+ WarningMessage message = foundIterator.next();
+ print('Additional $kind "${message}: ${message.message}"');
} while (foundIterator.hasNext);
fail('Too many ${kind}s');
}
@@ -436,3 +437,31 @@
bool get hasNode => false;
}
+
+// TODO(herhut): Disallow warnings and errors during compilation by default.
+MockCompiler compilerFor(String code, Uri uri,
+ {bool analyzeAll: false,
+ bool analyzeOnly: false,
+ Map<String, String> coreSource,
+ bool disableInlining: true,
+ bool minify: false,
+ bool trustTypeAnnotations: false,
+ bool enableTypeAssertions: false,
+ int expectedErrors,
+ int expectedWarnings,
+ api.CompilerOutputProvider outputProvider}) {
+ MockCompiler compiler = new MockCompiler.internal(
+ analyzeAll: analyzeAll,
+ analyzeOnly: analyzeOnly,
+ coreSource: coreSource,
+ disableInlining: disableInlining,
+ enableMinification: minify,
+ trustTypeAnnotations: trustTypeAnnotations,
+ enableTypeAssertions: enableTypeAssertions,
+ expectedErrors: expectedErrors,
+ expectedWarnings: expectedWarnings,
+ outputProvider: outputProvider);
+ compiler.registerSource(uri, code);
+ compiler.diagnosticHandler = createHandler(compiler, code);
+ return compiler;
+}
diff --git a/tests/compiler/dart2js/mock_libraries.dart b/tests/compiler/dart2js/mock_libraries.dart
index b10aedb..5de30cb 100644
--- a/tests/compiler/dart2js/mock_libraries.dart
+++ b/tests/compiler/dart2js/mock_libraries.dart
@@ -45,7 +45,14 @@
}''',
'identical': 'bool identical(Object a, Object b) { return true; }',
'int': 'abstract class int extends num { }',
- 'Iterable': 'abstract class Iterable {}',
+ 'Iterable': '''
+ abstract class Iterable<E> {
+ Iterator<E> get iterator => null;
+ }''',
+ 'Iterator': '''
+ abstract class Iterator<E> {
+ E get current => null;
+ }''',
'LinkedHashMap': r'''
class LinkedHashMap {
factory LinkedHashMap._empty() => null;
@@ -54,7 +61,7 @@
static _makeLiteral(elements) => null;
}''',
'List': r'''
- class List<E> {
+ class List<E> extends Iterable<E> {
var length;
List([length]);
List.filled(length, element);
@@ -286,6 +293,7 @@
E removeAt(index) => this[0];
E elementAt(index) => this[0];
E singleWhere(f) => this[0];
+ Iterator<E> get iterator => null;
}''',
'JSBool': 'class JSBool extends Interceptor implements bool {}',
'JSDouble': 'class JSDouble extends JSNumber implements double {}',
@@ -384,7 +392,7 @@
const Map<String, String> DEFAULT_ASYNC_LIBRARY = const <String, String>{
'DeferredLibrary': 'class DeferredLibrary {}',
- 'Future':
+ 'Future':
'''
class Future<T> {
Future.value([value]);
@@ -434,5 +442,5 @@
: _entries = const [], _nestedMaps = const [];
V operator[](K k) => null;
}''',
- '_version': 'const _version = "0.0.1";',
+ '_version': 'const _version = "0.0.1+1";',
};
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index 1981842..6077db8 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -125,24 +125,49 @@
return element;
}
-testPatchFunction() {
- asyncTest(() => applyPatch(
+Future testPatchFunction() async {
+ var compiler = await applyPatch(
"external test();",
- "@patch test() { return 'string'; } ").then((compiler) {
- ensure(compiler, "test", compiler.coreLibrary.find,
- expectIsPatched: true, checkHasBody: true);
- ensure(compiler, "test", compiler.coreLibrary.patch.find,
- expectIsPatch: true, checkHasBody: true);
+ "@patch test() { return 'string'; } ");
+ ensure(compiler, "test", compiler.coreLibrary.find,
+ expectIsPatched: true, checkHasBody: true);
+ ensure(compiler, "test", compiler.coreLibrary.patch.find,
+ expectIsPatch: true, checkHasBody: true);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isTrue(compiler.errors.isEmpty,
- "Unexpected errors: ${compiler.errors}");
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ Expect.isTrue(compiler.errors.isEmpty,
+ "Unexpected errors: ${compiler.errors}");
+}
+
+Future testPatchFunctionMetadata() async {
+ var compiler = await applyPatch(
+ """
+ const a = 0;
+ @a external test();
+ """,
+ """
+ const b = 1;
+ @patch @b test() {}
+ """);
+ Element origin = ensure(compiler, "test", compiler.coreLibrary.find,
+ expectIsPatched: true, checkHasBody: true);
+ Element patch = ensure(compiler, "test", compiler.coreLibrary.patch.find,
+ expectIsPatch: true, checkHasBody: true);
+
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ Expect.isTrue(compiler.errors.isEmpty,
+ "Unexpected errors: ${compiler.errors}");
+
+ Expect.equals(1, origin.metadata.length,
+ "Unexpected origin metadata: ${origin.metadata}.");
+ Expect.equals(3, patch.metadata.length,
+ "Unexpected patch metadata: ${patch.metadata}.");
}
-testPatchVersioned() {
+Future testPatchVersioned() async {
String fullPatch = "test(){return 'string';}";
String lazyPatch = "test(){return 'new and improved string';}";
@@ -152,64 +177,64 @@
@patch_lazy $lazyPatch
""";
- test(String patchVersion,
+ Future test(String patchVersion,
{String patchText,
bool expectIsPatched: true,
String expectedError,
String defaultPatch: '',
- String expectedInternalError}) {
- asyncTest(() => applyPatch(
+ String expectedInternalError}) async {
+ return applyPatch(
"external test();",
"""
$defaultPatch
$patchSource
""",
patchVersion: patchVersion).then((compiler) {
- Element origin =
- ensure(compiler, "test", compiler.coreLibrary.find,
- expectIsPatched: expectIsPatched, checkHasBody: true);
- if (expectIsPatched) {
- AstElement patch =
- ensure(compiler, "test", compiler.coreLibrary.patch.find,
- expectIsPatch: true, checkHasBody: true);
- Expect.equals(origin.patch, patch);
- Expect.equals(patch.origin, origin);
- Expect.equals(patchText, patch.node.toString());
- }
+ Element origin =
+ ensure(compiler, "test", compiler.coreLibrary.find,
+ expectIsPatched: expectIsPatched, checkHasBody: true);
+ if (expectIsPatched) {
+ AstElement patch =
+ ensure(compiler, "test", compiler.coreLibrary.patch.find,
+ expectIsPatch: true, checkHasBody: true);
+ Expect.equals(origin.patch, patch);
+ Expect.equals(patch.origin, origin);
+ Expect.equals(patchText, patch.node.toString());
+ }
- compiler.analyzeElement(origin);
- compiler.enqueuer.resolution.emptyDeferredTaskQueue();
+ compiler.analyzeElement(origin);
+ compiler.enqueuer.resolution.emptyDeferredTaskQueue();
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- if (expectedError != null) {
- Expect.equals(expectedError,
- compiler.errors[0].message.toString());
- } else {
- Expect.isTrue(compiler.errors.isEmpty,
- "Unexpected errors: ${compiler.errors}");
- }
- }).catchError((error) {
- if (expectedInternalError != null) {
- Expect.equals(
- 'Internal Error: $expectedInternalError', error.toString());
- } else {
- throw error;
- }
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ if (expectedError != null) {
+ Expect.equals(expectedError,
+ compiler.errors[0].message.toString());
+ } else {
+ Expect.isTrue(compiler.errors.isEmpty,
+ "Unexpected errors: ${compiler.errors}");
+ }
+ }).catchError((error) {
+ if (expectedInternalError != null) {
+ Expect.equals(
+ 'Internal Error: $expectedInternalError', error.toString());
+ } else {
+ throw error;
+ }
+ });
}
- test('full', patchText: fullPatch);
- test('lazy', patchText: lazyPatch);
- test('unknown', expectIsPatched: false,
+ await test('full', patchText: fullPatch);
+ await test('lazy', patchText: lazyPatch);
+ await test('unknown', expectIsPatched: false,
expectedError: 'External method without an implementation.');
- test('full',
+ await test('full',
defaultPatch: "@patch test(){}",
expectedInternalError: "Trying to patch a function more than once.");
}
-testPatchConstructor() {
- asyncTest(() => applyPatch(
+Future testPatchConstructor() async {
+ var compiler = await applyPatch(
"""
class Class {
external Class();
@@ -219,35 +244,34 @@
@patch class Class {
@patch Class();
}
- """).then((compiler) {
- var classOrigin = ensure(compiler, "Class", compiler.coreLibrary.find,
- expectIsPatched: true);
- classOrigin.ensureResolved(compiler);
- var classPatch = ensure(compiler, "Class", compiler.coreLibrary.patch.find,
- expectIsPatch: true);
+ """);
+ var classOrigin = ensure(compiler, "Class", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ classOrigin.ensureResolved(compiler);
+ var classPatch = ensure(compiler, "Class", compiler.coreLibrary.patch.find,
+ expectIsPatch: true);
- Expect.equals(classPatch, classOrigin.patch);
- Expect.equals(classOrigin, classPatch.origin);
+ Expect.equals(classPatch, classOrigin.patch);
+ Expect.equals(classOrigin, classPatch.origin);
- var constructorOrigin = ensure(compiler, "",
- (name) => classOrigin.localLookup(name),
- expectIsPatched: true);
- var constructorPatch = ensure(compiler, "",
- (name) => classPatch.localLookup(name),
- expectIsPatch: true);
+ var constructorOrigin = ensure(compiler, "",
+ (name) => classOrigin.localLookup(name),
+ expectIsPatched: true);
+ var constructorPatch = ensure(compiler, "",
+ (name) => classPatch.localLookup(name),
+ expectIsPatch: true);
- Expect.equals(constructorPatch, constructorOrigin.patch);
- Expect.equals(constructorOrigin, constructorPatch.origin);
+ Expect.equals(constructorPatch, constructorOrigin.patch);
+ Expect.equals(constructorOrigin, constructorPatch.origin);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isTrue(compiler.errors.isEmpty,
- "Unexpected errors: ${compiler.errors}");
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ Expect.isTrue(compiler.errors.isEmpty,
+ "Unexpected errors: ${compiler.errors}");
}
-testPatchRedirectingConstructor() {
- asyncTest(() => applyPatch(
+Future testPatchRedirectingConstructor() async {
+ var compiler = await applyPatch(
"""
class Class {
Class(x) : this._(x, false);
@@ -259,42 +283,41 @@
@patch class Class {
@patch Class._(x, y) { print('$x,$y'); }
}
- """).then((compiler) {
- var classOrigin = ensure(compiler, "Class", compiler.coreLibrary.find,
- expectIsPatched: true);
- classOrigin.ensureResolved(compiler);
+ """);
+ var classOrigin = ensure(compiler, "Class", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ classOrigin.ensureResolved(compiler);
- var classPatch = ensure(compiler, "Class", compiler.coreLibrary.patch.find,
- expectIsPatch: true);
+ var classPatch = ensure(compiler, "Class", compiler.coreLibrary.patch.find,
+ expectIsPatch: true);
- Expect.equals(classOrigin, classPatch.origin);
- Expect.equals(classPatch, classOrigin.patch);
+ Expect.equals(classOrigin, classPatch.origin);
+ Expect.equals(classPatch, classOrigin.patch);
- var constructorRedirecting =
- ensure(compiler, "",
- (name) => classOrigin.localLookup(name));
- var constructorOrigin =
- ensure(compiler, "_",
- (name) => classOrigin.localLookup(name),
- expectIsPatched: true);
- var constructorPatch =
- ensure(compiler, "_",
- (name) => classPatch.localLookup(name),
- expectIsPatch: true);
- Expect.equals(constructorOrigin, constructorPatch.origin);
- Expect.equals(constructorPatch, constructorOrigin.patch);
+ var constructorRedirecting =
+ ensure(compiler, "",
+ (name) => classOrigin.localLookup(name));
+ var constructorOrigin =
+ ensure(compiler, "_",
+ (name) => classOrigin.localLookup(name),
+ expectIsPatched: true);
+ var constructorPatch =
+ ensure(compiler, "_",
+ (name) => classPatch.localLookup(name),
+ expectIsPatch: true);
+ Expect.equals(constructorOrigin, constructorPatch.origin);
+ Expect.equals(constructorPatch, constructorOrigin.patch);
- compiler.resolver.resolve(constructorRedirecting);
+ compiler.resolver.resolve(constructorRedirecting);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isTrue(compiler.errors.isEmpty,
- "Unexpected errors: ${compiler.errors}");
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ Expect.isTrue(compiler.errors.isEmpty,
+ "Unexpected errors: ${compiler.errors}");
}
-testPatchMember() {
- asyncTest(() => applyPatch(
+Future testPatchMember() async {
+ var compiler = await applyPatch(
"""
class Class {
external String toString();
@@ -304,27 +327,26 @@
@patch class Class {
@patch String toString() => 'string';
}
- """).then((compiler) {
- var container = ensure(compiler, "Class", compiler.coreLibrary.find,
- expectIsPatched: true);
- container.parseNode(compiler);
- ensure(compiler, "Class", compiler.coreLibrary.patch.find,
- expectIsPatch: true);
+ """);
+ var container = ensure(compiler, "Class", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ container.parseNode(compiler);
+ ensure(compiler, "Class", compiler.coreLibrary.patch.find,
+ expectIsPatch: true);
- ensure(compiler, "toString", container.lookupLocalMember,
- expectIsPatched: true, checkHasBody: true);
- ensure(compiler, "toString", container.patch.lookupLocalMember,
- expectIsPatch: true, checkHasBody: true);
+ ensure(compiler, "toString", container.lookupLocalMember,
+ expectIsPatched: true, checkHasBody: true);
+ ensure(compiler, "toString", container.patch.lookupLocalMember,
+ expectIsPatch: true, checkHasBody: true);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isTrue(compiler.errors.isEmpty,
- "Unexpected errors: ${compiler.errors}");
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ Expect.isTrue(compiler.errors.isEmpty,
+ "Unexpected errors: ${compiler.errors}");
}
-testPatchGetter() {
- asyncTest(() => applyPatch(
+Future testPatchGetter() async {
+ var compiler = await applyPatch(
"""
class Class {
external int get field;
@@ -334,32 +356,31 @@
@patch class Class {
@patch int get field => 5;
}
- """).then((compiler) {
- var container = ensure(compiler, "Class", compiler.coreLibrary.find,
- expectIsPatched: true);
- container.parseNode(compiler);
- ensure(compiler,
- "field",
- container.lookupLocalMember,
- expectIsGetter: true,
- expectIsPatched: true,
- checkHasBody: true);
- ensure(compiler,
- "field",
- container.patch.lookupLocalMember,
- expectIsGetter: true,
- expectIsPatch: true,
- checkHasBody: true);
+ """);
+ var container = ensure(compiler, "Class", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ container.parseNode(compiler);
+ ensure(compiler,
+ "field",
+ container.lookupLocalMember,
+ expectIsGetter: true,
+ expectIsPatched: true,
+ checkHasBody: true);
+ ensure(compiler,
+ "field",
+ container.patch.lookupLocalMember,
+ expectIsGetter: true,
+ expectIsPatch: true,
+ checkHasBody: true);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isTrue(compiler.errors.isEmpty,
- "Unexpected errors: ${compiler.errors}");
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ Expect.isTrue(compiler.errors.isEmpty,
+ "Unexpected errors: ${compiler.errors}");
}
-testRegularMember() {
- asyncTest(() => applyPatch(
+Future testRegularMember() async {
+ var compiler = await applyPatch(
"""
class Class {
void regular() {}
@@ -368,27 +389,26 @@
"""
@patch class Class {
}
- """).then((compiler) {
- var container = ensure(compiler, "Class", compiler.coreLibrary.find,
- expectIsPatched: true);
- container.parseNode(compiler);
- ensure(compiler, "Class", compiler.coreLibrary.patch.find,
- expectIsPatch: true);
+ """);
+ var container = ensure(compiler, "Class", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ container.parseNode(compiler);
+ ensure(compiler, "Class", compiler.coreLibrary.patch.find,
+ expectIsPatch: true);
- ensure(compiler, "regular", container.lookupLocalMember,
- checkHasBody: true, expectIsRegular: true);
- ensure(compiler, "regular", container.patch.lookupLocalMember,
- checkHasBody: true, expectIsRegular: true);
+ ensure(compiler, "regular", container.lookupLocalMember,
+ checkHasBody: true, expectIsRegular: true);
+ ensure(compiler, "regular", container.patch.lookupLocalMember,
+ checkHasBody: true, expectIsRegular: true);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isTrue(compiler.errors.isEmpty,
- "Unexpected errors: ${compiler.errors}");
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ Expect.isTrue(compiler.errors.isEmpty,
+ "Unexpected errors: ${compiler.errors}");
}
-testGhostMember() {
- asyncTest(() => applyPatch(
+Future testGhostMember() async {
+ var compiler = await applyPatch(
"""
class Class {
}
@@ -397,47 +417,45 @@
@patch class Class {
void ghost() {}
}
- """).then((compiler) {
- var container = ensure(compiler, "Class", compiler.coreLibrary.find,
- expectIsPatched: true);
- container.parseNode(compiler);
- ensure(compiler, "Class", compiler.coreLibrary.patch.find,
- expectIsPatch: true);
+ """);
+ var container = ensure(compiler, "Class", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ container.parseNode(compiler);
+ ensure(compiler, "Class", compiler.coreLibrary.patch.find,
+ expectIsPatch: true);
- ensure(compiler, "ghost", container.lookupLocalMember,
- expectIsFound: false);
- ensure(compiler, "ghost", container.patch.lookupLocalMember,
- checkHasBody: true, expectIsRegular: true);
+ ensure(compiler, "ghost", container.lookupLocalMember,
+ expectIsFound: false);
+ ensure(compiler, "ghost", container.patch.lookupLocalMember,
+ checkHasBody: true, expectIsRegular: true);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isTrue(compiler.errors.isEmpty,
- "Unexpected errors: ${compiler.errors}");
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ Expect.isTrue(compiler.errors.isEmpty,
+ "Unexpected errors: ${compiler.errors}");
}
-testInjectFunction() {
- asyncTest(() => applyPatch(
+Future testInjectFunction() async {
+ var compiler = await applyPatch(
"",
- "int _function() => 5;").then((compiler) {
- ensure(compiler,
- "_function",
- compiler.coreLibrary.find,
- expectIsFound: false);
- ensure(compiler,
- "_function",
- compiler.coreLibrary.patch.find,
- checkHasBody: true, expectIsRegular: true);
+ "int _function() => 5;");
+ ensure(compiler,
+ "_function",
+ compiler.coreLibrary.find,
+ expectIsFound: false);
+ ensure(compiler,
+ "_function",
+ compiler.coreLibrary.patch.find,
+ checkHasBody: true, expectIsRegular: true);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isTrue(compiler.errors.isEmpty,
- "Unexpected errors: ${compiler.errors}");
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ Expect.isTrue(compiler.errors.isEmpty,
+ "Unexpected errors: ${compiler.errors}");
}
-testPatchSignatureCheck() {
- asyncTest(() => applyPatch(
+Future testPatchSignatureCheck() async {
+ var compiler = await applyPatch(
"""
class Class {
external String method1();
@@ -467,78 +485,76 @@
@patch void method10([int str]) {}
@patch void method11({int str}) {}
}
- """).then((compiler) {
- var container = ensure(compiler, "Class", compiler.coreLibrary.find,
- expectIsPatched: true);
- container.ensureResolved(compiler);
- container.parseNode(compiler);
+ """);
+ var container = ensure(compiler, "Class", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ container.ensureResolved(compiler);
+ container.parseNode(compiler);
- void expect(String methodName, List infos, List errors) {
- compiler.clearMessages();
- compiler.resolver.resolveMethodElement(
- ensure(compiler, methodName, container.lookupLocalMember,
- expectIsPatched: true, checkHasBody: true));
- Expect.equals(0, compiler.warnings.length);
- Expect.equals(infos.length, compiler.infos.length,
- "Unexpected infos: ${compiler.infos} on $methodName");
- for (int i = 0 ; i < infos.length ; i++) {
- Expect.equals(infos[i], compiler.infos[i].message.kind);
- }
- Expect.equals(errors.length, compiler.errors.length,
- "Unexpected errors: ${compiler.errors} on $methodName");
- for (int i = 0 ; i < errors.length ; i++) {
- Expect.equals(errors[i], compiler.errors[i].message.kind);
- }
+ void expect(String methodName, List infos, List errors) {
+ compiler.clearMessages();
+ compiler.resolver.resolveMethodElement(
+ ensure(compiler, methodName, container.lookupLocalMember,
+ expectIsPatched: true, checkHasBody: true));
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(infos.length, compiler.infos.length,
+ "Unexpected infos: ${compiler.infos} on $methodName");
+ for (int i = 0 ; i < infos.length ; i++) {
+ Expect.equals(infos[i], compiler.infos[i].message.kind);
}
+ Expect.equals(errors.length, compiler.errors.length,
+ "Unexpected errors: ${compiler.errors} on $methodName");
+ for (int i = 0 ; i < errors.length ; i++) {
+ Expect.equals(errors[i], compiler.errors[i].message.kind);
+ }
+ }
- expect("method1", [], [MessageKind.PATCH_RETURN_TYPE_MISMATCH]);
- expect("method2", [],
- [MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH]);
- expect("method3", [MessageKind.PATCH_POINT_TO_PARAMETER],
- [MessageKind.PATCH_PARAMETER_MISMATCH]);
- expect("method4", [],
- [MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]);
- expect("method5", [],
- [MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]);
- expect("method6", [],
- [MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH]);
- expect("method7", [MessageKind.PATCH_POINT_TO_PARAMETER],
- [MessageKind.PATCH_PARAMETER_MISMATCH]);
- expect("method8", [MessageKind.PATCH_POINT_TO_PARAMETER],
- [MessageKind.PATCH_PARAMETER_MISMATCH]);
- expect("method9", [MessageKind.PATCH_POINT_TO_PARAMETER],
- [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
- expect("method10", [MessageKind.PATCH_POINT_TO_PARAMETER],
- [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
- expect("method11", [MessageKind.PATCH_POINT_TO_PARAMETER],
- [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
- }));
+ expect("method1", [], [MessageKind.PATCH_RETURN_TYPE_MISMATCH]);
+ expect("method2", [],
+ [MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH]);
+ expect("method3", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_MISMATCH]);
+ expect("method4", [],
+ [MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]);
+ expect("method5", [],
+ [MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]);
+ expect("method6", [],
+ [MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH]);
+ expect("method7", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_MISMATCH]);
+ expect("method8", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_MISMATCH]);
+ expect("method9", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
+ expect("method10", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
+ expect("method11", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
}
-testExternalWithoutImplementationTopLevel() {
- asyncTest(() => applyPatch(
+Future testExternalWithoutImplementationTopLevel() async {
+ var compiler = await applyPatch(
"""
external void foo();
""",
"""
// @patch void foo() {}
- """).then((compiler) {
- var function = ensure(compiler, "foo", compiler.coreLibrary.find);
- compiler.resolver.resolve(function);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- print('testExternalWithoutImplementationTopLevel:${compiler.errors}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind ==
- MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION);
- Expect.stringEquals('External method without an implementation.',
- compiler.errors[0].message.toString());
- }));
+ """);
+ var function = ensure(compiler, "foo", compiler.coreLibrary.find);
+ compiler.resolver.resolve(function);
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ print('testExternalWithoutImplementationTopLevel:${compiler.errors}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind ==
+ MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION);
+ Expect.stringEquals('External method without an implementation.',
+ compiler.errors[0].message.toString());
}
-testExternalWithoutImplementationMember() {
- asyncTest(() => applyPatch(
+Future testExternalWithoutImplementationMember() async {
+ var compiler = await applyPatch(
"""
class Class {
external void foo();
@@ -548,63 +564,60 @@
@patch class Class {
// @patch void foo() {}
}
- """).then((compiler) {
- var container = ensure(compiler, "Class", compiler.coreLibrary.find,
- expectIsPatched: true);
- container.parseNode(compiler);
+ """);
+ var container = ensure(compiler, "Class", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ container.parseNode(compiler);
- compiler.warnings.clear();
- compiler.errors.clear();
- compiler.resolver.resolveMethodElement(
- ensure(compiler, "foo", container.lookupLocalMember));
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- print('testExternalWithoutImplementationMember:${compiler.errors}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind ==
- MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION);
- Expect.stringEquals('External method without an implementation.',
- compiler.errors[0].message.toString());
- }));
+ compiler.warnings.clear();
+ compiler.errors.clear();
+ compiler.resolver.resolveMethodElement(
+ ensure(compiler, "foo", container.lookupLocalMember));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ print('testExternalWithoutImplementationMember:${compiler.errors}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind ==
+ MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION);
+ Expect.stringEquals('External method without an implementation.',
+ compiler.errors[0].message.toString());
}
-testIsSubclass() {
- asyncTest(() => applyPatch(
+Future testIsSubclass() async {
+ var compiler = await applyPatch(
"""
class A {}
""",
"""
@patch class A {}
- """).then((compiler) {
- ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find,
- expectIsPatched: true);
- ClassElement patch = cls.patch;
- Expect.isTrue(cls != patch);
- Expect.isTrue(cls.isSubclassOf(patch));
- Expect.isTrue(patch.isSubclassOf(cls));
- }));
+ """);
+ ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ ClassElement patch = cls.patch;
+ Expect.isTrue(cls != patch);
+ Expect.isTrue(cls.isSubclassOf(patch));
+ Expect.isTrue(patch.isSubclassOf(cls));
}
-testPatchNonExistingTopLevel() {
- asyncTest(() => applyPatch(
+Future testPatchNonExistingTopLevel() async {
+ var compiler = await applyPatch(
"""
// class Class {}
""",
"""
@patch class Class {}
- """).then((compiler) {
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- print('testPatchNonExistingTopLevel:${compiler.errors}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXISTING);
- }));
+ """);
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ print('testPatchNonExistingTopLevel:${compiler.errors}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXISTING);
}
-testPatchNonExistingMember() {
- asyncTest(() => applyPatch(
+Future testPatchNonExistingMember() async {
+ var compiler = await applyPatch(
"""
class Class {}
""",
@@ -612,84 +625,80 @@
@patch class Class {
@patch void foo() {}
}
- """).then((compiler) {
- var container = ensure(compiler, "Class", compiler.coreLibrary.find,
- expectIsPatched: true);
- container.parseNode(compiler);
+ """);
+ var container = ensure(compiler, "Class", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ container.parseNode(compiler);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- print('testPatchNonExistingMember:${compiler.errors}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXISTING);
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ print('testPatchNonExistingMember:${compiler.errors}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXISTING);
}
-testPatchNonPatchablePatch() {
- asyncTest(() => applyPatch(
+Future testPatchNonPatchablePatch() async {
+ var compiler = await applyPatch(
"""
external get foo;
""",
"""
@patch var foo;
- """).then((compiler) {
- ensure(compiler, "foo", compiler.coreLibrary.find);
+ """);
+ ensure(compiler, "foo", compiler.coreLibrary.find);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- print('testPatchNonPatchablePatch:${compiler.errors}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NONPATCHABLE);
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ print('testPatchNonPatchablePatch:${compiler.errors}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NONPATCHABLE);
}
-testPatchNonPatchableOrigin() {
- asyncTest(() => applyPatch(
+Future testPatchNonPatchableOrigin() async {
+ var compiler = await applyPatch(
"""
external var foo;
""",
"""
@patch get foo => 0;
- """).then((compiler) {
- ensure(compiler, "foo", compiler.coreLibrary.find);
+ """);
+ ensure(compiler, "foo", compiler.coreLibrary.find);
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- print('testPatchNonPatchableOrigin:${compiler.errors}');
- Expect.equals(2, compiler.errors.length);
- Expect.equals(
- MessageKind.EXTRANEOUS_MODIFIER, compiler.errors[0].message.kind);
- Expect.equals(
- // TODO(ahe): Eventually, this error should be removed as it will be
- // handled by the regular parser.
- MessageKind.PATCH_NONPATCHABLE, compiler.errors[1].message.kind);
- }));
+ Expect.isTrue(compiler.warnings.isEmpty,
+ "Unexpected warnings: ${compiler.warnings}");
+ print('testPatchNonPatchableOrigin:${compiler.errors}');
+ Expect.equals(2, compiler.errors.length);
+ Expect.equals(
+ MessageKind.EXTRANEOUS_MODIFIER, compiler.errors[0].message.kind);
+ Expect.equals(
+ // TODO(ahe): Eventually, this error should be removed as it will be
+ // handled by the regular parser.
+ MessageKind.PATCH_NONPATCHABLE, compiler.errors[1].message.kind);
}
-testPatchNonExternalTopLevel() {
- asyncTest(() => applyPatch(
+Future testPatchNonExternalTopLevel() async {
+ var compiler = await applyPatch(
"""
void foo() {}
""",
"""
@patch void foo() {}
- """).then((compiler) {
- print('testPatchNonExternalTopLevel.errors:${compiler.errors}');
- print('testPatchNonExternalTopLevel.warnings:${compiler.warnings}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL);
- Expect.equals(0, compiler.warnings.length);
- Expect.equals(1, compiler.infos.length);
- Expect.isTrue(compiler.infos[0].message.kind ==
- MessageKind.PATCH_POINT_TO_FUNCTION);
- }));
+ """);
+ print('testPatchNonExternalTopLevel.errors:${compiler.errors}');
+ print('testPatchNonExternalTopLevel.warnings:${compiler.warnings}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL);
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(1, compiler.infos.length);
+ Expect.isTrue(compiler.infos[0].message.kind ==
+ MessageKind.PATCH_POINT_TO_FUNCTION);
}
-testPatchNonExternalMember() {
- asyncTest(() => applyPatch(
+Future testPatchNonExternalMember() async {
+ var compiler = await applyPatch(
"""
class Class {
void foo() {}
@@ -699,146 +708,139 @@
@patch class Class {
@patch void foo() {}
}
- """).then((compiler) {
- var container = ensure(compiler, "Class", compiler.coreLibrary.find,
- expectIsPatched: true);
- container.parseNode(compiler);
+ """);
+ var container = ensure(compiler, "Class", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ container.parseNode(compiler);
- print('testPatchNonExternalMember.errors:${compiler.errors}');
- print('testPatchNonExternalMember.warnings:${compiler.warnings}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL);
- Expect.equals(0, compiler.warnings.length);
- Expect.equals(1, compiler.infos.length);
- Expect.isTrue(compiler.infos[0].message.kind ==
- MessageKind.PATCH_POINT_TO_FUNCTION);
- }));
+ print('testPatchNonExternalMember.errors:${compiler.errors}');
+ print('testPatchNonExternalMember.warnings:${compiler.warnings}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL);
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(1, compiler.infos.length);
+ Expect.isTrue(compiler.infos[0].message.kind ==
+ MessageKind.PATCH_POINT_TO_FUNCTION);
}
-testPatchNonClass() {
- asyncTest(() => applyPatch(
+Future testPatchNonClass() async {
+ var compiler = await applyPatch(
"""
external void Class() {}
""",
"""
@patch class Class {}
- """).then((compiler) {
- print('testPatchNonClass.errors:${compiler.errors}');
- print('testPatchNonClass.warnings:${compiler.warnings}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NON_CLASS);
- Expect.equals(0, compiler.warnings.length);
- Expect.equals(1, compiler.infos.length);
- Expect.isTrue(
- compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_CLASS);
- }));
+ """);
+ print('testPatchNonClass.errors:${compiler.errors}');
+ print('testPatchNonClass.warnings:${compiler.warnings}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NON_CLASS);
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(1, compiler.infos.length);
+ Expect.isTrue(
+ compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_CLASS);
}
-testPatchNonGetter() {
- asyncTest(() => applyPatch(
+Future testPatchNonGetter() async {
+ var compiler = await applyPatch(
"""
external void foo() {}
""",
"""
@patch get foo => 0;
- """).then((compiler) {
- print('testPatchNonClass.errors:${compiler.errors}');
- print('testPatchNonClass.warnings:${compiler.warnings}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NON_GETTER);
- Expect.equals(0, compiler.warnings.length);
- Expect.equals(1, compiler.infos.length);
- Expect.isTrue(
- compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER);
- }));
+ """);
+ print('testPatchNonClass.errors:${compiler.errors}');
+ print('testPatchNonClass.warnings:${compiler.warnings}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NON_GETTER);
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(1, compiler.infos.length);
+ Expect.isTrue(
+ compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER);
}
-testPatchNoGetter() {
- asyncTest(() => applyPatch(
+Future testPatchNoGetter() async {
+ var compiler = await applyPatch(
"""
external set foo(var value) {}
""",
"""
@patch get foo => 0;
- """).then((compiler) {
- print('testPatchNonClass.errors:${compiler.errors}');
- print('testPatchNonClass.warnings:${compiler.warnings}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NO_GETTER);
- Expect.equals(0, compiler.warnings.length);
- Expect.equals(1, compiler.infos.length);
- Expect.isTrue(
- compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER);
- }));
+ """);
+ print('testPatchNonClass.errors:${compiler.errors}');
+ print('testPatchNonClass.warnings:${compiler.warnings}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NO_GETTER);
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(1, compiler.infos.length);
+ Expect.isTrue(
+ compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER);
}
-testPatchNonSetter() {
- asyncTest(() => applyPatch(
+Future testPatchNonSetter() async {
+ var compiler = await applyPatch(
"""
external void foo() {}
""",
"""
@patch set foo(var value) {}
- """).then((compiler) {
- print('testPatchNonClass.errors:${compiler.errors}');
- print('testPatchNonClass.warnings:${compiler.warnings}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NON_SETTER);
- Expect.equals(0, compiler.warnings.length);
- Expect.equals(1, compiler.infos.length);
- Expect.isTrue(
- compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER);
- }));
+ """);
+ print('testPatchNonClass.errors:${compiler.errors}');
+ print('testPatchNonClass.warnings:${compiler.warnings}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NON_SETTER);
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(1, compiler.infos.length);
+ Expect.isTrue(
+ compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER);
}
-testPatchNoSetter() {
- asyncTest(() => applyPatch(
+Future testPatchNoSetter() async {
+ var compiler = await applyPatch(
"""
external get foo;
""",
"""
@patch set foo(var value) {}
- """).then((compiler) {
- print('testPatchNonClass.errors:${compiler.errors}');
- print('testPatchNonClass.warnings:${compiler.warnings}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NO_SETTER);
- Expect.equals(0, compiler.warnings.length);
- Expect.equals(1, compiler.infos.length);
- Expect.isTrue(
- compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER);
- }));
+ """);
+ print('testPatchNonClass.errors:${compiler.errors}');
+ print('testPatchNonClass.warnings:${compiler.warnings}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NO_SETTER);
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(1, compiler.infos.length);
+ Expect.isTrue(
+ compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER);
}
-testPatchNonFunction() {
- asyncTest(() => applyPatch(
+Future testPatchNonFunction() async {
+ var compiler = await applyPatch(
"""
external get foo;
""",
"""
@patch void foo() {}
- """).then((compiler) {
- print('testPatchNonClass.errors:${compiler.errors}');
- print('testPatchNonClass.warnings:${compiler.warnings}');
- Expect.equals(1, compiler.errors.length);
- Expect.isTrue(
- compiler.errors[0].message.kind == MessageKind.PATCH_NON_FUNCTION);
- Expect.equals(0, compiler.warnings.length);
- Expect.equals(1, compiler.infos.length);
- Expect.isTrue(
- compiler.infos[0].message.kind ==
- MessageKind.PATCH_POINT_TO_FUNCTION);
- }));
+ """);
+ print('testPatchNonClass.errors:${compiler.errors}');
+ print('testPatchNonClass.warnings:${compiler.warnings}');
+ Expect.equals(1, compiler.errors.length);
+ Expect.isTrue(
+ compiler.errors[0].message.kind == MessageKind.PATCH_NON_FUNCTION);
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(1, compiler.infos.length);
+ Expect.isTrue(
+ compiler.infos[0].message.kind ==
+ MessageKind.PATCH_POINT_TO_FUNCTION);
}
-testPatchAndSelector() {
- asyncTest(() => applyPatch(
+Future testPatchAndSelector() async {
+ var compiler = await applyPatch(
"""
class A {
external void clear();
@@ -858,76 +860,73 @@
new B();
}
""",
- runCompiler: true, analyzeOnly: true).then((Compiler compiler) {
- World world = compiler.world;
+ runCompiler: true, analyzeOnly: true);
+ World world = compiler.world;
- ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find,
- expectIsPatched: true);
- cls.ensureResolved(compiler);
+ ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find,
+ expectIsPatched: true);
+ cls.ensureResolved(compiler);
- ensure(compiler, "method", cls.patch.lookupLocalMember,
- checkHasBody: true, expectIsRegular: true);
+ ensure(compiler, "method", cls.patch.lookupLocalMember,
+ checkHasBody: true, expectIsRegular: true);
- ensure(compiler, "clear", cls.lookupLocalMember,
- checkHasBody: true, expectIsPatched: true);
+ ensure(compiler, "clear", cls.lookupLocalMember,
+ checkHasBody: true, expectIsPatched: true);
- compiler.phase = Compiler.PHASE_DONE_RESOLVING;
+ compiler.phase = Compiler.PHASE_DONE_RESOLVING;
- // Check that a method just in the patch class is a target for a
- // typed selector.
- Selector selector =
- new Selector.call(const PublicName('method'), CallStructure.NO_ARGS);
- TypeMask typeMask = new TypeMask.exact(cls, world);
- FunctionElement method = cls.implementation.lookupLocalMember('method');
- method.computeType(compiler);
- Expect.isTrue(selector.applies(method, world));
- Expect.isTrue(typeMask.canHit(method, selector, world));
+ // Check that a method just in the patch class is a target for a
+ // typed selector.
+ Selector selector =
+ new Selector.call(const PublicName('method'), CallStructure.NO_ARGS);
+ TypeMask typeMask = new TypeMask.exact(cls, world);
+ FunctionElement method = cls.implementation.lookupLocalMember('method');
+ method.computeType(compiler);
+ Expect.isTrue(selector.applies(method, world));
+ Expect.isTrue(typeMask.canHit(method, selector, world));
- // Check that the declaration method in the declaration class is a target
- // for a typed selector.
- selector =
- new Selector.call(const PublicName('clear'), CallStructure.NO_ARGS);
- typeMask = new TypeMask.exact(cls, world);
- method = cls.lookupLocalMember('clear');
- method.computeType(compiler);
- Expect.isTrue(selector.applies(method, world));
- Expect.isTrue(typeMask.canHit(method, selector, world));
+ // Check that the declaration method in the declaration class is a target
+ // for a typed selector.
+ selector =
+ new Selector.call(const PublicName('clear'), CallStructure.NO_ARGS);
+ typeMask = new TypeMask.exact(cls, world);
+ method = cls.lookupLocalMember('clear');
+ method.computeType(compiler);
+ Expect.isTrue(selector.applies(method, world));
+ Expect.isTrue(typeMask.canHit(method, selector, world));
- // Check that the declaration method in the declaration class is a target
- // for a typed selector on a subclass.
- cls = ensure(compiler, "B", compiler.coreLibrary.find);
- cls.ensureResolved(compiler);
- typeMask = new TypeMask.exact(cls, world);
- Expect.isTrue(selector.applies(method, world));
- Expect.isTrue(typeMask.canHit(method, selector, world));
- }));
+ // Check that the declaration method in the declaration class is a target
+ // for a typed selector on a subclass.
+ cls = ensure(compiler, "B", compiler.coreLibrary.find);
+ cls.ensureResolved(compiler);
+ typeMask = new TypeMask.exact(cls, world);
+ Expect.isTrue(selector.applies(method, world));
+ Expect.isTrue(typeMask.canHit(method, selector, world));
}
-void testAnalyzeAllInjectedMembers() {
- void expect(String patchText, [expectedWarnings]) {
+Future testAnalyzeAllInjectedMembers() async {
+ Future expect(String patchText, [expectedWarnings]) async {
if (expectedWarnings == null) expectedWarnings = [];
if (expectedWarnings is! List) {
expectedWarnings = <MessageKind>[expectedWarnings];
}
- asyncTest(() => applyPatch('', patchText, analyzeAll: true,
- analyzeOnly: true).then((compiler) {
+ var compiler = await applyPatch('', patchText, analyzeAll: true,
+ analyzeOnly: true);
compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')];
- return compiler.runCompiler(null).then((_) {
- compareWarningKinds(patchText, expectedWarnings, compiler.warnings);
- });
- }));
+ await compiler.runCompiler(null);
+ compareWarningKinds(patchText, expectedWarnings, compiler.warnings);
}
- expect('String s = 0;', MessageKind.NOT_ASSIGNABLE);
- expect('void method() { String s = 0; }', MessageKind.NOT_ASSIGNABLE);
- expect('''
+ await expect('String s = 0;', MessageKind.NOT_ASSIGNABLE);
+ await expect('void method() { String s = 0; }', MessageKind.NOT_ASSIGNABLE);
+ await expect('''
class Class {
String s = 0;
}
''',
MessageKind.NOT_ASSIGNABLE);
- expect('''
+ await expect('''
class Class {
void method() {
String s = 0;
@@ -937,7 +936,7 @@
MessageKind.NOT_ASSIGNABLE);
}
-void testEffectiveTarget() {
+Future testEffectiveTarget() async {
String origin = """
class A {
A() : super();
@@ -958,76 +957,76 @@
}
""";
- asyncTest(() => applyPatch(origin, patch, analyzeAll: true,
- analyzeOnly: true, runCompiler: true).then((compiler) {
- ClassElement clsA = compiler.coreLibrary.find("A");
- ClassElement clsB = compiler.coreLibrary.find("B");
+ var compiler = await applyPatch(origin, patch, analyzeAll: true,
+ analyzeOnly: true, runCompiler: true);
+ ClassElement clsA = compiler.coreLibrary.find("A");
+ ClassElement clsB = compiler.coreLibrary.find("B");
- ConstructorElement forward = clsA.lookupConstructor("forward");
- ConstructorElement target = forward.effectiveTarget;
- Expect.isTrue(target.isPatch);
- Expect.equals("patchTarget", target.name);
+ ConstructorElement forward = clsA.lookupConstructor("forward");
+ ConstructorElement target = forward.effectiveTarget;
+ Expect.isTrue(target.isPatch);
+ Expect.equals("patchTarget", target.name);
- ConstructorElement forwardTwo = clsA.lookupConstructor("forwardTwo");
- target = forwardTwo.effectiveTarget;
- Expect.isFalse(forwardTwo.isErroneous);
- Expect.isFalse(target.isPatch);
- Expect.equals("originTarget", target.name);
- }));
+ ConstructorElement forwardTwo = clsA.lookupConstructor("forwardTwo");
+ target = forwardTwo.effectiveTarget;
+ Expect.isFalse(forwardTwo.isErroneous);
+ Expect.isFalse(target.isPatch);
+ Expect.equals("originTarget", target.name);
}
-void testTypecheckPatchedMembers() {
+Future testTypecheckPatchedMembers() async {
String originText = "external void method();";
String patchText = """
@patch void method() {
String s = 0;
}
""";
- asyncTest(() => applyPatch(originText, patchText,
- analyzeAll: true, analyzeOnly: true).then((compiler) {
- compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')];
- return compiler.runCompiler(null).then((_) {
- compareWarningKinds(patchText,
- [MessageKind.NOT_ASSIGNABLE], compiler.warnings);
- });
- }));
+ var compiler = await applyPatch(originText, patchText,
+ analyzeAll: true, analyzeOnly: true);
+ compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')];
+ await compiler.runCompiler(null);
+ compareWarningKinds(patchText,
+ [MessageKind.NOT_ASSIGNABLE], compiler.warnings);
}
main() {
- testPatchConstructor();
- testPatchRedirectingConstructor();
- testPatchFunction();
- testPatchMember();
- testPatchGetter();
- testRegularMember();
- testGhostMember();
- testInjectFunction();
- testPatchSignatureCheck();
+ asyncTest(() async {
+ await testPatchConstructor();
+ await testPatchRedirectingConstructor();
+ await testPatchFunction();
+ await testPatchFunctionMetadata();
+ await testPatchMember();
+ await testPatchGetter();
+ await testRegularMember();
+ await testGhostMember();
+ await testInjectFunction();
+ await testPatchSignatureCheck();
- testPatchVersioned();
+ await testPatchVersioned();
- testExternalWithoutImplementationTopLevel();
- testExternalWithoutImplementationMember();
+ await testExternalWithoutImplementationTopLevel();
+ await testExternalWithoutImplementationMember();
- testIsSubclass();
+ await testIsSubclass();
- testPatchNonExistingTopLevel();
- testPatchNonExistingMember();
- testPatchNonPatchablePatch();
- testPatchNonPatchableOrigin();
- testPatchNonExternalTopLevel();
- testPatchNonExternalMember();
- testPatchNonClass();
- testPatchNonGetter();
- testPatchNoGetter();
- testPatchNonSetter();
- testPatchNoSetter();
- testPatchNonFunction();
+ await testPatchNonExistingTopLevel();
+ await testPatchNonExistingMember();
+ await testPatchNonPatchablePatch();
+ await testPatchNonPatchableOrigin();
+ await testPatchNonExternalTopLevel();
+ await testPatchNonExternalMember();
+ await testPatchNonClass();
+ await testPatchNonGetter();
+ await testPatchNoGetter();
+ await testPatchNonSetter();
+ await testPatchNoSetter();
+ await testPatchNonFunction();
- testPatchAndSelector();
+ await testPatchAndSelector();
- testEffectiveTarget(); /// bug: ok
+ await testEffectiveTarget(); /// bug: ok
- testAnalyzeAllInjectedMembers();
- testTypecheckPatchedMembers();
+ await testAnalyzeAllInjectedMembers();
+ await testTypecheckPatchedMembers();
+ });
}
diff --git a/tests/compiler/dart2js/pretty_parameter_test.dart b/tests/compiler/dart2js/pretty_parameter_test.dart
index 723683b..3aa4db1 100644
--- a/tests/compiler/dart2js/pretty_parameter_test.dart
+++ b/tests/compiler/dart2js/pretty_parameter_test.dart
@@ -35,7 +35,7 @@
""";
const String NO_LOCAL = r"""
-foo(bar, bar) {
+foo(bar, baz) {
if (bar) {
baz = 2;
} else {
diff --git a/tests/compiler/dart2js/reexport_handled_test.dart b/tests/compiler/dart2js/reexport_handled_test.dart
index 4bdd62d..ade3373 100644
--- a/tests/compiler/dart2js/reexport_handled_test.dart
+++ b/tests/compiler/dart2js/reexport_handled_test.dart
@@ -32,24 +32,15 @@
return compiler.libraryLoader.loadLibrary(exportingLibraryUri);
}).then((exportingLibrary) {
Expect.isTrue(exportingLibrary.exportsHandled);
- var foo = findInExports(exportingLibrary, 'foo');
+ var foo = exportingLibrary.findExported('foo');
Expect.isNotNull(foo);
Expect.isTrue(foo.isField);
// Load reexporting library when exports are handled on the exporting library.
return compiler.libraryLoader.loadLibrary(reexportingLibraryUri);
}).then((reexportingLibrary) {
- var foo = findInExports(reexportingLibrary, 'foo');
+ var foo = reexportingLibrary.findExported('foo');
Expect.isNotNull(foo);
Expect.isTrue(foo.isField);
}));
}
-
-Element findInExports(LibraryElement library, String name) {
- for (var export in library.exports) {
- if (export.name == name) {
- return export;
- }
- }
- return null;
-}
diff --git a/tests/compiler/dart2js/related_types.dart b/tests/compiler/dart2js/related_types.dart
new file mode 100644
index 0000000..9843180
--- /dev/null
+++ b/tests/compiler/dart2js/related_types.dart
@@ -0,0 +1,430 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library related_types;
+
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/core_types.dart';
+import 'package:compiler/src/dart_types.dart';
+import 'package:compiler/src/diagnostics/messages.dart';
+import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/filenames.dart';
+import 'package:compiler/src/resolution/semantic_visitor.dart';
+import 'package:compiler/src/tree/tree.dart';
+import 'package:compiler/src/universe/universe.dart';
+import 'package:compiler/src/world.dart';
+import 'memory_compiler.dart';
+
+main(List<String> arguments) async {
+ if (arguments.isNotEmpty) {
+ Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.last));
+ CompilationResult result = await runCompiler(
+ entryPoint: entryPoint,
+ options: [Flags.analyzeOnly, '--categories=Client,Server']);
+ if (result.isSuccess) {
+ checkRelatedTypes(result.compiler);
+ }
+ } else {
+ print('Usage dart related_types.dart <entry-point>');
+ }
+}
+
+/// Check all loaded libraries in [compiler] for unrelated types.
+void checkRelatedTypes(Compiler compiler) {
+ for (LibraryElement library in compiler.libraryLoader.libraries) {
+ checkLibraryElement(compiler, library);
+ }
+}
+
+/// Check [library] for unrelated types.
+void checkLibraryElement(Compiler compiler, LibraryElement library) {
+ library.forEachLocalMember((Element element) {
+ if (element.isClass) {
+ ClassElement cls = element;
+ cls.forEachLocalMember((MemberElement member) {
+ checkMemberElement(compiler, member);
+ });
+ } else if (!element.isTypedef) {
+ checkMemberElement(compiler, element);
+ }
+ });
+}
+
+/// Check [member] for unrelated types.
+void checkMemberElement(Compiler compiler, MemberElement member) {
+ if (!compiler.enqueuer.resolution.hasBeenResolved(member)) return;
+
+ ResolvedAst resolvedAst = member.resolvedAst;
+ RelatedTypesChecker relatedTypesChecker =
+ new RelatedTypesChecker(compiler, resolvedAst);
+ if (resolvedAst.node != null) {
+ compiler.withCurrentElement(member.implementation, () {
+ relatedTypesChecker.apply(resolvedAst.node);
+ });
+ }
+}
+
+class RelatedTypesChecker extends TraversalVisitor<DartType, dynamic> {
+ final Compiler compiler;
+ final ResolvedAst resolvedAst;
+
+ RelatedTypesChecker(this.compiler, ResolvedAst resolvedAst)
+ : this.resolvedAst = resolvedAst,
+ super(resolvedAst.elements);
+
+ ClassWorld get world => compiler.world;
+
+ CoreTypes get coreTypes => compiler.coreTypes;
+
+ InterfaceType get thisType => resolvedAst.element.enclosingClass.thisType;
+
+ /// Returns `true` if there exists no common subtype of [left] and [right].
+ bool hasEmptyIntersection(DartType left, DartType right) {
+ if (left == right) return false;
+ if (left == null || right == null) return false;
+ ClassElement leftClass = const ClassFinder().findClass(left);
+ ClassElement rightClass = const ClassFinder().findClass(right);
+ if (leftClass != null && rightClass != null) {
+ return !world.haveAnyCommonSubtypes(leftClass, rightClass);
+ }
+ return false;
+ }
+
+ /// Checks that there exists a common subtype of [left] and [right] or report
+ /// a hint otherwise.
+ void checkRelated(Node node, DartType left, DartType right) {
+ if (hasEmptyIntersection(left, right)) {
+ compiler.reportHint(
+ node, MessageKind.NO_COMMON_SUBTYPES, {'left': left, 'right': right});
+ }
+ }
+
+ /// Check weakly typed collection methods, like `Map.containsKey`,
+ /// `Map.containsValue` and `Iterable.contains`.
+ void checkDynamicInvoke(
+ Node node,
+ DartType receiverType,
+ List<DartType> argumentTypes,
+ Selector selector) {
+ if (selector.name == 'containsKey' &&
+ selector.callStructure == CallStructure.ONE_ARG) {
+ InterfaceType mapType = findMapType(receiverType);
+ if (mapType != null) {
+ DartType keyType = findMapKeyType(mapType);
+ checkRelated(node, keyType, argumentTypes.first);
+ }
+ } else if (selector.name == 'containsValue' &&
+ selector.callStructure == CallStructure.ONE_ARG) {
+ InterfaceType mapType = findMapType(receiverType);
+ if (mapType != null) {
+ DartType valueType = findMapValueType(mapType);
+ checkRelated(node, valueType, argumentTypes.first);
+ }
+ } else if (selector.name == 'contains' &&
+ selector.callStructure == CallStructure.ONE_ARG) {
+ InterfaceType iterableType = findIterableType(receiverType);
+ if (iterableType != null) {
+ DartType elementType = findIterableElementType(iterableType);
+ checkRelated(node, elementType, argumentTypes.first);
+ }
+ } else if (selector.name == 'remove' &&
+ selector.callStructure == CallStructure.ONE_ARG) {
+ InterfaceType mapType = findMapType(receiverType);
+ if (mapType != null) {
+ DartType keyType = findMapKeyType(mapType);
+ checkRelated(node, keyType, argumentTypes.first);
+ }
+ InterfaceType listType = findListType(receiverType);
+ if (listType != null) {
+ DartType valueType = findListElementType(listType);
+ checkRelated(node, valueType, argumentTypes.first);
+ }
+ }
+ }
+
+ /// Return the interface type implemented by [type] or `null` if no interface
+ /// type is implied by [type].
+ InterfaceType findInterfaceType(DartType type) {
+ return Types.computeInterfaceType(compiler, type);
+ }
+
+ /// Returns the supertype of [receiver] that implements [cls], if any.
+ InterfaceType findClassType(DartType receiver, ClassElement cls) {
+ InterfaceType interfaceType = findInterfaceType(receiver);
+ if (interfaceType == null) return null;
+ InterfaceType mapType = interfaceType.asInstanceOf(cls);
+ if (mapType == null) return null;
+ return mapType;
+ }
+
+ /// Returns the supertype of [receiver] that implements `Iterable`, if any.
+ InterfaceType findIterableType(DartType receiver) {
+ return findClassType(receiver, compiler.iterableClass);
+ }
+
+ /// Returns the element type of the supertype of [receiver] that implements
+ /// `Iterable`, if any.
+ DartType findIterableElementType(InterfaceType iterableType) {
+ if (iterableType == null) return null;
+ return iterableType.typeArguments[0];
+ }
+
+ /// Returns the supertype of [receiver] that implements `Map`, if any.
+ InterfaceType findMapType(DartType receiver) {
+ return findClassType(receiver, compiler.mapClass);
+ }
+
+ /// Returns the key type of the supertype of [receiver] that implements
+ /// `Map`, if any.
+ DartType findMapKeyType(InterfaceType mapType) {
+ if (mapType == null) return null;
+ return mapType.typeArguments[0];
+ }
+
+ /// Returns the value type of the supertype of [receiver] that implements
+ /// `Map`, if any.
+ DartType findMapValueType(InterfaceType mapType) {
+ if (mapType == null) return null;
+ return mapType.typeArguments[1];
+ }
+
+ /// Returns the supertype of [receiver] that implements `List`, if any.
+ InterfaceType findListType(DartType receiver) {
+ return findClassType(receiver, compiler.listClass);
+ }
+
+ /// Returns the element type of the supertype of [receiver] that implements
+ /// `List`, if any.
+ DartType findListElementType(InterfaceType listType) {
+ if (listType == null) return null;
+ return listType.typeArguments[0];
+ }
+
+ /// Returns the implied return type of [type] or `dynamic` if no return type
+ /// is implied.
+ DartType findReturnType(DartType type) {
+ if (type is FunctionType) {
+ return type.returnType;
+ }
+ return const DynamicType();
+ }
+
+ /// Visits [arguments] and returns the list of their corresponding types.
+ List<DartType> findArgumentTypes(NodeList arguments) {
+ List<DartType> argumentTypes = <DartType>[];
+ for (Node argument in arguments) {
+ argumentTypes.add(apply(argument));
+ }
+ return argumentTypes;
+ }
+
+ /// Finds the [MemberSignature] of the [name] property on [type], if any.
+ MemberSignature lookupInterfaceMember(DartType type, Name name) {
+ InterfaceType interfaceType = findInterfaceType(type);
+ if (interfaceType == null) return null;
+ return interfaceType.lookupInterfaceMember(name);
+ }
+
+ /// Returns the type of an access of the [name] property on [type], or
+ /// `dynamic` if no property was found.
+ DartType lookupInterfaceMemberAccessType(DartType type, Name name) {
+ MemberSignature member = lookupInterfaceMember(type, name);
+ if (member == null) return const DynamicType();
+ return member.type;
+ }
+
+ /// Returns the function type of the [name] property on [type], or
+ /// `dynamic` if no property was found.
+ FunctionType lookupInterfaceMemberInvocationType(DartType type, Name name) {
+ MemberSignature member = lookupInterfaceMember(type, name);
+ if (member == null) return null;
+ return member.functionType;
+ }
+
+ DartType apply(Node node, [_]) {
+ DartType type = node.accept(this);
+ if (type == null) {
+ type = const DynamicType();
+ }
+ return type;
+ }
+
+ @override
+ DartType visitEquals(Send node, Node left, Node right, _) {
+ DartType leftType = apply(left);
+ DartType rightType = apply(right);
+ checkRelated(node, leftType, rightType);
+ return coreTypes.boolType;
+ }
+
+ @override
+ DartType visitNotEquals(Send node, Node left, Node right, _) {
+ DartType leftType = apply(left);
+ DartType rightType = apply(right);
+ checkRelated(node, leftType, rightType);
+ return coreTypes.boolType;
+ }
+
+ @override
+ DartType visitIndex(Send node, Node receiver, Node index, _) {
+ DartType receiverType = apply(receiver);
+ DartType indexType = apply(index);
+ InterfaceType mapType = findMapType(receiverType);
+ DartType keyType = findMapKeyType(mapType);
+ DartType valueType = findMapValueType(mapType);
+ checkRelated(index, keyType, indexType);
+ return valueType;
+ }
+
+ @override
+ DartType visitLiteralInt(LiteralInt node) {
+ return coreTypes.intType;
+ }
+
+ @override
+ DartType visitLiteralString(LiteralString node) {
+ return coreTypes.stringType;
+ }
+
+ @override
+ DartType visitLiteralBool(LiteralBool node) {
+ return coreTypes.boolType;
+ }
+
+ @override
+ DartType visitLiteralMap(LiteralMap node) {
+ return elements.getType(node);
+ }
+
+ @override
+ DartType visitLiteralList(LiteralList node) {
+ return elements.getType(node);
+ }
+
+ @override
+ DartType visitLiteralNull(LiteralNull node) {
+ return elements.getType(node);
+ }
+
+ @override
+ DartType visitLocalVariableGet(Send node, LocalVariableElement variable, _) {
+ return variable.type;
+ }
+
+ @override
+ DartType visitLocalFunctionGet(Send node, LocalFunctionElement function, _) {
+ return function.type;
+ }
+
+ @override
+ DartType visitParameterGet(Send node, ParameterElement parameter, _) {
+ return parameter.type;
+ }
+
+ @override
+ DartType visitThisPropertyGet(Send node, Name name, _) {
+ return lookupInterfaceMemberAccessType(thisType, name);
+ }
+
+ @override
+ DartType visitDynamicPropertyGet(Send node, Node receiver, Name name, _) {
+ DartType receiverType = apply(receiver);
+ return lookupInterfaceMemberAccessType(receiverType, name);
+ }
+
+ @override
+ DartType visitIfNotNullDynamicPropertyGet(
+ Send node, Node receiver, Name name, _) {
+ DartType receiverType = apply(receiver);
+ return lookupInterfaceMemberAccessType(receiverType, name);
+ }
+
+ @override
+ DartType visitStaticFieldGet(Send node, FieldElement field, _) {
+ return field.type;
+ }
+
+ @override
+ DartType visitTopLevelFieldGet(Send node, FieldElement field, _) {
+ return field.type;
+ }
+
+ @override
+ DartType visitDynamicPropertyInvoke(
+ Send node,
+ Node receiver,
+ NodeList arguments,
+ Selector selector, _) {
+ DartType receiverType = apply(receiver);
+ List<DartType> argumentTypes = findArgumentTypes(arguments);
+ FunctionType methodType = lookupInterfaceMemberInvocationType(
+ receiverType, selector.memberName);
+ checkDynamicInvoke(node, receiverType, argumentTypes, selector);
+ return findReturnType(methodType);
+ }
+
+ @override
+ DartType visitThisPropertyInvoke(
+ Send node,
+ NodeList arguments,
+ Selector selector, _) {
+ DartType receiverType = thisType;
+ List<DartType> argumentTypes = findArgumentTypes(arguments);
+ FunctionType methodType = lookupInterfaceMemberInvocationType(
+ receiverType, selector.memberName);
+ checkDynamicInvoke(node, receiverType, argumentTypes, selector);
+ return findReturnType(methodType);
+ }
+
+ @override
+ DartType visitIfNotNullDynamicPropertyInvoke(
+ Send node,
+ Node receiver,
+ NodeList arguments,
+ Selector selector, _) {
+ DartType receiverType = apply(receiver);
+ List<DartType> argumentTypes = findArgumentTypes(arguments);
+ FunctionType methodType = lookupInterfaceMemberInvocationType(
+ receiverType, selector.memberName);
+ checkDynamicInvoke(node, receiverType, argumentTypes, selector);
+ return findReturnType(methodType);
+ }
+
+ @override
+ DartType visitTopLevelFunctionInvoke(
+ Send node,
+ MethodElement function,
+ NodeList arguments,
+ CallStructure callStructure, _) {
+ apply(arguments);
+ return findReturnType(function.type);
+ }
+
+ @override
+ DartType visitStaticFunctionInvoke(
+ Send node,
+ MethodElement function,
+ NodeList arguments,
+ CallStructure callStructure, _) {
+ apply(arguments);
+ return findReturnType(function.type);
+ }
+}
+
+/// Computes the [ClassElement] implied by a type.
+// TODO(johnniwinther): Handle type variables, function types and typedefs.
+class ClassFinder extends BaseDartTypeVisitor<ClassElement, dynamic> {
+ const ClassFinder();
+
+ ClassElement findClass(DartType type) => type.accept(this, null);
+
+ @override
+ ClassElement visitType(DartType type, _) => null;
+
+ @override
+ ClassElement visitInterfaceType(InterfaceType type, _) {
+ return type.element;
+ }
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/related_types_test.dart b/tests/compiler/dart2js/related_types_test.dart
new file mode 100644
index 0000000..dfb50b4
--- /dev/null
+++ b/tests/compiler/dart2js/related_types_test.dart
@@ -0,0 +1,294 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library related_types;
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/diagnostics/messages.dart';
+import 'package:compiler/src/elements/elements.dart';
+import 'memory_compiler.dart';
+
+import 'related_types.dart';
+
+const String CODE = '''
+Map<String, int> topLevelMap;
+List<String> topLevelList;
+
+Map<String, int> getTopLevelMap() => null;
+List<String> getTopLevelList() => null;
+
+class Class {
+ Map<String, int> instanceMap;
+ List<String> instanceList;
+
+ Map<String, int> getInstanceMap() => null;
+ List<String> getInstanceList() => null;
+
+ static Map<String, int> staticMap;
+ static List<String> staticList;
+
+ static Map<String, int> getStaticMap() => null;
+ static List<String> getStaticList() => null;
+
+ test_instanceMapIndex() {
+ instanceMap[0];
+ }
+ test_instanceMapContainsKey() {
+ instanceMap.containsKey(0);
+ }
+ test_instanceMapContainsValue() {
+ instanceMap.containsValue('');
+ }
+ test_instanceMapRemove() {
+ instanceMap.remove(0);
+ }
+ test_instanceListContains() {
+ instanceList.contains(0);
+ }
+ test_instanceListRemove() {
+ instanceList.remove(0);
+ }
+
+ test_getInstanceMapIndex() {
+ getInstanceMap()[0];
+ }
+ test_getInstanceMapContainsKey() {
+ getInstanceMap().containsKey(0);
+ }
+ test_getInstanceMapContainsValue() {
+ getInstanceMap().containsValue('');
+ }
+ test_getInstanceMapRemove() {
+ getInstanceMap().remove(0);
+ }
+ test_getInstanceListContains() {
+ getInstanceList().contains(0);
+ }
+ test_getInstanceListRemove() {
+ getInstanceList().remove(0);
+ }
+
+ static test_staticMapIndex() {
+ staticMap[0];
+ }
+ static test_staticMapContainsKey() {
+ staticMap.containsKey(0);
+ }
+ static test_staticMapContainsValue() {
+ staticMap.containsValue('');
+ }
+ static test_staticMapRemove() {
+ staticMap.remove(0);
+ }
+ static test_staticListContains() {
+ staticList.contains(0);
+ }
+ static test_staticListRemove() {
+ staticList.remove(0);
+ }
+
+ static test_getStaticMapIndex() {
+ getStaticMap()[0];
+ }
+ static test_getStaticMapContainsKey() {
+ getStaticMap().containsKey(0);
+ }
+ static test_getStaticMapContainsValue() {
+ getStaticMap().containsValue('');
+ }
+ static test_getStaticMapRemove() {
+ getStaticMap().remove(0);
+ }
+ static test_getStaticListContains() {
+ getStaticList().contains(0);
+ }
+ static test_getStaticListRemove() {
+ getStaticList().remove(0);
+ }
+}
+
+main() {}
+
+test_equals() => 0 == '';
+test_notEquals() => 0 != '';
+test_index() => <String, int>{}[0];
+
+test_localMapIndex() {
+ Map<String, int> map;
+ map[0];
+}
+test_localMapContainsKey() {
+ Map<String, int> map;
+ map.containsKey(0);
+}
+test_localMapContainsValue() {
+ Map<String, int> map;
+ map.containsValue('');
+}
+test_localMapRemove() {
+ Map<String, int> map;
+ map.remove(0);
+}
+test_localListContains() {
+ List<String> list;
+ list.contains(0);
+}
+test_localListRemove() {
+ List<String> list;
+ list.remove(0);
+}
+
+test_topLevelMapIndex() {
+ topLevelMap[0];
+}
+test_topLevelMapContainsKey() {
+ topLevelMap.containsKey(0);
+}
+test_topLevelMapContainsValue() {
+ topLevelMap.containsValue('');
+}
+test_topLevelMapRemove() {
+ topLevelMap.remove(0);
+}
+test_topLevelListContains() {
+ topLevelList.contains(0);
+}
+test_topLevelListRemove() {
+ topLevelList.remove(0);
+}
+
+test_getTopLevelMapIndex() {
+ getTopLevelMap()[0];
+}
+test_getTopLevelMapContainsKey() {
+ getTopLevelMap().containsKey(0);
+}
+test_getTopLevelMapContainsValue() {
+ getTopLevelMap().containsValue('');
+}
+test_getTopLevelMapRemove() {
+ getTopLevelMap().remove(0);
+}
+test_getTopLevelListContains() {
+ getTopLevelList().contains(0);
+}
+test_getTopLevelListRemove() {
+ getTopLevelList().remove(0);
+}
+
+test_staticMapIndex() {
+ Class.staticMap[0];
+}
+test_staticMapContainsKey() {
+ Class.staticMap.containsKey(0);
+}
+test_staticMapContainsValue() {
+ Class.staticMap.containsValue('');
+}
+test_staticMapRemove() {
+ Class.staticMap.remove(0);
+}
+test_staticListContains() {
+ Class.staticList.contains(0);
+}
+test_staticListRemove() {
+ Class.staticList.remove(0);
+}
+
+test_getStaticMapIndex() {
+ Class.getStaticMap()[0];
+}
+test_getStaticMapContainsKey() {
+ Class.getStaticMap().containsKey(0);
+}
+test_getStaticMapContainsValue() {
+ Class.getStaticMap().containsValue('');
+}
+test_getStaticMapRemove() {
+ Class.getStaticMap().remove(0);
+}
+test_getStaticListContains() {
+ Class.getStaticList().contains(0);
+}
+test_getStaticListRemove() {
+ Class.getStaticList().remove(0);
+}
+
+test_instanceMapIndex(Class c) {
+ c.instanceMap[0];
+}
+test_instanceMapContainsKey(Class c) {
+ c.instanceMap.containsKey(0);
+}
+test_instanceMapContainsValue(Class c) {
+ c.instanceMap.containsValue('');
+}
+test_instanceMapRemove(Class c) {
+ c.instanceMap.remove(0);
+}
+test_instanceListContains(Class c) {
+ c.instanceList.contains(0);
+}
+test_instanceListRemove(Class c) {
+ c.instanceList.remove(0);
+}
+
+test_getInstanceMapIndex(Class c) {
+ c.getInstanceMap()[0];
+}
+test_getInstanceMapContainsKey(Class c) {
+ c.getInstanceMap().containsKey(0);
+}
+test_getInstanceMapContainsValue(Class c) {
+ c.getInstanceMap().containsValue('');
+}
+test_getInstanceMapRemove(Class c) {
+ c.getInstanceMap().remove(0);
+}
+test_getInstanceListContains(Class c) {
+ c.getInstanceList().contains(0);
+}
+test_getInstanceListRemove(Class c) {
+ c.getInstanceList().remove(0);
+}
+''';
+
+main(List<String> arguments) {
+ asyncTest(() async {
+ DiagnosticCollector collector = new DiagnosticCollector();
+ CompilationResult result = await runCompiler(
+ memorySourceFiles: {'main.dart': CODE},
+ options: [Flags.analyzeOnly, Flags.analyzeMain],
+ diagnosticHandler: collector);
+ Expect.isFalse(collector.hasRegularMessages, "Unexpected analysis messages.");
+ Compiler compiler = result.compiler;
+
+
+ void checkMember(MemberElement member) {
+ if (!member.name.startsWith('test_')) return;
+
+ collector.clear();
+ checkMemberElement(compiler, member);
+ Expect.equals(1, collector.hints.length,
+ "Unexpected hint count for $member.");
+ Expect.equals(
+ MessageKind.NO_COMMON_SUBTYPES,
+ collector.hints.first.message.kind,
+ "Unexpected message kind ${collector.hints.first.message.kind} "
+ "for $member.");
+ }
+
+ compiler.mainApp.forEachLocalMember((Element element) {
+ if (element.isClass) {
+ ClassElement cls = element;
+ cls.forEachLocalMember(checkMember);
+ } else {
+ checkMember(element);
+ }
+ });
+ });
+}
diff --git a/tests/compiler/dart2js/semantic_visitor_test.dart b/tests/compiler/dart2js/semantic_visitor_test.dart
index 37d83bb..575b758 100644
--- a/tests/compiler/dart2js/semantic_visitor_test.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test.dart
@@ -8,6 +8,7 @@
import 'dart:mirrors';
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/constants/expressions.dart';
import 'package:compiler/src/dart_types.dart';
import 'package:compiler/src/diagnostics/spannable.dart';
@@ -292,9 +293,7 @@
CompilationResult result = await runCompiler(
memorySourceFiles: sourceFiles,
- options: ['--analyze-all',
- '--analyze-only',
- '--enable-null-aware-operators']);
+ options: [Flags.analyzeAll, Flags.analyzeOnly]);
Compiler compiler = result.compiler;
testMap.forEach((String filename, Test test) {
LibraryElement library = compiler.libraryLoader.lookupLibrary(
diff --git a/tests/compiler/dart2js/serialization_analysis_test.dart b/tests/compiler/dart2js/serialization_analysis_test.dart
index e20726f..445ea45 100644
--- a/tests/compiler/dart2js/serialization_analysis_test.dart
+++ b/tests/compiler/dart2js/serialization_analysis_test.dart
@@ -7,6 +7,7 @@
import 'dart:async';
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/enqueue.dart';
@@ -180,7 +181,7 @@
await runCompiler(
entryPoint: entryPoint,
memorySourceFiles: test != null ? test.sourceFiles : const {},
- options: ['--analyze-only', '--output-type=dart'],
+ options: [Flags.analyzeOnly, '--output-type=dart'],
diagnosticHandler: diagnosticCollector,
beforeRun: (Compiler compiler) {
compiler.serialization.deserializer =
diff --git a/tests/compiler/dart2js/serialization_test.dart b/tests/compiler/dart2js/serialization_test.dart
index 53bfa02..c913a3c 100644
--- a/tests/compiler/dart2js/serialization_test.dart
+++ b/tests/compiler/dart2js/serialization_test.dart
@@ -427,6 +427,26 @@
element1.name, element2.name);
visit(element1.functionDeclaration, element2.functionDeclaration);
}
+
+ @override
+ void visitImportElement(ImportElement element1, ImportElement element2) {
+ visit(element1.importedLibrary, element2.importedLibrary);
+ visit(element1.library, element2.library);
+ }
+
+ @override
+ void visitExportElement(ExportElement element1, ExportElement element2) {
+ visit(element1.exportedLibrary, element2.exportedLibrary);
+ visit(element1.library, element2.library);
+ }
+
+ @override
+ void visitPrefixElement(PrefixElement element1, PrefixElement element2) {
+ check(element1, element2,
+ 'name',
+ element1.name, element2.name);
+ visit(element1.library, element2.library);
+ }
}
/// Visitor that checks for equivalence of [Element] properties.
@@ -448,8 +468,8 @@
void visitLibraryElement(LibraryElement element1, LibraryElement element2) {
checkElementIdentities(null, null, null, element1, element2);
check(element1, element2, 'name', element1.name, element2.name);
- check(element1, element2, 'getLibraryName',
- element1.getLibraryName(), element2.getLibraryName());
+ check(element1, element2, 'libraryName',
+ element1.libraryName, element2.libraryName);
visitMembers(element1, element2);
visit(element1.entryCompilationUnit, element2.entryCompilationUnit);
checkElementLists(
@@ -457,18 +477,10 @@
element1.compilationUnits.toList(),
element2.compilationUnits.toList());
- bool filterTags(LibraryTag tag) => tag.asLibraryDependency() != null;
-
- List<LibraryTag> tags1 = element1.tags.where(filterTags).toList();
- List<LibraryTag> tags2 = element2.tags.where(filterTags).toList();
- checkListEquivalence(element1, element2, 'tags', tags1, tags2,
- (Object object1, Object object2, String property,
- LibraryDependency tag1, LibraryDependency tag2) {
- checkElementIdentities(
- tag1, tag2, 'getLibraryFromTag',
- element1.getLibraryFromTag(tag1),
- element2.getLibraryFromTag(tag2));
- });
+ checkElementListIdentities(
+ element1, element2, 'imports', element1.imports, element2.imports);
+ checkElementListIdentities(
+ element1, element2, 'exports', element1.exports, element2.exports);
List<Element> imports1 = <Element>[];
List<Element> imports2 = <Element>[];
@@ -481,7 +493,7 @@
imports2.add(import);
});
checkElementListIdentities(
- element1, element2, 'imports', imports1, imports2);
+ element1, element2, 'importScope', imports1, imports2);
List<Element> exports1 = <Element>[];
List<Element> exports2 = <Element>[];
@@ -494,7 +506,7 @@
exports2.add(export);
});
checkElementListIdentities(
- element1, element2, 'exports', exports1, exports2);
+ element1, element2, 'exportScope', exports1, exports2);
}
@override
@@ -779,6 +791,39 @@
element1, element2, 'fieldElement',
element1.fieldElement, element2.fieldElement);
}
+
+ @override
+ void visitImportElement(ImportElement element1, ImportElement element2) {
+ check(element1, element2, 'uri', element1.uri, element2.uri);
+ check(
+ element1, element2, 'isDeferred',
+ element1.isDeferred, element2.isDeferred);
+ checkElementProperties(
+ element1, element2, 'prefix',
+ element1.prefix, element2.prefix);
+ checkElementIdentities(
+ element1, element2, 'importedLibrary',
+ element1.importedLibrary, element2.importedLibrary);
+ }
+
+ @override
+ void visitExportElement(ExportElement element1, ExportElement element2) {
+ check(element1, element2, 'uri', element1.uri, element2.uri);
+ checkElementIdentities(
+ element1, element2, 'importedLibrary',
+ element1.exportedLibrary, element2.exportedLibrary);
+ }
+
+ @override
+ void visitPrefixElement(PrefixElement element1, PrefixElement element2) {
+ check(
+ element1, element2, 'isDeferred',
+ element1.isDeferred, element2.isDeferred);
+ checkElementIdentities(
+ element1, element2, 'importedLibrary',
+ element1.deferredImport, element2.deferredImport);
+ // TODO(johnniwinther): Check members.
+ }
}
/// Visitor that checks for equivalence of [DartType]s.
diff --git a/tests/compiler/dart2js/show_package_warnings_test.dart b/tests/compiler/dart2js/show_package_warnings_test.dart
index 5673032..e94983c 100644
--- a/tests/compiler/dart2js/show_package_warnings_test.dart
+++ b/tests/compiler/dart2js/show_package_warnings_test.dart
@@ -7,6 +7,7 @@
import 'dart:async';
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'memory_compiler.dart';
/// Error code that creates 1 warning, 1 hint, and 1 info.
@@ -47,9 +48,9 @@
int warnings: 0,
int hints: 0,
int infos: 0}) async {
- var options = ['--analyze-only', '--analyze-all'];
+ var options = [Flags.analyzeOnly, Flags.analyzeAll];
if (showPackageWarnings) {
- options.add('--show-package-warnings');
+ options.add(Flags.showPackageWarnings);
}
var collector = new DiagnosticCollector();
await runCompiler(
diff --git a/tests/compiler/dart2js/space_test.dart b/tests/compiler/dart2js/space_test.dart
index fbf933d..b721952 100644
--- a/tests/compiler/dart2js/space_test.dart
+++ b/tests/compiler/dart2js/space_test.dart
@@ -5,6 +5,7 @@
import 'dart:io';
import 'package:compiler/src/dart2js.dart'
as dart2js;
+import 'package:compiler/src/commandline_options.dart';
main() {
Uri currentDirectory = Uri.base;
@@ -13,6 +14,6 @@
Directory.current = script.resolve("path with spaces").toFilePath();
return dart2js.main(["--library-root=${libraryRoot.toFilePath()}",
- "--analyze-only",
+ Flags.analyzeOnly,
"file with spaces.dart"]);
}
diff --git a/tests/compiler/dart2js/subtypeset_test.dart b/tests/compiler/dart2js/subtypeset_test.dart
new file mode 100644
index 0000000..6673041
--- /dev/null
+++ b/tests/compiler/dart2js/subtypeset_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test for iterators on for [SubclassNode].
+
+library world_test;
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'type_test_helper.dart';
+import 'package:compiler/src/elements/elements.dart'
+ show Element, ClassElement;
+import 'package:compiler/src/universe/class_set.dart';
+import 'package:compiler/src/world.dart';
+
+void main() {
+ asyncTest(() => TypeEnvironment.create(r"""
+ /// A
+ /// / \
+ /// B C
+ /// / /|\
+ /// D E F G
+ ///
+ class A {
+ call(H h, I i) {} // Make `H` and `I` part of the world.
+ }
+ class B extends A implements C {}
+ class C extends A {}
+ class D extends B implements A {}
+ class E extends C implements B {}
+ class F extends C {}
+ class G extends C {}
+ class H implements C {}
+ class I implements H {}
+ """,
+ mainSource: r"""
+ main() {
+ new A();
+ new C();
+ new D();
+ new E();
+ new F();
+ new G();
+ }
+ """,
+ useMockCompiler: false).then((env) {
+ World world = env.compiler.world;
+
+ ClassElement A = env.getElement("A");
+ ClassElement B = env.getElement("B");
+ ClassElement C = env.getElement("C");
+ ClassElement D = env.getElement("D");
+ ClassElement E = env.getElement("E");
+ ClassElement F = env.getElement("F");
+ ClassElement G = env.getElement("G");
+ ClassElement H = env.getElement("H");
+ ClassElement I = env.getElement("I");
+
+ void checkClass(ClassElement cls,
+ List<ClassElement> subtypes) {
+ ClassSet node = world.getClassSet(cls);
+ print('$cls:\n${node}');
+ Expect.listEquals(subtypes,
+ node.subtypes().toList(),
+ "Unexpected subtypes of ${cls.name}:\n"
+ "Expected: $subtypes\n"
+ "Found : ${node.subtypes().toList()}");
+ }
+
+ checkClass(A, [A, C, E, F, G, B, D, H, I]);
+ checkClass(B, [B, D, E]);
+ checkClass(C, [C, E, F, G, H, B, D, I]);
+ checkClass(D, [D]);
+ checkClass(E, [E]);
+ checkClass(F, [F]);
+ checkClass(G, [G]);
+ checkClass(H, [H, I]);
+ checkClass(I, [I]);
+ }));
+}
diff --git a/tests/compiler/dart2js/tag_mapping_test.dart b/tests/compiler/dart2js/tag_mapping_test.dart
index 04af1fc..ed781f3 100644
--- a/tests/compiler/dart2js/tag_mapping_test.dart
+++ b/tests/compiler/dart2js/tag_mapping_test.dart
@@ -33,11 +33,11 @@
Expect.isNotNull(mainApp, 'Could not find main.dart library');
Expect.isNotNull(lib, 'Could not find library.dart library');
- Import tag = mainApp.tags.single;
- Expect.isNotNull(tag, 'Could not find import tag in $mainApp');
+ ImportElement import = mainApp.imports.single;
+ Expect.isNotNull(import, 'Could not find import tag in $mainApp');
// Test that we can get from the import tag in main.dart to the
// library element representing library.dart.
- Expect.identical(lib, mainApp.getLibraryFromTag(tag));
+ Expect.identical(lib, import.importedLibrary);
}));
}
diff --git a/tests/compiler/dart2js/trust_type_annotations2_test.dart b/tests/compiler/dart2js/trust_type_annotations2_test.dart
index 4eeb0a6..f688380 100644
--- a/tests/compiler/dart2js/trust_type_annotations2_test.dart
+++ b/tests/compiler/dart2js/trust_type_annotations2_test.dart
@@ -30,7 +30,7 @@
options: ['--trust-type-annotations']);
var compiler = result.compiler;
var element = compiler.mainFunction;
- var code = compiler.backend.assembleCode(element);
+ var code = compiler.backend.getGeneratedCode(element);
Expect.isTrue(code.contains('+'), code);
});
}
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index c906192..0e6a54e 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -34,6 +34,8 @@
List tests = [testSimpleTypes,
testReturn,
testFor,
+ testSyncForIn,
+ testAsyncForIn,
testWhile,
testTry,
testSwitch,
@@ -126,6 +128,302 @@
// check("for (String s in true) {}", MessageKind.METHOD_NOT_FOUND);
}
+
+testSyncForIn(MockCompiler compiler) {
+ String script = """
+class HasUntypedIterator {
+ get iterator => null;
+}
+
+class HasIntIterator {
+ Iterator<int> get iterator => null;
+}
+
+class HasNoIterator {
+}
+
+class HasCustomIntIterator {
+ CustomIntIterator get iterator => null;
+}
+
+class CustomIntIterator {
+ int current;
+}
+
+class HasCustomNoCurrentIterator {
+ CustomNoCurrentIterator get iterator => null;
+}
+
+class CustomNoCurrentIterator {
+}
+
+var topLevelDyn;
+String topLevelString;
+int topLevelInt;
+
+class Class {
+ void forIn() {}
+
+ var instanceDyn;
+ String instanceString;
+ int instanceInt;
+
+ static var staticDyn;
+ static String staticString;
+ static int staticInt;
+}
+""";
+ compiler.parseScript(script);
+ ClassElement foo = compiler.mainApp.find("Class");
+ foo.ensureResolved(compiler);
+ FunctionElement method = foo.lookupLocalMember('forIn');
+
+ analyzeIn(compiler, method, """{
+ for (var e in <String>[]) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (String e in <String>[]) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (int e in <String>[]) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+ analyzeIn(compiler, method, """{
+ for (int e in []) {}
+ }""");
+
+ analyzeIn(compiler, method, """{
+ for (var e in new HasUntypedIterator()) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (String e in new HasUntypedIterator()) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (int e in new HasUntypedIterator()) {}
+ }""");
+
+ analyzeIn(compiler, method, """{
+ for (var e in new HasIntIterator()) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (String e in new HasIntIterator()) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+ analyzeIn(compiler, method, """{
+ for (int e in new HasIntIterator()) {}
+ }""");
+
+ analyzeIn(compiler, method, """{
+ for (var e in new HasNoIterator()) {}
+ }""", warnings: MessageKind.MEMBER_NOT_FOUND);
+ analyzeIn(compiler, method, """{
+ for (String e in new HasNoIterator()) {}
+ }""", warnings: MessageKind.MEMBER_NOT_FOUND);
+ analyzeIn(compiler, method, """{
+ for (int e in new HasNoIterator()) {}
+ }""", warnings: MessageKind.MEMBER_NOT_FOUND);
+
+ analyzeIn(compiler, method, """{
+ for (var e in new HasCustomIntIterator()) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (String e in new HasCustomIntIterator()) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+ analyzeIn(compiler, method, """{
+ for (int e in new HasCustomIntIterator()) {}
+ }""");
+
+ analyzeIn(compiler, method, """{
+ for (var e in new HasCustomNoCurrentIterator()) {}
+ }""", hints: MessageKind.MEMBER_NOT_FOUND);
+ analyzeIn(compiler, method, """{
+ for (String e in new HasCustomNoCurrentIterator()) {}
+ }""", hints: MessageKind.MEMBER_NOT_FOUND);
+ analyzeIn(compiler, method, """{
+ for (int e in new HasCustomNoCurrentIterator()) {}
+ }""", hints: MessageKind.MEMBER_NOT_FOUND);
+
+ analyzeIn(compiler, method, """{
+ var localDyn;
+ for (localDyn in <String>[]) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ String localString;
+ for (localString in <String>[]) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ int localInt;
+ for (localInt in <String>[]) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+
+ analyzeIn(compiler, method, """{
+ for (topLevelDyn in <String>[]) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (topLevelString in <String>[]) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (topLevelInt in <String>[]) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+
+ analyzeIn(compiler, method, """{
+ for (instanceDyn in <String>[]) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (instanceString in <String>[]) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (instanceInt in <String>[]) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+
+ analyzeIn(compiler, method, """{
+ for (staticDyn in <String>[]) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (staticString in <String>[]) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ for (staticInt in <String>[]) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+}
+
+testAsyncForIn(MockCompiler compiler) {
+ String script = """
+abstract class CustomStream<T> implements Stream<T> {}
+abstract class StringStream implements Stream<String> {}
+
+var topLevelDyn;
+String topLevelString;
+int topLevelInt;
+
+class Class {
+ void forIn() async {}
+
+ var instanceDyn;
+ String instanceString;
+ int instanceInt;
+
+ static var staticDyn;
+ static String staticString;
+ static int staticInt;
+}
+""";
+ compiler.parseScript(script);
+ ClassElement foo = compiler.mainApp.find("Class");
+ foo.ensureResolved(compiler);
+ FunctionElement method = foo.lookupLocalMember('forIn');
+
+ analyzeIn(compiler, method, """{
+ var stream;
+ await for (var e in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ var stream;
+ await for (String e in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ var stream;
+ await for (int e in stream) {}
+ }""");
+
+ analyzeIn(compiler, method, """{
+ await for (var e in []) {}
+ }""", hints: MessageKind.NOT_ASSIGNABLE);
+
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (var e in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (String e in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (int e in stream) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+
+ analyzeIn(compiler, method, """{
+ CustomStream<String> stream;
+ await for (var e in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ CustomStream<String> stream;
+ await for (String e in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ CustomStream<String> stream;
+ await for (int e in stream) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+
+ analyzeIn(compiler, method, """{
+ StringStream stream;
+ await for (var e in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ StringStream stream;
+ await for (String e in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ StringStream stream;
+ await for (int e in stream) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ var localDyn;
+ await for (localDyn in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ String localString;
+ await for (localString in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ int localInt;
+ await for (localInt in stream) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (topLevelDyn in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (topLevelString in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (topLevelInt in stream) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (instanceDyn in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (instanceString in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (instanceInt in stream) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (staticDyn in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (staticString in stream) {}
+ }""");
+ analyzeIn(compiler, method, """{
+ Stream<String> stream;
+ await for (staticInt in stream) {}
+ }""", hints: MessageKind.FORIN_NOT_ASSIGNABLE);
+}
+
+
testWhile(MockCompiler compiler) {
check(String code, {warnings}) {
analyze(compiler, code, warnings: warnings);
@@ -614,7 +912,7 @@
int localMethod(String str) { return 0; }
$text
}""",
- expectedWarnings);
+ warnings: expectedWarnings);
}
@@ -894,7 +1192,7 @@
ClassElement foo = compiler.mainApp.find("Foo");
foo.ensureResolved(compiler);
Element method = foo.lookupLocalMember('method');
- analyzeIn(compiler, method, "{ int i = this; }", NOT_ASSIGNABLE);
+ analyzeIn(compiler, method, "{ int i = this; }", warnings: NOT_ASSIGNABLE);
analyzeIn(compiler, method, "{ Object o = this; }");
analyzeIn(compiler, method, "{ Foo f = this; }");
}
@@ -914,7 +1212,8 @@
ClassElement B = compiler.mainApp.find("B");
B.ensureResolved(compiler);
Element method = B.lookupLocalMember('method');
- analyzeIn(compiler, method, "{ int i = super.field; }", NOT_ASSIGNABLE);
+ analyzeIn(compiler, method, "{ int i = super.field; }",
+ warnings: NOT_ASSIGNABLE);
analyzeIn(compiler, method, "{ Object o = super.field; }");
analyzeIn(compiler, method, "{ String s = super.field; }");
}
@@ -1222,14 +1521,17 @@
Element method = foo.lookupLocalMember('method');
analyzeIn(compiler, method, "{ Type type = T; }");
- analyzeIn(compiler, method, "{ T type = T; }", NOT_ASSIGNABLE);
- analyzeIn(compiler, method, "{ int type = T; }", NOT_ASSIGNABLE);
+ analyzeIn(compiler, method, "{ T type = T; }", warnings: NOT_ASSIGNABLE);
+ analyzeIn(compiler, method, "{ int type = T; }", warnings: NOT_ASSIGNABLE);
analyzeIn(compiler, method, "{ String typeName = T.toString(); }");
- analyzeIn(compiler, method, "{ T.foo; }", MEMBER_NOT_FOUND);
- analyzeIn(compiler, method, "{ T.foo = 0; }", MessageKind.SETTER_NOT_FOUND);
- analyzeIn(compiler, method, "{ T.foo(); }", MessageKind.METHOD_NOT_FOUND);
- analyzeIn(compiler, method, "{ T + 1; }", MessageKind.OPERATOR_NOT_FOUND);
+ analyzeIn(compiler, method, "{ T.foo; }", warnings: MEMBER_NOT_FOUND);
+ analyzeIn(compiler, method, "{ T.foo = 0; }",
+ warnings: MessageKind.SETTER_NOT_FOUND);
+ analyzeIn(compiler, method, "{ T.foo(); }",
+ warnings: MessageKind.METHOD_NOT_FOUND);
+ analyzeIn(compiler, method, "{ T + 1; }",
+ warnings: MessageKind.OPERATOR_NOT_FOUND);
}
void testTypeVariableLookup1(MockCompiler compiler) {
@@ -1254,7 +1556,7 @@
FunctionElement methodTest = classTest.lookupLocalMember("test");
test(String expression, [message]) {
- analyzeIn(compiler, methodTest, "{ $expression; }", message);
+ analyzeIn(compiler, methodTest, "{ $expression; }", warnings: message);
}
test('s.field');
@@ -1294,7 +1596,7 @@
FunctionElement methodTest = classTest.lookupLocalMember("test");
test(String expression, [message]) {
- analyzeIn(compiler, methodTest, "{ $expression; }", message);
+ analyzeIn(compiler, methodTest, "{ $expression; }", warnings: message);
}
test('s.field');
@@ -1316,7 +1618,7 @@
FunctionElement methodTest = classTest.lookupLocalMember("test");
test(String expression, [message]) {
- analyzeIn(compiler, methodTest, "{ $expression; }", message);
+ analyzeIn(compiler, methodTest, "{ $expression; }", warnings: message);
}
test('s.toString');
@@ -2027,18 +2329,19 @@
FunctionElement method = foo.lookupLocalMember('method');
analyzeIn(compiler, method, "{ await 0; }");
analyzeIn(compiler, method, "{ int i = await 0; }");
- analyzeIn(compiler, method, "{ String s = await 0; }", NOT_ASSIGNABLE);
+ analyzeIn(compiler, method, "{ String s = await 0; }",
+ warnings: NOT_ASSIGNABLE);
analyzeIn(compiler, method, "{ await asyncInt(); }");
analyzeIn(compiler, method, "{ int i = await asyncInt(); }");
analyzeIn(compiler, method, "{ String s = await asyncInt(); }",
- NOT_ASSIGNABLE);
+ warnings: NOT_ASSIGNABLE);
analyzeIn(compiler, method, "{ Foo f = self(); }");
analyzeIn(compiler, method, "{ Foo f = await self(); }");
analyzeIn(compiler, method, "{ Foo f = await self().asyncInt(); }",
- NOT_ASSIGNABLE);
+ warnings: NOT_ASSIGNABLE);
analyzeIn(compiler, method, "{ int i = await self().asyncInt(); }");
analyzeIn(compiler, method, "{ String s = await self().asyncInt(); }",
- NOT_ASSIGNABLE);
+ warnings: NOT_ASSIGNABLE);
}
testAsyncReturn(MockCompiler compiler) {
@@ -2283,9 +2586,11 @@
analyzeIn(MockCompiler compiler,
FunctionElement element,
String text,
- [expectedWarnings]) {
- if (expectedWarnings == null) expectedWarnings = [];
- if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
+ {warnings, hints}) {
+ if (warnings == null) warnings = [];
+ if (warnings is !List) warnings = [warnings];
+ if (hints == null) hints = [];
+ if (hints is !List) hints = [hints];
compiler.resolver.resolve(element);
Token tokens = scan(text);
@@ -2301,5 +2606,6 @@
compiler.clearMessages();
checker.analyze(node);
generateOutput(compiler, text);
- compareWarningKinds(text, expectedWarnings, compiler.warnings);
+ compareWarningKinds(text, warnings, compiler.warnings);
+ compareWarningKinds(text, hints, compiler.hints);
}
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index 4f6dcd1..c67d0ba 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -8,6 +8,7 @@
import 'package:expect/expect.dart';
import 'compiler_helper.dart' as mock;
import 'memory_compiler.dart' as memory;
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/dart_types.dart';
import 'package:compiler/src/compiler.dart'
show Compiler;
@@ -65,7 +66,7 @@
memorySourceFiles: {'main.dart': source},
diagnosticHandler: collector,
options: stopAfterTypeInference
- ? [] : ['--analyze-all', '--analyze-only']);
+ ? [] : [Flags.analyzeAll, Flags.analyzeOnly]);
getErrors = () => collector.errors;
getWarnings = () => collector.warnings;
}
diff --git a/tests/compiler/dart2js/use_checks_test.dart b/tests/compiler/dart2js/use_checks_test.dart
index 26d81c6..4056696 100644
--- a/tests/compiler/dart2js/use_checks_test.dart
+++ b/tests/compiler/dart2js/use_checks_test.dart
@@ -29,7 +29,7 @@
options: ['--enable-checked-mode']);
var compiler = result.compiler;
var element = compiler.mainFunction;
- var code = compiler.backend.assembleCode(element);
+ var code = compiler.backend.getGeneratedCode(element);
Expect.isTrue(code.contains('+'), code);
});
}
diff --git a/tests/compiler/dart2js/value_range3_test.dart b/tests/compiler/dart2js/value_range3_test.dart
index 2e65cee..91c3c37 100644
--- a/tests/compiler/dart2js/value_range3_test.dart
+++ b/tests/compiler/dart2js/value_range3_test.dart
@@ -27,7 +27,7 @@
var result = await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
var compiler = result.compiler;
var element = compiler.mainFunction;
- var code = compiler.backend.assembleCode(element);
+ var code = compiler.backend.getGeneratedCode(element);
Expect.isFalse(code.contains('ioore'));
});
}
diff --git a/tests/compiler/dart2js/warnings_checker.dart b/tests/compiler/dart2js/warnings_checker.dart
index cf31943..1652a1e 100644
--- a/tests/compiler/dart2js/warnings_checker.dart
+++ b/tests/compiler/dart2js/warnings_checker.dart
@@ -10,6 +10,7 @@
import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';
import 'memory_compiler.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/filenames.dart';
import 'package:compiler/src/io/source_file.dart';
import 'package:compiler/src/source_file_provider.dart';
@@ -41,7 +42,7 @@
await runCompiler(
entryPoint: uri,
diagnosticHandler: collector,
- options: ['--analyze-only'],
+ options: [Flags.analyzeOnly],
showDiagnostics: verbose);
Map<String, List<int>> statusMap = tests[test];
// Line numbers with known unexpected warnings.
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index e0321e9..2edae80 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -75,15 +75,13 @@
async_stacktrace_test/none: RuntimeError # $async$temp1.Tracer$ is not a function
closure_capture5_test: Crash # (i=0): For-loop variable captured in loop header
deferred/deferred_class_test: RuntimeError # Z.loadLibrary is not a function
-deferred/deferred_constant2_test: Crash # (lib.C1): deferred access is not implemented
-deferred/deferred_constant3_test: Crash # (lib.C1): deferred access is not implemented
+deferred/deferred_constant2_test: RuntimeError # TypeError: U.loadLibrary is not a function
+deferred/deferred_constant3_test: RuntimeError # TypeError: Y.loadLibrary is not a function
deferred/deferred_constant4_test: RuntimeError # B.loadLibrary is not a function
deferred/deferred_function_test: Crash # (lib.foo): deferred access is not implemented
-deferred/deferred_mirrors1_test: Crash # (lazy.foo()): deferred access is not implemented
+deferred/deferred_mirrors1_test: RuntimeError # TypeError: U.loadLibrary is not a function
deferred/deferred_overlapping_test: RuntimeError # E.loadLibrary is not a function
-deferred_fail_and_retry_test: Crash # (lib.foo()): deferred access is not implemented
-deferred_fail_and_retry_worker_test: Crash # (lib.foo()): deferred access is not implemented
-deferred_split_test: Crash # (b.createA()): deferred access is not implemented
+deferred_split_test: RuntimeError # TypeError: Z.loadLibrary is not a function
lookup_map/live_entry_through_mirrors_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
mirror_printer_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
mirror_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
diff --git a/tests/compiler/dart2js_extra/js_array_index_error_test.dart b/tests/compiler/dart2js_extra/js_array_index_error_test.dart
new file mode 100644
index 0000000..9cfc873
--- /dev/null
+++ b/tests/compiler/dart2js_extra/js_array_index_error_test.dart
@@ -0,0 +1,330 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that optimized JSArray indexers enerate the same error as dyncamically
+// dispatched calls.
+
+
+import 'package:expect/expect.dart';
+
+@NoInline() @AssumeDynamic()
+confuse(x) => x;
+
+
+Error getError(action(), name, part) {
+ try {
+ action();
+ } catch (e) {
+ return e;
+ }
+ Expect.fail('must throw: $name: $part');
+}
+
+indexErrorContainsIndex() {
+ makeFault(i) => () => confuse([])[i];
+
+ var name = 'index error contains index';
+ var e1 = getError(makeFault(1234), name, 'small');
+ var e2 = getError(makeFault(1234000), name, 'medium');
+ var e3 = getError(makeFault(1234000000000), name, 'large');
+
+ Expect.equals('$e1', '$e2'.replaceAll('000', ''));
+ Expect.equals('$e1', '$e3'.replaceAll('000', ''));
+ Expect.equals('$e1'.length + 3, '$e2'.length);
+ Expect.equals('$e1'.length + 9, '$e3'.length);
+}
+
+
+compare(name, fault1(), fault2(), fault3()) {
+ var e1 = getError(fault1, name, 'fault1');
+ var e2 = getError(fault2, name, 'fault2');
+ var e3 = getError(fault3, name, 'fault3');
+
+ Expect.equals('$e1', '$e2', '$name: fault1 vs fault2');
+ Expect.equals('$e1', '$e3', '$name: fault1 vs fault3');
+}
+
+// These tests are a bit tedious and avoid common helpers with higher order
+// functions to keep the type inference for each test independent from the
+// others.
+//
+// The 'constant' tests have a constant index which might permit different
+// optimizations to a variable index. e.g. the compiler might determine HUGE is
+// always out of range since the maximum JavaScript Array length is 2^32.
+//
+// The 'variable' forms take the index as an argument.
+
+const int HUGE = 1000000000000;
+
+constantIndexEmpty() {
+ // Single dynamic receiver indexing might go via one-shot interceptor that
+ // might have an accelerated path.
+ fault1() => confuse([])[0];
+
+ fault2() {
+ var a = [];
+ while (confuse(false)) a.add(1);
+ // Easily inferred type and open coded indexer.
+ return a[0];
+ }
+
+ fault3() {
+ var a = confuse([]);
+ // Multiple indexing might go via shared interceptor.
+ return [a[0], a[1], a[2]];
+ }
+
+ compare('constant index on empty list', fault1, fault2, fault3);
+}
+
+constantIndexHugeEmpty() {
+ // Single dynamic receiver indexing might go via one-shot interceptor that
+ // might have an accelerated path.
+ fault1() => confuse([])[HUGE];
+
+ fault2() {
+ var a = [];
+ while (confuse(false)) a.add(1);
+ return a[HUGE];
+ }
+
+ fault3() {
+ var a = confuse([]);
+ return [a[HUGE], a[1], a[2]];
+ }
+
+ compare('constant index on empty list with huge index',
+ fault1, fault2, fault3);
+}
+
+constantIndexNonempty() {
+ // Single dynamic receiver indexing might go via one-shot interceptor that
+ // might have an accelerated path.
+ fault1() => confuse([1])[1];
+
+ fault2() {
+ var a = [1];
+ while (confuse(false)) a.add(1);
+ // Easily inferred type and open coded indexer.
+ return a[1];
+ }
+
+ fault3() {
+ var a = confuse([1]);
+ // Multiple indexing might go via shared interceptor.
+ return [a[1], a[2], a[3]];
+ }
+
+ compare('constant index on non-empty list', fault1, fault2, fault3);
+}
+
+constantIndexHugeNonempty() {
+ // Single dynamic receiver indexing might go via one-shot interceptor that
+ // might have an accelerated path.
+ fault1() => confuse([1])[HUGE];
+
+ fault2() {
+ var a = [1];
+ while (confuse(false)) a.add(1);
+ // Easily inferred type and open coded indexer.
+ return a[HUGE];
+ }
+
+ fault3() {
+ var a = confuse([1]);
+ // Multiple indexing might go via shared interceptor.
+ return [a[HUGE], a[1], a[2]];
+ }
+
+ compare('constant index on non-empty list with huge index',
+ fault1, fault2, fault3);
+}
+
+constantIndexSetEmpty() {
+ fault1() {
+ // Single dynamic receiver indexing might go via one-shot interceptor that
+ // might have an accelerated path.
+ confuse([])[0] = 0;
+ }
+
+ fault2() {
+ var a = [];
+ while (confuse(false)) a.add(1);
+ // Easily inferred type and open coded indexer.
+ a[0] = 0;
+ return a;
+ }
+
+ fault3() {
+ var a = confuse([]);
+ // Multiple indexing might go via shared interceptor.
+ a[0] = 0;
+ a[1] = 0;
+ a[2] = 0;
+ return a;
+ }
+
+ compare('coinstant index-set on empty list', fault1, fault2, fault3);
+}
+
+constantIndexSetNonempty() {
+ fault1() {
+ // Single dynamic receiver indexing might go via one-shot interceptor that
+ // might have an accelerated path.
+ confuse([1])[1] = 0;
+ }
+
+ fault2() {
+ var a = [1];
+ while (confuse(false)) a.add(1);
+ // Easily inferred type and open coded indexer.
+ a[1] = 0;
+ return a;
+ }
+
+ fault3() {
+ var a = confuse([1]);
+ // Multiple indexing might go via shared interceptor.
+ a[0] = 0;
+ a[1] = 0;
+ a[2] = 0;
+ return a;
+ }
+
+ compare('constant index-set on non-empty list', fault1, fault2, fault3);
+}
+
+
+variableIndexEmpty(index, qualifier) {
+ // Single dynamic receiver indexing might go via one-shot interceptor that
+ // might have an accelerated path.
+ fault1() => confuse([])[index];
+
+ fault2() {
+ var a = [];
+ while (confuse(false)) a.add(1);
+ // Easily inferred type and open coded indexer.
+ return a[index];
+ }
+
+ fault3() {
+ var a = confuse([]);
+ // Multiple indexing might go via shared interceptor.
+ return [a[index], a[1], a[2]];
+ }
+
+ compare('general index on empty list $qualifier', fault1, fault2, fault3);
+}
+
+variableIndexNonempty(index, qualifier) {
+ // Single dynamic receiver indexing might go via one-shot interceptor that
+ // might have an accelerated path.
+ fault1() => confuse([1])[index];
+
+ fault2() {
+ var a = [1];
+ while (confuse(false)) a.add(1);
+ // Easily inferred type and open coded indexer.
+ return a[index];
+ }
+
+ fault3() {
+ var a = confuse([1]);
+ // Multiple indexing might go via shared interceptor.
+ return [a[index], a[1], a[2]];
+ }
+
+ compare('variable index on non-empty list $qualifier',
+ fault1, fault2, fault3);
+}
+
+variableIndexSetEmpty(index, qualifier) {
+ fault1() {
+ var a = confuse([]);
+ // Single dynamic receiver indexing might go via one-shot interceptor that
+ // might have an accelerated path.
+ a[index] = 1;
+ return a;
+ }
+
+ fault2() {
+ var a = [];
+ while (confuse(false)) a.add(1);
+ // Easily inferred type and open coded indexer.
+ a[index] = 1;
+ return a;
+ }
+
+ fault3() {
+ var a = confuse([]);
+ // Multiple indexing might go via shared interceptor.
+ a[index] = 1;
+ a[2] = 2;
+ a[3] = 3;
+ return a;
+ }
+
+ compare('variable index-set on empty list $qualifier',
+ fault1, fault2, fault3);
+}
+
+variableIndexSetNonempty(index, qualifier) {
+ fault1() {
+ var a = confuse([1]);
+ // Single dynamic receiver indexing might go via one-shot interceptor that
+ // might have an accelerated path.
+ a[index] = 1;
+ return a;
+ }
+
+ fault2() {
+ var a = [1];
+ while (confuse(false)) a.add(1);
+ // Easily inferred type and open coded indexer.
+ a[index] = 1;
+ return a;
+ }
+
+ fault3() {
+ var a = confuse([1]);
+ // Multiple indexing might go via shared interceptor.
+ a[index] = 1;
+ a[2] = 2;
+ a[3] = 3;
+ return a;
+ }
+
+ compare('variable index-set on non-empty list $qualifier',
+ fault1, fault2, fault3);
+}
+
+
+main() {
+ indexErrorContainsIndex();
+
+ constantIndexEmpty();
+ constantIndexHugeEmpty();
+ constantIndexNonempty();
+ constantIndexHugeNonempty();
+ constantIndexSetEmpty();
+ constantIndexSetNonempty();
+
+ variableIndexEmpty(0, 'zero index');
+ variableIndexEmpty(10, 'small index');
+ variableIndexEmpty(-1, 'negative index');
+ variableIndexEmpty(HUGE, 'huge index');
+
+ variableIndexNonempty(10, 'small index');
+ variableIndexNonempty(-1, 'negative index');
+ variableIndexNonempty(HUGE, 'huge index');
+
+ variableIndexSetEmpty(0, 'zero index');
+ variableIndexSetEmpty(10, 'small index');
+ variableIndexSetEmpty(-1, 'negative index');
+ variableIndexSetEmpty(HUGE, 'huge index');
+
+ variableIndexSetNonempty(10, 'small index');
+ variableIndexSetNonempty(-1, 'negative index');
+ variableIndexSetNonempty(HUGE, 'huge index');
+}
diff --git a/tests/compiler/dart2js_extra/js_array_removeLast_error_test.dart b/tests/compiler/dart2js_extra/js_array_removeLast_error_test.dart
new file mode 100644
index 0000000..6fc14dc
--- /dev/null
+++ b/tests/compiler/dart2js_extra/js_array_removeLast_error_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that optimized JSArray removeLast() calls generate the same error as
+// dyncamically dispatched calls.
+
+import 'package:expect/expect.dart';
+
+@NoInline() @AssumeDynamic()
+confuse(x) => x;
+
+
+Error getError(action()) {
+ try {
+ action();
+ Expect.fail('must throw');
+ } catch (e) {
+ return e;
+ }
+}
+
+main() {
+ fault1() {
+ return confuse([]).removeLast();
+ }
+
+ fault2() {
+ var a = [];
+ while (confuse(false)) a.add(1);
+ // This one should be optimized since [a] is a growable JSArray.
+ return a.removeLast();
+ }
+
+ var e1 = getError(fault1);
+ var e2 = getError(fault2);
+
+ Expect.equals('$e1', '$e2');
+}
diff --git a/tests/corelib/list_test.dart b/tests/corelib/list_test.dart
index 5187ee8..c26c1cf 100644
--- a/tests/corelib/list_test.dart
+++ b/tests/corelib/list_test.dart
@@ -46,6 +46,89 @@
testTypedGrowableList(new Int32List(0).toList());
testListConstructor();
+
+ testErrors();
+}
+
+void testErrors() {
+ // Regression for issue http://dartbug.com/24295
+ testIndexError(list, index, name) {
+ try {
+ list[list.length];
+ } catch (err, s) {
+ Expect.isTrue(err is RangeError, "$name[$index]");
+ Expect.equals(list.length, err.invalidValue, "$name[$index] value");
+ Expect.equals(list.length - 1, err.end, "$name[$index] end");
+ Expect.equals(0, err.start, "$name[$index] start");
+ }
+ }
+ testIndex(list, name) {
+ testIndexError(list, list.length, name); // Just too big.
+ testIndexError(list, -1, name); // Negative.
+ testIndexError(list, 0x123456789, name); // > 2^32.
+ testIndexError(list, -0x123456789, name); // < -2^32.
+ }
+
+ // Slices.
+ testSliceError(list, start, end, name) {
+ name = "$name[$start:$end]";
+ var realError;
+ try {
+ RangeError.checkValidRange(start, end, list.length);
+ } catch (e) {
+ realError = e;
+ }
+ var result;
+ try {
+ result = list.sublist(start, end);
+ } catch (actualError) {
+ Expect.isNotNull(realError, "$name should not fail");
+ Expect.isTrue(actualError is RangeError, "$name is-error: $actualError");
+ Expect.equals(realError.name, actualError.name, "$name name");
+ Expect.equals(realError.invalidValue, actualError.invalidValue,
+ "$name[0:l+1] value");
+ Expect.equals(realError.start, actualError.start, "$name[0:l+1] start");
+ Expect.equals(realError.end, actualError.end, "$name[0:l+1] end");
+ return;
+ }
+ // Didn't throw.
+ Expect.isNull(realError, "$name should fail");
+ Expect.equals(end - start, result.length, "$name result length");
+ }
+
+ testSlice(list, name) {
+ testSliceError(list, 0, list.length, name); // Should not fail.
+ testSliceError(list, 0, list.length + 1, name);
+ testSliceError(list, 0, 0x123456789, name);
+ testSliceError(list, -1, list.length, name);
+ testSliceError(list, -0x123456789, list.length, name);
+ testSliceError(list, list.length + 1, list.length + 1, name);
+ testSliceError(list, -1, null, name);
+ if (list.length > 0) {
+ testSliceError(list, list.length, list.length - 1, name);
+ }
+ }
+
+ testRangeErrors(list, name) {
+ testIndex(list, "$name#${list.length} index");
+ testSlice(list, "$name#${list.length} slice");
+ }
+ // Empty lists.
+ testRangeErrors([], "list");
+ testRangeErrors(new List(0), "fixed-list");
+ testRangeErrors(const [], "const-list");
+ testRangeErrors(new List.unmodifiable([]), "unmodifiable");
+ testRangeErrors(new Uint8List(0), "typed-list");
+ testRangeErrors(new Uint8List.view(new Uint8List(0).buffer), "typed-list");
+ testRangeErrors([1, 2, 3].sublist(1, 1), "sub-list");
+ // Non-empty lists.
+ testRangeErrors([1, 2, 3], "list");
+ testRangeErrors(new List(3), "fixed-list");
+ testRangeErrors(const [1, 2, 3], "const-list");
+ testRangeErrors(new List.unmodifiable([1, 2, 3]), "unmodifiable");
+ testRangeErrors(new Uint8List(3), "typed-list");
+ testRangeErrors(new Uint8List.view(new Uint8List(3).buffer), "typed-list");
+ testRangeErrors([1, 2, 3, 4, 5].sublist(1, 3), "sub-list");
}
void testLength(int length, List list) {
@@ -475,6 +558,7 @@
class Yes {
operator ==(var other) => true;
+ int get hashCode => 0;
}
class MyList<E> extends ListBase<E> {
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 4073b51..d686774 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -138,7 +138,7 @@
package_root_test: SkipByDesign # Uses dart:io.
[ $compiler == dart2js && $cps_ir ]
-deferred_in_isolate2_test: Crash # (lib.f()): deferred access is not implemented
+deferred_in_isolate2_test: RuntimeError # Exception: Some tests failed.
isolate_current_test: RuntimeError # Please triage this failure.
message3_test/byteBuffer: RuntimeError # Please triage this failure.
message3_test/fun: RuntimeError # Please triage this failure.
diff --git a/tests/isolate/nested_spawn2_test.dart b/tests/isolate/nested_spawn2_test.dart
index fbeaeef..faf105d 100644
--- a/tests/isolate/nested_spawn2_test.dart
+++ b/tests/isolate/nested_spawn2_test.dart
@@ -57,7 +57,7 @@
test("spawned isolate can spawn other isolates", () {
ReceivePort init = new ReceivePort();
Isolate.spawn(isolateA, init.sendPort);
- init.first.then(expectAsync((port) {
+ return init.first.then(expectAsync((port) {
_call(port, "launch nested!", expectAsync((msg, replyTo) {
expect(msg[0], "0");
_call(replyTo, msg1, expectAsync((msg, replyTo) {
diff --git a/tests/isolate/nested_spawn_test.dart b/tests/isolate/nested_spawn_test.dart
index 0dc35a0..083a94a 100644
--- a/tests/isolate/nested_spawn_test.dart
+++ b/tests/isolate/nested_spawn_test.dart
@@ -24,7 +24,7 @@
test("spawned isolates can spawn nested isolates", () {
ReceivePort port = new ReceivePort();
Isolate.spawn(isolateA, [port.sendPort, "main"]);
- port.first.then((message) {
+ return port.first.then((message) {
expect("main", message[1]);
expect("isolateA", message[2]);
expect("isolateB", message[3]);
diff --git a/tests/language/assertion_test.dart b/tests/language/assertion_test.dart
index 68bdf04..2f0a12d 100644
--- a/tests/language/assertion_test.dart
+++ b/tests/language/assertion_test.dart
@@ -1,7 +1,7 @@
// Copyright (c) 2011, 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.
-// VMOptions=--enable_type_checks
+// VMOptions=--enable_asserts
//
// Dart test program testing assert statements.
diff --git a/tests/language/bit_shift_test.dart b/tests/language/bit_shift_test.dart
index 3032736..e939e5a 100644
--- a/tests/language/bit_shift_test.dart
+++ b/tests/language/bit_shift_test.dart
@@ -7,6 +7,8 @@
constants() {
Expect.equals(0, 499 >> 33);
Expect.equals(0, (499 << 33) & 0xFFFFFFFF);
+ Expect.equals(0, (499 << 32) >> 65);
+ Expect.equals(0, ((499 << 32) << 65) & 0xFFFFFFFFFFFFFFFF);
}
foo(i) {
@@ -29,13 +31,18 @@
interceptors() {
Expect.equals(0, id(499) >> 33);
Expect.equals(0, (id(499) << 33) & 0xFFFFFFFF);
+ Expect.equals(0, id(499 << 32) >> 65);
+ Expect.equals(0, (id(499 << 32) << 65) & 0xFFFFFFFFFFFFFFFF);
}
speculative() {
var a = id(499);
+ var b = id(499 << 32);
for (int i = 0; i < 1; i++) {
Expect.equals(0, a >> 33);
Expect.equals(0, (a << 33) & 0xFFFFFFFF);
+ Expect.equals(0, b >> 65);
+ Expect.equals(0, (b << 65) & 0xFFFFFFFFFFFFFFFF);
}
}
diff --git a/tests/language/deferred_super_dependency_lib.dart b/tests/language/deferred_super_dependency_lib.dart
new file mode 100644
index 0000000..a592dab
--- /dev/null
+++ b/tests/language/deferred_super_dependency_lib.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+}
+
+class C extends A {
+ foo() {
+ super.foo = 3;
+ }
+}
\ No newline at end of file
diff --git a/tests/language/deferred_super_dependency_test.dart b/tests/language/deferred_super_dependency_test.dart
new file mode 100644
index 0000000..d2f801f
--- /dev/null
+++ b/tests/language/deferred_super_dependency_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test.
+// lib.C.foo has code that references `super.foo=` that does not exist. This
+// used to cause a crash.
+
+import "package:expect/expect.dart";
+import "deferred_super_dependency_lib.dart" deferred as lib; /// 01: static type warning
+
+main() async {
+ await lib.loadLibrary(); /// 01: continued
+ Expect.throws(() => new lib.C().foo(), (e) => e is NoSuchMethodError); /// 01: continued
+}
\ No newline at end of file
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 1ced213..58c8f07 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -148,6 +148,7 @@
double_int_to_string_test: RuntimeError # Issue 1533
mint_arithmetic_test: RuntimeError # Issue 1533
left_shift_test: RuntimeError # Issue 1533
+regress_24283_test: RuntimeError # Issue 1533
bad_override_test/01: CompileTimeError # Issue 11496
bad_override_test/02: CompileTimeError # Issue 11496
constructor_named_arguments_test/01: CompileTimeError # Issue 5519
@@ -279,6 +280,8 @@
async_star_stream_take_test: Crash # (await for(var v in s.take(5))r+= v;): await for
async_star_take_reyield_test: Crash # (fivePartialSums(Str... cannot handle sync*/async* functions
async_star_test: Crash # (f()async*{}): cannot handle sync*/async* functions
+async_switch_test/none: RuntimeError # Uncaught Error: Expect.equals(expected: <1>, actual: <null>) fails.
+async_switch_test/withDefault: RuntimeError # Uncaught Error: Expect.equals(expected: <1>, actual: <null>) fails.
asyncstar_concat_test: Crash # (concat(a,b)async*{yield* a;yield* b;}): cannot handle sync*/async* functions
asyncstar_throw_in_catch_test: Crash # (foo4(Tracer tracer)... cannot handle sync*/async* functions
asyncstar_yield_test: Crash # (Stream<int> foo4()a... cannot handle sync*/async* functions
@@ -286,7 +289,7 @@
await_for_cancel_test: Crash # (await for(var x in controller.stream){for(int j=0;j<10;j++ ){if(j==5)continue outer;}}): await for
await_for_test: Crash # (await for(var x in infiniteStream()){i++ ;if(i>10)break;t4.record(x);}): await for
await_for_use_local_test: Crash # (await for(var v in s){accum+= v;}): await for
-await_future_test: RuntimeError # Please triage this failure.
+await_future_test: Timeout
await_regression_test: RuntimeError # "Obelix".then$1 is not a function
cha_deopt1_test: Crash # (d.make_u()): deferred access is not implemented
cha_deopt2_test: Crash # (d.make_u()): deferred access is not implemented
@@ -298,30 +301,30 @@
crash_6725_test/01: Crash # unsupported operation on erroneous element
cyclic_default_values_test: RuntimeError # Z.cyclic_default_values_test__foo$closure is not a function
deferred_call_empty_before_load_test: Crash # (lib1.thefun()): deferred access is not implemented
-deferred_closurize_load_library_test: Crash # (lib.trueVar): deferred access is not implemented
-deferred_constant_list_test: Crash # (lib.finalConstList): deferred access is not implemented
+deferred_closurize_load_library_test: RuntimeError # TypeError: D.loadLibrary is not a function
+deferred_constant_list_test: RuntimeError # TypeError: K.loadLibrary is not a function
deferred_constraints_constants_test/none: Crash # (lib.constantInstance): deferred access is not implemented
deferred_constraints_constants_test/reference_after_load: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/as_operation: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/catch_check: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/is_check: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/new: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/new_before_load: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/new_generic1: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/new_generic2: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/new_generic3: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/none: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/static_method: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/type_annotation1: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/type_annotation_generic1: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/type_annotation_generic2: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/type_annotation_generic3: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/type_annotation_generic4: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/type_annotation_non_deferred: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/type_annotation_null: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_constraints_type_annotation_test/type_annotation_top_level: Crash # (lib.constantInstance): deferred access is not implemented
-deferred_function_type_test: Crash # (lib.runTest()): deferred access is not implemented
-deferred_global_test: Crash # (lib.finalConstGlobal): deferred access is not implemented
+deferred_constraints_type_annotation_test/as_operation: RuntimeError # TypeError: Z.loadLibrary is not a function
+deferred_constraints_type_annotation_test/catch_check: RuntimeError # TypeError: D.loadLibrary is not a function
+deferred_constraints_type_annotation_test/is_check: RuntimeError # TypeError: L.loadLibrary is not a function
+deferred_constraints_type_annotation_test/new: RuntimeError # TypeError: R.loadLibrary is not a function
+deferred_constraints_type_annotation_test/new_before_load: RuntimeError # TypeError: K.loadLibrary is not a function
+deferred_constraints_type_annotation_test/new_generic1: RuntimeError # TypeError: R.loadLibrary is not a function
+deferred_constraints_type_annotation_test/new_generic2: RuntimeError # TypeError: X.loadLibrary is not a function
+deferred_constraints_type_annotation_test/new_generic3: RuntimeError # TypeError: K.loadLibrary is not a function
+deferred_constraints_type_annotation_test/none: RuntimeError # TypeError: D.loadLibrary is not a function
+deferred_constraints_type_annotation_test/static_method: RuntimeError # TypeError: F.loadLibrary is not a function
+deferred_constraints_type_annotation_test/type_annotation1: RuntimeError # TypeError: K.loadLibrary is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic1: RuntimeError # TypeError: T.loadLibrary is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic2: RuntimeError # TypeError: Q.loadLibrary is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic3: RuntimeError # TypeError: Z.loadLibrary is not a function
+deferred_constraints_type_annotation_test/type_annotation_generic4: RuntimeError # TypeError: Q.loadLibrary is not a function
+deferred_constraints_type_annotation_test/type_annotation_non_deferred: RuntimeError # TypeError: R.loadLibrary is not a function
+deferred_constraints_type_annotation_test/type_annotation_null: RuntimeError # TypeError: Z.loadLibrary is not a function
+deferred_constraints_type_annotation_test/type_annotation_top_level: RuntimeError # TypeError: U.loadLibrary is not a function
+deferred_function_type_test: RuntimeError # TypeError: N.loadLibrary is not a function
+deferred_global_test: RuntimeError # TypeError: Y.loadLibrary is not a function
deferred_inlined_test: Crash # (lib.foo()): deferred access is not implemented
deferred_load_constants_test/none: Crash # (foo.c): deferred access is not implemented
deferred_load_inval_code_test: Crash # (d.foo()): deferred access is not implemented
@@ -329,18 +332,20 @@
deferred_mixin_test: RuntimeError # X.loadLibrary is not a function
deferred_no_such_method_test: RuntimeError # D.loadLibrary is not a function
deferred_not_loaded_check_test: Crash # (lib.closure(sideEffect())): deferred access is not implemented
-deferred_only_constant_test: Crash # (lib.constant): deferred access is not implemented
+deferred_only_constant_test: RuntimeError # TypeError: O.loadLibrary is not a function
deferred_optimized_test: Crash # (lib.foo()): deferred access is not implemented
deferred_redirecting_factory_test: Crash # (lib1.loadLib2()): deferred access is not implemented
-deferred_regression_22995_test: Crash # (lib.foofoo()): deferred access is not implemented
-deferred_shadow_load_library_test: Crash # (lib.trueVar): deferred access is not implemented
-deferred_shared_and_unshared_classes_test: Crash # (lib2.foo()): deferred access is not implemented
-deferred_static_seperate_test: Crash # (lib1.x): deferred access is not implemented
+deferred_regression_22995_test: RuntimeError # TypeError: U.loadLibrary is not a function
+deferred_shadow_load_library_test: RuntimeError # TypeError: Y.loadLibrary is not a function
+deferred_shared_and_unshared_classes_test: RuntimeError # TypeError: U.loadLibrary is not a function
+deferred_static_seperate_test: RuntimeError # TypeError: L.loadLibrary is not a function
+deferred_super_dependency_test/01: RuntimeError # Uncaught Error: NoSuchMethodError: method not found: 'loadLibrary' ($async$temp1.loadLibrary is not a function)
deferred_type_dependency_test/as: Crash # (lib1.fooAs("string")): deferred access is not implemented
deferred_type_dependency_test/is: Crash # (lib1.fooIs("string")): deferred access is not implemented
deferred_type_dependency_test/none: Crash # (lib2.getInstance()): deferred access is not implemented
deferred_type_dependency_test/type_annotation: Crash # (lib1.fooAnnotation("string")): deferred access is not implemented
enum_mirror_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
+field3a_negative_test: Fail # Bogus result from type inference in case of invalid program.
first_class_types_test: RuntimeError # Please triage this failure.
for2_test: Crash # The null object does not have a getter 'field'.
for_variable_capture_test: Crash # (i=0): For-loop variable captured in loop header
diff --git a/tests/language/regress_24283_test.dart b/tests/language/regress_24283_test.dart
new file mode 100644
index 0000000..d98e829
--- /dev/null
+++ b/tests/language/regress_24283_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+main() {
+ // Smi
+ var i = 1 << 30;
+ var j = -i;
+ Expect.equals(0, i >> 37);
+ Expect.equals(-1, j >> 37);
+ // Mint
+ i = 1 << 50;
+ j = -i;
+ Expect.equals(0, i >> 67);
+ Expect.equals(-1, j >> 67);
+ // Bigint
+ i = i << 120;
+ j = -i;
+ Expect.equals(0, i >> 199);
+ Expect.equals(-1, j >> 199);
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index e409184..9a65284 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -357,9 +357,9 @@
mirrors/constructors_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
mirrors/dart2js_mirrors_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
mirrors/declarations_type_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
-mirrors/deferred_mirrors_metadata_test: Crash # (lib1.foo()): deferred access is not implemented
-mirrors/deferred_mirrors_metatarget_test: Crash # (lib.foo()): deferred access is not implemented
-mirrors/deferred_mirrors_update_test: Crash # (l.foo()): deferred access is not implemented
+mirrors/deferred_mirrors_metadata_test: RuntimeError # TypeError: U.loadLibrary is not a function
+mirrors/deferred_mirrors_metatarget_test: RuntimeError # TypeError: X.loadLibrary is not a function
+mirrors/deferred_mirrors_update_test: RuntimeError # TypeError: U.loadLibrary is not a function
mirrors/deferred_type_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
mirrors/delegate_call_through_getter_test: RuntimeError # Please triage this failure.
mirrors/delegate_class_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
diff --git a/tests/standalone/no_assert_test.dart b/tests/standalone/no_assert_test.dart
new file mode 100644
index 0000000..825578b
--- /dev/null
+++ b/tests/standalone/no_assert_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--no-enable_asserts --enable_type_checks
+
+// Ensure that enabling of type checks does not automatically enable asserts.
+
+main() {
+ assert(false);
+ try {
+ int i = "String";
+ throw "FAIL";
+ } on TypeError catch (e) {
+ print("PASS");
+ }
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index b6e570b..7d7fc8f 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -17,6 +17,9 @@
javascript_compatibility_errors_test/none: Fail, OK # Not possible to exclude or annotate with '/// none:'
+[ $runtime != vm && ($runtime != drt || $compiler != none)) ]
+no_assert_test: Fail, OK # This is testing a vm flag.
+
[ $runtime == vm ]
package/package_isolate_test: Fail # Issue 12474
io/observatory_test: Fail
@@ -186,9 +189,6 @@
io/test_runner_test: Skip # Timeout.
io/http_client_stays_alive_test: Skip # Timeout.
-[ $compiler == dart2js ]
-io/observatory_test: Crash # Issue 24291
-
[ $runtime == vm ]
# Failures in secure networking while NSS is replaced with BoringSSL
io/https_client_certificate_test: RuntimeError # Issue 24070
@@ -198,11 +198,8 @@
io/secure_socket_bad_data_test: RuntimeError # An error in a secure connection just puts a READ_CLOSED on the stream, rather than signaling an error on the stream.
[ $compiler == dart2js && $cps_ir ]
-coverage_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
-io/addlatexhash_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
io/file_error_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
io/file_read_encoded_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
io/file_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
-io/http_client_connect_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
-io/skipping_dart2js_compilations_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
+io/observatory_test: Crash # (static Iterable<Str... cannot handle sync*/async* functions
priority_queue_stress_test: RuntimeError # Cannot read property 'length' of undefined
diff --git a/tests/try/poi/compiler_test_case.dart b/tests/try/poi/compiler_test_case.dart
index 8827c97..a1df70a 100644
--- a/tests/try/poi/compiler_test_case.dart
+++ b/tests/try/poi/compiler_test_case.dart
@@ -14,7 +14,7 @@
import 'package:async_helper/async_helper.dart' show
asyncTest;
-import '../../compiler/dart2js/compiler_helper.dart' show
+import '../../compiler/dart2js/mock_compiler.dart' show
MockCompiler,
compilerFor;
diff --git a/tests/try/poi/diff_test.dart b/tests/try/poi/diff_test.dart
index 17890ac..c6de2fd 100644
--- a/tests/try/poi/diff_test.dart
+++ b/tests/try/poi/diff_test.dart
@@ -31,7 +31,7 @@
Difference,
computeDifference;
-import '../../compiler/dart2js/compiler_helper.dart' show
+import '../../compiler/dart2js/mock_compiler.dart' show
MockCompiler,
compilerFor;
diff --git a/tests/try/poi/forget_element_assertion.dart b/tests/try/poi/forget_element_assertion.dart
index c098234..a825532 100644
--- a/tests/try/poi/forget_element_assertion.dart
+++ b/tests/try/poi/forget_element_assertion.dart
@@ -6,7 +6,7 @@
// Remove this file when dart2js support such features.
library trydart.forget_element_assertion;
-import '../../compiler/dart2js/compiler_helper.dart' show
+import '../../compiler/dart2js/mock_compiler.dart' show
compilerFor;
import 'compiler_test_case.dart';
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index f793816..77594d3 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -31,4 +31,4 @@
[ $compiler == dart2js && $cps_ir ]
dummy_compiler_test: Crash # (switch (function.na... continue to a labeled switch case
recursive_import_test: Crash # (switch (function.na... continue to a labeled switch case
-source_mirrors_test: Crash # (switch (function.na... continue to a labeled switch case
+source_mirrors_test: Crash, Slow # (switch (function.na... continue to a labeled switch case
diff --git a/tools/VERSION b/tools/VERSION
index 03c8deb..593aeba 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 1
MINOR 13
PATCH 0
-PRERELEASE 2
+PRERELEASE 3
PRERELEASE_PATCH 0
diff --git a/tools/bots/bot_utils.py b/tools/bots/bot_utils.py
index e5f5de2..da166aa 100644
--- a/tools/bots/bot_utils.py
+++ b/tools/bots/bot_utils.py
@@ -71,7 +71,7 @@
Under every base path, the following structure is used:
- /VERSION
- - /api-docs/dart-api-docs.zip
+ - /api-docs/{dart-api-docs.zip,dartdocs-gen-api.zip}
- /dartium/{chromedriver,content_shell,dartium}
-{linux,macos,windows}-{ia32,x64}-release.zip
- /sdk/dartsdk-{linux,macos,windows}-{ia32,x64}-release.zip
@@ -119,10 +119,6 @@
return '/'.join([self.dartium_directory(revision),
self.dartium_variant_zipfilename(name, system, arch, mode)])
- def apidocs_zipfilepath(self, revision):
- return '/'.join([self.apidocs_directory(revision),
- self.apidocs_zipfilename()])
-
def dartium_android_apk_filepath(self, revision, name, arch, mode):
return '/'.join([self.dartium_android_directory(revision),
self.dartium_android_apk_filename(name, arch, mode)])
diff --git a/tools/build.py b/tools/build.py
index fc2e1cf..0c5e235 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -77,11 +77,6 @@
help='Name of the devenv.com/msbuild executable on Windows (varies for '
'different versions of Visual Studio)',
default=vs_executable)
- result.add_option("--use-bootstrap-for-observatory",
- help='Use a stripped down Dart binary built on the host machine '
- 'for building Observatory. Necessary on Linux machines which have '
- 'libc incompatibilities with the prebuilt Dart binaries.',
- default=False, action="store_true")
return result
@@ -391,8 +386,6 @@
global filter_xcodebuild_output
start_time = time.time()
os.environ['DART_BUILD_MODE'] = mode
- if options.use_bootstrap_for_observatory != False:
- os.environ['DART_USE_BOOTSTRAP_BIN'] = '1'
build_config = utils.GetBuildConf(mode, arch, target_os)
if HOST_OS == 'macos':
filter_xcodebuild_output = True
diff --git a/tools/dart2js/angular2_testing_deps/CURRENT_ANGULAR_DEPS b/tools/dart2js/angular2_testing_deps/CURRENT_ANGULAR_DEPS
index 844cf2e..82a82d9 100644
--- a/tools/dart2js/angular2_testing_deps/CURRENT_ANGULAR_DEPS
+++ b/tools/dart2js/angular2_testing_deps/CURRENT_ANGULAR_DEPS
@@ -1 +1 @@
-be0739085976bbdbcf8f560475e87b07343f464d
+63e785902fbc6d5edbc1a4ed135f65d1cdf00acd
diff --git a/tools/observatory_tool.py b/tools/observatory_tool.py
index 6626143..90c2aa27 100755
--- a/tools/observatory_tool.py
+++ b/tools/observatory_tool.py
@@ -6,13 +6,16 @@
import argparse
import os
+import platform
import shutil
import subprocess
import sys
+import utils
SCRIPT_DIR = os.path.dirname(sys.argv[0])
DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
-RUN_PUB = os.path.join(DART_ROOT, 'tools/run_pub.py')
+PUB_PATH = os.path.join(DART_ROOT, 'third_party', 'pkg',
+ 'pub', 'bin', 'pub.dart')
IGNORE_PATTERNS = shutil.ignore_patterns(
'*.map',
'*.concat.js',
@@ -24,7 +27,7 @@
'*.log',
'*~')
-usage = """obs_tool.py [options]"""
+usage = """observatory_tool.py [options]"""
def BuildArguments():
result = argparse.ArgumentParser(usage=usage)
@@ -34,64 +37,74 @@
result.add_argument("--directory", help="observatory root", default=None)
result.add_argument("--command", help="[get, build, deploy]", default=None)
result.add_argument("--silent", help="silence all output", default=False)
+ result.add_argument("--sdk", help="Use prebuilt sdk", default=False)
return result
def ProcessOptions(options, args):
# Required options.
- if (options.command == None) or (options.directory == None):
+ if options.command is None or options.directory is None:
return False
- # If we have a pub executable, we are running from the dart-sdk.
- if (options.pub_executable != None):
- return True
- # Otherwise, we need a dart executable and a package root.
- return ((options.package_root != None) and
- (options.dart_executable != None))
+ # If we have a working pub executable, try and use that.
+ # TODO(whesse): Drop the pub-executable option if it isn't used.
+ if options.pub_executable is not None:
+ try:
+ if 0 == subprocess.call([options.pub_executable, '--version']):
+ return True
+ except OSError as e:
+ pass
+ options.pub_executable = None
+
+ if options.sdk is not None and utils.CheckedInSdkCheckExecutable():
+ # Use the checked in pub executable.
+ options.pub_snapshot = os.path.join(utils.CheckedInSdkPath(),
+ 'bin',
+ 'snapshots',
+ 'pub.dart.snapshot');
+ try:
+ if 0 == subprocess.call([utils.CheckedInSdkExecutable(),
+ options.pub_snapshot,
+ '--version']):
+ return True
+ except OSError as e:
+ pass
+ options.pub_snapshot = None
+
+ # We need a dart executable and a package root.
+ return (options.package_root is not None and
+ options.dart_executable is not None)
def ChangeDirectory(directory):
os.chdir(directory);
-def PubGet(dart_executable, pub_executable, pkg_root, silent):
- # Always remove pubspec.lock before running 'pub get'.
- try:
- os.remove('pubspec.lock');
- except OSError as e:
- pass
- with open(os.devnull, 'wb') as silent_sink:
- if (pub_executable != None):
- return subprocess.call([pub_executable,
- 'get',
- '--offline'],
- stdout=silent_sink if silent else None,
- stderr=silent_sink if silent else None)
- else:
- return subprocess.call(['python',
- RUN_PUB,
- '--package-root=' + pkg_root,
- '--dart-executable=' + dart_executable,
- 'get',
- '--offline'],
- stdout=silent_sink if silent else None,
- stderr=silent_sink if silent else None,)
+def DisplayBootstrapWarning():
+ print """\
-def PubBuild(dart_executable, pub_executable, pkg_root, silent, output_dir):
+
+WARNING: Your system cannot run the checked-in Dart SDK. Using the
+bootstrap Dart executable will make debug builds slow.
+Please see the Wiki for instructions on replacing the checked-in Dart SDK.
+
+https://github.com/dart-lang/sdk/wiki/The-checked-in-SDK-in--tools
+
+"""
+
+def PubCommand(dart_executable,
+ pub_executable,
+ pub_snapshot,
+ pkg_root,
+ command,
+ silent):
with open(os.devnull, 'wb') as silent_sink:
- if (pub_executable != None):
- return subprocess.call([pub_executable,
- 'build',
- '--output',
- output_dir],
- stdout=silent_sink if silent else None,
- stderr=silent_sink if silent else None,)
+ if pub_executable is not None:
+ executable = [pub_executable]
+ elif pub_snapshot is not None:
+ executable = [utils.CheckedInSdkExecutable(), pub_snapshot]
else:
- return subprocess.call(['python',
- RUN_PUB,
- '--package-root=' + pkg_root,
- '--dart-executable=' + dart_executable,
- 'build',
- '--output',
- output_dir],
- stdout=silent_sink if silent else None,
- stderr=silent_sink if silent else None,)
+ DisplayBootstrapWarning()
+ executable = [dart_executable, '--package-root=' + pkg_root, PUB_PATH]
+ return subprocess.call(executable + command,
+ stdout=silent_sink if silent else None,
+ stderr=silent_sink if silent else None)
def Deploy(input_dir, output_dir):
shutil.rmtree(output_dir)
@@ -110,16 +123,24 @@
def ExecuteCommand(options, args):
cmd = options.command
if (cmd == 'get'):
- return PubGet(options.dart_executable,
- options.pub_executable,
- options.package_root,
- options.silent)
+ # Always remove pubspec.lock before running 'pub get'.
+ try:
+ os.remove('pubspec.lock');
+ except OSError as e:
+ pass
+ return PubCommand(options.dart_executable,
+ options.pub_executable,
+ options.pub_snapshot,
+ options.package_root,
+ ['get', '--offline'],
+ options.silent)
elif (cmd == 'build'):
- return PubBuild(options.dart_executable,
- options.pub_executable,
- options.package_root,
- options.silent,
- args[0])
+ return PubCommand(options.dart_executable,
+ options.pub_executable,
+ options.pub_snapshot,
+ options.package_root,
+ ['build', '--output', args[0]],
+ options.silent)
elif (cmd == 'deploy'):
Deploy('build', 'deployed')
elif (cmd == 'rewrite'):
@@ -135,8 +156,6 @@
if not ProcessOptions(options, args):
parser.print_help()
return 1
- if os.getenv('DART_USE_BOOTSTRAP_BIN') != None:
- dart_executable = options.dart_executable
# Calculate absolute paths before changing directory.
if (options.package_root != None):
options.package_root = os.path.abspath(options.package_root)
@@ -144,6 +163,8 @@
options.dart_executable = os.path.abspath(options.dart_executable)
if (options.pub_executable != None):
options.pub_executable = os.path.abspath(options.pub_executable)
+ if (options.pub_snapshot != None):
+ options.pub_snapshot = os.path.abspath(options.pub_snapshot)
if len(args) == 1:
args[0] = os.path.abspath(args[0])
# Pub must be run from the project's root directory.
@@ -151,4 +172,4 @@
return ExecuteCommand(options, args)
if __name__ == '__main__':
- sys.exit(main());
\ No newline at end of file
+ sys.exit(main());
diff --git a/tools/promote.py b/tools/promote.py
index 81ab402..d3013ab 100644
--- a/tools/promote.py
+++ b/tools/promote.py
@@ -131,10 +131,11 @@
remove_gs_directory(to_loc)
Gsutil(['-m', 'cp', '-a', 'public-read', '-R', from_loc, to_loc])
- # Copy api-docs zipfile.
- from_loc = raw_namer.apidocs_zipfilepath(revision)
- to_loc = release_namer.apidocs_zipfilepath(to_revision)
- Gsutil(['-m', 'cp', '-a', 'public-read', from_loc, to_loc])
+ # Copy api-docs directory.
+ from_loc = raw_namer.apidocs_directory(revision)
+ to_loc = release_namer.apidocs_directory(to_revision)
+ remove_gs_directory(to_loc)
+ Gsutil(['-m', 'cp', '-a', 'public-read', '-R', from_loc, to_loc])
# Copy dartium directory.
from_loc = raw_namer.dartium_directory(revision)
diff --git a/tools/run_pub.py b/tools/run_pub.py
deleted file mode 100755
index f54a411..0000000
--- a/tools/run_pub.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-"""Used to run pub before the SDK has been built"""
-
-import argparse
-import os
-import platform
-import subprocess
-import sys
-
-SCRIPT_DIR = os.path.dirname(sys.argv[0])
-DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
-PUB_PATH = os.path.join(DART_ROOT, 'third_party/pkg/pub/bin/pub.dart')
-CANARY_PATH = os.path.join(DART_ROOT, 'tools', 'canary.dart')
-
-usage = """run_pub.py --package-root=<package root>"""
-
-def BuildArguments():
- result = argparse.ArgumentParser(usage=usage)
- result.add_argument("--package-root", help="package root", default=None)
- result.add_argument("--dart-executable", help="dart binary", default=None)
- return result
-
-def ProcessOptions(options, args):
- return ((options.package_root != None) and
- (options.dart_executable != None))
-
-def GetPrebuiltDartExecutablePath(suffix):
- osdict = {'Darwin':'macos', 'Linux':'linux', 'Windows':'windows'}
- system = platform.system()
- executable_name = 'dart'
- if system == 'Windows':
- executable_name = 'dart.exe'
- try:
- osname = osdict[system]
- except KeyError:
- print >>sys.stderr, ('WARNING: platform "%s" not supported') % (system)
- return None;
- return os.path.join(DART_ROOT,
- 'tools',
- 'testing',
- 'bin',
- osname,
- executable_name + suffix)
-
-def RunPub(dart, pkg_root, args):
- return subprocess.call([dart, '--package-root=' + pkg_root, PUB_PATH] + args)
-
-def TryRunningExecutable(dart_executable, pkg_root):
- try:
- return subprocess.call([dart_executable,
- '--package-root=' + pkg_root,
- CANARY_PATH]) == 42
- except:
- return False;
-
-def DisplayBootstrapWarning():
- print """\
-
-
-WARNING: Your system cannot run the prebuilt Dart executable. Using the
-bootstrap Dart executable will make Debug builds long.
-Please see Wiki for instructions on replacing prebuilt Dart executable.
-
-https://code.google.com/p/dart/wiki/ReplacingPrebuiltDartExecutable
-
-"""
-
-def FindDartExecutable(fallback_executable, package_root):
- # If requested, use the bootstrap binary instead of the prebuilt
- # executable.
- if os.getenv('DART_USE_BOOTSTRAP_BIN') != None:
- return fallback_executable
- # Try to find a working prebuilt dart executable.
- dart_executable = GetPrebuiltDartExecutablePath('')
- if TryRunningExecutable(dart_executable, package_root):
- return dart_executable
- dart_executable = GetPrebuiltDartExecutablePath('-arm')
- if TryRunningExecutable(dart_executable, package_root):
- return dart_executable
- dart_executable = GetPrebuiltDartExecutablePath('-mips')
- if TryRunningExecutable(dart_executable, package_root):
- return dart_executable
- # If the system cannot execute a prebuilt dart executable, use the bootstrap
- # executable instead.
- DisplayBootstrapWarning()
- return fallback_executable
-
-def main():
- # Parse the options.
- parser = BuildArguments()
- (options, args) = parser.parse_known_args()
- if not ProcessOptions(options, args):
- parser.print_help()
- return 1
- dart_executable = FindDartExecutable(options.dart_executable,
- options.package_root)
- return RunPub(dart_executable, options.package_root, args)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index fc1d536..9ec90f0 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -155,7 +155,12 @@
List<String> sharedOptions,
List<String> originalArguments,
CommandArtifact artifact) {
- return <String>[]
+ List<String> args = [];
+ if (isChecked) {
+ args.add('--enable_asserts');
+ args.add('--enable_type_checks');
+ }
+ return args
..addAll(vmOptions)
..addAll(sharedOptions)
..addAll(originalArguments);
@@ -315,6 +320,10 @@
CommandBuilder commandBuilder,
List arguments,
Map<String, String> environmentOverrides) {
+ arguments = new List.from(arguments);
+ if (isChecked) {
+ arguments.add('--enable_type_checks');
+ }
return new CommandArtifact(
<Command>[
commandBuilder.getAnalysisCommand(
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index aef5b3f..b4e7b53 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -2225,10 +2225,6 @@
static List<String> standardOptions(Map configuration) {
List args = ["--ignore-unrecognized-flags"];
- if (configuration["checked"]) {
- args.add('--enable_asserts');
- args.add("--enable_type_checks");
- }
String compiler = configuration["compiler"];
if (compiler == "dart2js") {
args = ['--generate-code-with-compile-time-errors', '--test-mode'];
diff --git a/tools/utils.py b/tools/utils.py
index 2301d9b..4b7fae5 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -565,6 +565,7 @@
def DartBinary():
+ # TODO(24311): Replace all uses of this with CheckedInSdk[Fix]Executable().
tools_dir = os.path.dirname(os.path.realpath(__file__))
dart_binary_prefix = os.path.join(tools_dir, 'testing', 'bin')
if IsWindows():
@@ -591,6 +592,51 @@
dart_binary_prefix = os.path.join(tools_dir, '..', 'sdk' , 'bin')
return os.path.join(dart_binary_prefix, 'dart')
+
+# The checked-in SDKs are documented at
+# https://github.com/dart-lang/sdk/wiki/The-checked-in-SDK-in-tools
+def CheckedInSdkPath():
+ # We don't use the normal macos, linux, win32 directory names here, instead,
+ # we use the names that the download_from_google_storage script uses.
+ osdict = {'Darwin':'mac', 'Linux':'linux', 'Windows':'win'}
+ system = platform.system()
+ try:
+ osname = osdict[system]
+ except KeyError:
+ print >>sys.stderr, ('WARNING: platform "%s" not supported') % (system)
+ return None;
+ tools_dir = os.path.dirname(os.path.realpath(__file__))
+ return os.path.join(tools_dir,
+ 'sdks',
+ osname,
+ 'dart-sdk')
+
+
+def CheckedInSdkExecutable():
+ name = 'dart'
+ if IsWindows():
+ name = 'dart.exe'
+ elif GuessOS() == 'linux':
+ arch = GuessArchitecture()
+ if arch == 'mips':
+ name = 'dart-mips'
+ elif arch == 'arm':
+ name = 'dart-arm'
+ return os.path.join(CheckedInSdkPath(), 'bin', name)
+
+
+def CheckedInSdkCheckExecutable():
+ executable = CheckedInSdkExecutable()
+ canary_script = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ 'canary.dart')
+ try:
+ if 42 == subprocess.call([executable, canary_script]):
+ return True
+ except OSError as e:
+ pass
+ return False
+
+
class TempDir(object):
def __init__(self, prefix=''):
self._temp_dir = None