Version 1.18.0-dev.2.0
Merge '9eed0f74d4373d80261e29d09208409ef34b3ae9' into dev
diff --git a/DEPS b/DEPS
index d46d997..626a258 100644
--- a/DEPS
+++ b/DEPS
@@ -42,21 +42,21 @@
"chrome_rev" : "@19997",
"cli_util_tag" : "@0.0.1+2",
"code_transformers_rev": "@bfe9799e88d9c231747435e1c1d2495ef5ecd966",
- "collection_tag": "@1.6.0",
- "convert_tag": "@1.0.0",
- "crypto_tag" : "@1.1.1",
+ "collection_tag": "@1.8.0",
+ "convert_tag": "@2.0.0",
+ "crypto_tag" : "@2.0.1",
"csslib_tag" : "@0.12.0",
"dart2js_info_rev" : "@0a221eaf16aec3879c45719de656680ccb80d8a1",
"dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
"dart_style_tag": "@0.2.4",
- "dartdoc_tag" : "@v0.9.0",
+ "dartdoc_tag" : "@v0.9.6",
"dev_compiler_rev": "@7e9708eb5e9f3fcdc68b9af039d78cf39ce502b7",
"fixnum_tag": "@0.10.5",
"func_rev": "@8d4aea75c21be2179cb00dc2b94a71414653094e",
"glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
"html_tag" : "@0.12.1+1",
"http_multi_server_tag" : "@2.0.0",
- "http_parser_tag" : "@1.1.0",
+ "http_parser_tag" : "@3.0.2",
"http_tag" : "@0.11.3+3",
"http_throttle_rev" : "@a81f08be942cdd608883c7b67795c12226abc235",
"idl_parser_rev": "@7fbe68cab90c38147dee4f48c30ad0d496c17915",
@@ -87,8 +87,8 @@
"resource_rev":"@a49101ba2deb29c728acba6fb86000a8f730f4b1",
"root_certificates_rev": "@aed07942ce98507d2be28cbd29e879525410c7fc",
"scheduled_test_tag": "@0.12.5+2",
- "shelf_static_tag": "@0.2.3+1",
- "shelf_tag": "@0.6.5",
+ "shelf_static_tag": "@0.2.3+4",
+ "shelf_tag": "@0.6.5+2",
"shelf_web_socket_tag": "@0.2.0",
"smoke_rev" : "@f3361191cc2a85ebc1e4d4c33aec672d7915aba9",
"source_map_stack_trace_tag": "@1.0.4",
@@ -100,13 +100,13 @@
"string_scanner_tag": "@0.1.4",
"sunflower_rev": "@879b704933413414679396b129f5dfa96f7a0b1e",
"test_reflective_loader_tag": "@0.0.3",
- "test_tag": "@0.12.13+1",
+ "test_tag": "@0.12.13+5",
"typed_data_tag": "@1.1.2",
"usage_rev": "@b5080dac0d26a5609b266f8fdb0d053bc4c1c638",
"utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
"watcher_tag": "@0.9.7+2",
"web_components_rev": "@6349e09f9118dce7ae1b309af5763745e25a9d61",
- "web_socket_channel_tag": "@1.0.0",
+ "web_socket_channel_tag": "@1.0.4",
"WebCore_rev": "@a86fe28efadcfc781f836037a80f27e22a5dad17",
"when_tag": "@0.2.0+2",
"which_tag": "@0.1.3+1",
diff --git a/pkg/analysis_server/benchmark/perf/benchmark_local.dart b/pkg/analysis_server/benchmark/perf/benchmark_local.dart
new file mode 100644
index 0000000..7b17591
--- /dev/null
+++ b/pkg/analysis_server/benchmark/perf/benchmark_local.dart
@@ -0,0 +1,195 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library server.performance.local;
+
+import 'package:analysis_server/plugin/protocol/protocol.dart';
+
+import 'benchmark_scenario.dart';
+
+main(List<String> args) async {
+ String pathRepository = args[0];
+ String pathServer = '$pathRepository/pkg/analysis_server';
+ String pathAnalyzer = '$pathRepository/pkg/analyzer';
+ {
+ String now = new DateTime.now().toUtc().toIso8601String();
+ print('Benchmark started: $now');
+ print('');
+ print('');
+ }
+
+ {
+ String id = 'local-initialAnalysis-1';
+ String description = r'''
+1. Start server, set 'analyzer' analysis root.
+2. Measure the time to finish initial analysis.
+3. Shutdown the server.
+4. Go to (1).
+''';
+ List<int> times = await BenchmarkScenario
+ .start_waitInitialAnalysis_shutdown(
+ roots: [pathAnalyzer], numOfRepeats: 3);
+ printBenchmarkResults(id, description, times);
+ }
+
+ {
+ String id = 'local-initialAnalysis-2';
+ String description = r'''
+1. Start server, set 'analyzer' and 'analysis_server' analysis roots.
+2. Measure the time to finish initial analysis.
+3. Shutdown the server.
+4. Go to (1).
+''';
+ List<int> times = await BenchmarkScenario
+ .start_waitInitialAnalysis_shutdown(
+ roots: [pathAnalyzer, pathServer], numOfRepeats: 3);
+ printBenchmarkResults(id, description, times);
+ }
+
+ {
+ String id = 'local-change-1';
+ String description = r'''
+1. Open 'analyzer'.
+2. Change a method body in src/task/dart.dart.
+3. Measure the time to finish analysis.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+ List<int> times = await new BenchmarkScenario().waitAnalyze_change_analyze(
+ roots: [pathAnalyzer],
+ file: '$pathAnalyzer/lib/src/task/dart.dart',
+ fileChange: new FileChange(
+ afterStr: 'if (hasDirectiveChange) {', insertStr: 'print(12345);'),
+ numOfRepeats: 10);
+ printBenchmarkResults(id, description, times);
+ }
+
+ {
+ String id = 'local-change-2';
+ String description = r'''
+1. Open 'analyzer'.
+2. Change the name of a public method in src/task/dart.dart.
+3. Measure the time to finish analysis.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+ List<int> times = await new BenchmarkScenario().waitAnalyze_change_analyze(
+ roots: [pathAnalyzer],
+ file: '$pathAnalyzer/lib/src/task/dart.dart',
+ fileChange: new FileChange(
+ afterStr: 'resolveDirective(An',
+ afterStrBack: 3,
+ insertStr: 'NewName'),
+ numOfRepeats: 5);
+ printBenchmarkResults(id, description, times);
+ }
+
+ {
+ String id = 'local-completion-1';
+ String description = r'''
+1. Open 'analyzer'.
+2. Change a method body in src/task/dart.dart.
+3. Request code completion in this method and measure time to get results.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+ List<int> times = await new BenchmarkScenario()
+ .waitAnalyze_change_getCompletion(
+ roots: [pathAnalyzer],
+ file: '$pathAnalyzer/lib/src/task/dart.dart',
+ fileChange: new FileChange(
+ afterStr: 'if (hasDirectiveChange) {',
+ insertStr: 'print(12345);'),
+ completeAfterStr: 'print(12345);',
+ numOfRepeats: 10);
+ printBenchmarkResults(id, description, times);
+ }
+
+ {
+ String id = 'local-completion-2';
+ String description = r'''
+1. Open 'analyzer'.
+2. Change the name of a public method in src/task/dart.dart.
+3. Request code completion in this method and measure time to get results.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+ List<int> times = await new BenchmarkScenario()
+ .waitAnalyze_change_getCompletion(
+ roots: [pathAnalyzer],
+ file: '$pathAnalyzer/lib/src/task/dart.dart',
+ fileChange: new FileChange(
+ afterStr: 'DeltaResult validate(In',
+ afterStrBack: 3,
+ insertStr: 'NewName'),
+ completeAfterStr: 'if (hasDirectiveChange) {',
+ numOfRepeats: 5);
+ printBenchmarkResults(id, description, times);
+ }
+
+ {
+ String id = 'local-completion-3';
+ String description = r'''
+1. Open 'analysis_server' and 'analyzer'.
+2. Change a method body in src/task/dart.dart.
+3. Request code completion in this method and measure time to get results.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+ List<int> times = await new BenchmarkScenario()
+ .waitAnalyze_change_getCompletion(
+ roots: [pathServer, pathAnalyzer],
+ file: '$pathAnalyzer/lib/src/task/dart.dart',
+ fileChange: new FileChange(
+ afterStr: 'if (hasDirectiveChange) {',
+ insertStr: 'print(12345);'),
+ completeAfterStr: 'print(12345);',
+ numOfRepeats: 10);
+ printBenchmarkResults(id, description, times);
+ }
+
+ {
+ String id = 'local-completion-4';
+ String description = r'''
+1. Open 'analysis_server' and 'analyzer'.
+2. Change the name of a public method in src/task/dart.dart.
+3. Request code completion in this method and measure time to get results.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+ List<int> times = await new BenchmarkScenario()
+ .waitAnalyze_change_getCompletion(
+ roots: [pathServer, pathAnalyzer],
+ file: '$pathAnalyzer/lib/src/task/dart.dart',
+ fileChange: new FileChange(
+ afterStr: 'DeltaResult validate(In',
+ afterStrBack: 3,
+ insertStr: 'NewName'),
+ completeAfterStr: 'if (hasDirectiveChange) {',
+ numOfRepeats: 5);
+ printBenchmarkResults(id, description, times);
+ }
+
+ {
+ String id = 'local-refactoring-1';
+ String description = r'''
+1. Open 'analyzer'.
+2. Change the name of a public method in src/context/cache.dart.
+3. Request rename refactoring for `getSourcesWithFullName` and measure time to get results.
+4. Rollback changes to the file and wait for analysis.
+5. Go to (2).
+''';
+ List<int> times = await new BenchmarkScenario()
+ .waitAnalyze_change_getRefactoring(
+ roots: [pathAnalyzer],
+ file: '$pathAnalyzer/lib/src/context/cache.dart',
+ fileChange: new FileChange(
+ afterStr: 'getState(An', afterStrBack: 3, insertStr: 'NewName'),
+ refactoringAtStr: 'getSourcesWithFullName(String path)',
+ refactoringKind: RefactoringKind.RENAME,
+ refactoringOptions: new RenameOptions('getSourcesWithFullName2'),
+ numOfRepeats: 5);
+ printBenchmarkResults(id, description, times);
+ }
+}
diff --git a/pkg/analysis_server/benchmark/perf/benchmark_scenario.dart b/pkg/analysis_server/benchmark/perf/benchmark_scenario.dart
new file mode 100644
index 0000000..aac844b
--- /dev/null
+++ b/pkg/analysis_server/benchmark/perf/benchmark_scenario.dart
@@ -0,0 +1,287 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library server.performance.scenarios;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:analysis_server/plugin/protocol/protocol.dart';
+import 'package:unittest/unittest.dart';
+
+import 'performance_tests.dart';
+
+void printBenchmarkResults(String id, String description, List<int> times) {
+ String now = new DateTime.now().toUtc().toIso8601String();
+ print('$now ========== $id');
+ print('times: $times');
+ print(description.trim());
+ print('--------------------');
+ print('');
+ print('');
+}
+
+class BenchmarkScenario extends AbstractTimingTest {
+ /**
+ * Init.
+ * - Start Analysis Server.
+ * - Set the analysis [roots].
+ * - Wait for analysis to complete.
+ * - Make [file] the priority file.
+ *
+ * Measurement.
+ * - Change the [file] according to the [fileChange].
+ * - Record the time to finish analysis.
+ *
+ * Repeat.
+ * - Undo changes to the [file].
+ * - Repeat measurement [numOfRepeats] times.
+ */
+ Future<List<int>> waitAnalyze_change_analyze(
+ {List<String> roots,
+ String file,
+ FileChange fileChange,
+ int numOfRepeats}) async {
+ expect(roots, isNotNull, reason: 'roots');
+ expect(file, isNotNull, reason: 'file');
+ expect(fileChange, isNotNull, reason: 'fileChange');
+ expect(numOfRepeats, isNotNull, reason: 'numOfRepeats');
+ // Initialize Analysis Server.
+ await super.setUp();
+ await subscribeToStatusNotifications();
+ // Set roots and analyze.
+ await sendAnalysisSetAnalysisRoots(roots, []);
+ await analysisFinished;
+ // Make the file priority.
+ await sendAnalysisSetPriorityFiles([file]);
+ // Repeat.
+ List<int> times = <int>[];
+ for (int i = 0; i < numOfRepeats; i++) {
+ // Update and wait for analysis.
+ Stopwatch stopwatch = new Stopwatch()..start();
+ await _applyFileChange(file, fileChange);
+ await analysisFinished;
+ times.add(stopwatch.elapsed.inMilliseconds);
+ // Remove the overlay and analyze.
+ await sendAnalysisUpdateContent({file: new RemoveContentOverlay()});
+ await analysisFinished;
+ }
+ // Done.
+ await shutdown();
+ return times;
+ }
+
+ /**
+ * Init.
+ * 1. Start Analysis Server.
+ * 2. Set the analysis [roots].
+ * 3. Wait for analysis to complete.
+ * 4. Make [file] the priority file.
+ *
+ * Measurement.
+ * 5. Change the [file] according to the [fileChange].
+ * 6. Request [completeAfterStr] in the updated file content.
+ * 7. Record the time to get completion results.
+ * 8. Undo changes to the [file] and analyze.
+ * 9. Go to (5).
+ */
+ Future<List<int>> waitAnalyze_change_getCompletion(
+ {List<String> roots,
+ String file,
+ FileChange fileChange,
+ String completeAfterStr,
+ int numOfRepeats}) async {
+ expect(roots, isNotNull, reason: 'roots');
+ expect(file, isNotNull, reason: 'file');
+ expect(fileChange, isNotNull, reason: 'fileChange');
+ expect(completeAfterStr, isNotNull, reason: 'completeAfterStr');
+ expect(numOfRepeats, isNotNull, reason: 'numOfRepeats');
+ // Initialize Analysis Server.
+ await super.setUp();
+ await subscribeToStatusNotifications();
+ // Set roots and analyze.
+ await sendAnalysisSetAnalysisRoots(roots, []);
+ await analysisFinished;
+ // Make the file priority.
+ await sendAnalysisSetPriorityFiles([file]);
+ // Repeat.
+ List<int> times = <int>[];
+ for (int i = 0; i < numOfRepeats; i++) {
+ String updatedContent = await _applyFileChange(file, fileChange);
+ // Measure completion time.
+ int completionOffset =
+ _indexOfEnd(file, updatedContent, completeAfterStr);
+ Duration completionDuration =
+ await _measureCompletionTime(file, completionOffset);
+ times.add(completionDuration.inMilliseconds);
+ // Remove the overlay and analyze.
+ await sendAnalysisUpdateContent({file: new RemoveContentOverlay()});
+ await analysisFinished;
+ }
+ // Done.
+ await shutdown();
+ return times;
+ }
+
+ /**
+ * Init.
+ * 1. Start Analysis Server.
+ * 2. Set the analysis [roots].
+ * 3. Wait for analysis to complete.
+ * 4. Make [file] the priority file.
+ *
+ * Measurement.
+ * 5. Change the [file] according to the [fileChange].
+ * 6. Request [refactoringAtStr] in the updated file content.
+ * 7. Record the time to get refactoring.
+ * 8. Undo changes to the [file] and analyze.
+ * 9. Go to (5).
+ */
+ Future<List<int>> waitAnalyze_change_getRefactoring(
+ {List<String> roots,
+ String file,
+ FileChange fileChange,
+ String refactoringAtStr,
+ RefactoringKind refactoringKind,
+ RefactoringOptions refactoringOptions,
+ int numOfRepeats}) async {
+ expect(roots, isNotNull, reason: 'roots');
+ expect(file, isNotNull, reason: 'file');
+ expect(fileChange, isNotNull, reason: 'fileChange');
+ expect(refactoringAtStr, isNotNull, reason: 'refactoringAtStr');
+ expect(refactoringKind, isNotNull, reason: 'refactoringKind');
+ expect(refactoringOptions, isNotNull, reason: 'refactoringOptions');
+ expect(numOfRepeats, isNotNull, reason: 'numOfRepeats');
+ // Initialize Analysis Server.
+ await super.setUp();
+ await subscribeToStatusNotifications();
+ // Set roots and analyze.
+ await sendAnalysisSetAnalysisRoots(roots, []);
+ await analysisFinished;
+ // Make the file priority.
+ await sendAnalysisSetPriorityFiles([file]);
+ // Repeat.
+ List<int> times = <int>[];
+ for (int i = 0; i < numOfRepeats; i++) {
+ String updatedContent = await _applyFileChange(file, fileChange);
+ // Measure time to get refactoring.
+ int refactoringOffset = _indexOf(file, updatedContent, refactoringAtStr);
+ Duration refactoringDuration = await _measureRefactoringTime(
+ file, refactoringOffset, refactoringKind, refactoringOptions);
+ times.add(refactoringDuration.inMilliseconds);
+ // Remove the overlay and analyze.
+ await sendAnalysisUpdateContent({file: new RemoveContentOverlay()});
+ await analysisFinished;
+ }
+ // Done.
+ await shutdown();
+ return times;
+ }
+
+ /**
+ * Compute updated content of the [file] as described by [desc], add overlay
+ * for the [file], and return the updated content.
+ */
+ Future<String> _applyFileChange(String file, FileChange desc) async {
+ String originalContent = _getFileContent(file);
+ int offset = _indexOfEnd(file, originalContent, desc.afterStr);
+ offset -= desc.afterStrBack;
+ String updatedContent = originalContent.substring(0, offset) +
+ desc.insertStr +
+ originalContent.substring(offset);
+ await sendAnalysisUpdateContent(
+ {file: new AddContentOverlay(updatedContent)});
+ return updatedContent;
+ }
+
+ Future<Duration> _measureCompletionTime(String file, int offset) async {
+ Stopwatch stopwatch = new Stopwatch();
+ stopwatch.start();
+ Completer<Duration> completer = new Completer<Duration>();
+ var completionSubscription = onCompletionResults.listen((_) {
+ completer.complete(stopwatch.elapsed);
+ });
+ try {
+ await sendCompletionGetSuggestions(file, offset);
+ return await completer.future;
+ } finally {
+ completionSubscription.cancel();
+ }
+ }
+
+ Future<Duration> _measureRefactoringTime(
+ String file,
+ int offset,
+ RefactoringKind refactoringKind,
+ RefactoringOptions refactoringOptions) async {
+ Stopwatch stopwatch = new Stopwatch();
+ stopwatch.start();
+ await sendEditGetRefactoring(refactoringKind, file, offset, 0, false,
+ options: refactoringOptions);
+ return stopwatch.elapsed;
+ }
+
+ /**
+ * 1. Start Analysis Server.
+ * 2. Set the analysis [roots].
+ * 3. Wait for analysis to complete.
+ * 4. Record the time to finish analysis.
+ * 5. Shutdown.
+ * 6. Go to (1).
+ */
+ static Future<List<int>> start_waitInitialAnalysis_shutdown(
+ {List<String> roots, int numOfRepeats}) async {
+ expect(roots, isNotNull, reason: 'roots');
+ expect(numOfRepeats, isNotNull, reason: 'numOfRepeats');
+ // Repeat.
+ List<int> times = <int>[];
+ for (int i = 0; i < numOfRepeats; i++) {
+ BenchmarkScenario instance = new BenchmarkScenario();
+ // Initialize Analysis Server.
+ await instance.setUp();
+ await instance.subscribeToStatusNotifications();
+ // Set roots and analyze.
+ Stopwatch stopwatch = new Stopwatch()..start();
+ await instance.sendAnalysisSetAnalysisRoots(roots, []);
+ await instance.analysisFinished;
+ times.add(stopwatch.elapsed.inMilliseconds);
+ // Stop the server.
+ await instance.shutdown();
+ }
+ return times;
+ }
+
+ static String _getFileContent(String path) {
+ File file = new File(path);
+ expect(file.existsSync(), isTrue, reason: 'File $path does not exist.');
+ return file.readAsStringSync();
+ }
+
+ /**
+ * Return the index of [what] in [where] in the [file], fail if not found.
+ */
+ static int _indexOf(String file, String where, String what) {
+ int index = where.indexOf(what);
+ expect(index, isNot(-1), reason: 'Cannot find |$what| in $file.');
+ return index;
+ }
+
+ /**
+ * Return the end index if [what] in [where] in the [file], fail if not found.
+ */
+ static int _indexOfEnd(String file, String where, String what) {
+ return _indexOf(file, where, what) + what.length;
+ }
+}
+
+class FileChange {
+ final String afterStr;
+ final int afterStrBack;
+ final String insertStr;
+
+ FileChange({this.afterStr, this.afterStrBack: 0, this.insertStr}) {
+ expect(afterStr, isNotNull, reason: 'afterStr');
+ expect(insertStr, isNotNull, reason: 'insertStr');
+ }
+}
diff --git a/pkg/analysis_server/benchmark/perf/performance_tests.dart b/pkg/analysis_server/benchmark/perf/performance_tests.dart
index b784c0c..6d301c9 100644
--- a/pkg/analysis_server/benchmark/perf/performance_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/performance_tests.dart
@@ -61,13 +61,11 @@
Future shutdown() async => await shutdownIfNeeded();
/**
- * Enable [SERVER_STATUS] notifications so that [analysisFinished]
+ * Enable [ServerService.STATUS] notifications so that [analysisFinished]
* can be used.
*/
- Future subscribeToStatusNotifications() {
- List<Future> futures = <Future>[];
- futures.add(sendServerSetSubscriptions([ServerService.STATUS]));
- return Future.wait(futures);
+ Future subscribeToStatusNotifications() async {
+ await sendServerSetSubscriptions([ServerService.STATUS]);
}
}
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 0c6b2dd..343d50b 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -61,7 +61,7 @@
</style></head>
<body>
<h1>Analysis Server API Specification</h1>
- <h1 style="color:#999999">Version 1.15.0</h1>
+ <h1 style="color:#999999">Version 1.16.0</h1>
<p>
This document contains a specification of the API provided by the
analysis server. The API in this document is currently under
@@ -305,6 +305,7 @@
"event": "server.connected"
"params": {
"<b>version</b>": String
+ "<b>pid</b>": int
}
}</pre></div>
<p>
@@ -321,7 +322,10 @@
<h4>Parameters</h4><dl><dt class="field"><b><i>version ( String )</i></b></dt><dd>
<p>The version number of the analysis server.</p>
- </dd></dl></dd><dt class="notification"><a name="notification_server.error">server.error</a> (<a href="#notification_server.error">#</a>)</dt><dd><div class="box"><pre>notification: {
+ </dd><dt class="field"><b><i>pid ( int )</i></b></dt><dd>
+
+ <p>The process id of the analysis server process.</p>
+ </dd></dl></dd><dt class="notification"><a name="notification_server.error">server.error</a> (<a href="#notification_server.error">#</a>)</dt><dd><div class="box"><pre>notification: {
"event": "server.error"
"params": {
"<b>isFatal</b>": bool
diff --git a/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart b/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
index c547af5..4b8fe8b 100644
--- a/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
@@ -266,6 +266,7 @@
*
* {
* "version": String
+ * "pid": int
* }
*
* Clients may not extend, implement or mix-in this class.
@@ -273,6 +274,8 @@
class ServerConnectedParams implements HasToJson {
String _version;
+ int _pid;
+
/**
* The version number of the analysis server.
*/
@@ -286,8 +289,22 @@
this._version = value;
}
- ServerConnectedParams(String version) {
+ /**
+ * The process id of the analysis server process.
+ */
+ int get pid => _pid;
+
+ /**
+ * The process id of the analysis server process.
+ */
+ void set pid(int value) {
+ assert(value != null);
+ this._pid = value;
+ }
+
+ ServerConnectedParams(String version, int pid) {
this.version = version;
+ this.pid = pid;
}
factory ServerConnectedParams.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) {
@@ -301,7 +318,13 @@
} else {
throw jsonDecoder.missingKey(jsonPath, "version");
}
- return new ServerConnectedParams(version);
+ int pid;
+ if (json.containsKey("pid")) {
+ pid = jsonDecoder.decodeInt(jsonPath + ".pid", json["pid"]);
+ } else {
+ throw jsonDecoder.missingKey(jsonPath, "pid");
+ }
+ return new ServerConnectedParams(version, pid);
} else {
throw jsonDecoder.mismatch(jsonPath, "server.connected params", json);
}
@@ -315,6 +338,7 @@
Map<String, dynamic> toJson() {
Map<String, dynamic> result = {};
result["version"] = version;
+ result["pid"] = pid;
return result;
}
@@ -328,7 +352,8 @@
@override
bool operator==(other) {
if (other is ServerConnectedParams) {
- return version == other.version;
+ return version == other.version &&
+ pid == other.pid;
}
return false;
}
@@ -337,6 +362,7 @@
int get hashCode {
int hash = 0;
hash = JenkinsSmiHash.combine(hash, version.hashCode);
+ hash = JenkinsSmiHash.combine(hash, pid.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index ed02817..bda82af 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -7,6 +7,7 @@
import 'dart:async';
import 'dart:collection';
import 'dart:core' hide Resource;
+import 'dart:io' as io;
import 'dart:math' show max;
import 'package:analysis_server/plugin/protocol/protocol.dart'
@@ -27,7 +28,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/embedder.dart';
import 'package:analyzer/source/pub_package_map_provider.dart';
@@ -296,6 +296,12 @@
new StreamController<ContextsChangedEvent>.broadcast();
/**
+ * The file resolver provider used to override the way file URI's are
+ * resolved in some contexts.
+ */
+ ResolverProvider fileResolverProvider;
+
+ /**
* Initialize a newly created server to receive requests from and send
* responses to the given [channel].
*
@@ -313,7 +319,7 @@
this.options,
this.defaultSdkCreator,
this.instrumentationService,
- {EmbeddedResolverProvider embeddedResolverProvider: null,
+ {ResolverProvider fileResolverProvider: null,
ResolverProvider packageResolverProvider: null,
bool useSingleContextManager: false,
this.rethrowExceptions: true})
@@ -336,12 +342,12 @@
resourceProvider,
sdkManager,
packageResolverProvider,
- embeddedResolverProvider,
packageMapProvider,
analyzedFilesGlobs,
instrumentationService,
defaultContextOptions);
}
+ this.fileResolverProvider = fileResolverProvider;
ServerContextManagerCallbacks contextManagerCallbacks =
new ServerContextManagerCallbacks(this, resourceProvider);
contextManager.callbacks = contextManagerCallbacks;
@@ -360,7 +366,7 @@
});
_setupIndexInvalidation();
Notification notification =
- new ServerConnectedParams(VERSION).toNotification();
+ new ServerConnectedParams(VERSION, io.pid).toNotification();
channel.sendNotification(notification);
channel.listen(handleRequest, onDone: done, onError: error);
handlers = serverPlugin.createDomains(this);
@@ -1559,13 +1565,14 @@
AnalysisEngine.instance.createAnalysisContext();
context.contentCache = analysisServer.overlayState;
analysisServer.folderMap[folder] = context;
- _locateEmbedderYamls(context, disposition);
+ context.fileResolverProvider = analysisServer.fileResolverProvider;
context.sourceFactory =
_createSourceFactory(context, options, disposition, folder);
context.analysisOptions = options;
analysisServer._onContextsChangedController
.add(new ContextsChangedEvent(added: [context]));
analysisServer.schedulePerformAnalysisOperation(context);
+
return context;
}
@@ -1626,48 +1633,27 @@
List<UriResolver> packageUriResolvers =
disposition.createPackageUriResolvers(resourceProvider);
- EmbedderUriResolver embedderUriResolver;
-
- // First check for a resolver provider.
- ContextManager contextManager = analysisServer.contextManager;
- if (contextManager is ContextManagerImpl) {
- EmbeddedResolverProvider resolverProvider =
- contextManager.embeddedUriResolverProvider;
- if (resolverProvider != null) {
- embedderUriResolver = resolverProvider(folder);
- }
- }
-
// If no embedded URI resolver was provided, defer to a locator-backed one.
- embedderUriResolver ??= new EmbedderUriResolver(
- context.embedderYamlLocator.embedderYamls);
- if (embedderUriResolver.length == 0) {
- // The embedder uri resolver has no mappings. Use the default Dart SDK
- // uri resolver.
+ EmbedderYamlLocator locator =
+ disposition.getEmbedderLocator(resourceProvider);
+ EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+ if (sdk.libraryMap.size() == 0) {
+ // The embedder file has no mappings, so use the default Dart SDK.
resolvers.add(new DartUriResolver(
analysisServer.sdkManager.getSdkForOptions(options)));
} else {
// The embedder uri resolver has mappings, use it instead of the default
// Dart SDK uri resolver.
- resolvers.add(embedderUriResolver);
+ resolvers.add(new DartUriResolver(sdk));
}
resolvers.addAll(packageUriResolvers);
- resolvers.add(new ResourceUriResolver(resourceProvider));
- return new SourceFactory(resolvers, disposition.packages);
- }
-
- /// If [disposition] has a package map, attempt to locate `_embedder.yaml`
- /// files.
- void _locateEmbedderYamls(
- InternalAnalysisContext context, FolderDisposition disposition) {
- Map<String, List<Folder>> packageMap;
- if (disposition is PackageMapDisposition) {
- packageMap = disposition.packageMap;
- } else if (disposition is PackagesFileDisposition) {
- packageMap = disposition.buildPackageMap(resourceProvider);
+ if (context.fileResolverProvider == null) {
+ resolvers.add(new ResourceUriResolver(resourceProvider));
+ } else {
+ resolvers.add(context.fileResolverProvider(folder));
}
- context.embedderYamlLocator.refresh(packageMap);
+ return new SourceFactory(resolvers, disposition.packages);
}
}
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 44c3595..785ccfe 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -12,7 +12,6 @@
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
import 'package:analyzer/plugin/options.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/analysis_options_provider.dart';
@@ -77,6 +76,11 @@
String packageDescriptionPath;
/**
+ * The folder disposition for this context.
+ */
+ final FolderDisposition disposition;
+
+ /**
* Paths to files which determine the folder disposition and package map.
*
* TODO(paulberry): if any of these files are outside of [folder], they won't
@@ -97,7 +101,7 @@
Map<String, Source> sources = new HashMap<String, Source>();
ContextInfo(ContextManagerImpl contextManager, this.parent, Folder folder,
- File packagespecFile, this.packageRoot)
+ File packagespecFile, this.packageRoot, this.disposition)
: folder = folder,
pathFilter = new PathFilter(
folder.path, null, contextManager.resourceProvider.pathContext) {
@@ -111,7 +115,9 @@
*/
ContextInfo._root()
: folder = null,
- pathFilter = null;
+ pathFilter = null,
+ packageRoot = null,
+ disposition = null;
/**
* Iterate through all [children] and their children, recursively.
@@ -408,13 +414,6 @@
pathos.Context pathContext;
/**
- * A function that will return a [UriResolver] that can be used to resolve
- * URI's for embedded libraries within a given folder, or `null` if we should
- * fall back to the standard URI resolver.
- */
- final EmbeddedResolverProvider embeddedUriResolverProvider;
-
- /**
* The list of excluded paths (folders and files) most recently passed to
* [setRoots].
*/
@@ -496,7 +495,6 @@
this.resourceProvider,
this.sdkManager,
this.packageResolverProvider,
- this.embeddedUriResolverProvider,
this._packageMapProvider,
this.analyzedFilesGlobs,
this._instrumentationService,
@@ -592,13 +590,13 @@
info.context.analysisOptions = new AnalysisOptionsImpl();
// Apply inherited options.
- options = _toStringMap(_getEmbeddedOptions(info.context));
+ options = _toStringMap(_getEmbeddedOptions(info));
if (options != null) {
configureContextOptions(info.context, options);
}
} else {
// Check for embedded options.
- Map embeddedOptions = _getEmbeddedOptions(info.context);
+ Map embeddedOptions = _getEmbeddedOptions(info);
if (embeddedOptions != null) {
options = _toStringMap(new Merger().merge(embeddedOptions, options));
}
@@ -910,22 +908,19 @@
// If there is no embedded URI resolver, a new source factory needs to
// be recreated.
if (sourceFactory is SourceFactoryImpl) {
- if (!sourceFactory.resolvers
- .any((UriResolver r) => r is EmbedderUriResolver)) {
- // Get all but the dart: Uri resolver.
- List<UriResolver> resolvers = sourceFactory.resolvers
- .where((r) => r is! DartUriResolver)
- .toList();
- // Add an embedded URI resolver in its place.
- resolvers.add(new EmbedderUriResolver(embedderYamls));
+ // Get all but the dart: Uri resolver.
+ List<UriResolver> resolvers = sourceFactory.resolvers
+ .where((r) => r is! DartUriResolver)
+ .toList();
+ // Add an embedded URI resolver in its place.
+ resolvers.add(new DartUriResolver(new EmbedderSdk(embedderYamls)));
- // Set a new source factory.
- SourceFactoryImpl newFactory = sourceFactory.clone();
- newFactory.resolvers.clear();
- newFactory.resolvers.addAll(resolvers);
- info.context.sourceFactory = newFactory;
- return;
- }
+ // Set a new source factory.
+ SourceFactoryImpl newFactory = sourceFactory.clone();
+ newFactory.resolvers.clear();
+ newFactory.resolvers.addAll(resolvers);
+ info.context.sourceFactory = newFactory;
+ return;
}
}
@@ -1051,17 +1046,11 @@
*/
ContextInfo _createContext(
ContextInfo parent, Folder folder, File packagespecFile) {
- ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile,
- normalizedPackageRoots[folder.path]);
-
- FolderDisposition disposition;
List<String> dependencies = <String>[];
-
- // Next resort to a package uri resolver.
- if (disposition == null) {
- disposition =
- _computeFolderDisposition(folder, dependencies.add, packagespecFile);
- }
+ FolderDisposition disposition =
+ _computeFolderDisposition(folder, dependencies.add, packagespecFile);
+ ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile,
+ normalizedPackageRoots[folder.path], disposition);
Map<String, Object> optionMap = readOptions(info.folder);
AnalysisOptions options =
@@ -1166,24 +1155,17 @@
List<UriResolver> packageUriResolvers =
disposition.createPackageUriResolvers(resourceProvider);
- EmbedderUriResolver embedderUriResolver;
-
- // First check for a resolver provider.
- if (embeddedUriResolverProvider != null) {
- embedderUriResolver = embeddedUriResolverProvider(folder);
- }
-
- // If no embedded URI resolver was provided, defer to a locator-backed one.
- embedderUriResolver ??=
- new EmbedderUriResolver(context.embedderYamlLocator.embedderYamls);
- if (embedderUriResolver.length == 0) {
+ EmbedderYamlLocator locator =
+ disposition.getEmbedderLocator(resourceProvider);
+ EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+ if (sdk.libraryMap.size() == 0) {
// The embedder uri resolver has no mappings. Use the default Dart SDK
// uri resolver.
resolvers.add(new DartUriResolver(sdkManager.getSdkForOptions(options)));
} else {
// The embedder uri resolver has mappings, use it instead of the default
// Dart SDK uri resolver.
- resolvers.add(embedderUriResolver);
+ resolvers.add(new DartUriResolver(sdk));
}
resolvers.addAll(packageUriResolvers);
@@ -1263,29 +1245,26 @@
/// skipped.
///
/// Returns null if there are no embedded/configured options.
- Map _getEmbeddedOptions(AnalysisContext context) {
- Map embeddedOptions;
+ Map _getEmbeddedOptions(ContextInfo info) {
+ Map embeddedOptions = null;
+ EmbedderYamlLocator locator =
+ info.disposition.getEmbedderLocator(resourceProvider);
+ Iterable<YamlMap> maps = locator.embedderYamls.values;
+ if (maps.length == 1) {
+ embeddedOptions = maps.first;
+ }
- if (context is InternalAnalysisContext) {
- EmbedderYamlLocator locator = context.embedderYamlLocator;
- Iterable<YamlMap> maps = locator.embedderYamls.values;
- if (maps.length == 1) {
- embeddedOptions = maps.first;
- }
-
- AnalysisConfiguration configuration = getConfiguration(context);
- if (configuration != null) {
- Map configMap = configuration.options;
- if (configMap != null) {
- if (embeddedOptions != null) {
- embeddedOptions = new Merger().merge(embeddedOptions, configMap);
- } else {
- embeddedOptions = configMap;
- }
+ AnalysisConfiguration configuration = getConfiguration(info.context);
+ if (configuration != null) {
+ Map configMap = configuration.options;
+ if (configMap != null) {
+ if (embeddedOptions != null) {
+ embeddedOptions = new Merger().merge(embeddedOptions, configMap);
+ } else {
+ embeddedOptions = configMap;
}
}
}
-
return embeddedOptions;
}
@@ -1717,6 +1696,10 @@
Iterable<UriResolver> createPackageUriResolvers(
ResourceProvider resourceProvider) =>
<UriResolver>[resolver];
+
+ @override
+ EmbedderYamlLocator getEmbedderLocator(ResourceProvider resourceProvider) =>
+ new EmbedderYamlLocator(null);
}
/**
@@ -1757,6 +1740,13 @@
*/
Iterable<UriResolver> createPackageUriResolvers(
ResourceProvider resourceProvider);
+
+ /**
+ * Return the locator used to locate the _embedder.yaml file used to configure
+ * the SDK. The [resourceProvider] is used to access the file system in cases
+ * where that is necessary.
+ */
+ EmbedderYamlLocator getEmbedderLocator(ResourceProvider resourceProvider);
}
/**
@@ -1776,6 +1766,10 @@
Iterable<UriResolver> createPackageUriResolvers(
ResourceProvider resourceProvider) =>
const <UriResolver>[];
+
+ @override
+ EmbedderYamlLocator getEmbedderLocator(ResourceProvider resourceProvider) =>
+ new EmbedderYamlLocator(null);
}
/**
@@ -1785,6 +1779,8 @@
class PackageMapDisposition extends FolderDisposition {
final Map<String, List<Folder>> packageMap;
+ EmbedderYamlLocator _embedderLocator;
+
@override
final String packageRoot;
@@ -1800,6 +1796,14 @@
new SdkExtUriResolver(packageMap),
new PackageMapUriResolver(resourceProvider, packageMap)
];
+
+ @override
+ EmbedderYamlLocator getEmbedderLocator(ResourceProvider resourceProvider) {
+ if (_embedderLocator == null) {
+ _embedderLocator = new EmbedderYamlLocator(packageMap);
+ }
+ return _embedderLocator;
+ }
}
/**
@@ -1810,22 +1814,27 @@
@override
final Packages packages;
+ Map<String, List<Folder>> packageMap;
+
+ EmbedderYamlLocator _embedderLocator;
+
PackagesFileDisposition(this.packages);
@override
String get packageRoot => null;
Map<String, List<Folder>> buildPackageMap(ResourceProvider resourceProvider) {
- Map<String, List<Folder>> packageMap = <String, List<Folder>>{};
- if (packages == null) {
- return packageMap;
- }
- packages.asMap().forEach((String name, Uri uri) {
- if (uri.scheme == 'file' || uri.scheme == '' /* unspecified */) {
- var path = resourceProvider.pathContext.fromUri(uri);
- packageMap[name] = <Folder>[resourceProvider.getFolder(path)];
+ if (packageMap == null) {
+ packageMap = <String, List<Folder>>{};
+ if (packages != null) {
+ packages.asMap().forEach((String name, Uri uri) {
+ if (uri.scheme == 'file' || uri.scheme == '' /* unspecified */) {
+ var path = resourceProvider.pathContext.fromUri(uri);
+ packageMap[name] = <Folder>[resourceProvider.getFolder(path)];
+ }
+ });
}
- });
+ }
return packageMap;
}
@@ -1840,4 +1849,13 @@
return const <UriResolver>[];
}
}
+
+ @override
+ EmbedderYamlLocator getEmbedderLocator(ResourceProvider resourceProvider) {
+ if (_embedderLocator == null) {
+ _embedderLocator =
+ new EmbedderYamlLocator(buildPackageMap(resourceProvider));
+ }
+ return _embedderLocator;
+ }
}
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index d70517b..a70ecb7 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -19,7 +19,6 @@
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/file_instrumentation.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/incremental_logger.dart';
@@ -298,10 +297,10 @@
InstrumentationServer instrumentationServer;
/**
- * The embedded library URI resolver provider used to override the way
- * embedded library URI's are resolved in some contexts.
+ * The file resolver provider used to override the way file URI's are
+ * resolved in some contexts.
*/
- EmbeddedResolverProvider embeddedUriResolverProvider;
+ ResolverProvider fileResolverProvider;
/**
* The package resolver provider used to override the way package URI's are
@@ -446,7 +445,7 @@
defaultSdk,
service,
serverPlugin,
- embeddedUriResolverProvider,
+ fileResolverProvider,
packageResolverProvider,
useSingleContextManager);
httpServer = new HttpAnalysisServer(socketServer);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/optype.dart b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
index 995ec27..917542c 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
@@ -556,7 +556,7 @@
if (node.parent is VariableDeclaration) {
VariableDeclaration varDeclaration =
node.parent as VariableDeclaration;
- localTypeAssertion = varDeclaration.element.type;
+ localTypeAssertion = varDeclaration.element?.type;
} else if (node.parent is AssignmentExpression) {
AssignmentExpression assignmentExpression =
node.parent as AssignmentExpression;
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index 1da32a1..380f3a8 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -11,7 +11,6 @@
import 'package:analysis_server/src/services/index/index.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/pub_package_map_provider.dart';
import 'package:analyzer/src/generated/sdk.dart';
@@ -35,7 +34,7 @@
final DirectoryBasedDartSdk defaultSdk;
final InstrumentationService instrumentationService;
final ServerPlugin serverPlugin;
- final EmbeddedResolverProvider embeddedResolverProvider;
+ final ResolverProvider fileResolverProvider;
final ResolverProvider packageResolverProvider;
final bool useSingleContextManager;
@@ -56,7 +55,7 @@
this.defaultSdk,
this.instrumentationService,
this.serverPlugin,
- this.embeddedResolverProvider,
+ this.fileResolverProvider,
this.packageResolverProvider,
this.useSingleContextManager);
@@ -100,7 +99,7 @@
analysisServerOptions,
defaultSdkCreator,
instrumentationService,
- embeddedResolverProvider: embeddedResolverProvider,
+ fileResolverProvider: fileResolverProvider,
packageResolverProvider: packageResolverProvider,
useSingleContextManager: useSingleContextManager,
rethrowExceptions: false);
diff --git a/pkg/analysis_server/lib/starter.dart b/pkg/analysis_server/lib/starter.dart
index bb2f0f6..be8aba7 100644
--- a/pkg/analysis_server/lib/starter.dart
+++ b/pkg/analysis_server/lib/starter.dart
@@ -6,7 +6,6 @@
import 'package:analysis_server/src/server/driver.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:plugin/plugin.dart';
@@ -23,19 +22,18 @@
factory ServerStarter() = Driver;
/**
- * Set the embedded resolver provider used to override the way embedded
- * library URI's are resolved in some contexts. The provider should return
- * `null` if the embedded library URI resolution scheme should be used
- * instead.
- */
- void set embeddedUriResolverProvider(EmbeddedResolverProvider provider);
-
- /**
* Set the instrumentation [server] that is to be used by the analysis server.
*/
void set instrumentationServer(InstrumentationServer server);
/**
+ * Set the file resolver provider used to override the way file URI's
+ * are resolved in some contexts. The provider should return `null` if the
+ * default file resolution scheme should be used instead.
+ */
+ void set fileResolverProvider(ResolverProvider provider);
+
+ /**
* Set the package resolver provider used to override the way package URI's
* are resolved in some contexts. The provider should return `null` if the
* default package resolution scheme should be used instead.
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index db85fcd..b6643de 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -9,6 +9,7 @@
import 'package:analysis_server/src/context_manager.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/source/embedder.dart';
import 'package:analyzer/source/error_processor.dart';
@@ -1738,8 +1739,6 @@
UriResolver packageResolver = null;
- UriResolver embeddedUriResolver = null;
-
String projPath = '/my/proj';
AnalysisError missing_required_param = new AnalysisError(
@@ -1815,9 +1814,6 @@
manager.processPlugins(plugins);
}
- EmbedderUriResolver provideEmbeddedUriResolver(Folder folder) =>
- embeddedUriResolver;
-
UriResolver providePackageResolver(Folder folder) => packageResolver;
void setUp() {
@@ -1831,7 +1827,6 @@
resourceProvider,
sdkManager,
providePackageResolver,
- provideEmbeddedUriResolver,
packageMapProvider,
analysisFilesGlobs,
InstrumentationService.NULL_SERVICE,
@@ -2653,21 +2648,19 @@
currentContextFilePaths[path] = <String, int>{};
currentContextSources[path] = new HashSet<Source>();
currentContext = AnalysisEngine.instance.createAnalysisContext();
- _locateEmbedderYamls(currentContext, disposition);
List<UriResolver> resolvers = [];
if (currentContext is InternalAnalysisContext) {
EmbedderYamlLocator embedderYamlLocator =
- (currentContext as InternalAnalysisContext).embedderYamlLocator;
- EmbedderUriResolver embedderUriResolver =
- new EmbedderUriResolver(embedderYamlLocator.embedderYamls);
- if (embedderUriResolver.length > 0) {
+ disposition.getEmbedderLocator(resourceProvider);
+ EmbedderSdk sdk = new EmbedderSdk(embedderYamlLocator.embedderYamls);
+ if (sdk.libraryMap.size() > 0) {
// We have some embedder dart: uri mappings, add the resolver
// to the list.
- resolvers.add(embedderUriResolver);
+ resolvers.add(new DartUriResolver(sdk));
}
}
resolvers.addAll(disposition.createPackageUriResolvers(resourceProvider));
- resolvers.add(new FileUriResolver());
+ resolvers.add(new ResourceUriResolver(PhysicalResourceProvider.INSTANCE));
currentContext.analysisOptions = options;
currentContext.sourceFactory =
new SourceFactory(resolvers, disposition.packages);
@@ -2740,19 +2733,6 @@
void updateContextPackageUriResolver(AnalysisContext context) {
// Nothing to do.
}
-
- /// If [disposition] has a package map, attempt to locate `_embedder.yaml`
- /// files.
- void _locateEmbedderYamls(
- InternalAnalysisContext context, FolderDisposition disposition) {
- Map<String, List<Folder>> packageMap;
- if (disposition is PackageMapDisposition) {
- packageMap = disposition.packageMap;
- } else if (disposition is PackagesFileDisposition) {
- packageMap = disposition.buildPackageMap(resourceProvider);
- }
- context.embedderYamlLocator.refresh(packageMap);
- }
}
/**
diff --git a/pkg/analysis_server/test/integration/integration_test_methods.dart b/pkg/analysis_server/test/integration/integration_test_methods.dart
index 2508d56..1fbdd7e 100644
--- a/pkg/analysis_server/test/integration/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/integration_test_methods.dart
@@ -94,6 +94,10 @@
* version ( String )
*
* The version number of the analysis server.
+ *
+ * pid ( int )
+ *
+ * The process id of the analysis server process.
*/
Stream<ServerConnectedParams> onServerConnected;
diff --git a/pkg/analysis_server/test/integration/protocol_matchers.dart b/pkg/analysis_server/test/integration/protocol_matchers.dart
index 487d6a7..1443aa0 100644
--- a/pkg/analysis_server/test/integration/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/protocol_matchers.dart
@@ -65,11 +65,13 @@
*
* {
* "version": String
+ * "pid": int
* }
*/
final Matcher isServerConnectedParams = new LazyMatcher(() => new MatchesJsonObject(
"server.connected params", {
- "version": isString
+ "version": isString,
+ "pid": isInt
}));
/**
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 644a1a9..7aa782a 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -6,7 +6,7 @@
</head>
<body>
<h1>Analysis Server API Specification</h1>
- <h1 style="color:#999999">Version <version>1.15.0</version></h1>
+ <h1 style="color:#999999">Version <version>1.16.0</version></h1>
<p>
This document contains a specification of the API provided by the
analysis server. The API in this document is currently under
@@ -239,6 +239,10 @@
<ref>String</ref>
<p>The version number of the analysis server.</p>
</field>
+ <field name="pid">
+ <ref>int</ref>
+ <p>The process id of the analysis server process.</p>
+ </field>
</params>
</notification>
<notification event="error">
diff --git a/pkg/analyzer/benchmark/errors_in_all_libraries.dart b/pkg/analyzer/benchmark/errors_in_all_libraries.dart
index 0d68c2f..6f02534 100644
--- a/pkg/analyzer/benchmark/errors_in_all_libraries.dart
+++ b/pkg/analyzer/benchmark/errors_in_all_libraries.dart
@@ -15,6 +15,8 @@
import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:path/path.dart' as p;
void main(List<String> args) {
@@ -36,7 +38,7 @@
var context = AnalysisEngine.instance.createAnalysisContext();
context.sourceFactory = new SourceFactory([
new DartUriResolver(DirectoryBasedDartSdk.defaultSdk),
- new FileUriResolver(),
+ new ResourceUriResolver(PhysicalResourceProvider.INSTANCE),
new PackageUriResolver([new JavaFile(packageRoot)])
]);
diff --git a/pkg/analyzer/example/resolver_driver.dart b/pkg/analyzer/example/resolver_driver.dart
index 3ba20f7..885a5225 100755
--- a/pkg/analyzer/example/resolver_driver.dart
+++ b/pkg/analyzer/example/resolver_driver.dart
@@ -14,6 +14,8 @@
import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/file_system/file_system.dart' hide File;
+import 'package:analyzer/file_system/physical_file_system.dart';
void main(List<String> args) {
print('working dir ${new File('.').resolveSymbolicLinksSync()}');
@@ -31,7 +33,10 @@
JavaSystemIO.setProperty("com.google.dart.sdk", args[0]);
DartSdk sdk = DirectoryBasedDartSdk.defaultSdk;
- var resolvers = [new DartUriResolver(sdk), new FileUriResolver()];
+ var resolvers = [
+ new DartUriResolver(sdk),
+ new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)
+ ];
if (packageRoot != null) {
var packageDirectory = new JavaFile(packageRoot);
diff --git a/pkg/analyzer/lib/analyzer.dart b/pkg/analyzer/lib/analyzer.dart
index c4642e8..59fea17 100644
--- a/pkg/analyzer/lib/analyzer.dart
+++ b/pkg/analyzer/lib/analyzer.dart
@@ -14,6 +14,8 @@
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/string_source.dart';
+import 'package:analyzer/file_system/file_system.dart' hide File;
+import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:path/path.dart' as pathos;
export 'package:analyzer/dart/ast/ast.dart';
@@ -50,7 +52,8 @@
CompilationUnit parseDartFile(String path,
{bool suppressErrors: false, bool parseFunctionBodies: true}) {
String contents = new File(path).readAsStringSync();
- var sourceFactory = new SourceFactory([new FileUriResolver()]);
+ var sourceFactory = new SourceFactory(
+ [new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)]);
var absolutePath = pathos.absolute(path);
var source = sourceFactory.forUri(pathos.toUri(absolutePath).toString());
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index 0acbc14..7a12c6f1c 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -219,7 +219,7 @@
/**
* The name of the `file` scheme.
*/
- static String _FILE_SCHEME = "file";
+ static final String FILE_SCHEME = "file";
final ResourceProvider _provider;
@@ -227,7 +227,7 @@
@override
Source resolveAbsolute(Uri uri, [Uri actualUri]) {
- if (!_isFileUri(uri)) {
+ if (!isFileUri(uri)) {
return null;
}
Resource resource =
@@ -242,8 +242,10 @@
Uri restoreAbsolute(Source source) =>
_provider.pathContext.toUri(source.fullName);
+ ResourceProvider get provider => _provider;
+
/**
* Return `true` if the given [uri] is a `file` URI.
*/
- static bool _isFileUri(Uri uri) => uri.scheme == _FILE_SCHEME;
+ static bool isFileUri(Uri uri) => uri.scheme == FILE_SCHEME;
}
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 789095c..3391433 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -451,7 +451,7 @@
return UriKind.PACKAGE_URI;
} else if (scheme == DartUriResolver.DART_SCHEME) {
return UriKind.DART_URI;
- } else if (scheme == FileUriResolver.FILE_SCHEME) {
+ } else if (scheme == ResourceUriResolver.FILE_SCHEME) {
return UriKind.FILE_URI;
}
return UriKind.FILE_URI;
diff --git a/pkg/analyzer/lib/plugin/embedded_resolver_provider.dart b/pkg/analyzer/lib/plugin/embedded_resolver_provider.dart
index b248e34..217ab7f 100644
--- a/pkg/analyzer/lib/plugin/embedded_resolver_provider.dart
+++ b/pkg/analyzer/lib/plugin/embedded_resolver_provider.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+@deprecated
library analyzer.plugin.embedded_resolver_provider;
import 'package:analyzer/file_system/file_system.dart';
@@ -12,4 +13,5 @@
* URI's for embedded libraries within a given folder, or `null` if we should
* fall back to the standard URI resolver.
*/
+@deprecated
typedef EmbedderUriResolver EmbeddedResolverProvider(Folder folder);
diff --git a/pkg/analyzer/lib/source/embedder.dart b/pkg/analyzer/lib/source/embedder.dart
index 1b43e00..56abc6a 100644
--- a/pkg/analyzer/lib/source/embedder.dart
+++ b/pkg/analyzer/lib/source/embedder.dart
@@ -10,14 +10,13 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/package_map_provider.dart'
show PackageMapProvider;
-import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/java_io.dart' show JavaFile;
import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/sdk_io.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart' show FileBasedSource;
+import 'package:analyzer/src/summary/idl.dart';
import 'package:yaml/yaml.dart';
const String _DART_COLON_PREFIX = 'dart:';
@@ -27,104 +26,28 @@
bool definesEmbeddedLibs(Map map) => map[_EMBEDDED_LIB_MAP_KEY] != null;
/// An SDK backed by URI mappings derived from an `_embedder.yaml` file.
-class EmbedderSdk implements DartSdk {
- /// The resolver associated with this SDK.
- EmbedderUriResolver _resolver;
-
- /// The [AnalysisContext] used for this SDK's sources.
- InternalAnalysisContext _analysisContext;
-
- final LibraryMap _librariesMap = new LibraryMap();
-
+class EmbedderSdk extends AbstractDartSdk {
final Map<String, String> _urlMappings = new HashMap<String, String>();
- /// Analysis options for this SDK.
- AnalysisOptions analysisOptions;
-
EmbedderSdk([Map<Folder, YamlMap> embedderYamls]) {
embedderYamls?.forEach(_processEmbedderYaml);
- _resolver = new EmbedderUriResolver._forSdk(this);
}
- @override
- AnalysisContext get context {
- if (_analysisContext == null) {
- _analysisContext = new SdkAnalysisContext(analysisOptions);
- SourceFactory factory = new SourceFactory([_resolver]);
- _analysisContext.sourceFactory = factory;
-
- ChangeSet changeSet = new ChangeSet();
- for (String uri in uris) {
- changeSet.addedSource(factory.forUri(uri));
- }
- _analysisContext.applyChanges(changeSet);
- }
- return _analysisContext;
- }
-
- @override
- List<SdkLibrary> get sdkLibraries => _librariesMap.sdkLibraries;
-
// TODO(danrubel) Determine SDK version
@override
String get sdkVersion => '0';
- @override
- List<String> get uris => _librariesMap.uris;
-
/// The url mappings for this SDK.
Map<String, String> get urlMappings => _urlMappings;
@override
- Source fromFileUri(Uri uri) {
- JavaFile file = new JavaFile.fromUri(uri);
- String filePath = file.getAbsolutePath();
-
- String path;
- for (SdkLibrary library in _librariesMap.sdkLibraries) {
- String libraryPath = library.path.replaceAll('/', JavaFile.separator);
- if (filePath == libraryPath) {
- path = library.shortName;
- break;
- }
- }
- if (path == null) {
- for (SdkLibrary library in _librariesMap.sdkLibraries) {
- String libraryPath = library.path.replaceAll('/', JavaFile.separator);
- int index = libraryPath.lastIndexOf(JavaFile.separator);
- if (index == -1) {
- continue;
- }
- String prefix = libraryPath.substring(0, index + 1);
- if (!filePath.startsWith(prefix)) {
- continue;
- }
- var relPath = filePath
- .substring(prefix.length)
- .replaceAll(JavaFile.separator, '/');
- path = '${library.shortName}/$relPath';
- break;
- }
- }
-
- if (path != null) {
- try {
- return new FileBasedSource(file, parseUriWithException(path));
- } on URISyntaxException catch (exception, stackTrace) {
- AnalysisEngine.instance.logger.logInformation(
- "Failed to create URI: $path",
- new CaughtException(exception, stackTrace));
- return null;
- }
- }
- return null;
- }
+ String getRelativePathFromFile(JavaFile file) => file.getAbsolutePath();
@override
- SdkLibrary getSdkLibrary(String dartUri) => _librariesMap.getLibrary(dartUri);
+ PackageBundle getSummarySdkBundle(bool strongMode) => null;
@override
- Source mapDartUri(String dartUri) {
+ FileBasedSource internalMapDartUri(String dartUri) {
String libraryName;
String relativePath;
int index = dartUri.indexOf('/');
@@ -173,7 +96,7 @@
_urlMappings[name] = libPath;
SdkLibraryImpl library = new SdkLibraryImpl(name);
library.path = libPath;
- _librariesMap.setLibrary(name, library);
+ libraryMap.setLibrary(name, library);
}
/// Given the 'embedderYamls' from [EmbedderYamlLocator] check each one for the
@@ -205,14 +128,27 @@
///
/// If a key doesn't begin with `dart:` it is ignored.
///
+/// This class is deprecated; use DartUriResolver directly. In particular, if
+/// there used to be an instance creation of the form:
+///
+/// ```
+/// new EmbedderUriResolver(embedderMap)
+/// ```
+///
+/// This should be replaced by
+///
+/// ```
+/// new DartUriResolver(new EmbedderSdk(embedderMap))
+/// ```
+@deprecated
class EmbedderUriResolver implements DartUriResolver {
EmbedderSdk _embedderSdk;
DartUriResolver _dartUriResolver;
/// Construct a [EmbedderUriResolver] from a package map
/// (see [PackageMapProvider]).
- EmbedderUriResolver(Map<Folder, YamlMap> embedderMap) :
- this._forSdk(new EmbedderSdk(embedderMap));
+ EmbedderUriResolver(Map<Folder, YamlMap> embedderMap)
+ : this._forSdk(new EmbedderSdk(embedderMap));
/// (Provisional API.)
EmbedderUriResolver._forSdk(this._embedderSdk) {
@@ -251,7 +187,7 @@
EmbedderYamlLocator(Map<String, List<Folder>> packageMap) {
if (packageMap != null) {
- refresh(packageMap);
+ _processPackageMap(packageMap);
}
}
@@ -263,10 +199,9 @@
void refresh(Map<String, List<Folder>> packageMap) {
// Clear existing.
embedderYamls.clear();
- if (packageMap == null) {
- return;
+ if (packageMap != null) {
+ _processPackageMap(packageMap);
}
- packageMap.forEach(_processPackage);
}
/// Given the yaml for an embedder ([embedderYaml]) and a folder
@@ -295,6 +230,10 @@
}
}
+ void _processPackageMap(Map<String, List<Folder>> packageMap) {
+ packageMap.forEach(_processPackage);
+ }
+
/// Read the contents of [libDir]/[EMBEDDER_FILE_NAME] as a string.
/// Returns null if the file doesn't exist.
String _readEmbedderYaml(Folder libDir) {
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 1cc85bc..dd0e0ee 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -11,6 +11,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/plugin/task.dart';
import 'package:analyzer/source/embedder.dart';
import 'package:analyzer/src/cancelable_future.dart';
@@ -80,7 +81,10 @@
*/
AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
- /// The embedder yaml locator for this context.
+ /**
+ * The embedder yaml locator for this context.
+ */
+ @deprecated
EmbedderYamlLocator _embedderYamlLocator = new EmbedderYamlLocator(null);
/**
@@ -225,6 +229,9 @@
*/
CompilationUnit incrementalResolutionValidation_lastUnit;
+ @override
+ ResolverProvider fileResolverProvider;
+
/**
* Initialize a newly created analysis context.
*/
@@ -341,6 +348,7 @@
@override
DeclaredVariables get declaredVariables => _declaredVariables;
+ @deprecated
@override
EmbedderYamlLocator get embedderYamlLocator => _embedderYamlLocator;
@@ -1885,6 +1893,9 @@
dartDelta.hasDirectiveChange = unitDelta.hasDirectiveChange;
unitDelta.addedDeclarations.forEach(dartDelta.elementAdded);
unitDelta.removedDeclarations.forEach(dartDelta.elementRemoved);
+ for (ClassElementDelta classDelta in unitDelta.classDeltas) {
+ dartDelta.elementChanged(classDelta.element);
+ }
// print(
// 'dartDelta: add=${dartDelta.addedNames} remove=${dartDelta.removedNames}');
delta = dartDelta;
diff --git a/pkg/analyzer/lib/src/dart/ast/token.dart b/pkg/analyzer/lib/src/dart/ast/token.dart
index 9828113..baae1b8 100644
--- a/pkg/analyzer/lib/src/dart/ast/token.dart
+++ b/pkg/analyzer/lib/src/dart/ast/token.dart
@@ -569,5 +569,6 @@
}
@override
- Token copy() => new TokenWithComment(type, offset, precedingComments);
+ Token copy() =>
+ new TokenWithComment(type, offset, copyComments(precedingComments));
}
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index e3e379f..e2867a3 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -994,6 +994,37 @@
AstNode _other;
/**
+ * Notify that [first] and second have different length.
+ * This implementation returns `false`. Subclasses can override and throw.
+ */
+ bool failDifferentLength(List first, List second) {
+ return false;
+ }
+
+ /**
+ * Check whether [second] is null. Subclasses can override to throw.
+ */
+ bool failIfNotNull(Object first, Object second) {
+ return second == null;
+ }
+
+ /**
+ * Notify that [first] is not `null` while [second] one is `null`.
+ * This implementation returns `false`. Subclasses can override and throw.
+ */
+ bool failIsNull(Object first, Object second) {
+ return false;
+ }
+
+ /**
+ * Notify that [first] and [second] have different types.
+ * This implementation returns `false`. Subclasses can override and throw.
+ */
+ bool failRuntimeType(Object first, Object second) {
+ return false;
+ }
+
+ /**
* Return `true` if the [first] node and the [second] node have the same
* structure.
*
@@ -1002,11 +1033,11 @@
*/
bool isEqualNodes(AstNode first, AstNode second) {
if (first == null) {
- return second == null;
+ return failIfNotNull(first, second);
} else if (second == null) {
- return false;
+ return failIsNull(first, second);
} else if (first.runtimeType != second.runtimeType) {
- return false;
+ return failRuntimeType(first, second);
}
_other = second;
return first.accept(this);
@@ -1021,17 +1052,24 @@
*/
bool isEqualTokens(Token first, Token second) {
if (first == null) {
- return second == null;
+ return failIfNotNull(first, second);
} else if (second == null) {
- return false;
+ return failIsNull(first, second);
} else if (identical(first, second)) {
return true;
}
- return first.offset == second.offset &&
- first.length == second.length &&
- first.lexeme == second.lexeme;
+ return isEqualTokensNotNull(first, second);
}
+ /**
+ * Return `true` if the [first] token and the [second] token have the same
+ * structure. Both [first] and [second] are not `null`.
+ */
+ bool isEqualTokensNotNull(Token first, Token second) =>
+ first.offset == second.offset &&
+ first.length == second.length &&
+ first.lexeme == second.lexeme;
+
@override
bool visitAdjacentStrings(AdjacentStrings node) {
AdjacentStrings other = _other as AdjacentStrings;
@@ -2016,13 +2054,13 @@
*/
bool _isEqualNodeLists(NodeList first, NodeList second) {
if (first == null) {
- return second == null;
+ return failIfNotNull(first, second);
} else if (second == null) {
- return false;
+ return failIsNull(first, second);
}
int size = first.length;
if (second.length != size) {
- return false;
+ return failDifferentLength(first, second);
}
for (int i = 0; i < size; i++) {
if (!isEqualNodes(first[i], second[i])) {
@@ -2039,7 +2077,7 @@
bool _isEqualTokenLists(List<Token> first, List<Token> second) {
int length = first.length;
if (second.length != length) {
- return false;
+ return failDifferentLength(first, second);
}
for (int i = 0; i < length; i++) {
if (!isEqualTokens(first[i], second[i])) {
diff --git a/pkg/analyzer/lib/src/generated/bazel.dart b/pkg/analyzer/lib/src/generated/bazel.dart
new file mode 100644
index 0000000..8198f46
--- /dev/null
+++ b/pkg/analyzer/lib/src/generated/bazel.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.src.generated.bazel;
+
+import 'dart:core' hide Resource;
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+
+/**
+ * Instances of the class `BazelFileUriResolver` resolve `file` URI's by first
+ * resolving file uri's in the expected way, and then by looking in the
+ * corresponding generated directories.
+ */
+class BazelFileUriResolver extends ResourceUriResolver {
+ /**
+ * The Bazel workspace directory.
+ */
+ final Folder _workspaceDir;
+
+ /**
+ * The build directories that relative `file` URI's should use to resolve
+ * relative URIs.
+ */
+ final List<Folder> _buildDirectories;
+
+ BazelFileUriResolver(
+ ResourceProvider provider, this._workspaceDir, this._buildDirectories)
+ : super(provider);
+
+ @override
+ Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+ if (!ResourceUriResolver.isFileUri(uri)) {
+ return null;
+ }
+
+ File uriFile = provider.getFile(provider.pathContext.fromUri(uri));
+ if (uriFile.exists) {
+ return uriFile.createSource(actualUri ?? uri);
+ }
+
+ String relativeFromWorkspaceDir = _getPathFromWorkspaceDir(uri);
+ if (_buildDirectories.isEmpty || relativeFromWorkspaceDir.isEmpty) {
+ return null;
+ }
+
+ for (Folder buildDir in _buildDirectories) {
+ File file = buildDir.getChildAssumingFile(relativeFromWorkspaceDir);
+ if (file.exists) {
+ return file.createSource(actualUri ?? uri);
+ }
+ }
+ return null;
+ }
+
+ String _getPathFromWorkspaceDir(Uri uri) {
+ String uriPath = uri.path;
+ String workspacePath = _workspaceDir.path;
+
+ if (uriPath.startsWith(workspacePath) &&
+ workspacePath.length < uriPath.length) {
+ return uriPath.substring(workspacePath.length + 1);
+ }
+ return '';
+ }
+}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 61816ab..4e67792 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -11,6 +11,7 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/embedder.dart';
import 'package:analyzer/src/cancelable_future.dart';
import 'package:analyzer/src/context/cache.dart';
@@ -332,6 +333,12 @@
bool exists(Source source);
/**
+ * The file resolver provider used to override the way file URI's are
+ * resolved in some contexts.
+ */
+ ResolverProvider fileResolverProvider;
+
+ /**
* Return the element model corresponding to the compilation unit defined by
* the given [unitSource] in the library defined by the given [librarySource],
* or `null` if the element model does not currently exist or if the library
@@ -1965,7 +1972,10 @@
*/
set contentCache(ContentCache value);
- /// Get the [EmbedderYamlLocator] for this context.
+ /**
+ * Get the [EmbedderYamlLocator] for this context.
+ */
+ @deprecated
EmbedderYamlLocator get embedderYamlLocator;
/**
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart b/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
index 67885d1..518d6f6 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
@@ -5,8 +5,10 @@
library analyzer.src.generated.incremental_resolution_validator;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
@@ -16,9 +18,8 @@
*/
void assertSameResolution(CompilationUnit actual, CompilationUnit expected,
{bool validateTypes: false}) {
- _SameResolutionValidator validator =
- new _SameResolutionValidator(validateTypes, expected);
- actual.accept(validator);
+ _SameResolutionValidator validator = new _SameResolutionValidator(validateTypes);
+ validator.isEqualNodes(expected, actual);
}
/**
@@ -33,808 +34,91 @@
String toString() => "IncrementalResolutionMismatch: $message";
}
-class _SameResolutionValidator implements AstVisitor {
+/**
+ * An [AstVisitor] that compares the structure of two [AstNode]s and their
+ * resolution to see whether they are equal.
+ */
+class _SameResolutionValidator extends AstComparator {
final bool validateTypes;
- /// The expected node to compare with the visited node.
- AstNode other;
-
- _SameResolutionValidator(this.validateTypes, this.other);
+ _SameResolutionValidator(this.validateTypes);
@override
- visitAdjacentStrings(AdjacentStrings node) {}
-
- @override
- visitAnnotation(Annotation node) {
- Annotation other = this.other;
- _visitNode(node.name, other.name);
- _visitNode(node.constructorName, other.constructorName);
- _visitNode(node.arguments, other.arguments);
- _verifyElement(node.element, other.element);
- }
-
- @override
- visitArgumentList(ArgumentList node) {
- ArgumentList other = this.other;
- _visitList(node.arguments, other.arguments);
- }
-
- @override
- visitAsExpression(AsExpression node) {
- AsExpression other = this.other;
- _visitExpression(node, other);
- _visitNode(node.expression, other.expression);
- _visitNode(node.type, other.type);
- }
-
- @override
- visitAssertStatement(AssertStatement node) {
- AssertStatement other = this.other;
- _visitNode(node.condition, other.condition);
- _visitNode(node.message, other.message);
- }
-
- @override
- visitAssignmentExpression(AssignmentExpression node) {
- AssignmentExpression other = this.other;
- _visitExpression(node, other);
- _verifyElement(node.staticElement, other.staticElement);
- _verifyElement(node.propagatedElement, other.propagatedElement);
- _visitNode(node.leftHandSide, other.leftHandSide);
- _visitNode(node.rightHandSide, other.rightHandSide);
- }
-
- @override
- visitAwaitExpression(AwaitExpression node) {
- AwaitExpression other = this.other;
- _visitExpression(node, other);
- _visitNode(node.expression, other.expression);
- }
-
- @override
- visitBinaryExpression(BinaryExpression node) {
- BinaryExpression other = this.other;
- _visitExpression(node, other);
- _verifyElement(node.staticElement, other.staticElement);
- _verifyElement(node.propagatedElement, other.propagatedElement);
- _visitNode(node.leftOperand, other.leftOperand);
- _visitNode(node.rightOperand, other.rightOperand);
- }
-
- @override
- visitBlock(Block node) {
- Block other = this.other;
- _visitList(node.statements, other.statements);
- }
-
- @override
- visitBlockFunctionBody(BlockFunctionBody node) {
- BlockFunctionBody other = this.other;
- _visitNode(node.block, other.block);
- }
-
- @override
- visitBooleanLiteral(BooleanLiteral node) {
- BooleanLiteral other = this.other;
- _visitExpression(node, other);
- }
-
- @override
- visitBreakStatement(BreakStatement node) {
- BreakStatement other = this.other;
- _visitNode(node.label, other.label);
- }
-
- @override
- visitCascadeExpression(CascadeExpression node) {
- CascadeExpression other = this.other;
- _visitExpression(node, other);
- _visitNode(node.target, other.target);
- _visitList(node.cascadeSections, other.cascadeSections);
- }
-
- @override
- visitCatchClause(CatchClause node) {
- CatchClause other = this.other;
- _visitNode(node.exceptionType, other.exceptionType);
- _visitNode(node.exceptionParameter, other.exceptionParameter);
- _visitNode(node.stackTraceParameter, other.stackTraceParameter);
- _visitNode(node.body, other.body);
- }
-
- @override
- visitClassDeclaration(ClassDeclaration node) {
- ClassDeclaration other = this.other;
- _visitDeclaration(node, other);
- _visitNode(node.name, other.name);
- _visitNode(node.typeParameters, other.typeParameters);
- _visitNode(node.extendsClause, other.extendsClause);
- _visitNode(node.implementsClause, other.implementsClause);
- _visitNode(node.withClause, other.withClause);
- _visitList(node.members, other.members);
- }
-
- @override
- visitClassTypeAlias(ClassTypeAlias node) {
- ClassTypeAlias other = this.other;
- _visitDeclaration(node, other);
- _visitNode(node.name, other.name);
- _visitNode(node.typeParameters, other.typeParameters);
- _visitNode(node.superclass, other.superclass);
- _visitNode(node.withClause, other.withClause);
- }
-
- @override
- visitComment(Comment node) {
- Comment other = this.other;
- _visitList(node.references, other.references);
- }
-
- @override
- visitCommentReference(CommentReference node) {
- CommentReference other = this.other;
- _visitNode(node.identifier, other.identifier);
- }
-
- @override
- visitCompilationUnit(CompilationUnit node) {
- CompilationUnit other = this.other;
- _verifyElement(node.element, other.element);
- _visitList(node.directives, other.directives);
- _visitList(node.declarations, other.declarations);
- }
-
- @override
- visitConditionalExpression(ConditionalExpression node) {
- ConditionalExpression other = this.other;
- _visitExpression(node, other);
- _visitNode(node.condition, other.condition);
- _visitNode(node.thenExpression, other.thenExpression);
- _visitNode(node.elseExpression, other.elseExpression);
- }
-
- @override
- visitConfiguration(Configuration node) {
- Configuration other = this.other;
- _visitNode(node.name, other.name);
- _visitNode(node.value, other.value);
- _visitNode(node.libraryUri, other.libraryUri);
- }
-
- @override
- visitConstructorDeclaration(ConstructorDeclaration node) {
- ConstructorDeclaration other = this.other;
- _visitDeclaration(node, other);
- _visitNode(node.returnType, other.returnType);
- _visitNode(node.name, other.name);
- _visitNode(node.parameters, other.parameters);
- _visitNode(node.redirectedConstructor, other.redirectedConstructor);
- _visitList(node.initializers, other.initializers);
- }
-
- @override
- visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
- ConstructorFieldInitializer other = this.other;
- _visitNode(node.fieldName, other.fieldName);
- _visitNode(node.expression, other.expression);
- }
-
- @override
- visitConstructorName(ConstructorName node) {
- ConstructorName other = this.other;
- _verifyElement(node.staticElement, other.staticElement);
- _visitNode(node.type, other.type);
- _visitNode(node.name, other.name);
- }
-
- @override
- visitContinueStatement(ContinueStatement node) {
- ContinueStatement other = this.other;
- _visitNode(node.label, other.label);
- }
-
- @override
- visitDeclaredIdentifier(DeclaredIdentifier node) {
- DeclaredIdentifier other = this.other;
- _visitNode(node.type, other.type);
- _visitNode(node.identifier, other.identifier);
- }
-
- @override
- visitDefaultFormalParameter(DefaultFormalParameter node) {
- DefaultFormalParameter other = this.other;
- _visitNode(node.parameter, other.parameter);
- _visitNode(node.defaultValue, other.defaultValue);
- }
-
- @override
- visitDoStatement(DoStatement node) {
- DoStatement other = this.other;
- _visitNode(node.condition, other.condition);
- _visitNode(node.body, other.body);
- }
-
- @override
- visitDottedName(DottedName node) {
- DottedName other = this.other;
- _visitList(node.components, other.components);
- }
-
- @override
- visitDoubleLiteral(DoubleLiteral node) {
- DoubleLiteral other = this.other;
- _visitExpression(node, other);
- }
-
- @override
- visitEmptyFunctionBody(EmptyFunctionBody node) {}
-
- @override
- visitEmptyStatement(EmptyStatement node) {}
-
- @override
- visitEnumConstantDeclaration(EnumConstantDeclaration node) {
- EnumConstantDeclaration other = this.other;
- _visitDeclaration(node, other);
- _visitNode(node.name, other.name);
- }
-
- @override
- visitEnumDeclaration(EnumDeclaration node) {
- EnumDeclaration other = this.other;
- _visitDeclaration(node, other);
- _visitNode(node.name, other.name);
- _visitList(node.constants, other.constants);
- }
-
- @override
- visitExportDirective(ExportDirective node) {
- ExportDirective other = this.other;
- _visitDirective(node, other);
- }
-
- @override
- visitExpressionFunctionBody(ExpressionFunctionBody node) {
- ExpressionFunctionBody other = this.other;
- _visitNode(node.expression, other.expression);
- }
-
- @override
- visitExpressionStatement(ExpressionStatement node) {
- ExpressionStatement other = this.other;
- _visitNode(node.expression, other.expression);
- }
-
- @override
- visitExtendsClause(ExtendsClause node) {
- ExtendsClause other = this.other;
- _visitNode(node.superclass, other.superclass);
- }
-
- @override
- visitFieldDeclaration(FieldDeclaration node) {
- FieldDeclaration other = this.other;
- _visitDeclaration(node, other);
- _visitNode(node.fields, other.fields);
- }
-
- @override
- visitFieldFormalParameter(FieldFormalParameter node) {
- FieldFormalParameter other = this.other;
- _visitNormalFormalParameter(node, other);
- _visitNode(node.type, other.type);
- _visitNode(node.parameters, other.parameters);
- }
-
- @override
- visitForEachStatement(ForEachStatement node) {
- ForEachStatement other = this.other;
- _visitNode(node.identifier, other.identifier);
- _visitNode(node.loopVariable, other.loopVariable);
- _visitNode(node.iterable, other.iterable);
- }
-
- @override
- visitFormalParameterList(FormalParameterList node) {
- FormalParameterList other = this.other;
- _visitList(node.parameters, other.parameters);
- }
-
- @override
- visitForStatement(ForStatement node) {
- ForStatement other = this.other;
- _visitNode(node.variables, other.variables);
- _visitNode(node.initialization, other.initialization);
- _visitNode(node.condition, other.condition);
- _visitList(node.updaters, other.updaters);
- _visitNode(node.body, other.body);
- }
-
- @override
- visitFunctionDeclaration(FunctionDeclaration node) {
- FunctionDeclaration other = this.other;
- _visitDeclaration(node, other);
- _visitNode(node.returnType, other.returnType);
- _visitNode(node.name, other.name);
- _visitNode(node.functionExpression, other.functionExpression);
- }
-
- @override
- visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
- FunctionDeclarationStatement other = this.other;
- _visitNode(node.functionDeclaration, other.functionDeclaration);
- }
-
- @override
- visitFunctionExpression(FunctionExpression node) {
- FunctionExpression other = this.other;
- _visitExpression(node, other);
- _verifyElement(node.element, other.element);
- _visitNode(node.parameters, other.parameters);
- _visitNode(node.body, other.body);
- }
-
- @override
- visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
- FunctionExpressionInvocation other = this.other;
- _visitExpression(node, other);
- _verifyElement(node.staticElement, other.staticElement);
- _verifyElement(node.propagatedElement, other.propagatedElement);
- _visitNode(node.function, other.function);
- _visitNode(node.argumentList, other.argumentList);
- }
-
- @override
- visitFunctionTypeAlias(FunctionTypeAlias node) {
- FunctionTypeAlias other = this.other;
- _visitDeclaration(node, other);
- _visitNode(node.returnType, other.returnType);
- _visitNode(node.name, other.name);
- _visitNode(node.typeParameters, other.typeParameters);
- _visitNode(node.parameters, other.parameters);
- }
-
- @override
- visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
- FunctionTypedFormalParameter other = this.other;
- _visitNormalFormalParameter(node, other);
- _visitNode(node.returnType, other.returnType);
- _visitNode(node.parameters, other.parameters);
- }
-
- @override
- visitHideCombinator(HideCombinator node) {
- HideCombinator other = this.other;
- _visitList(node.hiddenNames, other.hiddenNames);
- }
-
- @override
- visitIfStatement(IfStatement node) {
- IfStatement other = this.other;
- _visitNode(node.condition, other.condition);
- _visitNode(node.thenStatement, other.thenStatement);
- _visitNode(node.elseStatement, other.elseStatement);
- }
-
- @override
- visitImplementsClause(ImplementsClause node) {
- ImplementsClause other = this.other;
- _visitList(node.interfaces, other.interfaces);
- }
-
- @override
- visitImportDirective(ImportDirective node) {
- ImportDirective other = this.other;
- _visitDirective(node, other);
- _visitNode(node.prefix, other.prefix);
- _verifyElement(node.uriElement, other.uriElement);
- }
-
- @override
- visitIndexExpression(IndexExpression node) {
- IndexExpression other = this.other;
- _visitExpression(node, other);
- _verifyElement(node.staticElement, other.staticElement);
- _verifyElement(node.propagatedElement, other.propagatedElement);
- _visitNode(node.target, other.target);
- _visitNode(node.index, other.index);
- }
-
- @override
- visitInstanceCreationExpression(InstanceCreationExpression node) {
- InstanceCreationExpression other = this.other;
- _visitExpression(node, other);
- _verifyElement(node.staticElement, other.staticElement);
- _visitNode(node.constructorName, other.constructorName);
- _visitNode(node.argumentList, other.argumentList);
- }
-
- @override
- visitIntegerLiteral(IntegerLiteral node) {
- IntegerLiteral other = this.other;
- _visitExpression(node, other);
- }
-
- @override
- visitInterpolationExpression(InterpolationExpression node) {
- InterpolationExpression other = this.other;
- _visitNode(node.expression, other.expression);
- }
-
- @override
- visitInterpolationString(InterpolationString node) {}
-
- @override
- visitIsExpression(IsExpression node) {
- IsExpression other = this.other;
- _visitExpression(node, other);
- _visitNode(node.expression, other.expression);
- _visitNode(node.type, other.type);
- }
-
- @override
- visitLabel(Label node) {
- Label other = this.other;
- _visitNode(node.label, other.label);
- }
-
- @override
- visitLabeledStatement(LabeledStatement node) {
- LabeledStatement other = this.other;
- _visitList(node.labels, other.labels);
- _visitNode(node.statement, other.statement);
- }
-
- @override
- visitLibraryDirective(LibraryDirective node) {
- LibraryDirective other = this.other;
- _visitDirective(node, other);
- _visitNode(node.name, other.name);
- }
-
- @override
- visitLibraryIdentifier(LibraryIdentifier node) {
- LibraryIdentifier other = this.other;
- _visitList(node.components, other.components);
- }
-
- @override
- visitListLiteral(ListLiteral node) {
- ListLiteral other = this.other;
- _visitExpression(node, other);
- _visitList(node.elements, other.elements);
- }
-
- @override
- visitMapLiteral(MapLiteral node) {
- MapLiteral other = this.other;
- _visitExpression(node, other);
- _visitList(node.entries, other.entries);
- }
-
- @override
- visitMapLiteralEntry(MapLiteralEntry node) {
- MapLiteralEntry other = this.other;
- _visitNode(node.key, other.key);
- _visitNode(node.value, other.value);
- }
-
- @override
- visitMethodDeclaration(MethodDeclaration node) {
- MethodDeclaration other = this.other;
- _visitDeclaration(node, other);
- _visitNode(node.name, other.name);
- _visitNode(node.parameters, other.parameters);
- _visitNode(node.body, other.body);
- }
-
- @override
- visitMethodInvocation(MethodInvocation node) {
- MethodInvocation other = this.other;
- _visitNode(node.target, other.target);
- _visitNode(node.methodName, other.methodName);
- _visitNode(node.argumentList, other.argumentList);
- }
-
- @override
- visitNamedExpression(NamedExpression node) {
- NamedExpression other = this.other;
- _visitNode(node.name, other.name);
- _visitNode(node.expression, other.expression);
- }
-
- @override
- visitNativeClause(NativeClause node) {}
-
- @override
- visitNativeFunctionBody(NativeFunctionBody node) {}
-
- @override
- visitNullLiteral(NullLiteral node) {
- NullLiteral other = this.other;
- _visitExpression(node, other);
- }
-
- @override
- visitParenthesizedExpression(ParenthesizedExpression node) {
- ParenthesizedExpression other = this.other;
- _visitNode(node.expression, other.expression);
- }
-
- @override
- visitPartDirective(PartDirective node) {
- PartDirective other = this.other;
- _visitDirective(node, other);
- }
-
- @override
- visitPartOfDirective(PartOfDirective node) {
- PartOfDirective other = this.other;
- _visitDirective(node, other);
- _visitNode(node.libraryName, other.libraryName);
- }
-
- @override
- visitPostfixExpression(PostfixExpression node) {
- PostfixExpression other = this.other;
- _visitExpression(node, other);
- _verifyElement(node.staticElement, other.staticElement);
- _verifyElement(node.propagatedElement, other.propagatedElement);
- _visitNode(node.operand, other.operand);
- }
-
- @override
- visitPrefixedIdentifier(PrefixedIdentifier node) {
- PrefixedIdentifier other = this.other;
- _visitExpression(node, other);
- _visitNode(node.prefix, other.prefix);
- _visitNode(node.identifier, other.identifier);
- }
-
- @override
- visitPrefixExpression(PrefixExpression node) {
- PrefixExpression other = this.other;
- _visitExpression(node, other);
- _verifyElement(node.staticElement, other.staticElement);
- _verifyElement(node.propagatedElement, other.propagatedElement);
- _visitNode(node.operand, other.operand);
- }
-
- @override
- visitPropertyAccess(PropertyAccess node) {
- PropertyAccess other = this.other;
- _visitExpression(node, other);
- _visitNode(node.target, other.target);
- _visitNode(node.propertyName, other.propertyName);
- }
-
- @override
- visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
- RedirectingConstructorInvocation other = this.other;
- _verifyElement(node.staticElement, other.staticElement);
- _visitNode(node.constructorName, other.constructorName);
- _visitNode(node.argumentList, other.argumentList);
- }
-
- @override
- visitRethrowExpression(RethrowExpression node) {
- RethrowExpression other = this.other;
- _visitExpression(node, other);
- }
-
- @override
- visitReturnStatement(ReturnStatement node) {
- ReturnStatement other = this.other;
- _visitNode(node.expression, other.expression);
- }
-
- @override
- visitScriptTag(ScriptTag node) {}
-
- @override
- visitShowCombinator(ShowCombinator node) {
- ShowCombinator other = this.other;
- _visitList(node.shownNames, other.shownNames);
- }
-
- @override
- visitSimpleFormalParameter(SimpleFormalParameter node) {
- SimpleFormalParameter other = this.other;
- _visitNormalFormalParameter(node, other);
- _visitNode(node.type, other.type);
- }
-
- @override
- visitSimpleIdentifier(SimpleIdentifier node) {
- SimpleIdentifier other = this.other;
- _verifyElement(node.staticElement, other.staticElement);
- _verifyElement(node.propagatedElement, other.propagatedElement);
- _visitExpression(node, other);
- }
-
- @override
- visitSimpleStringLiteral(SimpleStringLiteral node) {}
-
- @override
- visitStringInterpolation(StringInterpolation node) {
- StringInterpolation other = this.other;
- _visitList(node.elements, other.elements);
- }
-
- @override
- visitSuperConstructorInvocation(SuperConstructorInvocation node) {
- SuperConstructorInvocation other = this.other;
- _verifyElement(node.staticElement, other.staticElement);
- _visitNode(node.constructorName, other.constructorName);
- _visitNode(node.argumentList, other.argumentList);
- }
-
- @override
- visitSuperExpression(SuperExpression node) {
- SuperExpression other = this.other;
- _visitExpression(node, other);
- }
-
- @override
- visitSwitchCase(SwitchCase node) {
- SwitchCase other = this.other;
- _visitList(node.labels, other.labels);
- _visitNode(node.expression, other.expression);
- _visitList(node.statements, other.statements);
- }
-
- @override
- visitSwitchDefault(SwitchDefault node) {
- SwitchDefault other = this.other;
- _visitList(node.statements, other.statements);
- }
-
- @override
- visitSwitchStatement(SwitchStatement node) {
- SwitchStatement other = this.other;
- _visitNode(node.expression, other.expression);
- _visitList(node.members, other.members);
- }
-
- @override
- visitSymbolLiteral(SymbolLiteral node) {}
-
- @override
- visitThisExpression(ThisExpression node) {
- ThisExpression other = this.other;
- _visitExpression(node, other);
- }
-
- @override
- visitThrowExpression(ThrowExpression node) {
- ThrowExpression other = this.other;
- _visitNode(node.expression, other.expression);
- }
-
- @override
- visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- TopLevelVariableDeclaration other = this.other;
- _visitNode(node.variables, other.variables);
- }
-
- @override
- visitTryStatement(TryStatement node) {
- TryStatement other = this.other;
- _visitNode(node.body, other.body);
- _visitList(node.catchClauses, other.catchClauses);
- _visitNode(node.finallyBlock, other.finallyBlock);
- }
-
- @override
- visitTypeArgumentList(TypeArgumentList node) {
- TypeArgumentList other = this.other;
- _visitList(node.arguments, other.arguments);
- }
-
- @override
- visitTypeName(TypeName node) {
- TypeName other = this.other;
- _verifyType(node.type, other.type);
- _visitNode(node.name, node.name);
- _visitNode(node.typeArguments, other.typeArguments);
- }
-
- @override
- visitTypeParameter(TypeParameter node) {
- TypeParameter other = this.other;
- _visitNode(node.name, other.name);
- _visitNode(node.bound, other.bound);
- }
-
- @override
- visitTypeParameterList(TypeParameterList node) {
- TypeParameterList other = this.other;
- _visitList(node.typeParameters, other.typeParameters);
- }
-
- @override
- visitVariableDeclaration(VariableDeclaration node) {
- VariableDeclaration other = this.other;
- _visitDeclaration(node, other);
- _visitNode(node.name, other.name);
- _visitNode(node.initializer, other.initializer);
- }
-
- @override
- visitVariableDeclarationList(VariableDeclarationList node) {
- VariableDeclarationList other = this.other;
- _visitNode(node.type, other.type);
- _visitList(node.variables, other.variables);
- }
-
- @override
- visitVariableDeclarationStatement(VariableDeclarationStatement node) {
- VariableDeclarationStatement other = this.other;
- _visitNode(node.variables, other.variables);
- }
-
- @override
- visitWhileStatement(WhileStatement node) {
- WhileStatement other = this.other;
- _visitNode(node.condition, other.condition);
- _visitNode(node.body, other.body);
- }
-
- @override
- visitWithClause(WithClause node) {
- WithClause other = this.other;
- _visitList(node.mixinTypes, other.mixinTypes);
- }
-
- @override
- visitYieldStatement(YieldStatement node) {
- YieldStatement other = this.other;
- _visitNode(node.expression, other.expression);
- }
-
- void _assertNode(AstNode a, AstNode b) {
- _expectEquals(a.offset, b.offset);
- _expectEquals(a.length, b.length);
- }
-
- void _expectEquals(actual, expected) {
- if (actual != expected) {
- String message = '';
- message += 'Expected: $expected\n';
- message += ' Actual: $actual\n';
- _fail(message);
- }
- }
-
- void _expectIsNull(obj) {
- if (obj != null) {
- String message = '';
- message += 'Expected: null\n';
- message += ' Actual: $obj\n';
- _fail(message);
- }
- }
-
- void _expectLength(List actualList, int expected) {
+ bool failDifferentLength(List expectedList, List actualList) {
+ int expectedLength = expectedList.length;
+ int actualLength = actualList.length;
String message = '';
- message += 'Expected length: $expected\n';
- if (actualList == null) {
- message += 'but null found.';
- _fail(message);
+ message += 'Expected length: $expectedLength\n';
+ message += 'but $actualLength found\n';
+ message += 'in $actualList';
+ _fail(message);
+ return false;
+ }
+
+ @override
+ bool failIfNotNull(Object expected, Object actual) {
+ if (actual != null) {
+ _fail('Expected null, but found $actual');
+ return false;
}
- int actual = actualList.length;
- if (actual != expected) {
- message += 'but $actual found\n';
- message += 'in $actualList';
- _fail(message);
+ return true;
+ }
+
+ @override
+ bool failIsNull(Object expected, Object actual) {
+ _fail('Expected not null, but found null');
+ return false;
+ }
+
+ @override
+ bool failRuntimeType(Object expected, Object actual) {
+ _fail('Expected ${expected.runtimeType}, but found ${actual.runtimeType}');
+ return false;
+ }
+
+ @override
+ bool isEqualNodes(AstNode first, AstNode second) {
+ super.isEqualNodes(first, second);
+ if (first is SimpleIdentifier && second is SimpleIdentifier) {
+ int offset = first.offset;
+ _verifyElement(
+ first.staticElement, second.staticElement, 'staticElement[$offset]');
+ _verifyElement(first.propagatedElement, second.propagatedElement,
+ 'propagatedElement[$offset]');
+ } else if (first is Declaration && second is Declaration) {
+ int offset = first.offset;
+ _verifyElement(first.element, second.element, 'declaration[$offset]');
+ } else if (first is Directive && second is Directive) {
+ int offset = first.offset;
+ _verifyElement(first.element, second.element, 'directive[$offset]');
+ } else if (first is Expression && second is Expression) {
+ int offset = first.offset;
+ _verifyType(first.staticType, second.staticType, 'staticType[$offset]');
+ _verifyType(first.propagatedType, second.propagatedType,
+ 'propagatedType[$offset]');
+ _verifyElement(first.staticParameterElement,
+ second.staticParameterElement, 'staticParameterElement[$offset]');
+ _verifyElement(
+ first.propagatedParameterElement,
+ second.propagatedParameterElement,
+ 'propagatedParameterElement[$offset]');
}
+ return true;
+ }
+
+ @override
+ bool isEqualTokensNotNull(Token expected, Token actual) {
+ _verifyEqual('lexeme', expected.lexeme, actual.lexeme);
+ _verifyEqual('offset', expected.offset, actual.offset);
+ _verifyEqual('offset', expected.length, actual.length);
+ return true;
}
void _fail(String message) {
throw new IncrementalResolutionMismatch(message);
}
- void _verifyElement(Element a, Element b) {
+ void _verifyElement(Element a, Element b, String desc) {
if (a is Member && b is Member) {
a = (a as Member).baseElement;
b = (b as Member).baseElement;
@@ -842,8 +126,7 @@
String locationA = _getElementLocationWithoutUri(a);
String locationB = _getElementLocationWithoutUri(b);
if (locationA != locationB) {
- int offset = other.offset;
- _fail('[$offset]\nExpected: $b ($locationB)\n Actual: $a ($locationA)');
+ _fail('$desc\nExpected: $b ($locationB)\n Actual: $a ($locationA)');
}
if (a == null && b == null) {
return;
@@ -866,66 +149,15 @@
}
}
- void _verifyType(DartType a, DartType b) {
+ void _verifyType(DartType a, DartType b, String desc) {
if (!validateTypes) {
return;
}
if (a != b) {
- int offset = other.offset;
- _fail('[$offset]\nExpected: $b\n Actual: $a');
+ _fail('$desc\nExpected: $b\n Actual: $a');
}
}
- void _visitAnnotatedNode(AnnotatedNode node, AnnotatedNode other) {
- _visitNode(node.documentationComment, other.documentationComment);
- _visitList(node.metadata, other.metadata);
- }
-
- _visitDeclaration(Declaration node, Declaration other) {
- _verifyElement(node.element, other.element);
- _visitAnnotatedNode(node, other);
- }
-
- _visitDirective(Directive node, Directive other) {
- _verifyElement(node.element, other.element);
- _visitAnnotatedNode(node, other);
- }
-
- void _visitExpression(Expression a, Expression b) {
-// print('[${a.offset}] |$a| vs. [${b.offset}] |$b|');
- _verifyType(a.staticType, b.staticType);
- _verifyType(a.propagatedType, b.propagatedType);
- _verifyElement(a.staticParameterElement, b.staticParameterElement);
- _verifyElement(a.propagatedParameterElement, b.propagatedParameterElement);
- _assertNode(a, b);
- }
-
- void _visitList(NodeList nodeList, NodeList expected) {
- int length = nodeList.length;
- _expectLength(nodeList, expected.length);
- for (int i = 0; i < length; i++) {
- _visitNode(nodeList[i], expected[i]);
- }
- }
-
- void _visitNode(AstNode node, AstNode other) {
- if (node == null) {
- _expectIsNull(other);
- } else {
- this.other = other;
- _assertNode(node, other);
- node.accept(this);
- }
- }
-
- void _visitNormalFormalParameter(
- NormalFormalParameter node, NormalFormalParameter other) {
- _verifyElement(node.element, other.element);
- _visitNode(node.documentationComment, other.documentationComment);
- _visitList(node.metadata, other.metadata);
- _visitNode(node.identifier, other.identifier);
- }
-
/**
* Returns an URI scheme independent version of the [element] location.
*/
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 889e156..31ed260 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -697,8 +697,12 @@
return false;
}
+ bool inCommentReference(SimpleIdentifier identifier) =>
+ identifier.getAncestor((AstNode node) => node is CommentReference) !=
+ null;
+
Element element = identifier.bestElement;
- if (isProtected(element)) {
+ if (isProtected(element) && !inCommentReference(identifier)) {
ClassElement definingClass = element.enclosingElement;
ClassDeclaration accessingClass =
identifier.getAncestor((AstNode node) => node is ClassDeclaration);
@@ -2049,8 +2053,8 @@
* This allows for a final break, continue, return, or throw statement
* at the end of a switch case, that are mandated by the language spec.
*/
- void _checkForDeadStatementsInNodeList(
- NodeList<Statement> statements, {bool allowMandated: false}) {
+ void _checkForDeadStatementsInNodeList(NodeList<Statement> statements,
+ {bool allowMandated: false}) {
bool statementExits(Statement statement) {
if (statement is BreakStatement) {
return statement.label == null;
@@ -5954,7 +5958,6 @@
@override
Object visitAsExpression(AsExpression node) {
- InferenceContext.setType(node.expression, node.type.type);
super.visitAsExpression(node);
// Since an as-statement doesn't actually change the type, we don't
// let it affect the propagated type when it would result in a loss
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index 0d053f6b..be7c27a 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -25,6 +25,205 @@
import 'package:path/path.dart' as pathos;
/**
+ * An abstract implementation of a Dart SDK in which the available libraries are
+ * stored in a library map. Subclasses are responsible for populating the
+ * library map.
+ */
+abstract class AbstractDartSdk implements DartSdk {
+ /**
+ * A mapping from Dart library URI's to the library represented by that URI.
+ */
+ LibraryMap libraryMap = new LibraryMap();
+
+ /**
+ * The [AnalysisOptions] to use to create the [context].
+ */
+ AnalysisOptions _analysisOptions;
+
+ /**
+ * The flag that specifies whether an SDK summary should be used. This is a
+ * temporary flag until summaries are enabled by default.
+ */
+ bool _useSummary = false;
+
+ /**
+ * The [AnalysisContext] which is used for all of the sources in this SDK.
+ */
+ InternalAnalysisContext _analysisContext;
+
+ /**
+ * The mapping from Dart URI's to the corresponding sources.
+ */
+ Map<String, Source> _uriToSourceMap = new HashMap<String, Source>();
+
+ /**
+ * Set the [options] for this SDK analysis context. Throw [StateError] if the
+ * context has been already created.
+ */
+ void set analysisOptions(AnalysisOptions options) {
+ if (_analysisContext != null) {
+ throw new StateError(
+ 'Analysis options cannot be changed after context creation.');
+ }
+ _analysisOptions = options;
+ }
+
+ @override
+ AnalysisContext get context {
+ if (_analysisContext == null) {
+ _analysisContext = new SdkAnalysisContext(_analysisOptions);
+ SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
+ _analysisContext.sourceFactory = factory;
+ if (_useSummary) {
+ bool strongMode = _analysisOptions?.strongMode ?? false;
+ PackageBundle sdkBundle = getSummarySdkBundle(strongMode);
+ if (sdkBundle != null) {
+ _analysisContext.resultProvider = new SdkSummaryResultProvider(
+ _analysisContext, sdkBundle, strongMode);
+ }
+ }
+ }
+ return _analysisContext;
+ }
+
+ @override
+ List<SdkLibrary> get sdkLibraries => libraryMap.sdkLibraries;
+
+ @override
+ List<String> get uris => libraryMap.uris;
+
+ /**
+ * Return `true` if the SDK summary will be used when available.
+ */
+ bool get useSummary => _useSummary;
+
+ /**
+ * Specify whether SDK summary should be used.
+ */
+ void set useSummary(bool use) {
+ if (_analysisContext != null) {
+ throw new StateError(
+ 'The "useSummary" flag cannot be changed after context creation.');
+ }
+ _useSummary = use;
+ }
+
+ @override
+ Source fromFileUri(Uri uri) {
+ JavaFile file = new JavaFile.fromUri(uri);
+
+ String path = _getPath(file);
+ if (path == null) {
+ return null;
+ }
+ try {
+ return new FileBasedSource(file, parseUriWithException(path));
+ } on URISyntaxException catch (exception, stackTrace) {
+ AnalysisEngine.instance.logger.logInformation(
+ "Failed to create URI: $path",
+ new CaughtException(exception, stackTrace));
+ }
+ return null;
+ }
+
+ String getRelativePathFromFile(JavaFile file);
+
+ @override
+ SdkLibrary getSdkLibrary(String dartUri) => libraryMap.getLibrary(dartUri);
+
+ /**
+ * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise.
+ * This method should not be used outside of `analyzer` and `analyzer_cli`
+ * packages.
+ */
+ PackageBundle getSummarySdkBundle(bool strongMode);
+
+ FileBasedSource internalMapDartUri(String dartUri) {
+ // TODO(brianwilkerson) Figure out how to unify the implementations in the
+ // two subclasses.
+ String libraryName;
+ String relativePath;
+ int index = dartUri.indexOf('/');
+ if (index >= 0) {
+ libraryName = dartUri.substring(0, index);
+ relativePath = dartUri.substring(index + 1);
+ } else {
+ libraryName = dartUri;
+ relativePath = "";
+ }
+ SdkLibrary library = getSdkLibrary(libraryName);
+ if (library == null) {
+ return null;
+ }
+ String srcPath;
+ if (relativePath.isEmpty) {
+ srcPath = library.path;
+ } else {
+ String libraryPath = library.path;
+ int index = libraryPath.lastIndexOf(JavaFile.separator);
+ if (index == -1) {
+ index = libraryPath.lastIndexOf('/');
+ if (index == -1) {
+ return null;
+ }
+ }
+ String prefix = libraryPath.substring(0, index + 1);
+ srcPath = '$prefix$relativePath';
+ }
+ String filePath = srcPath.replaceAll('/', JavaFile.separator);
+ try {
+ JavaFile file = new JavaFile(filePath);
+ return new FileBasedSource(file, parseUriWithException(dartUri));
+ } on URISyntaxException {
+ return null;
+ }
+ }
+
+ @override
+ Source mapDartUri(String dartUri) {
+ Source source = _uriToSourceMap[dartUri];
+ if (source == null) {
+ source = internalMapDartUri(dartUri);
+ _uriToSourceMap[dartUri] = source;
+ }
+ return source;
+ }
+
+ String _getPath(JavaFile file) {
+ List<SdkLibrary> libraries = libraryMap.sdkLibraries;
+ int length = libraries.length;
+ List<String> paths = new List(length);
+ String filePath = getRelativePathFromFile(file);
+ if (filePath == null) {
+ return null;
+ }
+ for (int i = 0; i < length; i++) {
+ SdkLibrary library = libraries[i];
+ String libraryPath = library.path.replaceAll('/', JavaFile.separator);
+ if (filePath == libraryPath) {
+ return library.shortName;
+ }
+ paths[i] = libraryPath;
+ }
+ for (int i = 0; i < length; i++) {
+ SdkLibrary library = libraries[i];
+ String libraryPath = paths[i];
+ int index = libraryPath.lastIndexOf(JavaFile.separator);
+ if (index >= 0) {
+ String prefix = libraryPath.substring(0, index + 1);
+ if (filePath.startsWith(prefix)) {
+ String relPath = filePath
+ .substring(prefix.length)
+ .replaceAll(JavaFile.separator, '/');
+ return '${library.shortName}/$relPath';
+ }
+ }
+ }
+ return null;
+ }
+}
+
+/**
* A Dart SDK installed in a specified directory. Typical Dart SDK layout is
* something like...
*
@@ -40,7 +239,7 @@
* ... Dart utilities ...
* Chromium/ <-- Dartium typically exists in a sibling directory
*/
-class DirectoryBasedDartSdk implements DartSdk {
+class DirectoryBasedDartSdk extends AbstractDartSdk {
/**
* The default SDK, or `null` if the default SDK either has not yet been
* created or cannot be created for some reason.
@@ -193,11 +392,6 @@
}
/**
- * The [AnalysisContext] which is used for all of the sources in this sdk.
- */
- InternalAnalysisContext _analysisContext;
-
- /**
* The directory containing the SDK.
*/
JavaFile _sdkDirectory;
@@ -208,11 +402,6 @@
JavaFile _libraryDirectory;
/**
- * The flag that specifies whether SDK summary should be used.
- */
- bool _useSummary = false;
-
- /**
* The revision number of this SDK, or `"0"` if the revision number cannot be
* discovered.
*/
@@ -239,58 +428,13 @@
JavaFile _vmExecutable;
/**
- * A mapping from Dart library URI's to the library represented by that URI.
- */
- LibraryMap _libraryMap;
-
- /**
- * The mapping from Dart URI's to the corresponding sources.
- */
- Map<String, Source> _uriToSourceMap = new HashMap<String, Source>();
-
- /**
- * The [AnalysisOptions] to use to create the [context].
- */
- AnalysisOptions _analysisOptions;
-
- /**
* Initialize a newly created SDK to represent the Dart SDK installed in the
* [sdkDirectory]. The flag [useDart2jsPaths] is `true` if the dart2js path
* should be used when it is available
*/
DirectoryBasedDartSdk(JavaFile sdkDirectory, [bool useDart2jsPaths = false]) {
this._sdkDirectory = sdkDirectory.getAbsoluteFile();
- _libraryMap = initialLibraryMap(useDart2jsPaths);
- }
-
- /**
- * Set the [options] for this SDK analysis context. Throw [StateError] if the
- * context has been already created.
- */
- void set analysisOptions(AnalysisOptions options) {
- if (_analysisContext != null) {
- throw new StateError(
- 'Analysis options cannot be changed after context creation.');
- }
- _analysisOptions = options;
- }
-
- @override
- AnalysisContext get context {
- if (_analysisContext == null) {
- _analysisContext = new SdkAnalysisContext(_analysisOptions);
- SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
- _analysisContext.sourceFactory = factory;
- if (_useSummary) {
- PackageBundle sdkBundle = getSummarySdkBundle();
- if (sdkBundle != null) {
- bool strongMode = _analysisOptions?.strongMode ?? false;
- _analysisContext.resultProvider = new SdkSummaryResultProvider(
- _analysisContext, sdkBundle, strongMode);
- }
- }
- }
- return _analysisContext;
+ libraryMap = initialLibraryMap(useDart2jsPaths);
}
/**
@@ -386,9 +530,6 @@
return _pubExecutable;
}
- @override
- List<SdkLibrary> get sdkLibraries => _libraryMap.sdkLibraries;
-
/**
* Return the revision number of this SDK, or `"0"` if the revision number
* cannot be discovered.
@@ -411,25 +552,6 @@
return _sdkVersion;
}
- @override
- List<String> get uris => _libraryMap.uris;
-
- /**
- * Whether an SDK summary should be used.
- */
- bool get useSummary => _useSummary;
-
- /**
- * Specify whether SDK summary should be used.
- */
- void set useSummary(bool use) {
- if (_analysisContext != null) {
- throw new StateError(
- 'The "useSummary" flag cannot be changed after context creation.');
- }
- _useSummary = use;
- }
-
/**
* Return the name of the file containing the VM executable.
*/
@@ -470,45 +592,6 @@
_LIBRARIES_FILE);
}
- @override
- Source fromFileUri(Uri uri) {
- JavaFile file = new JavaFile.fromUri(uri);
- String filePath = file.getAbsolutePath();
- String libPath = libraryDirectory.getAbsolutePath();
- if (!filePath.startsWith("$libPath${JavaFile.separator}")) {
- return null;
- }
- filePath = filePath.substring(libPath.length + 1);
- for (SdkLibrary library in _libraryMap.sdkLibraries) {
- String libraryPath = library.path;
- if (filePath.replaceAll('\\', '/') == libraryPath) {
- String path = library.shortName;
- try {
- return new FileBasedSource(file, parseUriWithException(path));
- } on URISyntaxException catch (exception, stackTrace) {
- AnalysisEngine.instance.logger.logInformation(
- "Failed to create URI: $path",
- new CaughtException(exception, stackTrace));
- return null;
- }
- }
- libraryPath = new JavaFile(library.path).getParent();
- if (filePath.startsWith("$libraryPath${JavaFile.separator}")) {
- String path =
- "${library.shortName}/${filePath.substring(libraryPath.length + 1)}";
- try {
- return new FileBasedSource(file, parseUriWithException(path));
- } on URISyntaxException catch (exception, stackTrace) {
- AnalysisEngine.instance.logger.logInformation(
- "Failed to create URI: $path",
- new CaughtException(exception, stackTrace));
- return null;
- }
- }
- }
- return null;
- }
-
/**
* Return the directory where dartium can be found (the directory that will be
* the working directory if Dartium is invoked without changing the default),
@@ -536,16 +619,22 @@
}
@override
- SdkLibrary getSdkLibrary(String dartUri) => _libraryMap.getLibrary(dartUri);
+ String getRelativePathFromFile(JavaFile file) {
+ String filePath = file.getAbsolutePath();
+ String libPath = libraryDirectory.getAbsolutePath();
+ if (!filePath.startsWith("$libPath${JavaFile.separator}")) {
+ return null;
+ }
+ return filePath.substring(libPath.length + 1);
+ }
/**
* Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise.
* This method should not be used outside of `analyzer` and `analyzer_cli`
* packages.
*/
- PackageBundle getSummarySdkBundle() {
+ PackageBundle getSummarySdkBundle(bool strongMode) {
String rootPath = directory.getAbsolutePath();
- bool strongMode = _analysisOptions?.strongMode ?? false;
String name = strongMode ? 'strong.sum' : 'spec.sum';
String path = pathos.join(rootPath, 'lib', '_internal', name);
try {
@@ -589,16 +678,7 @@
}
@override
- Source mapDartUri(String dartUri) {
- Source source = _uriToSourceMap[dartUri];
- if (source == null) {
- source = _mapDartUri(dartUri);
- _uriToSourceMap[dartUri] = source;
- }
- return source;
- }
-
- FileBasedSource _mapDartUri(String dartUri) {
+ FileBasedSource internalMapDartUri(String dartUri) {
String libraryName;
String relativePath;
int index = dartUri.indexOf('/');
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 4ba4c51..4492037 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -15,7 +15,7 @@
import 'package:analyzer/src/generated/java_io.dart' show JavaFile;
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:analyzer/src/generated/source_io.dart'
- show FileBasedSource, FileUriResolver, PackageUriResolver;
+ show FileBasedSource, PackageUriResolver;
import 'package:analyzer/task/model.dart';
import 'package:package_config/packages.dart';
import 'package:path/path.dart' as pathos;
@@ -905,7 +905,7 @@
return UriKind.PACKAGE_URI;
} else if (scheme == DartUriResolver.DART_SCHEME) {
return UriKind.DART_URI;
- } else if (scheme == FileUriResolver.FILE_SCHEME) {
+ } else if (scheme == ResourceUriResolver.FILE_SCHEME) {
return UriKind.FILE_URI;
}
return UriKind.FILE_URI;
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index b7cb0fd..f7b47ef 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -262,7 +262,11 @@
/**
* Instances of the class `FileUriResolver` resolve `file` URI's.
+ *
+ * This class is now deprecated, 'new FileUriResolver()' is equivalent to
+ * 'new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)'.
*/
+@deprecated
class FileUriResolver extends UriResolver {
/**
* The name of the `file` scheme.
@@ -516,7 +520,12 @@
/**
* Instances of the class `RelativeFileUriResolver` resolve `file` URI's.
+ *
+ * This class is now deprecated, file URI resolution should be done with
+ * ResourceUriResolver, i.e.
+ * 'new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)'.
*/
+@deprecated
class RelativeFileUriResolver extends UriResolver {
/**
* The name of the `file` scheme.
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index 0d340b9..3cd21f1 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -14,10 +14,16 @@
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/sdk_io.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/flat_buffers.dart' as fb;
import 'package:analyzer/src/summary/index_unit.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'package:path/path.dart';
+const int FIELD_SPEC_INDEX = 1;
+const int FIELD_SPEC_SUM = 0;
+const int FIELD_STRONG_INDEX = 3;
+const int FIELD_STRONG_SUM = 2;
+
class BuilderOutput {
final List<int> sum;
final List<int> index;
@@ -40,13 +46,72 @@
}
}
+/**
+ * Summary build configuration.
+ */
+class SummaryBuildConfig {
+
+ /**
+ * Whether to use exclude informative data from created summaries.
+ */
+ final bool buildSummaryExcludeInformative;
+
+ /**
+ * Whether to output a summary in "fallback mode".
+ */
+ final bool buildSummaryFallback;
+
+ /**
+ * Whether to create summaries directly from ASTs, i.e. don't create a
+ * full element model.
+ */
+ final bool buildSummaryOnlyAst;
+
+ /**
+ * Path to the dart SDK summary file.
+ */
+ final String dartSdkSummaryPath;
+
+ /**
+ * Whether to use strong static checking.
+ */
+ final bool strongMode;
+
+ /**
+ * List of summary input file paths.
+ */
+ final Iterable<String> summaryInputs;
+
+ /**
+ * Create a build configuration with the given set options.
+ */
+ SummaryBuildConfig(
+ {this.strongMode: false,
+ this.summaryInputs,
+ this.dartSdkSummaryPath,
+ this.buildSummaryExcludeInformative: false,
+ this.buildSummaryFallback: false,
+ this.buildSummaryOnlyAst: false});
+}
+
class SummaryBuilder {
- final AnalysisContext _context;
- final Iterable<Source> _librarySources;
+ final AnalysisContext context;
+ final Iterable<Source> librarySources;
+ final SummaryBuildConfig config;
- SummaryBuilder(this._librarySources, this._context);
+ /**
+ * Create a summary builder for these [librarySources] and [context] using the
+ * given [config].
+ */
+ SummaryBuilder(this.librarySources, this.context, this.config);
- factory SummaryBuilder.forSdk(String sdkPath, bool strongMode) {
+ /**
+ * Create an SDK summary builder for the dart SDK at the given [sdkPath],
+ * using this [config].
+ */
+ factory SummaryBuilder.forSdk(String sdkPath, SummaryBuildConfig config) {
+ bool strongMode = config.strongMode;
+
//
// Prepare SDK.
//
@@ -70,10 +135,39 @@
librarySources.add(sdk.mapDartUri(uri));
}
- return new SummaryBuilder(librarySources, sdk.context);
+ return new SummaryBuilder(librarySources, sdk.context, config);
}
- BuilderOutput build() => new _Builder(_context, _librarySources).build();
+ BuilderOutput build() => new _Builder(context, librarySources).build();
+}
+
+/**
+ * Intermediary summary output result.
+ */
+class SummaryOutput {
+ final BuilderOutput spec;
+ final BuilderOutput strong;
+ SummaryOutput(this.spec, this.strong);
+
+ /**
+ * Write this summary output to the given [outputPath] and return the
+ * created file.
+ */
+ File write(String outputPath) {
+ fb.Builder builder = new fb.Builder();
+ fb.Offset specSumOffset = builder.writeListUint8(spec.sum);
+ fb.Offset specIndexOffset = builder.writeListUint8(spec.index);
+ fb.Offset strongSumOffset = builder.writeListUint8(strong.sum);
+ fb.Offset strongIndexOffset = builder.writeListUint8(strong.index);
+ builder.startTable();
+ builder.addOffset(FIELD_SPEC_SUM, specSumOffset);
+ builder.addOffset(FIELD_SPEC_INDEX, specIndexOffset);
+ builder.addOffset(FIELD_STRONG_SUM, strongSumOffset);
+ builder.addOffset(FIELD_STRONG_INDEX, strongIndexOffset);
+ fb.Offset offset = builder.endTable();
+ return new File(outputPath)
+ ..writeAsBytesSync(builder.finish(offset), mode: FileMode.WRITE_ONLY);
+ }
}
class _Builder {
@@ -88,7 +182,7 @@
_Builder(this.context, this.librarySources);
/**
- * Build a strong or spec mode summary for the Dart SDK at [sdkPath].
+ * Build summary output.
*/
BuilderOutput build() {
//
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 148499e..5d3d3b2 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -4610,6 +4610,20 @@
}
@override
+ visitClassTypeAlias(ClassTypeAlias node) {
+ ReferencedNamesScope outerScope = scope;
+ try {
+ scope = new ReferencedNamesScope.forClassTypeAlias(scope, node);
+ dependsOn = new Set<String>();
+ super.visitClassTypeAlias(node);
+ names.userToDependsOn[node.name.name] = dependsOn;
+ } finally {
+ dependsOn = null;
+ scope = outerScope;
+ }
+ }
+
+ @override
visitConstructorName(ConstructorName node) {
if (node.parent is! ConstructorDeclaration) {
super.visitConstructorName(node);
@@ -4696,6 +4710,23 @@
dependsOn.add(name);
}
}
+
+ @override
+ visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ VariableDeclarationList variableList = node.variables;
+ // Prepare type dependencies.
+ Set<String> typeDependencies = new Set<String>();
+ dependsOn = typeDependencies;
+ variableList.type?.accept(this);
+ // Combine individual variable dependencies with the type dependencies.
+ for (VariableDeclaration variable in variableList.variables) {
+ dependsOn = new Set<String>();
+ variable.accept(this);
+ dependsOn.addAll(typeDependencies);
+ names.userToDependsOn[variable.name.name] = dependsOn;
+ }
+ dependsOn = null;
+ }
}
class ReferencedNamesScope {
@@ -4735,6 +4766,13 @@
return scope;
}
+ factory ReferencedNamesScope.forClassTypeAlias(
+ ReferencedNamesScope enclosing, ClassTypeAlias node) {
+ ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
+ scope._addTypeParameters(node.typeParameters);
+ return scope;
+ }
+
factory ReferencedNamesScope.forFunction(
ReferencedNamesScope enclosing, FunctionDeclaration node) {
ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index 66a5bbe..20c6a76 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -18,6 +18,26 @@
import 'package:analyzer/src/generated/source.dart';
/**
+ * The change of a single [ClassElement].
+ */
+class ClassElementDelta {
+ final ClassElement element;
+
+ final List<PropertyAccessorElement> addedAccessors =
+ <PropertyAccessorElement>[];
+ final List<PropertyAccessorElement> removedAccessors =
+ <PropertyAccessorElement>[];
+
+ final List<ConstructorElement> addedConstructors = <ConstructorElement>[];
+ final List<ConstructorElement> removedConstructors = <ConstructorElement>[];
+
+ final List<MethodElement> addedMethods = <MethodElement>[];
+ final List<MethodElement> removedMethods = <MethodElement>[];
+
+ ClassElementDelta(this.element);
+}
+
+/**
* The change of a single [CompilationUnitElement].
*/
class CompilationUnitElementDelta {
@@ -35,6 +55,11 @@
* The list of removed top-level elements.
*/
final List<Element> removedDeclarations = <Element>[];
+
+ /**
+ * The list of changed class elements.
+ */
+ final List<ClassElementDelta> classDeltas = <ClassElementDelta>[];
}
/**
@@ -47,7 +72,7 @@
final CompilationUnit oldUnit;
final CompilationUnitElementImpl unitElement;
final CompilationUnit newUnit;
- final ElementHolder holder = new ElementHolder();
+ final ElementHolder unitElementHolder = new ElementHolder();
/**
* The change between element models of [oldUnit] and [newUnit].
@@ -78,28 +103,176 @@
.buildCompilationUnit(unitSource, newUnit, librarySource);
_processDirectives();
_processUnitMembers();
- newUnit.element = unitElement;
_replaceUnitContents(oldUnit, newUnit);
+ newUnit.element = unitElement;
+ unitElement.setCodeRange(0, newUnit.endToken.end);
}
- void _addElementToHolder(Element element) {
- if (element is PropertyAccessorElement) {
- holder.addAccessor(element);
- } else if (element is ClassElement) {
+ void _addElementToUnitHolder(Element element) {
+ if (element is ClassElement) {
if (element.isEnum) {
- holder.addEnum(element);
+ unitElementHolder.addEnum(element);
} else {
- holder.addType(element);
+ unitElementHolder.addType(element);
}
} else if (element is FunctionElement) {
- holder.addFunction(element);
+ unitElementHolder.addFunction(element);
} else if (element is FunctionTypeAliasElement) {
- holder.addTypeAlias(element);
+ unitElementHolder.addTypeAlias(element);
+ } else if (element is PropertyAccessorElement) {
+ unitElementHolder.addAccessor(element);
} else if (element is TopLevelVariableElement) {
- holder.addTopLevelVariable(element);
+ unitElementHolder.addTopLevelVariable(element);
}
}
+ ClassElementDelta _processClassMembers(
+ ClassDeclaration oldClass, ClassDeclaration newClass) {
+ // TODO(scheglov) Compare class structure: type parameters, supertype,
+ // mixins and interfaces.
+ Map<String, ClassMember> oldNodeMap = new HashMap<String, ClassMember>();
+ for (ClassMember oldNode in oldClass.members) {
+ String code = TokenUtils.getFullCode(oldNode);
+ oldNodeMap[code] = oldNode;
+ }
+ // Prepare elements.
+ ClassElement newElement = newClass.element;
+ ClassElement oldElement = oldClass.element;
+ // Use the old element for the new node.
+ newClass.name.staticElement = oldElement;
+ if (newElement is ClassElementImpl && oldElement is ClassElementImpl) {
+ oldElement.setCodeRange(newElement.codeOffset, newElement.codeLength);
+ }
+ // Prepare delta.
+ ClassElementImpl classElement = oldClass.element;
+ ElementHolder classElementHolder = new ElementHolder();
+ ClassElementDelta classDelta = new ClassElementDelta(classElement);
+ // Prepare all old member elements.
+ var removedAccessors = new Set<PropertyAccessorElement>();
+ var removedConstructors = new Set<ConstructorElement>();
+ var removedMethods = new Set<MethodElement>();
+ removedAccessors.addAll(classElement.accessors);
+ removedConstructors.addAll(classElement.constructors);
+ removedMethods.addAll(classElement.methods);
+ // Utilities.
+ void processConstructorDeclaration(
+ ConstructorDeclaration node, bool isNew) {
+ ConstructorElement element = node.element;
+ if (element != null) {
+ classElementHolder.addConstructor(element);
+ if (isNew) {
+ classDelta.addedConstructors.add(element);
+ } else {
+ removedConstructors.remove(element);
+ }
+ }
+ }
+ void processFieldDeclaration(FieldDeclaration node, bool isNew) {
+ for (VariableDeclaration field in node.fields.variables) {
+ PropertyInducingElement element = field.element;
+ if (element != null) {
+ PropertyAccessorElement getter = element.getter;
+ PropertyAccessorElement setter = element.setter;
+ if (getter != null) {
+ classElementHolder.addAccessor(getter);
+ if (isNew) {
+ classDelta.addedAccessors.add(getter);
+ } else {
+ removedAccessors.remove(getter);
+ }
+ }
+ if (setter != null) {
+ classElementHolder.addAccessor(setter);
+ if (isNew) {
+ classDelta.addedAccessors.add(setter);
+ } else {
+ removedAccessors.remove(setter);
+ }
+ }
+ }
+ }
+ }
+ void processMethodDeclaration(MethodDeclaration node, bool isNew) {
+ Element element = node.element;
+ if (element is MethodElement) {
+ classElementHolder.addMethod(element);
+ if (isNew) {
+ classDelta.addedMethods.add(element);
+ } else {
+ removedMethods.remove(element);
+ }
+ } else if (element is PropertyAccessorElement) {
+ classElementHolder.addAccessor(element);
+ if (isNew) {
+ classDelta.addedAccessors.add(element);
+ } else {
+ removedAccessors.remove(element);
+ }
+ }
+ }
+ // Replace new nodes with the identical old nodes.
+ bool newHasConstructor = false;
+ for (ClassMember newNode in newClass.members) {
+ String code = TokenUtils.getFullCode(newNode);
+ ClassMember oldNode = oldNodeMap[code];
+ // Add the new element.
+ if (oldNode == null) {
+ if (newNode is ConstructorDeclaration) {
+ newHasConstructor = true;
+ processConstructorDeclaration(newNode, true);
+ }
+ if (newNode is FieldDeclaration) {
+ processFieldDeclaration(newNode, true);
+ }
+ if (newNode is MethodDeclaration) {
+ processMethodDeclaration(newNode, true);
+ }
+ continue;
+ }
+ // Do replacement.
+ _replaceNode(newNode, oldNode);
+ if (oldNode is ConstructorDeclaration) {
+ processConstructorDeclaration(oldNode, false);
+ }
+ if (oldNode is FieldDeclaration) {
+ processFieldDeclaration(oldNode, false);
+ }
+ if (oldNode is MethodDeclaration) {
+ processMethodDeclaration(oldNode, false);
+ }
+ }
+ // If the class had only a default synthetic constructor, and there are
+ // no explicit constructors in the new AST, keep the constructor.
+ if (!newHasConstructor) {
+ List<ConstructorElement> constructors = classElement.constructors;
+ if (constructors.length == 1) {
+ ConstructorElement constructor = constructors[0];
+ if (constructor.isSynthetic && constructor.isDefaultConstructor) {
+ classElementHolder.addConstructor(constructor);
+ removedConstructors.remove(constructor);
+ }
+ }
+ }
+ // Update the delta.
+ classDelta.removedAccessors.addAll(removedAccessors);
+ classDelta.removedConstructors.addAll(removedConstructors);
+ classDelta.removedMethods.addAll(removedMethods);
+ // Update ClassElement.
+ classElement.accessors = classElementHolder.accessors;
+ classElement.constructors = classElementHolder.constructors;
+ classElement.methods = classElementHolder.methods;
+ classElementHolder.validate();
+ // Ensure at least a default synthetic constructor.
+ if (classElement.constructors.isEmpty) {
+ ConstructorElementImpl constructor =
+ new ConstructorElementImpl.forNode(null);
+ constructor.synthetic = true;
+ classElement.constructors = <ConstructorElement>[constructor];
+ }
+ // OK
+ return classDelta;
+ }
+
void _processDirectives() {
Map<String, Directive> oldDirectiveMap = new HashMap<String, Directive>();
for (Directive oldDirective in oldUnit.directives) {
@@ -136,9 +309,14 @@
void _processUnitMembers() {
Map<String, CompilationUnitMember> oldNodeMap =
new HashMap<String, CompilationUnitMember>();
+ Map<String, ClassDeclaration> nameToOldClassMap =
+ new HashMap<String, ClassDeclaration>();
for (CompilationUnitMember oldNode in oldUnit.declarations) {
String code = TokenUtils.getFullCode(oldNode);
oldNodeMap[code] = oldNode;
+ if (oldNode is ClassDeclaration) {
+ nameToOldClassMap[oldNode.name.name] = oldNode;
+ }
}
// Prepare all old top-level elements.
Set<Element> removedElements = new Set<Element>();
@@ -151,29 +329,41 @@
// Replace new nodes with the identical old nodes.
for (CompilationUnitMember newNode in newUnit.declarations) {
String code = TokenUtils.getFullCode(newNode);
- // Prepare an old node.
CompilationUnitMember oldNode = oldNodeMap[code];
+ // Add the new element.
if (oldNode == null) {
+ // Compute a delta for the class.
+ if (newNode is ClassDeclaration) {
+ ClassDeclaration oldClass = nameToOldClassMap[newNode.name.name];
+ if (oldClass != null) {
+ ClassElementDelta delta = _processClassMembers(oldClass, newNode);
+ unitDelta.classDeltas.add(delta);
+ _addElementToUnitHolder(delta.element);
+ removedElements.remove(delta.element);
+ continue;
+ }
+ }
+ // Add the new node elements.
List<Element> elements = _getElements(newNode);
- elements.forEach(_addElementToHolder);
+ elements.forEach(_addElementToUnitHolder);
elements.forEach(unitDelta.addedDeclarations.add);
continue;
}
// Do replacement.
_replaceNode(newNode, oldNode);
List<Element> elements = _getElements(oldNode);
- elements.forEach(_addElementToHolder);
+ elements.forEach(_addElementToUnitHolder);
elements.forEach(removedElements.remove);
}
unitDelta.removedDeclarations.addAll(removedElements);
// Update CompilationUnitElement.
- unitElement.accessors = holder.accessors;
- unitElement.enums = holder.enums;
- unitElement.functions = holder.functions;
- unitElement.typeAliases = holder.typeAliases;
- unitElement.types = holder.types;
- unitElement.topLevelVariables = holder.topLevelVariables;
- holder.validate();
+ unitElement.accessors = unitElementHolder.accessors;
+ unitElement.enums = unitElementHolder.enums;
+ unitElement.functions = unitElementHolder.functions;
+ unitElement.typeAliases = unitElementHolder.typeAliases;
+ unitElement.types = unitElementHolder.types;
+ unitElement.topLevelVariables = unitElementHolder.topLevelVariables;
+ unitElementHolder.validate();
}
/**
@@ -213,23 +403,29 @@
*/
static List<Element> _getElements(AstNode node) {
List<Element> elements = <Element>[];
- if (node is TopLevelVariableDeclaration) {
- VariableDeclarationList variableList = node.variables;
+ void addPropertyAccessors(VariableDeclarationList variableList) {
if (variableList != null) {
for (VariableDeclaration variable in variableList.variables) {
- TopLevelVariableElement element = variable.element;
- elements.add(element);
- if (element.getter != null) {
- elements.add(element.getter);
- }
- if (element.setter != null) {
- elements.add(element.setter);
+ PropertyInducingElement element = variable.element;
+ if (element != null) {
+ elements.add(element);
+ if (element.getter != null) {
+ elements.add(element.getter);
+ }
+ if (element.setter != null) {
+ elements.add(element.setter);
+ }
}
}
}
- } else if (node is PartDirective || node is PartOfDirective) {} else if (node
- is Directive &&
- node.element != null) {
+ }
+ if (node is FieldDeclaration) {
+ addPropertyAccessors(node.fields);
+ } else if (node is TopLevelVariableDeclaration) {
+ addPropertyAccessors(node.variables);
+ } else if (node is PartDirective || node is PartOfDirective) {
+ // Ignore.
+ } else if (node is Directive && node.element != null) {
elements.add(node.element);
} else if (node is Declaration && node.element != null) {
Element element = node.element;
@@ -273,8 +469,21 @@
copyTokenOffsets(offsetMap, (oldToken as CommentToken).parent,
(newToken as CommentToken).parent, oldEndToken, newEndToken);
}
+ // Update (otherwise unlinked) reference tokens in documentation.
+ if (oldToken is DocumentationCommentToken &&
+ newToken is DocumentationCommentToken) {
+ List<Token> oldReferences = oldToken.references;
+ List<Token> newReferences = newToken.references;
+ assert(oldReferences.length == newReferences.length);
+ for (int i = 0; i < oldReferences.length; i++) {
+ copyTokenOffsets(offsetMap, oldReferences[i], newReferences[i],
+ oldEndToken, newEndToken);
+ }
+ }
+ // Update documentation tokens.
while (oldToken != null) {
offsetMap[oldToken.offset] = newToken.offset;
+ offsetMap[oldToken.end] = newToken.end;
oldToken.offset = newToken.offset;
oldToken = oldToken.next;
newToken = newToken.next;
@@ -290,7 +499,12 @@
newToken.precedingComments, oldEndToken, newEndToken);
}
offsetMap[oldToken.offset] = newToken.offset;
+ offsetMap[oldToken.end] = newToken.end;
oldToken.offset = newToken.offset;
+ if (oldToken.type == TokenType.EOF) {
+ assert(newToken.type == TokenType.EOF);
+ break;
+ }
if (oldToken == oldEndToken) {
assert(newToken == newEndToken);
break;
@@ -355,18 +569,57 @@
_UpdateElementOffsetsVisitor(this.map);
void visitElement(Element element) {
- if (element is CompilationUnitElement) {
+ if (element is LibraryElement) {
return;
}
if (element.isSynthetic) {
return;
}
- int oldOffset = element.nameOffset;
- int newOffset = map[oldOffset];
- assert(newOffset != null);
- (element as ElementImpl).nameOffset = newOffset;
- if (element is! LibraryElement) {
- super.visitElement(element);
+ if (element is ElementImpl) {
+ // name offset
+ {
+ int oldOffset = element.nameOffset;
+ int newOffset = map[oldOffset];
+ assert(newOffset != null);
+ element.nameOffset = newOffset;
+ }
+ // code range
+ {
+ int oldOffset = element.codeOffset;
+ if (oldOffset != null) {
+ int oldEnd = oldOffset + element.codeLength;
+ int newOffset = map[oldOffset];
+ int newEnd = map[oldEnd];
+ assert(newOffset != null);
+ assert(newEnd != null);
+ int newLength = newEnd - newOffset;
+ element.setCodeRange(newOffset, newLength);
+ }
+ }
+ // visible range
+ if (element is LocalElement) {
+ SourceRange oldVisibleRange = (element as LocalElement).visibleRange;
+ if (oldVisibleRange != null) {
+ int oldOffset = oldVisibleRange.offset;
+ int oldLength = oldVisibleRange.length;
+ int oldEnd = oldOffset + oldLength;
+ int newOffset = map[oldOffset];
+ int newEnd = map[oldEnd];
+ assert(newOffset != null);
+ assert(newEnd != null);
+ int newLength = newEnd - newOffset;
+ if (newOffset != oldOffset || newLength != oldLength) {
+ if (element is FunctionElementImpl) {
+ element.setVisibleRange(newOffset, newLength);
+ } else if (element is LocalVariableElementImpl) {
+ element.setVisibleRange(newOffset, newLength);
+ } else if (element is ParameterElementImpl) {
+ element.setVisibleRange(newOffset, newLength);
+ }
+ }
+ }
+ }
}
+ super.visitElement(element);
}
}
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 36d7e4c..9124fe8 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.27.4-alpha.12
+version: 0.27.4-alpha.13
author: Dart Team <misc@dartlang.org>
description: Static analyzer for Dart.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
diff --git a/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart b/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart
index 53247c1..6ca5bbe 100644
--- a/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart
+++ b/pkg/analyzer/test/file_system/resource_uri_resolver_test.dart
@@ -29,6 +29,11 @@
provider.newFolder('/folder');
}
+ void test_creation() {
+ expect(provider, isNotNull);
+ expect(resolver, isNotNull);
+ }
+
void test_resolveAbsolute_file() {
var uri = new Uri(scheme: 'file', path: '/test.dart');
Source source = resolver.resolveAbsolute(uri);
@@ -43,12 +48,18 @@
expect(source, isNull);
}
- void test_resolveAbsolute_notFile() {
+ void test_resolveAbsolute_notFile_httpsUri() {
var uri = new Uri(scheme: 'https', path: '127.0.0.1/test.dart');
Source source = resolver.resolveAbsolute(uri);
expect(source, isNull);
}
+ void test_resolveAbsolute_notFile_dartUri() {
+ var uri = new Uri(scheme: 'dart', path: 'core');
+ Source source = resolver.resolveAbsolute(uri);
+ expect(source, isNull);
+ }
+
void test_restoreAbsolute() {
var uri = new Uri(scheme: 'file', path: '/test.dart');
Source source = resolver.resolveAbsolute(uri);
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index ba1ba00..925eb8d 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/utilities.dart' hide ConstantEvaluator;
@@ -53,7 +54,6 @@
runReflectiveTests(ExitDetectorTest);
runReflectiveTests(ExitDetectorTest2);
runReflectiveTests(FileBasedSourceTest);
- runReflectiveTests(FileUriResolverTest);
runReflectiveTests(ResolveRelativeUriTest);
runReflectiveTests(SDKLibrariesReaderTest);
runReflectiveTests(UriKindTest);
@@ -4186,7 +4186,8 @@
}
void test_getEncoding() {
- SourceFactory factory = new SourceFactory([new FileUriResolver()]);
+ SourceFactory factory = new SourceFactory(
+ [new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)]);
String fullPath = "/does/not/exist.dart";
JavaFile file = FileUtilities2.createFile(fullPath);
FileBasedSource source = new FileBasedSource(file);
@@ -4305,41 +4306,6 @@
}
@reflectiveTest
-class FileUriResolverTest {
- void test_creation() {
- expect(new FileUriResolver(), isNotNull);
- }
-
- void test_resolve_file() {
- UriResolver resolver = new FileUriResolver();
- Source result = resolver
- .resolveAbsolute(parseUriWithException("file:/does/not/exist.dart"));
- expect(result, isNotNull);
- expect(result.fullName,
- FileUtilities2.createFile("/does/not/exist.dart").getAbsolutePath());
- }
-
- void test_resolve_nonFile() {
- UriResolver resolver = new FileUriResolver();
- Source result =
- resolver.resolveAbsolute(parseUriWithException("dart:core"));
- expect(result, isNull);
- }
-
- void test_restore() {
- UriResolver resolver = new FileUriResolver();
- Uri uri = parseUriWithException('file:///foo/bar.dart');
- Source source = resolver.resolveAbsolute(uri);
- expect(source, isNotNull);
- expect(resolver.restoreAbsolute(source), uri);
- expect(
- resolver.restoreAbsolute(
- new NonExistingSource(source.fullName, null, null)),
- uri);
- }
-}
-
-@reflectiveTest
class ResolveRelativeUriTest {
void test_resolveRelative_dart_dartUri() {
Uri uri = parseUriWithException('dart:foo');
diff --git a/pkg/analyzer/test/generated/bazel_test.dart b/pkg/analyzer/test/generated/bazel_test.dart
new file mode 100644
index 0000000..bac7e66
--- /dev/null
+++ b/pkg/analyzer/test/generated/bazel_test.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.generated.bazel_test;
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/generated/bazel.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:unittest/unittest.dart';
+
+import '../reflective_tests.dart';
+import '../utils.dart';
+
+main() {
+ initializeTestEnvironment();
+ runReflectiveTests(BazelFileUriResolverTest);
+}
+
+@reflectiveTest
+class BazelFileUriResolverTest {
+ MemoryResourceProvider provider;
+ Folder workspace;
+ List<Folder> buildDirs;
+ ResourceUriResolver resolver;
+
+ void setUp() {
+ provider = new MemoryResourceProvider();
+ workspace = provider.newFolder('/workspace');
+ buildDirs = [provider.newFolder('/workspace/one'), provider.newFolder('/workspace/two')];
+ resolver = new BazelFileUriResolver(provider, workspace, buildDirs);
+ provider.newFile('/workspace/test.dart', '');
+ provider.newFile('/workspace/one/gen1.dart', '');
+ provider.newFile('/workspace/two/gen2.dart', '');
+ }
+
+ void test_creation() {
+ expect(provider, isNotNull);
+ expect(workspace, isNotNull);
+ expect(buildDirs, isNotNull);
+ expect(buildDirs.length, 2);
+ expect(resolver, isNotNull);
+ }
+
+ void test_resolveAbsolute_file() {
+ var uri = new Uri(scheme: 'file', path: '/workspace/test.dart');
+ Source source = resolver.resolveAbsolute(uri);
+ expect(source, isNotNull);
+ expect(source.exists(), isTrue);
+ expect(source.fullName, '/workspace/test.dart');
+ }
+
+ void test_resolveAbsolute_folder() {
+ var uri = new Uri(scheme: 'file', path: '/workspace');
+ Source source = resolver.resolveAbsolute(uri);
+ expect(source, isNull);
+ }
+
+ void test_resolveAbsolute_notFile_httpsUri() {
+ var uri = new Uri(scheme: 'https', path: '127.0.0.1/test.dart');
+ Source source = resolver.resolveAbsolute(uri);
+ expect(source, isNull);
+ }
+
+ void test_resolveAbsolute_notFile_dartUri() {
+ var uri = new Uri(scheme: 'dart', path: 'core');
+ Source source = resolver.resolveAbsolute(uri);
+ expect(source, isNull);
+ }
+
+ void test_resolveAbsolute_generated_file_exists_one() {
+ var uri = new Uri(scheme: 'file', path: '/workspace/gen1.dart');
+ Source source = resolver.resolveAbsolute(uri);
+ expect(source, isNotNull);
+ expect(source.exists(), isTrue);
+ expect(source.fullName, '/workspace/one/gen1.dart');
+ }
+
+ void test_resolveAbsolute_generated_file_exists_two() {
+ var uri = new Uri(scheme: 'file', path: '/workspace/gen2.dart');
+ Source source = resolver.resolveAbsolute(uri);
+ expect(source, isNotNull);
+ expect(source.exists(), isTrue);
+ expect(source.fullName, '/workspace/two/gen2.dart');
+ }
+
+ void test_resolveAbsolute_generated_file_does_not_exist_three() {
+ var uri = new Uri(scheme: 'file', path: '/workspace/gen3.dart');
+ Source source = resolver.resolveAbsolute(uri);
+ expect(source, isNull);
+ }
+
+ void test_restoreAbsolute() {
+ var uri = new Uri(scheme: 'file', path: '/workspace/test.dart');
+ Source source = resolver.resolveAbsolute(uri);
+ expect(source, isNotNull);
+ expect(resolver.restoreAbsolute(source), uri);
+ expect(
+ resolver.restoreAbsolute(
+ new NonExistingSource(source.fullName, null, null)),
+ uri);
+ }
+}
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index e679466..b3ceaa5 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/embedder.dart';
import 'package:analyzer/src/cancelable_future.dart';
import 'package:analyzer/src/context/cache.dart';
@@ -234,6 +235,7 @@
return null;
}
+ @deprecated
@override
EmbedderYamlLocator get embedderYamlLocator {
fail("Unexpected invocation of get embedderYamlLocator");
@@ -247,6 +249,17 @@
}
@override
+ ResolverProvider get fileResolverProvider {
+ fail("Unexpected invocation of fileResolverProvider");
+ return null;
+ }
+
+ @override
+ void set fileResolverProvider(ResolverProvider resolverProvider) {
+ fail("Unexpected invocation of fileResolverProvider");
+ }
+
+ @override
List<Source> get htmlSources {
fail("Unexpected invocation of getHtmlSources");
return null;
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index bd01388..645ebeb 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -377,6 +377,49 @@
verify([source]);
}
+ void test_deadCode_deadFinalReturnInCase() {
+ Source source = addSource(r'''
+f() {
+ switch (true) {
+ case true:
+ try {
+ int a = 1;
+ } finally {
+ return;
+ }
+ return;
+ default:
+ break;
+ }
+}''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [HintCode.DEAD_CODE]);
+ verify([source]);
+ }
+
+ void test_deadCode_deadFinalStatementInCase() {
+ Source source = addSource(r'''
+f() {
+ switch (true) {
+ case true:
+ try {
+ int a = 1;
+ } finally {
+ return;
+ }
+ int b = 1;
+ default:
+ break;
+ }
+}''');
+ computeLibrarySourceErrors(source);
+ // A single dead statement at the end of a switch case that is not a
+ // terminating statement will yield two errors.
+ assertErrors(source,
+ [HintCode.DEAD_CODE, StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]);
+ verify([source]);
+ }
+
void test_deadCode_deadOperandLHS_and() {
Source source = addSource(r'''
f() {
@@ -473,49 +516,6 @@
verify([source]);
}
- void test_deadCode_deadFinalReturnInCase() {
- Source source = addSource(r'''
-f() {
- switch (true) {
- case true:
- try {
- int a = 1;
- } finally {
- return;
- }
- return;
- default:
- break;
- }
-}''');
- computeLibrarySourceErrors(source);
- assertErrors(source, [HintCode.DEAD_CODE]);
- verify([source]);
- }
-
- void test_deadCode_deadFinalStatementInCase() {
- Source source = addSource(r'''
-f() {
- switch (true) {
- case true:
- try {
- int a = 1;
- } finally {
- return;
- }
- int b = 1;
- default:
- break;
- }
-}''');
- computeLibrarySourceErrors(source);
- // A single dead statement at the end of a switch case that is not a
- // terminating statement will yield two errors.
- assertErrors(source,
- [HintCode.DEAD_CODE, StaticWarningCode.CASE_BLOCK_NOT_TERMINATED]);
- verify([source]);
- }
-
void test_deadCode_statementAfterBreak_inWhileStatement() {
Source source = addSource(r'''
f(v) {
@@ -1196,6 +1196,27 @@
verify([source]);
}
+ void test_invalidUseOfProtectedMember_in_docs_OK() {
+ Source source = addSource(r'''
+import 'package:meta/meta.dart';
+
+class A {
+ @protected
+ int a() => c;
+ @protected
+ int get b => a();
+ @protected
+ int c = 42;
+}
+
+/// OK: [A.a], [A.b], [A.c].
+f() {}
+''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
void test_invalidUseOfProtectedMember_message() {
Source source = addSource(r'''
import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 518f8c8a..03309dd 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -3556,10 +3556,13 @@
}
static void _shiftTokens(Token token, int afterOffset, int delta) {
- while (token.type != TokenType.EOF) {
- if (token.offset >= afterOffset) {
+ while (true) {
+ if (token.offset > afterOffset) {
token.applyDelta(delta);
}
+ if (token.type == TokenType.EOF) {
+ break;
+ }
token = token.next;
}
}
diff --git a/pkg/analyzer/test/generated/source_factory_test.dart b/pkg/analyzer/test/generated/source_factory_test.dart
index 9932cf8..9aa7fc1 100644
--- a/pkg/analyzer/test/generated/source_factory_test.dart
+++ b/pkg/analyzer/test/generated/source_factory_test.dart
@@ -7,6 +7,7 @@
import 'dart:convert';
import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/source/package_map_resolver.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine, Logger;
@@ -40,7 +41,9 @@
void runPackageMapTests() {
final Uri baseUri = new Uri.file('test/base');
- final List<UriResolver> testResolvers = [new FileUriResolver()];
+ final List<UriResolver> testResolvers = [
+ new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)
+ ];
Packages createPackageMap(Uri base, String configFileContents) {
List<int> bytes = UTF8.encode(configFileContents);
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index 3536c10..96e525e 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -8,6 +8,7 @@
import '../utils.dart';
import 'all_the_rest_test.dart' as all_the_rest;
+import 'bazel_test.dart' as bazel_test;
import 'checked_mode_compile_time_error_code_test.dart'
as checked_mode_compile_time_error_code_test;
import 'compile_time_error_code_test.dart' as compile_time_error_code_test;
@@ -41,6 +42,7 @@
initializeTestEnvironment();
group('generated tests', () {
all_the_rest.main();
+ bazel_test.main();
checked_mode_compile_time_error_code_test.main();
compile_time_error_code_test.main();
constant_test.main();
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index 344612b..a4de8c0 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -59,6 +59,12 @@
fail('Failed to copy token: ${first.lexeme} (${first.offset})');
return false;
}
+ if (first is TokenWithComment) {
+ CommentToken comment = first.precedingComments;
+ if (comment.parent != first) {
+ fail('Failed to link the comment "$comment" with the token "$first".');
+ }
+ }
return super.isEqualTokens(first, second);
}
}
@@ -77,6 +83,13 @@
_assertCloneUnitMember('@A.c() main() {}');
}
+ void test_visitAnnotation_withComment() {
+ CompilationUnitMember clazz =
+ _parseUnitMember('/** comment */ @deprecated class A {}');
+ Annotation annotation = clazz.metadata.single;
+ _assertClone(annotation);
+ }
+
void test_visitArgumentList() {
_assertCloneExpression('m(a, b)');
}
diff --git a/pkg/analyzer/test/source/embedder_test.dart b/pkg/analyzer/test/source/embedder_test.dart
index 80072b8..c16e6f9 100644
--- a/pkg/analyzer/test/source/embedder_test.dart
+++ b/pkg/analyzer/test/source/embedder_test.dart
@@ -9,149 +9,59 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/source/embedder.dart';
+import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:path/path.dart' as path;
import 'package:unittest/unittest.dart';
+import '../reflective_tests.dart';
import '../resource_utils.dart';
import '../utils.dart';
main() {
- group('EmbedderUriResolverTest', () {
- setUp(() {
- initializeTestEnvironment(path.context);
- buildResourceProvider();
- });
- tearDown(() {
- initializeTestEnvironment();
- clearResourceProvider();
- });
- test('test_NullEmbedderYamls', () {
- var resolver = new EmbedderUriResolver(null);
- expect(resolver.length, 0);
- });
- test('test_NoEmbedderYamls', () {
- var locator = new EmbedderYamlLocator({
- 'fox': [pathTranslator.getResource('/empty')]
- });
- expect(locator.embedderYamls.length, 0);
- });
- test('test_EmbedderYaml', () {
- var locator = new EmbedderYamlLocator({
- 'fox': [pathTranslator.getResource('/tmp')]
- });
- var resolver = new EmbedderUriResolver(locator.embedderYamls);
-
- expectResolved(dartUri, posixPath) {
- Source source = resolver.resolveAbsolute(Uri.parse(dartUri));
- expect(source, isNotNull, reason: dartUri);
- expect(source.fullName, posixToOSPath(posixPath));
- }
-
- // We have five mappings.
- expect(resolver.length, 5);
- // Check that they map to the correct paths.
- expectResolved('dart:core', '/tmp/core.dart');
- expectResolved('dart:fox', '/tmp/slippy.dart');
- expectResolved('dart:bear', '/tmp/grizzly.dart');
- expectResolved('dart:relative', '/relative.dart');
- expectResolved('dart:deep', '/tmp/deep/directory/file.dart');
- });
- test('test_BadYAML', () {
- var locator = new EmbedderYamlLocator(null);
- locator.addEmbedderYaml(null, r'''{{{,{{}}},}}''');
- expect(locator.embedderYamls.length, 0);
- });
- test('test_restoreAbsolute', () {
- var locator = new EmbedderYamlLocator({
- 'fox': [pathTranslator.getResource('/tmp')]
- });
- var resolver = new EmbedderUriResolver(locator.embedderYamls);
-
- expectRestore(String dartUri, [String expected]) {
- var parsedUri = Uri.parse(dartUri);
- var source = resolver.resolveAbsolute(parsedUri);
- expect(source, isNotNull);
- // Restore source's uri.
- var restoreUri = resolver.restoreAbsolute(source);
- expect(restoreUri, isNotNull, reason: dartUri);
- // Verify that it is 'dart:fox'.
- expect(restoreUri.toString(), expected ?? dartUri);
- List<String> split = (expected ?? dartUri).split(':');
- expect(restoreUri.scheme, split[0]);
- expect(restoreUri.path, split[1]);
- }
-
- expectRestore('dart:deep');
- expectRestore('dart:deep/file.dart', 'dart:deep');
- expectRestore('dart:deep/part.dart');
- expectRestore('dart:deep/deep/file.dart');
- });
-
- test('test_EmbedderSdk_fromFileUri', () {
- var locator = new EmbedderYamlLocator({
- 'fox': [pathTranslator.getResource('/tmp')]
- });
- var resolver = new EmbedderUriResolver(locator.embedderYamls);
- var sdk = resolver.dartSdk;
-
- expectSource(String posixPath, String dartUri) {
- var uri = Uri.parse(posixToOSFileUri(posixPath));
- var source = sdk.fromFileUri(uri);
- expect(source, isNotNull, reason: posixPath);
- expect(source.uri.toString(), dartUri);
- expect(source.fullName, posixToOSPath(posixPath));
- }
-
- expectSource('/tmp/slippy.dart', 'dart:fox');
- expectSource('/tmp/deep/directory/file.dart', 'dart:deep');
- expectSource('/tmp/deep/directory/part.dart', 'dart:deep/part.dart');
- });
- test('test_EmbedderSdk_getSdkLibrary', () {
- var locator = new EmbedderYamlLocator({
- 'fox': [pathTranslator.getResource('/tmp')]
- });
- var resolver = new EmbedderUriResolver(locator.embedderYamls);
- var sdk = resolver.dartSdk;
- var lib = sdk.getSdkLibrary('dart:fox');
- expect(lib, isNotNull);
- expect(lib.path, posixToOSPath('/tmp/slippy.dart'));
- expect(lib.shortName, 'dart:fox');
- });
- test('test_EmbedderSdk_mapDartUri', () {
- var locator = new EmbedderYamlLocator({
- 'fox': [pathTranslator.getResource('/tmp')]
- });
- var resolver = new EmbedderUriResolver(locator.embedderYamls);
- var sdk = resolver.dartSdk;
-
- expectSource(String dartUri, String posixPath) {
- var source = sdk.mapDartUri(dartUri);
- expect(source, isNotNull, reason: posixPath);
- expect(source.uri.toString(), dartUri);
- expect(source.fullName, posixToOSPath(posixPath));
- }
-
- expectSource('dart:core', '/tmp/core.dart');
- expectSource('dart:fox', '/tmp/slippy.dart');
- expectSource('dart:deep', '/tmp/deep/directory/file.dart');
- expectSource('dart:deep/part.dart', '/tmp/deep/directory/part.dart');
- });
- });
+ runReflectiveTests(DartUriResolverTest);
+ runReflectiveTests(EmbedderSdkTest);
+ runReflectiveTests(EmbedderUriResolverTest);
+ runReflectiveTests(EmbedderYamlLocatorTest);
}
-TestPathTranslator pathTranslator;
-ResourceProvider resourceProvider;
+@reflectiveTest
+class DartUriResolverTest extends EmbedderRelatedTest {
+ void test_embedderYaml() {
+ EmbedderYamlLocator locator = new EmbedderYamlLocator({
+ 'fox': [pathTranslator.getResource('/tmp')]
+ });
+ EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+ DartUriResolver resolver = new DartUriResolver(sdk);
-buildResourceProvider() {
- var rawProvider = new MemoryResourceProvider(isWindows: isWindows);
- resourceProvider = new TestResourceProvider(rawProvider);
- pathTranslator = new TestPathTranslator(rawProvider)
- ..newFolder('/empty')
- ..newFolder('/tmp')
- ..newFile(
- '/tmp/_embedder.yaml',
- r'''
+ void expectResolved(dartUri, posixPath) {
+ Source source = resolver.resolveAbsolute(Uri.parse(dartUri));
+ expect(source, isNotNull, reason: dartUri);
+ expect(source.fullName, posixToOSPath(posixPath));
+ }
+ // Check that they map to the correct paths.
+ expectResolved('dart:core', '/tmp/core.dart');
+ expectResolved('dart:fox', '/tmp/slippy.dart');
+ expectResolved('dart:bear', '/tmp/grizzly.dart');
+ expectResolved('dart:relative', '/relative.dart');
+ expectResolved('dart:deep', '/tmp/deep/directory/file.dart');
+ }
+}
+
+abstract class EmbedderRelatedTest {
+ TestPathTranslator pathTranslator;
+ ResourceProvider resourceProvider;
+
+ buildResourceProvider() {
+ MemoryResourceProvider rawProvider =
+ new MemoryResourceProvider(isWindows: isWindows);
+ resourceProvider = new TestResourceProvider(rawProvider);
+ pathTranslator = new TestPathTranslator(rawProvider)
+ ..newFolder('/empty')
+ ..newFolder('/tmp')
+ ..newFile(
+ '/tmp/_embedder.yaml',
+ r'''
embedded_libs:
"dart:core" : "core.dart"
"dart:fox": "slippy.dart"
@@ -160,9 +70,161 @@
"dart:deep": "deep/directory/file.dart"
"fart:loudly": "nomatter.dart"
''');
+ }
+
+ clearResourceProvider() {
+ resourceProvider = null;
+ pathTranslator = null;
+ }
+
+ void setUp() {
+ initializeTestEnvironment(path.context);
+ buildResourceProvider();
+ }
+
+ void tearDown() {
+ initializeTestEnvironment();
+ clearResourceProvider();
+ }
}
-clearResourceProvider() {
- resourceProvider = null;
- pathTranslator = null;
+@reflectiveTest
+class EmbedderSdkTest extends EmbedderRelatedTest {
+ void test_creation() {
+ EmbedderYamlLocator locator = new EmbedderYamlLocator({
+ 'fox': [pathTranslator.getResource('/tmp')]
+ });
+ EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+
+ expect(sdk.urlMappings, hasLength(5));
+ }
+
+ void test_fromFileUri() {
+ EmbedderYamlLocator locator = new EmbedderYamlLocator({
+ 'fox': [pathTranslator.getResource('/tmp')]
+ });
+ EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+
+ expectSource(String posixPath, String dartUri) {
+ Uri uri = Uri.parse(posixToOSFileUri(posixPath));
+ Source source = sdk.fromFileUri(uri);
+ expect(source, isNotNull, reason: posixPath);
+ expect(source.uri.toString(), dartUri);
+ expect(source.fullName, posixToOSPath(posixPath));
+ }
+
+ expectSource('/tmp/slippy.dart', 'dart:fox');
+ expectSource('/tmp/deep/directory/file.dart', 'dart:deep');
+ expectSource('/tmp/deep/directory/part.dart', 'dart:deep/part.dart');
+ }
+
+ void test_getSdkLibrary() {
+ EmbedderYamlLocator locator = new EmbedderYamlLocator({
+ 'fox': [pathTranslator.getResource('/tmp')]
+ });
+ EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+
+ SdkLibrary lib = sdk.getSdkLibrary('dart:fox');
+ expect(lib, isNotNull);
+ expect(lib.path, posixToOSPath('/tmp/slippy.dart'));
+ expect(lib.shortName, 'dart:fox');
+ }
+
+ void test_mapDartUri() {
+ EmbedderYamlLocator locator = new EmbedderYamlLocator({
+ 'fox': [pathTranslator.getResource('/tmp')]
+ });
+ EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls);
+
+ void expectSource(String dartUri, String posixPath) {
+ Source source = sdk.mapDartUri(dartUri);
+ expect(source, isNotNull, reason: posixPath);
+ expect(source.uri.toString(), dartUri);
+ expect(source.fullName, posixToOSPath(posixPath));
+ }
+
+ expectSource('dart:core', '/tmp/core.dart');
+ expectSource('dart:fox', '/tmp/slippy.dart');
+ expectSource('dart:deep', '/tmp/deep/directory/file.dart');
+ expectSource('dart:deep/part.dart', '/tmp/deep/directory/part.dart');
+ }
+}
+
+@reflectiveTest
+class EmbedderUriResolverTest extends EmbedderRelatedTest {
+ void test_embedderYaml() {
+ var locator = new EmbedderYamlLocator({
+ 'fox': [pathTranslator.getResource('/tmp')]
+ });
+ var resolver = new EmbedderUriResolver(locator.embedderYamls);
+
+ expectResolved(dartUri, posixPath) {
+ Source source = resolver.resolveAbsolute(Uri.parse(dartUri));
+ expect(source, isNotNull, reason: dartUri);
+ expect(source.fullName, posixToOSPath(posixPath));
+ }
+
+ // We have five mappings.
+ expect(resolver, hasLength(5));
+ // Check that they map to the correct paths.
+ expectResolved('dart:core', '/tmp/core.dart');
+ expectResolved('dart:fox', '/tmp/slippy.dart');
+ expectResolved('dart:bear', '/tmp/grizzly.dart');
+ expectResolved('dart:relative', '/relative.dart');
+ expectResolved('dart:deep', '/tmp/deep/directory/file.dart');
+ }
+
+ void test_nullEmbedderYamls() {
+ var resolver = new EmbedderUriResolver(null);
+ expect(resolver, hasLength(0));
+ }
+
+ void test_restoreAbsolute() {
+ var locator = new EmbedderYamlLocator({
+ 'fox': [pathTranslator.getResource('/tmp')]
+ });
+ var resolver = new EmbedderUriResolver(locator.embedderYamls);
+
+ expectRestore(String dartUri, [String expected]) {
+ var parsedUri = Uri.parse(dartUri);
+ var source = resolver.resolveAbsolute(parsedUri);
+ expect(source, isNotNull);
+ // Restore source's uri.
+ var restoreUri = resolver.restoreAbsolute(source);
+ expect(restoreUri, isNotNull, reason: dartUri);
+ // Verify that it is 'dart:fox'.
+ expect(restoreUri.toString(), expected ?? dartUri);
+ List<String> split = (expected ?? dartUri).split(':');
+ expect(restoreUri.scheme, split[0]);
+ expect(restoreUri.path, split[1]);
+ }
+
+ expectRestore('dart:deep');
+ expectRestore('dart:deep/file.dart', 'dart:deep');
+ expectRestore('dart:deep/part.dart');
+ expectRestore('dart:deep/deep/file.dart');
+ }
+}
+
+@reflectiveTest
+class EmbedderYamlLocatorTest extends EmbedderRelatedTest {
+ void test_empty() {
+ EmbedderYamlLocator locator = new EmbedderYamlLocator({
+ 'fox': [pathTranslator.getResource('/empty')]
+ });
+ expect(locator.embedderYamls, hasLength(0));
+ }
+
+ void test_invalid() {
+ EmbedderYamlLocator locator = new EmbedderYamlLocator(null);
+ locator.addEmbedderYaml(null, r'''{{{,{{}}},}}''');
+ expect(locator.embedderYamls, hasLength(0));
+ }
+
+ void test_valid() {
+ EmbedderYamlLocator locator = new EmbedderYamlLocator({
+ 'fox': [pathTranslator.getResource('/tmp')]
+ });
+ expect(locator.embedderYamls, hasLength(1));
+ }
}
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 89cbfbc..33bd37b 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -4174,6 +4174,43 @@
expect(info.userToDependsOn['f'], unorderedEquals(['A']));
}
+ test_referencedNames_topLevelVariable() {
+ ReferencedNames info = _computeReferencedNames('''
+A v = new B(c);
+''');
+ expect(info.names, unorderedEquals(['A', 'B', 'c']));
+ expect(info.userToDependsOn.keys, unorderedEquals(['v']));
+ expect(info.userToDependsOn['v'], unorderedEquals(['A', 'B', 'c']));
+ }
+
+ test_referencedNames_topLevelVariable_multiple() {
+ ReferencedNames info = _computeReferencedNames('''
+A v1 = new B(c), v2 = new D<E>(f);
+''');
+ expect(info.names, unorderedEquals(['A', 'B', 'c', 'D', 'E', 'f']));
+ expect(info.userToDependsOn.keys, unorderedEquals(['v1', 'v2']));
+ expect(info.userToDependsOn['v1'], unorderedEquals(['A', 'B', 'c']));
+ expect(info.userToDependsOn['v2'], unorderedEquals(['A', 'D', 'E', 'f']));
+ }
+
+ test_referencedNames_unit_classTypeAlias() {
+ ReferencedNames info = _computeReferencedNames('''
+class U = A with B implements C;
+''');
+ expect(info.names, unorderedEquals(['A', 'B', 'C']));
+ expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+ expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B', 'C']));
+ }
+
+ test_referencedNames_unit_classTypeAlias_typeParameters() {
+ ReferencedNames info = _computeReferencedNames('''
+class U<T1, T2 extends D> = A<T1> with B<T2> implements C<T1, T2>;
+''');
+ expect(info.names, unorderedEquals(['A', 'B', 'C', 'D']));
+ expect(info.userToDependsOn.keys, unorderedEquals(['U']));
+ expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B', 'C', 'D']));
+ }
+
test_referencedNames_unit_function() {
ReferencedNames info = _computeReferencedNames('''
A f(B b) {
diff --git a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
index 8ef225a..975de87 100644
--- a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
+++ b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
@@ -6,8 +6,12 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/src/task/incremental_element_builder.dart';
+import 'package:analyzer/task/dart.dart';
import 'package:unittest/unittest.dart';
import '../../reflective_tests.dart';
@@ -36,6 +40,631 @@
return newCode.substring(node.offset, node.end);
}
+ test_classDelta_constructor_0to1() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+}
+''');
+ helper.initOld(oldUnit);
+ ConstructorElement oldConstructorElement =
+ helper.element.unnamedConstructor;
+ _buildNewUnit(r'''
+class A {
+ A.a();
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ ClassMember newConstructorNode = helper.newMembers[0];
+ // elements
+ ConstructorElement newConstructorElement = newConstructorNode.element;
+ expect(newConstructorElement, isNotNull);
+ expect(newConstructorElement.name, 'a');
+ // classElement.constructors
+ ClassElement classElement = helper.element;
+ expect(classElement.constructors, unorderedEquals([newConstructorElement]));
+ // verify delta
+ expect(helper.delta.addedConstructors,
+ unorderedEquals([newConstructorElement]));
+ expect(helper.delta.removedConstructors,
+ unorderedEquals([oldConstructorElement]));
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_constructor_1to0() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ A.a();
+}
+''');
+ helper.initOld(oldUnit);
+ ConstructorElement oldElementA = helper.element.getNamedConstructor('a');
+ _buildNewUnit(r'''
+class A {
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // classElement.constructors
+ ClassElement classElement = helper.element;
+ {
+ List<ConstructorElement> constructors = classElement.constructors;
+ expect(constructors, hasLength(1));
+ expect(constructors[0].isDefaultConstructor, isTrue);
+ expect(constructors[0].isSynthetic, isTrue);
+ }
+ // verify delta
+ expect(helper.delta.addedConstructors, unorderedEquals([]));
+ expect(helper.delta.removedConstructors, unorderedEquals([oldElementA]));
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_constructor_1to2() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ A.a();
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ A.a();
+ A.b();
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ ClassMember nodeA = helper.newMembers[0];
+ ClassMember nodeB = helper.newMembers[1];
+ expect(nodeA, same(helper.oldMembers[0]));
+ // elements
+ ConstructorElement elementA = nodeA.element;
+ ConstructorElement elementB = nodeB.element;
+ expect(elementA, isNotNull);
+ expect(elementB, isNotNull);
+ expect(elementA.name, 'a');
+ expect(elementB.name, 'b');
+ // classElement.constructors
+ ClassElement classElement = helper.element;
+ expect(classElement.constructors, unorderedEquals([elementA, elementB]));
+ // verify delta
+ expect(helper.delta.addedConstructors, unorderedEquals([elementB]));
+ expect(helper.delta.removedConstructors, unorderedEquals([]));
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_constructor_2to1() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ A.a();
+ A.b();
+}
+''');
+ helper.initOld(oldUnit);
+ ConstructorElement oldElementA = helper.element.getNamedConstructor('a');
+ _buildNewUnit(r'''
+class A {
+ A.b();
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ ClassMember nodeB = helper.newMembers[0];
+ expect(nodeB, same(helper.oldMembers[1]));
+ // elements
+ ConstructorElement elementB = nodeB.element;
+ expect(elementB, isNotNull);
+ expect(elementB.name, 'b');
+ // classElement.constructors
+ ClassElement classElement = helper.element;
+ expect(classElement.constructors, unorderedEquals([elementB]));
+ // verify delta
+ expect(helper.delta.addedConstructors, unorderedEquals([]));
+ expect(helper.delta.removedConstructors, unorderedEquals([oldElementA]));
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_constructor_2to2_reorder() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ A.a();
+ A.b();
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ A.b();
+ A.a();
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ ClassMember nodeB = helper.newMembers[0];
+ ClassMember nodeA = helper.newMembers[1];
+ expect(nodeB, same(helper.oldMembers[1]));
+ expect(nodeA, same(helper.oldMembers[0]));
+ // elements
+ ConstructorElement elementB = nodeB.element;
+ ConstructorElement elementA = nodeA.element;
+ expect(elementB, isNotNull);
+ expect(elementA, isNotNull);
+ expect(elementB.name, 'b');
+ expect(elementA.name, 'a');
+ // classElement.constructors
+ ClassElement classElement = helper.element;
+ expect(classElement.constructors, unorderedEquals([elementB, elementA]));
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_field_add() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ int aaa;
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ int aaa;
+ int bbb;
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ FieldDeclaration nodeA = helper.newMembers[0];
+ FieldDeclaration newNodeB = helper.newMembers[1];
+ List<VariableDeclaration> newFieldsB = newNodeB.fields.variables;
+ expect(nodeA, same(helper.oldMembers[0]));
+ expect(newFieldsB, hasLength(1));
+ // elements
+ FieldElement newFieldElementB = newFieldsB[0].name.staticElement;
+ expect(newFieldElementB.name, 'bbb');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors,
+ unorderedEquals([newFieldElementB.getter, newFieldElementB.setter]));
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_field_changeName() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ int aaa;
+ int bbb;
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ int aaa2;
+ int bbb;
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ FieldDeclaration oldNodeA = helper.oldMembers[0];
+ FieldDeclaration newNodeA = helper.newMembers[0];
+ List<VariableDeclaration> oldFieldsA = oldNodeA.fields.variables;
+ List<VariableDeclaration> newFieldsA = newNodeA.fields.variables;
+ expect(oldFieldsA, hasLength(1));
+ expect(newFieldsA, hasLength(1));
+ FieldDeclaration nodeB = helper.newMembers[1];
+ expect(nodeB, same(helper.oldMembers[1]));
+ // elements
+ FieldElement oldFieldElementA = oldFieldsA[0].name.staticElement;
+ FieldElement newFieldElementA = newFieldsA[0].name.staticElement;
+ expect(oldFieldElementA.name, 'aaa');
+ expect(newFieldElementA.name, 'aaa2');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors,
+ unorderedEquals([newFieldElementA.getter, newFieldElementA.setter]));
+ expect(helper.delta.removedAccessors,
+ unorderedEquals([oldFieldElementA.getter, oldFieldElementA.setter]));
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_field_remove() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ int aaa;
+ int bbb;
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ int aaa;
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ FieldDeclaration nodeA = helper.newMembers[0];
+ FieldDeclaration oldNodeB = helper.oldMembers[1];
+ List<VariableDeclaration> oldFieldsB = oldNodeB.fields.variables;
+ expect(nodeA, same(helper.oldMembers[0]));
+ // elements
+ FieldElement oldFieldElementB = oldFieldsB[0].name.staticElement;
+ expect(oldFieldElementB.name, 'bbb');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors,
+ unorderedEquals([oldFieldElementB.getter, oldFieldElementB.setter]));
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_getter_add() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ int get aaa => 1;
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ int get aaa => 1;
+ int get bbb => 2;
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ MethodDeclaration nodeA = helper.oldMembers[0];
+ MethodDeclaration newNodeB = helper.newMembers[1];
+ expect(nodeA, same(helper.oldMembers[0]));
+ // elements
+ PropertyAccessorElement elementA = nodeA.element;
+ PropertyAccessorElement newElementB = newNodeB.element;
+ expect(elementA, isNotNull);
+ expect(elementA.name, 'aaa');
+ expect(newElementB, isNotNull);
+ expect(newElementB.name, 'bbb');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, unorderedEquals([newElementB]));
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_getter_remove() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ int get aaa => 1;
+ int get bbb => 2;
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ int get aaa => 1;
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ MethodDeclaration nodeA = helper.oldMembers[0];
+ MethodDeclaration oldNodeB = helper.oldMembers[1];
+ expect(nodeA, same(helper.oldMembers[0]));
+ // elements
+ PropertyAccessorElement elementA = nodeA.element;
+ PropertyAccessorElement oldElementB = oldNodeB.element;
+ expect(elementA, isNotNull);
+ expect(elementA.name, 'aaa');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, unorderedEquals([oldElementB]));
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_method_add() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ aaa() {}
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ aaa() {}
+ bbb() {}
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ ClassMember nodeA = helper.oldMembers[0];
+ ClassMember newNodeB = helper.newMembers[1];
+ expect(nodeA, same(helper.oldMembers[0]));
+ // elements
+ MethodElement elementA = nodeA.element;
+ MethodElement newElementB = newNodeB.element;
+ expect(elementA, isNotNull);
+ expect(elementA.name, 'aaa');
+ expect(newElementB, isNotNull);
+ expect(newElementB.name, 'bbb');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, unorderedEquals([newElementB]));
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_method_addParameter() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ aaa() {}
+ bbb() {}
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ aaa(int p) {}
+ bbb() {}
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ ClassMember oldNodeA = helper.oldMembers[0];
+ ClassMember newNodeA = helper.newMembers[0];
+ ClassMember nodeB = helper.newMembers[1];
+ expect(newNodeA, isNot(same(oldNodeA)));
+ expect(nodeB, same(helper.oldMembers[1]));
+ // elements
+ MethodElement oldElementA = oldNodeA.element;
+ MethodElement newElementA = newNodeA.element;
+ MethodElement elementB = nodeB.element;
+ expect(newElementA, isNotNull);
+ expect(newElementA.name, 'aaa');
+ expect(oldElementA.parameters, hasLength(0));
+ expect(newElementA.parameters, hasLength(1));
+ expect(elementB, isNotNull);
+ expect(elementB.name, 'bbb');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, unorderedEquals([newElementA]));
+ expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
+ }
+
+ test_classDelta_method_changeName() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ aaa(int ap) {
+ int av = 1;
+ af(afp) {}
+ }
+ bbb(int bp) {
+ int bv = 1;
+ bf(bfp) {}
+ }
+}
+''');
+ helper.initOld(oldUnit);
+ ConstructorElement oldConstructor = helper.element.unnamedConstructor;
+ _buildNewUnit(r'''
+class A {
+ aaa2(int ap) {
+ int av = 1;
+ af(afp) {}
+ }
+ bbb(int bp) {
+ int bv = 1;
+ bf(bfp) {}
+ }
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ expect(helper.element.unnamedConstructor, same(oldConstructor));
+ // nodes
+ ClassMember oldNodeA = helper.oldMembers[0];
+ ClassMember newNodeA = helper.newMembers[0];
+ ClassMember nodeB = helper.newMembers[1];
+ expect(nodeB, same(helper.oldMembers[1]));
+ // elements
+ MethodElement oldElementA = oldNodeA.element;
+ MethodElement newElementA = newNodeA.element;
+ MethodElement elementB = nodeB.element;
+ expect(newElementA, isNotNull);
+ expect(newElementA.name, 'aaa2');
+ expect(elementB, isNotNull);
+ expect(elementB.name, 'bbb');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, unorderedEquals([newElementA]));
+ expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
+ }
+
+ test_classDelta_method_remove() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ aaa() {}
+ bbb() {}
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ aaa() {}
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ ClassMember nodeA = helper.oldMembers[0];
+ ClassMember oldNodeB = helper.oldMembers[1];
+ expect(nodeA, same(helper.oldMembers[0]));
+ // elements
+ MethodElement elementA = nodeA.element;
+ MethodElement oldElementB = oldNodeB.element;
+ expect(elementA, isNotNull);
+ expect(elementA.name, 'aaa');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, unorderedEquals([oldElementB]));
+ }
+
+ test_classDelta_method_removeParameter() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ aaa(int p) {}
+ bbb() {}
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ aaa() {}
+ bbb() {}
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ ClassMember oldNodeA = helper.oldMembers[0];
+ ClassMember newNodeA = helper.newMembers[0];
+ ClassMember nodeB = helper.newMembers[1];
+ expect(newNodeA, isNot(same(oldNodeA)));
+ expect(nodeB, same(helper.oldMembers[1]));
+ // elements
+ MethodElement oldElementA = oldNodeA.element;
+ MethodElement newElementA = newNodeA.element;
+ MethodElement elementB = nodeB.element;
+ expect(newElementA, isNotNull);
+ expect(newElementA.name, 'aaa');
+ expect(oldElementA.parameters, hasLength(1));
+ expect(newElementA.parameters, hasLength(0));
+ expect(elementB, isNotNull);
+ expect(elementB.name, 'bbb');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, unorderedEquals([newElementA]));
+ expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
+ }
+
+ test_classDelta_setter_add() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ void set aaa(int pa) {}
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ void set aaa(int pa) {}
+ void set bbb(int pb) {}
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ MethodDeclaration nodeA = helper.oldMembers[0];
+ MethodDeclaration newNodeB = helper.newMembers[1];
+ expect(nodeA, same(helper.oldMembers[0]));
+ // elements
+ PropertyAccessorElement elementA = nodeA.element;
+ PropertyAccessorElement newElementB = newNodeB.element;
+ expect(elementA, isNotNull);
+ expect(elementA.name, 'aaa=');
+ expect(newElementB, isNotNull);
+ expect(newElementB.name, 'bbb=');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, unorderedEquals([newElementB]));
+ expect(helper.delta.removedAccessors, isEmpty);
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
+ test_classDelta_setter_remove() {
+ var helper = new _ClassDeltaHelper('A');
+ _buildOldUnit(r'''
+class A {
+ void set aaa(int pa) {}
+ void set bbb(int pb) {}
+}
+''');
+ helper.initOld(oldUnit);
+ _buildNewUnit(r'''
+class A {
+ void set aaa(int pa) {}
+}
+''');
+ helper.initNew(newUnit, unitDelta);
+ // nodes
+ MethodDeclaration nodeA = helper.oldMembers[0];
+ MethodDeclaration oldNodeB = helper.oldMembers[1];
+ expect(nodeA, same(helper.oldMembers[0]));
+ // elements
+ PropertyAccessorElement elementA = nodeA.element;
+ PropertyAccessorElement oldElementB = oldNodeB.element;
+ expect(elementA, isNotNull);
+ expect(elementA.name, 'aaa=');
+ // verify delta
+ expect(helper.delta.addedConstructors, isEmpty);
+ expect(helper.delta.removedConstructors, isEmpty);
+ expect(helper.delta.addedAccessors, isEmpty);
+ expect(helper.delta.removedAccessors, unorderedEquals([oldElementB]));
+ expect(helper.delta.addedMethods, isEmpty);
+ expect(helper.delta.removedMethods, isEmpty);
+ }
+
test_directives_add() {
_buildOldUnit(r'''
library test;
@@ -679,6 +1308,18 @@
builder.build();
unitDelta = builder.unitDelta;
expect(newUnit.element, unitElement);
+ // Flush all tokens, ASTs and elements.
+ context.analysisCache.flush((target, result) {
+ return result == TOKEN_STREAM ||
+ result == PARSED_UNIT ||
+ RESOLVED_UNIT_RESULTS.contains(result) ||
+ LIBRARY_ELEMENT_RESULTS.contains(result);
+ });
+ // Compute a new AST with built elements.
+ CompilationUnit newUnitFull = context.computeResult(
+ new LibrarySpecificUnit(source, source), RESOLVED_UNIT1);
+ expect(newUnitFull, isNot(same(newUnit)));
+ new _BuiltElementsValidator().isEqualNodes(newUnitFull, newUnit);
}
void _buildOldUnit(String oldCode, [Source libSource]) {
@@ -692,3 +1333,107 @@
expect(unitElement, isNotNull);
}
}
+
+/**
+ * Compares tokens and ASTs, and built elements of declared identifiers.
+ */
+class _BuiltElementsValidator extends AstComparator {
+ @override
+ bool isEqualNodes(AstNode expected, AstNode actual) {
+ // Elements of constructors must be linked to the elements of the
+ // corresponding enclosing classes.
+ if (actual is ConstructorDeclaration) {
+ ConstructorElement actualConstructorElement = actual.element;
+ ClassDeclaration actualClassNode = actual.parent;
+ expect(actualConstructorElement.enclosingElement,
+ same(actualClassNode.element));
+ }
+ // Compare nodes.
+ bool result = super.isEqualNodes(expected, actual);
+ if (!result) {
+ fail('|$actual| != expected |$expected|');
+ }
+ // Verify that declared identifiers have equal elements.
+ if (expected is SimpleIdentifier && actual is SimpleIdentifier) {
+ if (expected.inDeclarationContext()) {
+ expect(actual.inDeclarationContext(), isTrue);
+ Element expectedElement = expected.staticElement;
+ Element actualElement = actual.staticElement;
+ _verifyElement(expectedElement, actualElement, 'staticElement');
+ }
+ }
+ return true;
+ }
+
+ void _verifyElement(Element expected, Element actual, String desc) {
+ if (expected == null && actual == null) {
+ return;
+ }
+ // Prefixes are built later.
+ if (actual is PrefixElement) {
+ return;
+ }
+ // Compare properties.
+ _verifyEqual('$desc name', expected.name, actual.name);
+ _verifyEqual('$desc nameOffset', expected.nameOffset, actual.nameOffset);
+ if (expected is ElementImpl && actual is ElementImpl) {
+ _verifyEqual('$desc codeOffset', expected.codeOffset, actual.codeOffset);
+ _verifyEqual('$desc codeLength', expected.codeLength, actual.codeLength);
+ }
+ if (expected is LocalElement && actual is LocalElement) {
+ _verifyEqual(
+ '$desc visibleRange', expected.visibleRange, actual.visibleRange);
+ }
+ _verifyEqual('$desc documentationComment', expected.documentationComment,
+ actual.documentationComment);
+ {
+ var expectedEnclosing = expected.enclosingElement;
+ var actualEnclosing = actual.enclosingElement;
+ if (expectedEnclosing != null) {
+ expect(actualEnclosing, isNotNull, reason: '$desc enclosingElement');
+ _verifyElement(expectedEnclosing, actualEnclosing,
+ '${expectedEnclosing.name}.$desc');
+ }
+ }
+ }
+
+ void _verifyEqual(String name, expected, actual) {
+ if (actual != expected) {
+ fail('$name\nExpected: $expected\n Actual: $actual');
+ }
+ }
+}
+
+class _ClassDeltaHelper {
+ final String name;
+
+ ClassElementDelta delta;
+ ClassElement element;
+ List<ClassMember> oldMembers;
+ List<ClassMember> newMembers;
+
+ _ClassDeltaHelper(this.name);
+
+ void initNew(CompilationUnit newUnit, CompilationUnitElementDelta unitDelta) {
+ ClassDeclaration newClass = _findClassNode(newUnit, name);
+ expect(newClass, isNotNull);
+ newMembers = newClass.members.toList();
+ for (ClassElementDelta delta in unitDelta.classDeltas) {
+ if (delta.element.name == name) {
+ this.delta = delta;
+ }
+ }
+ expect(this.delta, isNotNull, reason: 'No delta for class: $name');
+ }
+
+ void initOld(CompilationUnit oldUnit) {
+ ClassDeclaration oldClass = _findClassNode(oldUnit, name);
+ expect(oldClass, isNotNull);
+ element = oldClass.element;
+ oldMembers = oldClass.members.toList();
+ }
+
+ ClassDeclaration _findClassNode(CompilationUnit unit, String name) =>
+ unit.declarations.singleWhere((unitMember) =>
+ unitMember is ClassDeclaration && unitMember.name.name == name);
+}
diff --git a/pkg/analyzer/tool/summary/build_sdk_summaries.dart b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
index fc7ec0e..bf6d8b5 100644
--- a/pkg/analyzer/tool/summary/build_sdk_summaries.dart
+++ b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
@@ -29,7 +29,7 @@
// Prepare results.
//
String sdkPath = args.length > 2 ? args[2] : null;
- _Output output = _buildMultipleOutputs(sdkPath, includeSpec);
+ SummaryOutput output = _buildMultipleOutputs(sdkPath, includeSpec);
if (output == null) {
exitCode = 1;
return;
@@ -49,43 +49,32 @@
//
// Prepare results.
//
- _Output output = _buildMultipleOutputs(sdkPath, true);
+ SummaryOutput output = _buildMultipleOutputs(sdkPath, true);
if (output == null) {
exitCode = 1;
return;
}
+
//
// Write results.
//
- fb.Builder builder = new fb.Builder();
- fb.Offset specSumOffset = builder.writeListUint8(output.spec.sum);
- fb.Offset specIndexOffset = builder.writeListUint8(output.spec.index);
- fb.Offset strongSumOffset = builder.writeListUint8(output.strong.sum);
- fb.Offset strongIndexOffset = builder.writeListUint8(output.strong.index);
- builder.startTable();
- builder.addOffset(_FIELD_SPEC_SUM, specSumOffset);
- builder.addOffset(_FIELD_SPEC_INDEX, specIndexOffset);
- builder.addOffset(_FIELD_STRONG_SUM, strongSumOffset);
- builder.addOffset(_FIELD_STRONG_INDEX, strongIndexOffset);
- fb.Offset offset = builder.endTable();
- new File(outputPath)
- .writeAsBytesSync(builder.finish(offset), mode: FileMode.WRITE_ONLY);
+ output.write(outputPath);
} else if (command == 'extract-spec-sum' && args.length == 3) {
String inputPath = args[1];
String outputPath = args[2];
- _extractSingleOutput(inputPath, _FIELD_SPEC_SUM, outputPath);
+ _extractSingleOutput(inputPath, FIELD_SPEC_SUM, outputPath);
} else if (command == 'extract-spec-index' && args.length == 3) {
String inputPath = args[1];
String outputPath = args[2];
- _extractSingleOutput(inputPath, _FIELD_SPEC_INDEX, outputPath);
+ _extractSingleOutput(inputPath, FIELD_SPEC_INDEX, outputPath);
} else if (command == 'extract-strong-sum' && args.length == 3) {
String inputPath = args[1];
String outputPath = args[2];
- _extractSingleOutput(inputPath, _FIELD_STRONG_SUM, outputPath);
+ _extractSingleOutput(inputPath, FIELD_STRONG_SUM, outputPath);
} else if (command == 'extract-strong-index' && args.length == 3) {
String inputPath = args[1];
String outputPath = args[2];
- _extractSingleOutput(inputPath, _FIELD_STRONG_INDEX, outputPath);
+ _extractSingleOutput(inputPath, FIELD_STRONG_INDEX, outputPath);
} else {
_printUsage();
exitCode = 1;
@@ -98,12 +87,7 @@
*/
const BINARY_NAME = "build_sdk_summaries";
-const int _FIELD_SPEC_INDEX = 1;
-const int _FIELD_SPEC_SUM = 0;
-const int _FIELD_STRONG_INDEX = 3;
-const int _FIELD_STRONG_SUM = 2;
-
-_Output _buildMultipleOutputs(String sdkPath, bool includeSpec) {
+SummaryOutput _buildMultipleOutputs(String sdkPath, bool includeSpec) {
//
// Validate the SDK path.
//
@@ -122,14 +106,15 @@
//
BuilderOutput spec = includeSpec ? _buildOutput(sdkPath, false) : null;
BuilderOutput strong = _buildOutput(sdkPath, true);
- return new _Output(spec, strong);
+ return new SummaryOutput(spec, strong);
}
BuilderOutput _buildOutput(String sdkPath, bool strongMode) {
String modeName = strongMode ? 'strong' : 'spec';
print('Generating $modeName mode summary and index.');
Stopwatch sw = new Stopwatch()..start();
- BuilderOutput output = new SummaryBuilder.forSdk(sdkPath, strongMode).build();
+ SummaryBuildConfig config = new SummaryBuildConfig(strongMode: strongMode);
+ BuilderOutput output = new SummaryBuilder.forSdk(sdkPath, config).build();
print('\tDone in ${sw.elapsedMilliseconds} ms.');
return output;
}
@@ -169,10 +154,3 @@
print(' extract-strong-index input_file output_file');
print(' Extract the strong-mode index file.');
}
-
-class _Output {
- final BuilderOutput spec;
- final BuilderOutput strong;
-
- _Output(this.spec, this.strong);
-}
diff --git a/pkg/analyzer/tool/task_dependency_graph/generate.dart b/pkg/analyzer/tool/task_dependency_graph/generate.dart
index 2b904bb..fc88511 100644
--- a/pkg/analyzer/tool/task_dependency_graph/generate.dart
+++ b/pkg/analyzer/tool/task_dependency_graph/generate.dart
@@ -162,7 +162,7 @@
List<UriResolver> uriResolvers = [
new DartUriResolver(sdk),
new PackageUriResolver(<JavaFile>[packagesDir]),
- new FileUriResolver()
+ new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)
];
context.sourceFactory = new SourceFactory(uriResolvers);
Source dartDartSource =
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index f6b3ddd..879ec69 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -257,7 +257,7 @@
Driver.createAnalysisOptionsForCommandLineOptions(options);
directorySdk.useSummary = !options.buildSummaryOnlyAst;
sdk = directorySdk;
- sdkBundle = directorySdk.getSummarySdkBundle();
+ sdkBundle = directorySdk.getSummarySdkBundle(options.strongMode);
}
// In AST mode include SDK bundle to avoid parsing SDK sources.
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index a116073..44cc1d1 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -10,7 +10,6 @@
import 'package:analyzer/file_system/file_system.dart' as file_system;
import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
import 'package:analyzer/plugin/options.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/analysis_options_provider.dart';
@@ -90,9 +89,6 @@
IncrementalAnalysisSession incrementalSession;
@override
- EmbeddedResolverProvider embeddedUriResolverProvider;
-
- @override
ResolverProvider packageResolverProvider;
/// SDK instance.
@@ -346,25 +342,13 @@
PhysicalResourceProvider.INSTANCE.getResource('.');
UriResolver resolver = packageResolverProvider(folder);
if (resolver != null) {
- UriResolver sdkResolver;
-
- // Check for a resolver provider.
- if (embeddedUriResolverProvider != null) {
- EmbedderUriResolver embedderUriResolver =
- embeddedUriResolverProvider(folder);
- if (embedderUriResolver != null && embedderUriResolver.length != 0) {
- sdkResolver = embedderUriResolver;
- }
- }
-
- // Default to a Dart URI resolver if no embedder is found.
- sdkResolver ??= new DartUriResolver(sdk);
+ UriResolver sdkResolver = new DartUriResolver(sdk);
// TODO(brianwilkerson) This doesn't handle sdk extensions.
List<UriResolver> resolvers = <UriResolver>[
sdkResolver,
resolver,
- new FileUriResolver()
+ new file_system.ResourceUriResolver(PhysicalResourceProvider.INSTANCE)
];
return new SourceFactory(resolvers);
}
@@ -404,16 +388,15 @@
// 'dart:' URIs come first.
// Setup embedding.
- EmbedderUriResolver embedderUriResolver =
- new EmbedderUriResolver(embedderMap);
- if (embedderUriResolver.length == 0) {
+ EmbedderSdk embedderSdk = new EmbedderSdk(embedderMap);
+ if (embedderSdk.libraryMap.size() == 0) {
// The embedder uri resolver has no mappings. Use the default Dart SDK
// uri resolver.
resolvers.add(new DartUriResolver(sdk));
} else {
// The embedder uri resolver has mappings, use it instead of the default
// Dart SDK uri resolver.
- resolvers.add(embedderUriResolver);
+ resolvers.add(new DartUriResolver(embedderSdk));
}
// Next SdkExts.
@@ -427,7 +410,8 @@
}
// Finally files.
- resolvers.add(new FileUriResolver());
+ resolvers.add(
+ new file_system.ResourceUriResolver(PhysicalResourceProvider.INSTANCE));
return new SourceFactory(resolvers, packageInfo.packages);
}
@@ -501,7 +485,7 @@
// Process embedders.
Map<file_system.Folder, YamlMap> embedderMap =
- _findEmbedders(packageInfo.packageMap);
+ new EmbedderYamlLocator(packageInfo.packageMap).embedderYamls;
// Scan for SDK extenders.
bool hasSdkExt = _hasSdkExt(packageInfo.packageMap?.values);
@@ -536,14 +520,6 @@
return null;
}
- Map<file_system.Folder, YamlMap> _findEmbedders(
- Map<String, List<file_system.Folder>> packageMap) {
- EmbedderYamlLocator locator =
- (_context as InternalAnalysisContext).embedderYamlLocator;
- locator.refresh(packageMap);
- return locator.embedderYamls;
- }
-
_PackageInfo _findPackages(CommandLineOptions options) {
if (packageResolverProvider != null) {
// The resolver provider will do all the work later.
@@ -627,8 +603,8 @@
/// Analyze a single source.
ErrorSeverity _runAnalyzer(Source source, CommandLineOptions options) {
int startTime = currentTimeMillis();
- AnalyzerImpl analyzer =
- new AnalyzerImpl(_context, incrementalSession, source, options, stats, startTime);
+ AnalyzerImpl analyzer = new AnalyzerImpl(
+ _context, incrementalSession, source, options, stats, startTime);
var errorSeverity = analyzer.analyzeSync();
if (errorSeverity == ErrorSeverity.ERROR) {
exitCode = errorSeverity.ordinal;
diff --git a/pkg/analyzer_cli/lib/starter.dart b/pkg/analyzer_cli/lib/starter.dart
index e42d39a..a784a75 100644
--- a/pkg/analyzer_cli/lib/starter.dart
+++ b/pkg/analyzer_cli/lib/starter.dart
@@ -4,7 +4,6 @@
library analyzer_cli.starter;
-import 'package:analyzer/plugin/embedded_resolver_provider.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer_cli/src/driver.dart';
import 'package:plugin/plugin.dart';
@@ -23,14 +22,6 @@
factory CommandLineStarter() = Driver;
/**
- * Set the embedded resolver provider used to override the way embedded
- * library URI's are resolved in some contexts. The provider should return
- * `null` if the embedded library URI resolution scheme should be used
- * instead.
- */
- void set embeddedUriResolverProvider(EmbeddedResolverProvider provider);
-
- /**
* Set the package resolver provider used to override the way package URI's
* are resolved in some contexts. The provider should return `null` if the
* default package resolution scheme should be used instead.
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index 5bbb2f0..c4c9020 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -131,11 +131,6 @@
/// Called during codegen when [constant] has been used.
void registerCompileTimeConstant(ConstantValue constant, Registry registry) {}
- /// Called during resolution when a constant value for [metadata] on
- /// [annotatedElement] has been evaluated.
- void registerMetadataConstant(MetadataAnnotation metadata,
- Element annotatedElement, Registry registry) {}
-
/// Called to notify to the backend that a class is being instantiated.
// TODO(johnniwinther): Remove this. It's only called once for each [cls] and
// only with [Compiler.globalDependencies] as [registry].
@@ -278,23 +273,25 @@
/// been scanned.
Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
// TODO(johnniwinther): Move this to [JavaScriptBackend].
- if (canLibraryUseNative(library)) {
+ if (!compiler.serialization.isDeserialized(library)) {
+ if (canLibraryUseNative(library)) {
+ library.forEachLocalMember((Element element) {
+ if (element.isClass) {
+ checkNativeAnnotation(compiler, element);
+ }
+ });
+ }
+ checkJsInteropAnnotation(compiler, library);
library.forEachLocalMember((Element element) {
- if (element.isClass) {
- checkNativeAnnotation(compiler, element);
+ checkJsInteropAnnotation(compiler, element);
+ if (element.isClass && isJsInterop(element)) {
+ ClassElement classElement = element;
+ classElement.forEachMember((_, memberElement) {
+ checkJsInteropAnnotation(compiler, memberElement);
+ });
}
});
}
- checkJsInteropAnnotation(compiler, library);
- library.forEachLocalMember((Element element) {
- checkJsInteropAnnotation(compiler, element);
- if (element.isClass && isJsInterop(element)) {
- ClassElement classElement = element;
- classElement.forEachMember((_, memberElement) {
- checkJsInteropAnnotation(compiler, memberElement);
- });
- }
- });
return new Future.value();
}
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index bbabcf9..71962e8 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -165,7 +165,9 @@
@override
@deprecated
ConstantValue getConstantValueForVariable(VariableElement element) {
- return getConstantValue(initialVariableValues[element.declaration]);
+ ConstantExpression constant = initialVariableValues[element.declaration];
+ // TODO(johnniwinther): Support eager evaluation of the constant.
+ return constant != null ? getConstantValue(constant) : null;
}
ConstantExpression compileConstant(VariableElement element) {
@@ -320,8 +322,27 @@
return constantValueMap.containsKey(expression);
}
+ @override
ConstantValue getConstantValue(ConstantExpression expression) {
- return constantValueMap[expression];
+ assert(invariant(CURRENT_ELEMENT_SPANNABLE, expression != null,
+ message: "ConstantExpression is null in getConstantValue."));
+ // TODO(johnniwinther): ensure expressions have been evaluated at this
+ // point. This can't be enabled today due to dartbug.com/26406.
+ if (compiler.serialization.supportsDeserialization) {
+ evaluate(expression);
+ }
+ ConstantValue value = constantValueMap[expression];
+ if (value == null &&
+ expression != null &&
+ expression.kind == ConstantExpressionKind.ERRONEOUS) {
+ // TODO(johnniwinther): When the Dart constant system sees a constant
+ // expression as erroneous but the JavaScript constant system finds it ok
+ // we have store a constant value for the erroneous constant expression.
+ // Ensure the computed constant expressions are always the same; that only
+ // the constant values may be different.
+ value = new NullConstantValue();
+ }
+ return value;
}
ConstantExpression compileNode(Node node, TreeElements elements,
@@ -359,7 +380,7 @@
Node node, TreeElements definitions,
{bool isConst: true}) {
ConstantExpression constant = definitions.getConstant(node);
- if (constant != null && getConstantValue(constant) != null) {
+ if (constant != null && hasConstantValue(constant)) {
return constant;
}
constant =
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 234c7e1..ced831b 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1064,7 +1064,6 @@
return const WorldImpact();
}
WorldImpact worldImpact = analyzeElement(element);
- backend.onElementResolved(element);
world.registerProcessedElement(element);
return worldImpact;
});
@@ -1659,7 +1658,12 @@
Token from = astElement.node.getBeginToken();
Token to = astElement.node.getEndToken();
if (astElement.metadata.isNotEmpty) {
- from = astElement.metadata.first.beginToken;
+ if (!astElement.metadata.first.hasNode) {
+ // We might try to report an error while parsing the metadata
+ // itself.
+ return true;
+ }
+ from = astElement.metadata.first.node.getBeginToken();
}
return validateToken(from, to);
}
@@ -1740,8 +1744,7 @@
} else if (node is Element) {
return spanFromElement(node);
} else if (node is MetadataAnnotation) {
- Uri uri = node.annotatedElement.compilationUnit.script.resourceUri;
- return spanFromTokens(node.beginToken, node.endToken, uri);
+ return node.sourcePosition;
} else if (node is Local) {
Local local = node;
return spanFromElement(local.executableContext);
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index 37f5646..434fcfa 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -28,6 +28,7 @@
R visitInterceptor(InterceptorConstantValue constant, A arg);
R visitSynthetic(SyntheticConstantValue constant, A arg);
R visitDeferred(DeferredConstantValue constant, A arg);
+ R visitNonConstant(NonConstantValue constant, A arg);
}
abstract class ConstantValue {
@@ -657,6 +658,8 @@
}
class ConstructedConstantValue extends ObjectConstantValue {
+ // TODO(johnniwinther): Make [fields] private to avoid misuse of the map
+ // ordering and mutability.
final Map<FieldElement, ConstantValue> fields;
final int hashCode;
@@ -751,7 +754,9 @@
String toDartText() => 'deferred(${referenced.toDartText()})';
- String toStructuredText() => 'DeferredConstant($referenced)';
+ String toStructuredText() {
+ return 'DeferredConstant(${referenced.toStructuredText()})';
+ }
}
/// A constant value resulting from a non constant or erroneous constant
@@ -762,7 +767,7 @@
@override
accept(ConstantValueVisitor visitor, arg) {
- // TODO(johnniwinther): Should this be part of the visiting?
+ return visitor.visitNonConstant(this, arg);
}
@override
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 1402b1d8..d788549 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
@@ -475,6 +475,10 @@
return '(Null)';
}
+ String visitNonConstant(NonConstantValue constant, _) {
+ return '(NonConstant)';
+ }
+
String visitInt(IntConstantValue constant, _) {
return '(Int ${constant.toDartText()})';
}
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index e5338de..06e0d00 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -1620,9 +1620,7 @@
/// The front-end constant of this metadata annotation.
ConstantExpression get constant;
Element get annotatedElement;
- int get resolutionState;
- Token get beginToken;
- Token get endToken;
+ SourceSpan get sourcePosition;
bool get hasNode;
Node get node;
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index e1fd271..248a9ef 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -3193,6 +3193,8 @@
*/
Token get beginToken;
+ Token get endToken;
+
MetadataAnnotationX([this.resolutionState = STATE_NOT_STARTED]);
MetadataAnnotation ensureResolved(Resolution resolution) {
@@ -3208,6 +3210,11 @@
Node parseNode(ParsingContext parsing);
+ SourceSpan get sourcePosition {
+ Uri uri = annotatedElement.compilationUnit.script.resourceUri;
+ return new SourceSpan.fromTokens(uri, beginToken, endToken);
+ }
+
String toString() => 'MetadataAnnotation($constant, $resolutionState)';
}
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index bcaec4a..01b258e 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -449,6 +449,7 @@
bool includeLibrary =
shouldIncludeElementDueToMirrors(lib, includedEnclosing: false);
lib.forEachLocalMember((Element member) {
+ if (member.isInjected) return;
if (member.isClass) {
enqueueReflectiveElementsInClass(member, recents, includeLibrary);
} else {
@@ -715,6 +716,7 @@
/// Registers [element] as processed by the resolution enqueuer.
void registerProcessedElement(AstElement element) {
processedElements.add(element);
+ compiler.backend.onElementResolved(element);
}
/**
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index e04aa6c..7489914 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -40,6 +40,11 @@
final Map<FunctionElement, int> _cachedDecisions =
new Map<FunctionElement, int>();
+ /// Returns the current cache decision. This should only be used for testing.
+ int getCurrentCacheDecisionForTesting(Element element) {
+ return _cachedDecisions[element];
+ }
+
// Returns `true`/`false` if we have a cached decision.
// Returns `null` otherwise.
bool canInline(FunctionElement element, {bool insideLoop}) {
@@ -449,6 +454,9 @@
/// these constants must be registered.
final List<Dependency> metadataConstants = <Dependency>[];
+ /// Set of elements for which metadata has been registered as dependencies.
+ final Set<Element> _registeredMetadata = new Set<Element>();
+
/// List of elements that the user has requested for reflection.
final Set<Element> targetsUsed = new Set<Element>();
@@ -1047,21 +1055,12 @@
// helper so we register a use of that.
registry.registerStaticUse(new StaticUse.staticInvoke(
// TODO(johnniwinther): Find the right [CallStructure].
-
helpers.createRuntimeType,
null));
}
}
}
- void registerMetadataConstant(MetadataAnnotation metadata,
- Element annotatedElement, Registry registry) {
- assert(registry.isForResolution);
- ConstantValue constant = constants.getConstantValueForMetadata(metadata);
- registerCompileTimeConstant(constant, registry);
- metadataConstants.add(new Dependency(constant, annotatedElement));
- }
-
void registerInstantiatedClass(
ClassElement cls, Enqueuer enqueuer, Registry registry) {
_processClass(cls, enqueuer, registry);
@@ -1272,6 +1271,7 @@
super.onResolutionComplete();
computeMembersNeededForReflection();
rti.computeClassesNeedingRti();
+ _registeredMetadata.clear();
}
onTypeInferenceComplete() {
@@ -2304,17 +2304,67 @@
reporter.log('Retaining metadata.');
compiler.libraryLoader.libraries.forEach(retainMetadataOf);
- for (Dependency dependency in metadataConstants) {
- registerCompileTimeConstant(dependency.constant,
- new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
- }
- if (!enqueuer.isResolutionQueue) {
+
+ if (enqueuer.isResolutionQueue && !enqueuer.queueIsClosed) {
+ /// Register the constant value of [metadata] as live in resolution.
+ void registerMetadataConstant(MetadataAnnotation metadata) {
+ ConstantValue constant =
+ constants.getConstantValueForMetadata(metadata);
+ Dependency dependency =
+ new Dependency(constant, metadata.annotatedElement);
+ metadataConstants.add(dependency);
+ registerCompileTimeConstant(dependency.constant,
+ new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
+ }
+
+ // TODO(johnniwinther): We should have access to all recently processed
+ // elements and process these instead.
+ processMetadata(compiler.enqueuer.resolution.processedElements,
+ registerMetadataConstant);
+ } else {
+ for (Dependency dependency in metadataConstants) {
+ registerCompileTimeConstant(dependency.constant,
+ new EagerRegistry('EagerRegistry for ${dependency}', enqueuer));
+ }
metadataConstants.clear();
}
}
return true;
}
+ /// Call [registerMetadataConstant] on all metadata from [elements].
+ void processMetadata(Iterable<Element> elements,
+ void onMetadata(MetadataAnnotation metadata)) {
+ void processLibraryMetadata(LibraryElement library) {
+ if (_registeredMetadata.add(library)) {
+ library.metadata.forEach(onMetadata);
+ library.entryCompilationUnit.metadata.forEach(onMetadata);
+ for (ImportElement import in library.imports) {
+ import.metadata.forEach(onMetadata);
+ }
+ }
+ }
+
+ void processElementMetadata(Element element) {
+ if (_registeredMetadata.add(element)) {
+ element.metadata.forEach(onMetadata);
+ if (element.isFunction) {
+ FunctionElement function = element;
+ for (ParameterElement parameter in function.parameters) {
+ parameter.metadata.forEach(onMetadata);
+ }
+ }
+ if (element.enclosingClass != null) {
+ processElementMetadata(element.enclosingClass);
+ } else {
+ processLibraryMetadata(element.library);
+ }
+ }
+ }
+
+ elements.forEach(processElementMetadata);
+ }
+
void onQueueClosed() {
lookupMapAnalysis.onQueueClosed();
jsInteropAnalysis.onQueueClosed();
@@ -3037,6 +3087,8 @@
final Element annotatedElement;
const Dependency(this.constant, this.annotatedElement);
+
+ String toString() => '$annotatedElement:${constant.toStructuredText()}';
}
class JavaScriptImpactStrategy extends ImpactStrategy {
diff --git a/pkg/compiler/lib/src/js_backend/backend_serialization.dart b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
index d0594f4..97da2f5 100644
--- a/pkg/compiler/lib/src/js_backend/backend_serialization.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
@@ -4,6 +4,7 @@
library js_backend.serialization;
+import '../common.dart';
import '../common/backend_api.dart' show BackendSerialization;
import '../dart_types.dart';
import '../elements/elements.dart';
@@ -38,6 +39,9 @@
const Key JS_INTEROP_NAME = const Key('jsInteropName');
const Key NATIVE_MEMBER_NAME = const Key('nativeMemberName');
const Key NATIVE_CLASS_TAG_INFO = const Key('nativeClassTagInfo');
+const Key NATIVE_METHOD_BEHAVIOR = const Key('nativeMethodBehavior');
+const Key NATIVE_FIELD_LOAD_BEHAVIOR = const Key('nativeFieldLoadBehavior');
+const Key NATIVE_FIELD_STORE_BEHAVIOR = const Key('nativeFieldStoreBehavior');
class JavaScriptBackendSerializer implements SerializerPlugin {
final JavaScriptBackend backend;
@@ -63,41 +67,31 @@
if (nativeClassTagInfo != null) {
getEncoder().setString(NATIVE_CLASS_TAG_INFO, nativeClassTagInfo);
}
- }
-
- /// Returns a list of the [DartType]s in [types].
- static List<DartType> filterDartTypes(List types) {
- return types.where((type) => type is DartType).toList();
- }
-
- /// Returns a list of the names of the [SpecialType]s in [types].
- static List<String> filterSpecialTypes(List types) {
- return types
- .where((type) => type is SpecialType)
- .map((SpecialType type) => type.name)
- .toList();
+ NativeBehavior nativeMethodBehavior =
+ backend.nativeData.nativeMethodBehavior[element];
+ if (nativeMethodBehavior != null) {
+ NativeBehaviorSerialization.serializeNativeBehavior(nativeMethodBehavior,
+ getEncoder().createObject(NATIVE_METHOD_BEHAVIOR));
+ }
+ NativeBehavior nativeFieldLoadBehavior =
+ backend.nativeData.nativeFieldLoadBehavior[element];
+ if (nativeFieldLoadBehavior != null) {
+ NativeBehaviorSerialization.serializeNativeBehavior(
+ nativeFieldLoadBehavior,
+ getEncoder().createObject(NATIVE_FIELD_LOAD_BEHAVIOR));
+ }
+ NativeBehavior nativeFieldStoreBehavior =
+ backend.nativeData.nativeFieldStoreBehavior[element];
+ if (nativeFieldStoreBehavior != null) {
+ NativeBehaviorSerialization.serializeNativeBehavior(
+ nativeFieldStoreBehavior,
+ getEncoder().createObject(NATIVE_FIELD_STORE_BEHAVIOR));
+ }
}
@override
void onData(NativeBehavior behavior, ObjectEncoder encoder) {
- encoder.setTypes(
- DART_TYPES_RETURNED, filterDartTypes(behavior.typesReturned));
- encoder.setStrings(
- SPECIAL_TYPES_RETURNED, filterSpecialTypes(behavior.typesReturned));
-
- encoder.setTypes(
- DART_TYPES_INSTANTIATED, filterDartTypes(behavior.typesInstantiated));
- encoder.setStrings(SPECIAL_TYPES_INSTANTIATED,
- filterSpecialTypes(behavior.typesInstantiated));
-
- if (behavior.codeTemplateText != null) {
- encoder.setString(CODE_TEMPLATE, behavior.codeTemplateText);
- }
-
- encoder.setInt(SIDE_EFFECTS, behavior.sideEffects.flags);
- encoder.setEnum(THROW_BEHAVIOR, behavior.throwBehavior);
- encoder.setBool(IS_ALLOCATION, behavior.isAllocation);
- encoder.setBool(USE_GVN, behavior.useGvn);
+ NativeBehaviorSerialization.serializeNativeBehavior(behavior, encoder);
}
}
@@ -125,11 +119,73 @@
if (nativeClassTagInfo != null) {
backend.nativeData.nativeClassTagInfo[element] = nativeClassTagInfo;
}
+ ObjectDecoder nativeMethodBehavior =
+ decoder.getObject(NATIVE_METHOD_BEHAVIOR, isOptional: true);
+ if (nativeMethodBehavior != null) {
+ backend.nativeData.nativeMethodBehavior[element] =
+ NativeBehaviorSerialization
+ .deserializeNativeBehavior(nativeMethodBehavior);
+ }
+ ObjectDecoder nativeFieldLoadBehavior =
+ decoder.getObject(NATIVE_FIELD_LOAD_BEHAVIOR, isOptional: true);
+ if (nativeFieldLoadBehavior != null) {
+ backend.nativeData.nativeFieldLoadBehavior[element] =
+ NativeBehaviorSerialization
+ .deserializeNativeBehavior(nativeFieldLoadBehavior);
+ }
+ ObjectDecoder nativeFieldStoreBehavior =
+ decoder.getObject(NATIVE_FIELD_STORE_BEHAVIOR, isOptional: true);
+ if (nativeFieldStoreBehavior != null) {
+ backend.nativeData.nativeFieldStoreBehavior[element] =
+ NativeBehaviorSerialization
+ .deserializeNativeBehavior(nativeFieldStoreBehavior);
+ }
}
}
@override
NativeBehavior onData(ObjectDecoder decoder) {
+ return NativeBehaviorSerialization.deserializeNativeBehavior(decoder);
+ }
+}
+
+class NativeBehaviorSerialization {
+ /// Returns a list of the [DartType]s in [types].
+ static List<DartType> filterDartTypes(List types) {
+ return types.where((type) => type is DartType).toList();
+ }
+
+ /// Returns a list of the names of the [SpecialType]s in [types].
+ static List<String> filterSpecialTypes(List types) {
+ return types
+ .where((type) => type is SpecialType)
+ .map((SpecialType type) => type.name)
+ .toList();
+ }
+
+ static void serializeNativeBehavior(
+ NativeBehavior behavior, ObjectEncoder encoder) {
+ encoder.setTypes(
+ DART_TYPES_RETURNED, filterDartTypes(behavior.typesReturned));
+ encoder.setStrings(
+ SPECIAL_TYPES_RETURNED, filterSpecialTypes(behavior.typesReturned));
+
+ encoder.setTypes(
+ DART_TYPES_INSTANTIATED, filterDartTypes(behavior.typesInstantiated));
+ encoder.setStrings(SPECIAL_TYPES_INSTANTIATED,
+ filterSpecialTypes(behavior.typesInstantiated));
+
+ if (behavior.codeTemplateText != null) {
+ encoder.setString(CODE_TEMPLATE, behavior.codeTemplateText);
+ }
+
+ encoder.setInt(SIDE_EFFECTS, behavior.sideEffects.flags);
+ encoder.setEnum(THROW_BEHAVIOR, behavior.throwBehavior);
+ encoder.setBool(IS_ALLOCATION, behavior.isAllocation);
+ encoder.setBool(USE_GVN, behavior.useGvn);
+ }
+
+ static NativeBehavior deserializeNativeBehavior(ObjectDecoder decoder) {
SideEffects sideEffects =
new SideEffects.fromFlags(decoder.getInt(SIDE_EFFECTS));
NativeBehavior behavior = new NativeBehavior.internal(sideEffects);
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index fc53cb4..eba60d9 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -64,6 +64,11 @@
return new jsAst.LiteralNull();
}
+ @override
+ jsAst.Expression visitNonConstant(NonConstantValue constant, [_]) {
+ return new jsAst.LiteralNull();
+ }
+
static final _exponentialRE = new RegExp('^'
'\([-+]?\)' // 1: sign
'\([0-9]+\)' // 2: leading digit(s)
@@ -280,7 +285,7 @@
@override
jsAst.Expression visitConstructed(ConstructedConstantValue constant, [_]) {
- Element element = constant.type.element;
+ ClassElement element = constant.type.element;
if (backend.isForeign(element) && element.name == 'JS_CONST') {
StringConstantValue str = constant.fields.values.single;
String value = str.primitiveValue.slowToString();
@@ -288,9 +293,10 @@
}
jsAst.Expression constructor =
backend.emitter.constructorAccess(constant.type.element);
- List<jsAst.Expression> fields = constant.fields.values
- .map(constantReferenceGenerator)
- .toList(growable: false);
+ List<jsAst.Expression> fields = <jsAst.Expression>[];
+ element.forEachInstanceField((_, FieldElement field) {
+ fields.add(constantReferenceGenerator(constant.fields[field]));
+ }, includeSuperAndInjectedMembers: true);
jsAst.New instantiation = new jsAst.New(constructor, fields);
return maybeAddTypeArguments(constant.type, instantiation);
}
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 6077e6d..8e6de54 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -116,6 +116,8 @@
new Map<Node, ConstantExpression>();
// Constants computed for metadata.
+ // TODO(johnniwinther): Remove this when no longer used by
+ // poi/forget_element_test.
final Map<MetadataAnnotation, ConstantExpression> metadataConstantMap =
new Map<MetadataAnnotation, ConstantExpression>();
@@ -212,9 +214,10 @@
}
ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata) {
- return getConstantValue(metadataConstantMap[metadata]);
+ return getConstantValue(metadata.constant);
}
+ @override
ConstantExpression compileMetadata(
MetadataAnnotation metadata, Node node, TreeElements elements) {
ConstantExpression constant =
@@ -230,29 +233,6 @@
element.node.accept(new ForgetConstantNodeVisitor(this));
}
}
-
- @override
- ConstantValue getConstantValue(ConstantExpression expression) {
- assert(invariant(CURRENT_ELEMENT_SPANNABLE, expression != null,
- message: "ConstantExpression is null in getConstantValue."));
- // TODO(johhniwinther): ensure expressions have been evaluated at this
- // point. This can't be enabled today due to dartbug.com/26406.
- if (compiler.serialization.supportsDeserialization) {
- evaluate(expression);
- }
- ConstantValue value = super.getConstantValue(expression);
- if (value == null &&
- expression != null &&
- expression.kind == ConstantExpressionKind.ERRONEOUS) {
- // TODO(johnniwinther): When the Dart constant system sees a constant
- // expression as erroneous but the JavaScript constant system finds it ok
- // we have store a constant value for the erroneous constant expression.
- // Ensure the computed constant expressions are always the same; that only
- // the constant values may be different.
- value = new NullConstantValue();
- }
- return value;
- }
}
class ForgetConstantElementVisitor
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index 410d1c8..bfd156e 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -357,7 +357,7 @@
symbolClass.forEachInstanceField(
(ClassElement enclosingClass, FieldElement field) {
fields[field] = argument;
- });
+ }, includeSuperAndInjectedMembers: true);
assert(fields.length == 1);
return new ConstructedConstantValue(type, fields);
}
diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
index 448f979..e2ebe39 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -5,6 +5,7 @@
/// Analysis to determine how to generate code for typed JavaScript interop.
library compiler.src.js_backend.js_interop_analysis;
+import '../common.dart';
import '../constants/values.dart'
show ConstantValue, ConstructedConstantValue, StringConstantValue;
import '../diagnostics/messages.dart' show MessageKind;
@@ -54,6 +55,8 @@
void processJsInteropAnnotation(Element e) {
for (MetadataAnnotation annotation in e.implementation.metadata) {
+ // TODO(johnniwinther): Avoid processing unresolved elements.
+ if (annotation.constant == null) continue;
ConstantValue constant =
backend.compiler.constants.getConstantValue(annotation.constant);
if (constant == null || constant is! ConstructedConstantValue) continue;
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index c0f21c5..c4a86ef 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -331,6 +331,7 @@
final String callPrefix = 'call';
final String callCatchAllName = r'call*';
final String callNameField = r'$callName';
+ final String stubNameField = r'$stubName';
final String reflectableField = r'$reflectable';
final String reflectionInfoField = r'$reflectionInfo';
final String reflectionNameField = r'$reflectionName';
@@ -1672,6 +1673,11 @@
}
@override
+ void visitNonConstant(NonConstantValue constant, [_]) {
+ add('null');
+ }
+
+ @override
void visitInt(IntConstantValue constant, [_]) {
// No `addRoot` since IntConstants are always inlined.
if (constant.primitiveValue < 0) {
@@ -1730,10 +1736,10 @@
@override
void visitConstructed(ConstructedConstantValue constant, [_]) {
addRoot(constant.type.element.name);
- for (ConstantValue value in constant.fields.values) {
- _visit(value);
+ constant.type.element.forEachInstanceField((_, FieldElement field) {
if (failed) return;
- }
+ _visit(constant.fields[field]);
+ }, includeSuperAndInjectedMembers: true);
}
@override
@@ -1816,6 +1822,9 @@
int visitNull(NullConstantValue constant, [_]) => 1;
@override
+ int visitNonConstant(NonConstantValue constant, [_]) => 1;
+
+ @override
int visitBool(BoolConstantValue constant, [_]) {
return constant.isTrue ? 2 : 3;
}
@@ -1854,9 +1863,9 @@
@override
int visitConstructed(ConstructedConstantValue constant, [_]) {
int hash = _hashString(3, constant.type.element.name);
- for (ConstantValue value in constant.fields.values) {
- hash = _combine(hash, _visit(value));
- }
+ constant.type.element.forEachInstanceField((_, FieldElement field) {
+ hash = _combine(hash, _visit(constant.fields[field]));
+ }, includeSuperAndInjectedMembers: true);
return hash;
}
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
index 42712f0..67b473b 100644
--- a/pkg/compiler/lib/src/js_backend/native_data.dart
+++ b/pkg/compiler/lib/src/js_backend/native_data.dart
@@ -23,7 +23,6 @@
/// [setNativeClassTagInfo].
Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{};
- // TODO(johnniwinther): Serialize these.
/// Cache for [NativeBehavior]s for calling native methods.
Map<FunctionElement, NativeBehavior> nativeMethodBehavior =
<FunctionElement, NativeBehavior>{};
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index a2a0d7d..27651c2 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -76,6 +76,10 @@
return 0;
}
+ int visitNonConstant(NonConstantValue a, NonConstantValue b) {
+ return 0;
+ }
+
int visitInt(IntConstantValue a, IntConstantValue b) {
return a.primitiveValue.compareTo(b.primitiveValue);
}
@@ -189,12 +193,14 @@
static const int INTERCEPTOR = 11;
static const int SYNTHETIC = 12;
static const int DEFERRED = 13;
+ static const int NONCONSTANT = 13;
static int kind(ConstantValue constant) =>
constant.accept(const _KindVisitor(), null);
int visitFunction(FunctionConstantValue a, _) => FUNCTION;
int visitNull(NullConstantValue a, _) => NULL;
+ int visitNonConstant(NonConstantValue a, _) => NONCONSTANT;
int visitInt(IntConstantValue a, _) => INT;
int visitDouble(DoubleConstantValue a, _) => DOUBLE;
int visitBool(BoolConstantValue a, _) => BOOL;
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 48ccd6d..846ce8b 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -233,6 +233,7 @@
reflectionInfo = reflectionInfo + typesOffset;
}
var name = funsOrNames[0];
+ fun.#stubName = name;
var getterFunction =
tearOff(funs, reflectionInfo, isStatic, name, isIntercepted);
container[getterName] = getterFunction;
@@ -455,6 +456,7 @@
'constantHolderReference': buildConstantHolderReference(program),
'holders': emitHolders(program.holders, fragment),
'callName': js.string(namer.callNameField),
+ 'stubName': js.string(namer.stubNameField),
'argumentCount': js.string(namer.requiredParameterField),
'defaultArgumentValues': js.string(namer.defaultValuesField),
'prototypes': emitPrototypes(fragment),
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 63b601d..e8f3340 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -318,7 +318,7 @@
// TODO(sra): Better validation of the constant.
if (fields.length != 1 || fields.single is! StringConstantValue) {
reporter.internalError(
- annotation, 'Annotations needs one string: ${annotation.node}');
+ annotation, 'Annotations needs one string: ${annotation}');
}
StringConstantValue specStringConstant = fields.single;
String specString = specStringConstant.toDartString().slowToString();
@@ -326,7 +326,7 @@
name = specString;
} else {
reporter.internalError(
- annotation, 'Too many JSName annotations: ${annotation.node}');
+ annotation, 'Too many JSName annotations: ${annotation}');
}
}
return name;
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
index 6fe019c..6d9bd82 100644
--- a/pkg/compiler/lib/src/parser/element_listener.dart
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -17,6 +17,7 @@
EnumClassElementX,
FieldElementX,
LibraryElementX,
+ MetadataAnnotationX,
NamedMixinApplicationElementX,
VariableList;
import '../id_generator.dart';
@@ -233,8 +234,8 @@
void endTopLevelDeclaration(Token token) {
if (!metadata.isEmpty) {
- recoverableError(
- metadata.first.beginToken, 'Metadata not supported here.');
+ MetadataAnnotationX first = metadata.first;
+ recoverableError(first.beginToken, 'Metadata not supported here.');
metadata.clear();
}
}
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index a2246c4..9f51036 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -128,6 +128,7 @@
ClassElementX,
GetterElementX,
LibraryElementX,
+ MetadataAnnotationX,
SetterElementX;
import 'id_generator.dart';
import 'js_backend/js_backend.dart' show JavaScriptBackend;
@@ -403,7 +404,7 @@
class NativeAnnotationHandler implements EagerAnnotationHandler<String> {
const NativeAnnotationHandler();
- String getNativeAnnotation(MetadataAnnotation annotation) {
+ String getNativeAnnotation(MetadataAnnotationX annotation) {
if (annotation.beginToken != null &&
annotation.beginToken.next.value == 'Native') {
// Skipping '@', 'Native', and '('.
@@ -443,7 +444,7 @@
class JsInteropAnnotationHandler implements EagerAnnotationHandler<bool> {
const JsInteropAnnotationHandler();
- bool hasJsNameAnnotation(MetadataAnnotation annotation) =>
+ bool hasJsNameAnnotation(MetadataAnnotationX annotation) =>
annotation.beginToken != null && annotation.beginToken.next.value == 'JS';
bool apply(
@@ -474,7 +475,7 @@
class PatchAnnotationHandler implements EagerAnnotationHandler<PatchVersion> {
const PatchAnnotationHandler();
- PatchVersion getPatchVersion(MetadataAnnotation annotation) {
+ PatchVersion getPatchVersion(MetadataAnnotationX annotation) {
if (annotation.beginToken != null) {
if (annotation.beginToken.next.value == 'patch') {
return const PatchVersion(null);
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 54bd495..e52b185 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -334,10 +334,6 @@
worldImpact.registerStaticUse(staticUse);
}
- void registerMetadataConstant(MetadataAnnotation metadata) {
- backend.registerMetadataConstant(metadata, metadata.annotatedElement, this);
- }
-
/// Register the use of a type.
void registerTypeUse(TypeUse typeUse) {
worldImpact.registerTypeUse(typeUse);
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index f1ca6d0..2fd4e685 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -1088,7 +1088,6 @@
// and the annotated element instead. This will allow the backend to
// retrieve the backend constant and only register metadata on the
// elements for which it is needed. (Issue 17732).
- registry.registerMetadataConstant(annotation);
annotation.resolutionState = STATE_DONE;
}));
}
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index b115ae0..b025533 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -120,6 +120,31 @@
}
}
+ /// Serialize the metadata of [element] into [encoder].
+ static void serializeMetadata(Element element, ObjectEncoder encoder) {
+ ListEncoder list;
+
+ void encodeAnnotation(MetadataAnnotation metadata) {
+ ObjectEncoder object = list.createObject();
+ object.setElement(Key.ELEMENT, metadata.annotatedElement);
+ SourceSpan sourcePosition = metadata.sourcePosition;
+ // TODO(johnniwinther): What is the base URI here?
+ object.setUri(Key.URI, sourcePosition.uri, sourcePosition.uri);
+ object.setInt(Key.OFFSET, sourcePosition.begin);
+ object.setInt(Key.LENGTH, sourcePosition.end - sourcePosition.begin);
+ object.setConstant(Key.CONSTANT, metadata.constant);
+ }
+
+ if (element.metadata.isNotEmpty) {
+ list = encoder.createList(Key.METADATA);
+ element.metadata.forEach(encodeAnnotation);
+ }
+ if (element.isPatched && element.implementation.metadata.isNotEmpty) {
+ list ??= encoder.createList(Key.METADATA);
+ element.implementation.metadata.forEach(encodeAnnotation);
+ }
+ }
+
/// Serialize the parent relation for [element] into [encoder], i.e library,
/// enclosing class, and compilation unit references.
static void serializeParentRelation(Element element, ObjectEncoder encoder) {
@@ -225,6 +250,7 @@
void serialize(LibraryElement element, ObjectEncoder encoder,
SerializedElementKind kind) {
+ SerializerUtil.serializeMetadata(element, encoder);
encoder.setUri(
Key.CANONICAL_URI, element.canonicalUri, element.canonicalUri);
encoder.setString(Key.LIBRARY_NAME, element.libraryName);
@@ -252,6 +278,7 @@
void serialize(CompilationUnitElement element, ObjectEncoder encoder,
SerializedElementKind kind) {
+ SerializerUtil.serializeMetadata(element, encoder);
encoder.setElement(Key.LIBRARY, element.library);
encoder.setUri(
Key.URI, element.library.canonicalUri, element.script.resourceUri);
@@ -299,6 +326,7 @@
void serialize(
ClassElement element, ObjectEncoder encoder, SerializedElementKind kind) {
+ SerializerUtil.serializeMetadata(element, encoder);
encoder.setElement(Key.LIBRARY, element.library);
encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
encoder.setString(Key.NAME, element.name);
@@ -307,6 +335,7 @@
encoder.setBool(Key.IS_ABSTRACT, element.isAbstract);
SerializerUtil.serializeMembers(getMembers(element), encoder);
encoder.setBool(Key.IS_PROXY, element.isProxy);
+ encoder.setBool(Key.IS_INJECTED, element.isInjected);
if (kind == SerializedElementKind.ENUM) {
EnumClassElement enumClass = element;
encoder.setElements(Key.FIELDS, enumClass.enumValues);
@@ -368,12 +397,14 @@
if (kind == SerializedElementKind.FORWARDING_CONSTRUCTOR) {
encoder.setElement(Key.ELEMENT, element.definingConstructor);
} else {
+ SerializerUtil.serializeMetadata(element, encoder);
encoder.setType(Key.TYPE, element.type);
encoder.setString(Key.NAME, element.name);
SerializerUtil.serializePosition(element, encoder);
SerializerUtil.serializeParameters(element, encoder);
encoder.setBool(Key.IS_CONST, element.isConst);
encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
+ encoder.setBool(Key.IS_INJECTED, element.isInjected);
if (element.isConst && !element.isFromEnvironmentConstructor) {
ConstantConstructor constantConstructor = element.constantConstructor;
ObjectEncoder constantEncoder = encoder.createObject(Key.CONSTRUCTOR);
@@ -419,10 +450,12 @@
void serialize(
FieldElement element, ObjectEncoder encoder, SerializedElementKind kind) {
encoder.setString(Key.NAME, element.name);
+ SerializerUtil.serializeMetadata(element, encoder);
SerializerUtil.serializePosition(element, encoder);
encoder.setType(Key.TYPE, element.type);
encoder.setBool(Key.IS_FINAL, element.isFinal);
encoder.setBool(Key.IS_CONST, element.isConst);
+ encoder.setBool(Key.IS_INJECTED, element.isInjected);
ConstantExpression constant = element.constant;
if (constant != null) {
encoder.setConstant(Key.CONSTANT, constant);
@@ -469,6 +502,7 @@
void serialize(FunctionElement element, ObjectEncoder encoder,
SerializedElementKind kind) {
encoder.setString(Key.NAME, element.name);
+ SerializerUtil.serializeMetadata(element, encoder);
SerializerUtil.serializePosition(element, encoder);
SerializerUtil.serializeParameters(element, encoder);
encoder.setType(Key.TYPE, element.type);
@@ -479,6 +513,7 @@
SerializerUtil.serializeParentRelation(element, encoder);
encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
encoder.setBool(Key.IS_ABSTRACT, element.isAbstract);
+ encoder.setBool(Key.IS_INJECTED, element.isInjected);
if (element.isLocal) {
LocalFunctionElement localFunction = element;
encoder.setElement(
@@ -500,6 +535,7 @@
void serialize(TypedefElement element, ObjectEncoder encoder,
SerializedElementKind kind) {
encoder.setString(Key.NAME, element.name);
+ SerializerUtil.serializeMetadata(element, encoder);
SerializerUtil.serializePosition(element, encoder);
encoder.setType(Key.ALIAS, element.alias);
encoder.setElement(Key.LIBRARY, element.library);
@@ -522,6 +558,7 @@
SerializedElementKind kind) {
encoder.setElement(Key.TYPE_DECLARATION, element.typeDeclaration);
encoder.setString(Key.NAME, element.name);
+ SerializerUtil.serializeMetadata(element, encoder);
SerializerUtil.serializePosition(element, encoder);
encoder.setType(Key.TYPE, element.type);
encoder.setInt(Key.INDEX, element.index);
@@ -545,6 +582,7 @@
SerializedElementKind kind) {
encoder.setElement(Key.FUNCTION, element.functionDeclaration);
encoder.setString(Key.NAME, element.name);
+ SerializerUtil.serializeMetadata(element, encoder);
SerializerUtil.serializePosition(element, encoder);
encoder.setType(Key.TYPE, element.type);
encoder.setBool(Key.IS_OPTIONAL, element.isOptional);
@@ -573,6 +611,7 @@
void serialize(LocalVariableElement element, ObjectEncoder encoder,
SerializedElementKind kind) {
encoder.setString(Key.NAME, element.name);
+ SerializerUtil.serializeMetadata(element, encoder);
SerializerUtil.serializePosition(element, encoder);
encoder.setType(Key.TYPE, element.type);
encoder.setBool(Key.IS_FINAL, element.isFinal);
@@ -597,6 +636,7 @@
void serialize(ImportElement element, ObjectEncoder encoder,
SerializedElementKind kind) {
+ SerializerUtil.serializeMetadata(element, encoder);
encoder.setElement(Key.LIBRARY, element.library);
encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
encoder.setElement(Key.LIBRARY_DEPENDENCY, element.importedLibrary);
@@ -621,6 +661,7 @@
void serialize(ExportElement element, ObjectEncoder encoder,
SerializedElementKind kind) {
+ SerializerUtil.serializeMetadata(element, encoder);
encoder.setElement(Key.LIBRARY, element.library);
encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
encoder.setElement(Key.LIBRARY_DEPENDENCY, element.exportedLibrary);
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart
index 563783f..a7c08b5 100644
--- a/pkg/compiler/lib/src/serialization/equivalence.dart
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart
@@ -14,7 +14,7 @@
import '../elements/elements.dart';
import '../elements/visitor.dart';
import '../js_backend/backend_serialization.dart'
- show JavaScriptBackendSerializer;
+ show NativeBehaviorSerialization;
import '../native/native.dart' show NativeBehavior;
import '../resolution/access_semantics.dart';
import '../resolution/send_structure.dart';
@@ -860,6 +860,43 @@
return false;
}
+bool testNativeBehavior(NativeBehavior a, NativeBehavior b,
+ [TestStrategy strategy = const TestStrategy()]) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ return strategy.test(
+ a, b, 'codeTemplateText', a.codeTemplateText, b.codeTemplateText) &&
+ strategy.test(a, b, 'isAllocation', a.isAllocation, b.isAllocation) &&
+ strategy.test(a, b, 'sideEffects', a.sideEffects, b.sideEffects) &&
+ strategy.test(a, b, 'throwBehavior', a.throwBehavior, b.throwBehavior) &&
+ strategy.testTypeLists(
+ a,
+ b,
+ 'dartTypesReturned',
+ NativeBehaviorSerialization.filterDartTypes(a.typesReturned),
+ NativeBehaviorSerialization.filterDartTypes(b.typesReturned)) &&
+ strategy.testLists(
+ a,
+ b,
+ 'specialTypesReturned',
+ NativeBehaviorSerialization.filterSpecialTypes(a.typesReturned),
+ NativeBehaviorSerialization.filterSpecialTypes(b.typesReturned)) &&
+ strategy.testTypeLists(
+ a,
+ b,
+ 'dartTypesInstantiated',
+ NativeBehaviorSerialization.filterDartTypes(a.typesInstantiated),
+ NativeBehaviorSerialization.filterDartTypes(b.typesInstantiated)) &&
+ strategy.testLists(
+ a,
+ b,
+ 'specialTypesInstantiated',
+ NativeBehaviorSerialization.filterSpecialTypes(a.typesInstantiated),
+ NativeBehaviorSerialization
+ .filterSpecialTypes(b.typesInstantiated)) &&
+ strategy.test(a, b, 'useGvn', a.useGvn, b.useGvn);
+}
+
/// Visitor that checks the equivalence of [TreeElements] data.
class TreeElementsEquivalenceVisitor extends Visitor {
final TestStrategy strategy;
@@ -911,41 +948,7 @@
if (identical(a, b)) return true;
if (a == null || b == null) return false;
if (a is NativeBehavior && b is NativeBehavior) {
- return strategy.test(a, b, 'codeTemplateText', a.codeTemplateText,
- b.codeTemplateText) &&
- strategy.test(a, b, 'isAllocation', a.isAllocation, b.isAllocation) &&
- strategy.test(a, b, 'sideEffects', a.sideEffects, b.sideEffects) &&
- strategy.test(
- a, b, 'throwBehavior', a.throwBehavior, b.throwBehavior) &&
- strategy.testTypeLists(
- a,
- b,
- 'dartTypesReturned',
- JavaScriptBackendSerializer.filterDartTypes(a.typesReturned),
- JavaScriptBackendSerializer.filterDartTypes(b.typesReturned)) &&
- strategy.testLists(
- a,
- b,
- 'specialTypesReturned',
- JavaScriptBackendSerializer.filterSpecialTypes(a.typesReturned),
- JavaScriptBackendSerializer
- .filterSpecialTypes(b.typesReturned)) &&
- strategy.testTypeLists(
- a,
- b,
- 'dartTypesInstantiated',
- JavaScriptBackendSerializer.filterDartTypes(a.typesInstantiated),
- JavaScriptBackendSerializer
- .filterDartTypes(b.typesInstantiated)) &&
- strategy.testLists(
- a,
- b,
- 'specialTypesInstantiated',
- JavaScriptBackendSerializer
- .filterSpecialTypes(a.typesInstantiated),
- JavaScriptBackendSerializer
- .filterSpecialTypes(b.typesInstantiated)) &&
- strategy.test(a, b, 'useGvn', a.useGvn, b.useGvn);
+ return testNativeBehavior(a, b, strategy);
}
return true;
}
@@ -1829,3 +1832,12 @@
throw new UnsupportedError('Unexpected nodes: $node1 <> $node2');
}
}
+
+bool areMetadataAnnotationsEquivalent(
+ MetadataAnnotation metadata1, MetadataAnnotation metadata2) {
+ if (metadata1 == metadata2) return true;
+ if (metadata1 == null || metadata2 == null) return false;
+ return areElementsEquivalent(
+ metadata1.annotatedElement, metadata2.annotatedElement) &&
+ areConstantsEquivalent(metadata1.constant, metadata2.constant);
+}
diff --git a/pkg/compiler/lib/src/serialization/keys.dart b/pkg/compiler/lib/src/serialization/keys.dart
index 179b727..fb5151b 100644
--- a/pkg/compiler/lib/src/serialization/keys.dart
+++ b/pkg/compiler/lib/src/serialization/keys.dart
@@ -59,6 +59,7 @@
static const Key IS_EMPTY = const Key('isEmpty');
static const Key IS_EXTERNAL = const Key('isExternal');
static const Key IS_FINAL = const Key('isFinal');
+ static const Key IS_INJECTED = const Key('isInjected');
static const Key IS_NAMED = const Key('isNamed');
static const Key IS_OPERATOR = const Key('isOperator');
static const Key IS_OPTIONAL = const Key('isOptional');
@@ -83,6 +84,7 @@
static const Key LISTS = const Key('lists');
static const Key MAPS = const Key('maps');
static const Key MEMBERS = const Key('members');
+ static const Key METADATA = const Key('metadata');
static const Key MIXIN = const Key('mixin');
static const Key MIXINS = const Key('mixins');
static const Key NAME = const Key('name');
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index a03ef2f..c909f9a 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -112,7 +112,6 @@
@override
bool get isTopLevel => false;
- // TODO(johnniwinther): Support metadata.
@override
Iterable<MetadataAnnotation> get metadata => const <MetadataAnnotation>[];
@@ -122,6 +121,7 @@
abstract class DeserializedElementZ extends ElementZ {
ObjectDecoder _decoder;
+ List<MetadataAnnotation> _metadata;
DeserializedElementZ(this._decoder);
@@ -147,6 +147,27 @@
}
return new SourceSpan(uri, offset, offset + length);
}
+
+ @override
+ Iterable<MetadataAnnotation> get metadata {
+ if (_metadata == null) {
+ _metadata = <MetadataAnnotation>[];
+ ListDecoder list = _decoder.getList(Key.METADATA, isOptional: true);
+ if (list != null) {
+ for (int index = 0; index < list.length; index++) {
+ ObjectDecoder object = list.getObject(index);
+ Element element = object.getElement(Key.ELEMENT);
+ Uri uri = object.getUri(Key.URI);
+ int offset = object.getInt(Key.OFFSET);
+ int length = object.getInt(Key.LENGTH);
+ ConstantExpression constant = object.getConstant(Key.CONSTANT);
+ _metadata.add(new MetadataAnnotationZ(
+ element, new SourceSpan(uri, offset, offset + length), constant));
+ }
+ }
+ }
+ return _metadata;
+ }
}
/// Deserializer for a collection of member elements serialized as a map from
@@ -946,6 +967,9 @@
bool get isProxy => _decoder.getBool(Key.IS_PROXY);
@override
+ bool get isInjected => _decoder.getBool(Key.IS_INJECTED);
+
+ @override
bool get isUnnamedMixinApplication => false;
@override
@@ -1480,6 +1504,9 @@
@override
List<FunctionElement> get nestedClosures => <FunctionElement>[];
+
+ @override
+ bool get isInjected => _decoder.getBool(Key.IS_INJECTED);
}
abstract class FieldElementZ extends DeserializedElementZ
@@ -2263,3 +2290,25 @@
return _unsupported('lookupLocalMember');
}
}
+
+class MetadataAnnotationZ implements MetadataAnnotation {
+ final Element annotatedElement;
+ final SourceSpan sourcePosition;
+ final ConstantExpression constant;
+
+ MetadataAnnotationZ(
+ this.annotatedElement, this.sourcePosition, this.constant);
+
+ @override
+ MetadataAnnotation ensureResolved(Resolution resolution) {
+ // Do nothing.
+ }
+
+ @override
+ Node get node => throw new UnsupportedError('${this}.node');
+
+ @override
+ bool get hasNode => false;
+
+ String toString() => 'MetadataAnnotationZ(${constant.toDartText()})';
+}
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 0ff32f2..9637549 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1496,8 +1496,25 @@
js.Statement elsePart =
unwrapStatement(generateStatementsInNewBlock(elseGraph));
- pushStatement(new js.If(test, thenPart, elsePart)
- .withSourceInformation(node.sourceInformation));
+ js.Statement code;
+ // Peephole rewrites:
+ //
+ // if (e); else S; --> if(!e) S;
+ //
+ // if (e); --> e;
+ //
+ // TODO(sra): This peephole optimization would be better done as an SSA
+ // optimization.
+ if (thenPart is js.EmptyStatement) {
+ if (elsePart is js.EmptyStatement) {
+ code = new js.ExpressionStatement(test);
+ } else {
+ code = new js.If.noElse(new js.Prefix('!', test), elsePart);
+ }
+ } else {
+ code = new js.If(test, thenPart, elsePart);
+ }
+ pushStatement(code.withSourceInformation(node.sourceInformation));
}
visitIf(HIf node) {
diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/types/constants.dart
index a3b2faa..d66a31c 100644
--- a/pkg/compiler/lib/src/types/constants.dart
+++ b/pkg/compiler/lib/src/types/constants.dart
@@ -105,6 +105,11 @@
}
@override
+ TypeMask visitNonConstant(NonConstantValue constant, Compiler compiler) {
+ return compiler.typesTask.nullType;
+ }
+
+ @override
TypeMask visitString(StringConstantValue constant, Compiler compiler) {
return compiler.typesTask.stringType;
}
diff --git a/pkg/meta/CHANGELOG.md b/pkg/meta/CHANGELOG.md
index 6e1655ae..bf761f1 100644
--- a/pkg/meta/CHANGELOG.md
+++ b/pkg/meta/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 1.0.1
+* Updated `@factory` to allow statics and methods returning `null`.
+
## 1.0.0
* First stable API release.
diff --git a/pkg/meta/lib/meta.dart b/pkg/meta/lib/meta.dart
index 17f7f1f..99a3924 100644
--- a/pkg/meta/lib/meta.dart
+++ b/pkg/meta/lib/meta.dart
@@ -18,17 +18,16 @@
/// in the language tour.
library meta;
-/// Used to annotate an instance method `m`. Indicates that `m` must either be
-/// abstract or must return a newly allocated object. In addition, every method
-/// that either implements or overrides `m` is implicitly annotated with this
-/// same annotation.
+/// Used to annotate an instance or static method `m`. Indicates that `m` must
+/// either be abstract or must return a newly allocated object or `null`. In
+/// addition, every method that either implements or overrides `m` is implicitly
+/// annotated with this same annotation.
///
/// Tools, such as the analyzer, can provide feedback if
///
-/// * the annotation is associated with anything other than an instance method,
-/// or
-/// * a method that has this annotation that can return anything other than a
-/// newly allocated object.
+/// * the annotation is associated with anything other than a method, or
+/// * the annotation is associated with a method that has this annotation that
+/// can return anything other than a newly allocated object or `null`.
const _Factory factory = const _Factory();
/// Used to annotate a const constructor `c`. Indicates that any invocation of
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
index a629570..acab306 100644
--- a/pkg/meta/pubspec.yaml
+++ b/pkg/meta/pubspec.yaml
@@ -1,5 +1,5 @@
name: meta
-version: 1.0.0
+version: 1.0.1
author: Dart Team <misc@dartlang.org>
homepage: http://www.dartlang.org
description: >
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 4ddace9..a8fadfb 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -84,6 +84,7 @@
analyzer/test/generated/strong_mode_test: Pass, Slow # Issue 21628
analyzer/test/generated/type_system_test: Pass, Slow # Issue 21628
analyzer/test/generated/utilities_test: Pass, Slow # Issue 21628
+analyzer/test/source/embedder_test: Skip # Issue 21628
analyzer/test/source/package_map_provider_test: Skip # Issue 21628
analyzer/test/src/context/cache_test: Pass, Slow # Issue 21628
analyzer/test/src/context/context_test: Pass, Timeout # dartbug.com/23658
@@ -117,6 +118,7 @@
analyzer/test/src/task/options_work_manager_test: Pass, Slow # Issue 21628
analyzer/test/src/task/strong/checker_test: Pass, Slow # Issue 21628
analyzer/test/src/task/strong/inferred_type_test: Pass, Slow # Issue 21628
+analyzer/test/src/task/strong_mode_test: Pass, Slow # Issue 21628
analyzer/test/src/task/yaml_test: Pass, Slow # Issue 21628
analyzer/tool/task_dependency_graph/check_test: Skip # Issue 21628
collection/test/equality_test/01: Fail # Issue 1533
@@ -165,8 +167,6 @@
[ $compiler == dart2analyzer ]
compiler/samples/compile_loop/compile_loop: CompileTimeError # Issue 16524
-lookup_map/test/version_check_test: StaticWarning # https://github.com/dart-lang/http_parser/issues/6
-lookup_map/test/lookup_map_test: StaticWarning # https://github.com/dart-lang/http_parser/issues/6
[ $compiler == dart2js && $csp ]
# This test cannot run under CSP because it is injecting a JavaScript polyfill
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index a57ef87..1b1f42f 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -32,6 +32,7 @@
namespace bin {
const char* DartUtils::original_working_directory = NULL;
+CommandLineOptions* DartUtils::url_mapping = NULL;
const char* const DartUtils::kDartScheme = "dart:";
const char* const DartUtils::kDartExtensionScheme = "dart-ext:";
const char* const DartUtils::kAsyncLibURL = "dart:async";
@@ -47,6 +48,7 @@
const uint8_t DartUtils::magic_number[] = { 0xf5, 0xf5, 0xdc, 0xdc };
+
static bool IsWindowsHost() {
#if defined(TARGET_OS_WINDOWS)
return true;
@@ -56,8 +58,7 @@
}
-const char* DartUtils::MapLibraryUrl(CommandLineOptions* url_mapping,
- const char* url_string) {
+const char* DartUtils::MapLibraryUrl(const char* url_string) {
ASSERT(url_mapping != NULL);
// We need to check if the passed in url is found in the url_mapping array,
// in that case use the mapped entry.
@@ -345,17 +346,6 @@
}
-Dart_Handle DartUtils::FilePathFromUri(Dart_Handle script_uri) {
- const int kNumArgs = 1;
- Dart_Handle dart_args[kNumArgs];
- dart_args[0] = script_uri;
- return Dart_Invoke(DartUtils::BuiltinLib(),
- NewString("_filePathFromUri"),
- kNumArgs,
- dart_args);
-}
-
-
Dart_Handle DartUtils::LibraryFilePath(Dart_Handle library_uri) {
const int kNumArgs = 1;
Dart_Handle dart_args[kNumArgs];
@@ -367,18 +357,6 @@
}
-Dart_Handle DartUtils::ResolveUri(Dart_Handle library_url, Dart_Handle url) {
- const int kNumArgs = 2;
- Dart_Handle dart_args[kNumArgs];
- dart_args[0] = library_url;
- dart_args[1] = url;
- return Dart_Invoke(DartUtils::BuiltinLib(),
- NewString("_resolveUri"),
- kNumArgs,
- dart_args);
-}
-
-
Dart_Handle DartUtils::ResolveScript(Dart_Handle url) {
const int kNumArgs = 1;
Dart_Handle dart_args[kNumArgs];
@@ -966,6 +944,18 @@
}
+Dart_Handle DartUtils::GetCanonicalizableWorkingDirectory() {
+ const char* str = DartUtils::original_working_directory;
+ intptr_t len = strlen(str);
+ if ((str[len] == '/') || (IsWindowsHost() && str[len] == '\\')) {
+ return Dart_NewStringFromCString(str);
+ }
+ char* new_str = reinterpret_cast<char*>(Dart_ScopeAllocate(len + 2));
+ snprintf(new_str, (len + 2), "%s%s", str, File::PathSeparator());
+ return Dart_NewStringFromCString(new_str);
+}
+
+
// Statically allocated Dart_CObject instances for immutable
// objects. As these will be used by different threads the use of
// these depends on the fact that the marking internally in the
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 9c3bc72..b9fe476 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -193,13 +193,11 @@
}
static bool SetOriginalWorkingDirectory();
+ static Dart_Handle GetCanonicalizableWorkingDirectory();
- static const char* MapLibraryUrl(CommandLineOptions* url_mapping,
- const char* url_string);
+ static const char* MapLibraryUrl(const char* url_string);
static Dart_Handle ResolveUriInWorkingDirectory(Dart_Handle script_uri);
- static Dart_Handle FilePathFromUri(Dart_Handle script_uri);
- static Dart_Handle ResolveUri(Dart_Handle library_url, Dart_Handle url);
static Dart_Handle ResolveScript(Dart_Handle url);
// Sniffs the specified text_buffer to see if it contains the magic number
@@ -217,6 +215,9 @@
// Global state that stores the original working directory..
static const char* original_working_directory;
+ // Global state that captures the URL mappings specified on the command line.
+ static CommandLineOptions* url_mapping;
+
static const char* const kDartScheme;
static const char* const kDartExtensionScheme;
static const char* const kAsyncLibURL;
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 5d70175..cc8bb06 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -15,6 +15,7 @@
#include "bin/dartutils.h"
#include "bin/eventhandler.h"
#include "bin/file.h"
+#include "bin/loader.h"
#include "bin/log.h"
#include "bin/thread.h"
#include "bin/utils.h"
@@ -81,10 +82,6 @@
// of a generic snapshot that contains only the corelibs).
static char* app_script_name = NULL;
-
-// Global state that captures the URL mappings specified on the command line.
-static CommandLineOptions* url_mapping = NULL;
-
// Global state that captures the entry point manifest files specified on the
// command line.
static CommandLineOptions* entry_points_files = NULL;
@@ -282,7 +279,7 @@
mapping = ProcessOption(option, "--url-mapping=");
}
if (mapping != NULL) {
- url_mapping->AddArgument(mapping);
+ DartUtils::url_mapping->AddArgument(mapping);
return true;
}
return false;
@@ -418,9 +415,42 @@
DISALLOW_COPY_AND_ASSIGN(UriResolverIsolateScope);
};
+
Dart_Isolate UriResolverIsolateScope::isolate = NULL;
+static Dart_Handle LoadUrlContents(const char* uri_string) {
+ bool failed = false;
+ char* result_string = NULL;
+ uint8_t* payload = NULL;
+ intptr_t payload_length = 0;
+ // Switch to the UriResolver Isolate and load the script.
+ {
+ UriResolverIsolateScope scope;
+
+ Dart_Handle resolved_uri = Dart_NewStringFromCString(uri_string);
+ Dart_Handle result = Loader::LoadUrlContents(resolved_uri,
+ &payload,
+ &payload_length);
+ if (Dart_IsError(result)) {
+ failed = true;
+ result_string = strdup(Dart_GetError(result));
+ }
+ }
+ // Switch back to the isolate from which we generate the snapshot and
+ // create the source string for the specified uri.
+ Dart_Handle result;
+ if (!failed) {
+ result = Dart_NewStringFromUTF8(payload, payload_length);
+ free(payload);
+ } else {
+ result = DartUtils::NewString(result_string);
+ free(result_string);
+ }
+ return result;
+}
+
+
static Dart_Handle ResolveUriInWorkingDirectory(const char* script_uri) {
bool failed = false;
char* result_string = NULL;
@@ -447,57 +477,27 @@
}
-static Dart_Handle FilePathFromUri(const char* script_uri) {
- bool failed = false;
- char* result_string = NULL;
-
- {
- UriResolverIsolateScope scope;
-
- // Run DartUtils::FilePathFromUri in context of uri resolver isolate.
- Dart_Handle result = DartUtils::FilePathFromUri(
- DartUtils::NewString(script_uri));
- if (Dart_IsError(result)) {
- failed = true;
- result_string = strdup(Dart_GetError(result));
- } else {
- result_string = strdup(DartUtils::GetStringValue(result));
- }
+static Dart_Handle LoadSnapshotCreationScript(const char* script_name) {
+ // First resolve the specified script uri with respect to the original
+ // working directory.
+ Dart_Handle resolved_uri = ResolveUriInWorkingDirectory(script_name);
+ if (Dart_IsError(resolved_uri)) {
+ return resolved_uri;
}
-
- Dart_Handle result = failed ? Dart_NewApiError(result_string) :
- DartUtils::NewString(result_string);
- free(result_string);
- return result;
-}
-
-
-static Dart_Handle ResolveUri(const char* library_uri, const char* uri) {
- bool failed = false;
- char* result_string = NULL;
-
- {
- UriResolverIsolateScope scope;
-
- // Run DartUtils::ResolveUri in context of uri resolver isolate.
- Dart_Handle result = DartUtils::ResolveUri(
- DartUtils::NewString(library_uri), DartUtils::NewString(uri));
- if (Dart_IsError(result)) {
- failed = true;
- result_string = strdup(Dart_GetError(result));
- } else {
- result_string = strdup(DartUtils::GetStringValue(result));
- }
+ // Now load the contents of the specified uri.
+ const char* resolved_uri_string = DartUtils::GetStringValue(resolved_uri);
+ Dart_Handle source = LoadUrlContents(resolved_uri_string);
+ if (Dart_IsError(source)) {
+ return source;
}
-
- Dart_Handle result = failed ? Dart_NewApiError(result_string) :
- DartUtils::NewString(result_string);
- free(result_string);
- return result;
+ if (IsSnapshottingForPrecompilation()) {
+ return Dart_LoadScript(resolved_uri, source, 0, 0);
+ } else {
+ return Dart_LoadLibrary(resolved_uri, source, 0, 0);
+ }
}
-
static Builtin::BuiltinLibraryId BuiltinId(const char* url) {
if (DartUtils::IsDartBuiltinLibURL(url)) {
return Builtin::kBuiltinLibrary;
@@ -521,7 +521,7 @@
}
const char* library_url_string = DartUtils::GetStringValue(library_url);
const char* mapped_library_url_string = DartUtils::MapLibraryUrl(
- url_mapping, library_url_string);
+ library_url_string);
if (mapped_library_url_string != NULL) {
library_url = ResolveUriInWorkingDirectory(mapped_library_url_string);
library_url_string = DartUtils::GetStringValue(library_url);
@@ -531,8 +531,7 @@
return Dart_NewApiError("url is not a string");
}
const char* url_string = DartUtils::GetStringValue(url);
- const char* mapped_url_string = DartUtils::MapLibraryUrl(url_mapping,
- url_string);
+ const char* mapped_url_string = DartUtils::MapLibraryUrl(url_string);
Builtin::BuiltinLibraryId libraryBuiltinId = BuiltinId(library_url_string);
if (tag == Dart_kCanonicalizeUrl) {
@@ -543,7 +542,7 @@
if (libraryBuiltinId != Builtin::kInvalidLibrary) {
return url;
}
- return ResolveUri(library_url_string, url_string);
+ return Dart_DefaultCanonicalizeUrl(library_url, url);
}
Builtin::BuiltinLibraryId builtinId = BuiltinId(url_string);
@@ -574,15 +573,8 @@
return resolved_url;
}
}
-
- // Get the file path out of the url.
- Dart_Handle file_path = FilePathFromUri(
- DartUtils::GetStringValue(resolved_url));
- if (Dart_IsError(file_path)) {
- return file_path;
- }
- const char* raw_path = DartUtils::GetStringValue(file_path);
- Dart_Handle source = DartUtils::ReadStringFromFile(raw_path);
+ const char* resolved_uri_string = DartUtils::GetStringValue(resolved_url);
+ Dart_Handle source = LoadUrlContents(resolved_uri_string);
if (Dart_IsError(source)) {
return source;
}
@@ -595,29 +587,6 @@
}
-static Dart_Handle LoadSnapshotCreationScript(const char* script_name) {
- Dart_Handle resolved_script_uri = ResolveUriInWorkingDirectory(script_name);
- if (Dart_IsError(resolved_script_uri)) {
- return resolved_script_uri;
- }
- Dart_Handle script_path = FilePathFromUri(
- DartUtils::GetStringValue(resolved_script_uri));
- if (Dart_IsError(script_path)) {
- return script_path;
- }
- Dart_Handle source = DartUtils::ReadStringFromFile(
- DartUtils::GetStringValue(script_path));
- if (Dart_IsError(source)) {
- return source;
- }
- if (IsSnapshottingForPrecompilation()) {
- return Dart_LoadScript(resolved_script_uri, source, 0, 0);
- } else {
- return Dart_LoadLibrary(resolved_script_uri, source, 0, 0);
- }
-}
-
-
static Dart_Handle LoadGenericSnapshotCreationScript(
Builtin::BuiltinLibraryId id) {
Dart_Handle source = Builtin::Source(id);
@@ -1131,7 +1100,7 @@
static void SetupForUriResolution() {
// Set up the library tag handler for this isolate.
- Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler);
+ Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
if (Dart_IsError(result)) {
Log::PrintErr("%s", Dart_GetError(result));
Dart_ExitScope();
@@ -1189,7 +1158,7 @@
Log::PrintErr("Error: We only expect to create the service isolate");
return NULL;
}
- Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler);
+ Dart_Handle result = Dart_SetLibraryTagHandler(Loader::LibraryTagHandler);
// Setup the native resolver.
Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
@@ -1215,8 +1184,8 @@
CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
// Initialize the URL mapping array.
- CommandLineOptions url_mapping_array(argc);
- url_mapping = &url_mapping_array;
+ CommandLineOptions cmdline_url_mapping(argc);
+ DartUtils::url_mapping = &cmdline_url_mapping;
// Initialize the entrypoints array.
CommandLineOptions entry_points_files_array(argc);
@@ -1278,7 +1247,9 @@
return 255;
}
- IsolateData* isolate_data = new IsolateData(NULL, NULL, NULL);
+ IsolateData* isolate_data = new IsolateData(NULL,
+ commandline_package_root,
+ commandline_packages_file);
Dart_Isolate isolate = Dart_CreateIsolate(
NULL, NULL, NULL, NULL, isolate_data, &error);
if (isolate == NULL) {
@@ -1302,7 +1273,6 @@
// create a full snapshot. The current isolate is set up so that we can
// invoke the dart uri resolution code like _resolveURI. App script is
// loaded into a separate isolate.
-
SetupForUriResolution();
// Prepare builtin and its dependent libraries for use to resolve URIs.
@@ -1321,11 +1291,10 @@
commandline_packages_file);
CHECK_RESULT(result);
+ UriResolverIsolateScope::isolate = isolate;
Dart_ExitScope();
Dart_ExitIsolate();
- UriResolverIsolateScope::isolate = isolate;
-
// Now we create an isolate into which we load all the code that needs to
// be in the snapshot.
isolate_data = new IsolateData(NULL, NULL, NULL);
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index 4b887ad..8e24f67 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -25,7 +25,9 @@
pending_operations_(0),
results_(NULL),
results_length_(0),
- results_capacity_(0) {
+ results_capacity_(0),
+ payload_(NULL),
+ payload_length_(0) {
monitor_ = new Monitor();
ASSERT(isolate_data_ != NULL);
port_ = Dart_NewNativePort("Loader",
@@ -54,6 +56,8 @@
}
free(results_);
results_ = NULL;
+ payload_ = NULL;
+ payload_length_ = 0;
}
@@ -191,13 +195,13 @@
}
-void Loader::BlockUntilComplete() {
+void Loader::BlockUntilComplete(ProcessResult process_result) {
MonitorLocker ml(monitor_);
while (true) {
// If |ProcessQueueLocked| returns false, we've hit an error and should
// stop loading.
- if (!ProcessQueueLocked()) {
+ if (!ProcessQueueLocked(process_result)) {
break;
}
@@ -225,7 +229,7 @@
}
-bool Loader::ProcessResultLocked(Loader::IOResult* result) {
+bool Loader::ProcessResultLocked(Loader* loader, Loader::IOResult* result) {
// We have to copy everything we care about out of |result| because after
// dropping the lock below |result| may no longer valid.
Dart_Handle uri =
@@ -249,7 +253,7 @@
return true;
}
// Fall through
- error_ = Dart_NewUnhandledExceptionError(error);
+ loader->error_ = Dart_NewUnhandledExceptionError(error);
return false;
}
@@ -267,8 +271,9 @@
source = Dart_NewStringFromUTF8(result->payload,
result->payload_length);
if (Dart_IsError(source)) {
- error_ = DartUtils::NewError("%s is not a valid UTF-8 script",
- reinterpret_cast<char*>(result->uri));
+ loader->error_ = DartUtils::NewError(
+ "%s is not a valid UTF-8 script",
+ reinterpret_cast<char*>(result->uri));
return false;
}
}
@@ -279,7 +284,7 @@
// We must drop the lock here because the tag handler may be recursively
// invoked and it will attempt to acquire the lock to queue more work.
- monitor_->Exit();
+ loader->monitor_->Exit();
Dart_Handle dart_result = Dart_Null();
@@ -306,10 +311,10 @@
}
// Re-acquire the lock before exiting the function (it was held before entry),
- monitor_->Enter();
+ loader->monitor_->Enter();
if (Dart_IsError(dart_result)) {
// Remember the error if we encountered one.
- error_ = dart_result;
+ loader->error_ = dart_result;
return false;
}
@@ -317,11 +322,29 @@
}
-bool Loader::ProcessQueueLocked() {
+bool Loader::ProcessUrlLoadResultLocked(Loader* loader,
+ Loader::IOResult* result) {
+ // A negative result tag indicates a loading error occurred in the service
+ // isolate. The payload is a C string of the error message.
+ if (result->tag < 0) {
+ Dart_Handle error = Dart_NewStringFromUTF8(result->payload,
+ result->payload_length);
+ loader->error_ = Dart_NewUnhandledExceptionError(error);
+ return false;
+ }
+ loader->payload_length_ = result->payload_length;
+ loader->payload_ =
+ reinterpret_cast<uint8_t*>(::malloc(loader->payload_length_));
+ memmove(loader->payload_, result->payload, loader->payload_length_);
+ return true;
+}
+
+
+bool Loader::ProcessQueueLocked(ProcessResult process_result) {
bool hit_error = false;
for (intptr_t i = 0; i < results_length(); i++) {
if (!hit_error) {
- hit_error = !ProcessResultLocked(&results_[i]);
+ hit_error = !(*process_result)(this, &results_[i]);
}
pending_operations_--;
ASSERT(hit_error || (pending_operations_ >= 0));
@@ -358,6 +381,48 @@
}
+Dart_Handle Loader::LoadUrlContents(Dart_Handle url,
+ uint8_t** payload,
+ intptr_t* payload_length) {
+ IsolateData* isolate_data =
+ reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
+ ASSERT(isolate_data != NULL);
+ ASSERT(!isolate_data->HasLoader());
+ Loader* loader = NULL;
+
+ // Setup the loader. The constructor does a bunch of leg work.
+ loader = new Loader(isolate_data);
+ loader->Init(isolate_data->package_root,
+ isolate_data->packages_file,
+ DartUtils::original_working_directory,
+ NULL);
+ ASSERT(loader != NULL);
+ ASSERT(isolate_data->HasLoader());
+
+ // Now send a load request to the service isolate.
+ loader->SendRequest(Dart_kScriptTag, url, Dart_Null());
+
+ // Wait for a reply to the load request.
+ loader->BlockUntilComplete(ProcessUrlLoadResultLocked);
+
+ // Copy fields from the loader before deleting it.
+ // The payload array itself which was malloced above is freed by
+ // the caller of LoadUrlContents.
+ Dart_Handle error = loader->error();
+ *payload = loader->payload_;
+ *payload_length = loader->payload_length_;
+
+ // Destroy the loader. The destructor does a bunch of leg work.
+ delete loader;
+
+ // An error occurred during loading.
+ if (!Dart_IsNull(error)) {
+ return error;
+ }
+ return Dart_Null();
+}
+
+
Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle url) {
@@ -466,7 +531,7 @@
if (blocking_call) {
// The outer invocation of the tag handler will block here until all nested
// invocations complete.
- loader->BlockUntilComplete();
+ loader->BlockUntilComplete(ProcessResultLocked);
// Remember the error (if any).
Dart_Handle error = loader->error();
diff --git a/runtime/bin/loader.h b/runtime/bin/loader.h
index 792ea45..088ce2e 100644
--- a/runtime/bin/loader.h
+++ b/runtime/bin/loader.h
@@ -22,6 +22,12 @@
static void InitForSnapshot(const char* snapshot_uri);
+ // Loads contents of the specified url.
+ static Dart_Handle LoadUrlContents(Dart_Handle url,
+ uint8_t** payload,
+ intptr_t* payload_length);
+
+
// A static tag handler that hides all usage of a loader for an isolate.
static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,
@@ -62,6 +68,9 @@
IOResult* results_;
intptr_t results_length_;
intptr_t results_capacity_;
+ uint8_t* payload_;
+ intptr_t payload_length_;
+ typedef bool (*ProcessResult)(Loader* loader, IOResult* result);
intptr_t results_length() {
return *static_cast<volatile intptr_t*>(&results_length_);
@@ -82,13 +91,16 @@
void QueueMessage(Dart_CObject* message);
/// Blocks the caller until the loader is finished.
- void BlockUntilComplete();
+ void BlockUntilComplete(ProcessResult process_result);
/// Returns false if |result| is an error and the loader should quit.
- bool ProcessResultLocked(IOResult* result);
+ static bool ProcessResultLocked(Loader* loader, IOResult* result);
+
+ /// Returns false if |result| is an error and the loader should quit.
+ static bool ProcessUrlLoadResultLocked(Loader* loader, IOResult* result);
/// Returns false if an error occurred and the loader should quit.
- bool ProcessQueueLocked();
+ bool ProcessQueueLocked(ProcessResult process_result);
// Special inner tag handler for dart: uris.
static Dart_Handle DartColonLibraryTagHandler(Dart_LibraryTag tag,
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 6c8ca4b..d7bfb3b 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -207,7 +207,7 @@
static bool ProcessPackageRootOption(const char* arg,
CommandLineOptions* vm_options) {
ASSERT(arg != NULL);
- if (*arg == '\0' || *arg == '-') {
+ if (*arg == '-') {
return false;
}
commandline_package_root = arg;
@@ -216,9 +216,9 @@
static bool ProcessPackagesOption(const char* arg,
- CommandLineOptions* vm_options) {
+ CommandLineOptions* vm_options) {
ASSERT(arg != NULL);
- if ((*arg == '\0') || (*arg == '-')) {
+ if (*arg == '-') {
return false;
}
commandline_packages_file = arg;
@@ -592,6 +592,16 @@
"file is invalid.\n");
return -1;
}
+ if ((commandline_package_root != NULL) &&
+ (strlen(commandline_package_root) == 0)) {
+ Log::PrintErr("Empty package root specified.\n");
+ return -1;
+ }
+ if ((commandline_packages_file != NULL) &&
+ (strlen(commandline_packages_file) == 0)) {
+ Log::PrintErr("Empty package file name specified.\n");
+ return -1;
+ }
if (is_noopt && gen_snapshot_kind != kNone) {
Log::PrintErr("Generating a snapshot with dart_noopt is invalid.\n");
return -1;
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
index 82fbe5e..cb6792b 100644
--- a/runtime/bin/vmservice/loader.dart
+++ b/runtime/bin/vmservice/loader.dart
@@ -480,7 +480,7 @@
Uri uri,
Uri resolvedUri,
String libraryUrl) {
- if (resolvedUri.scheme == 'file') {
+ if (resolvedUri.scheme == '' || resolvedUri.scheme == 'file') {
_loadFile(sp, tag, uri, resolvedUri, libraryUrl);
} else if ((resolvedUri.scheme == 'http') ||
(resolvedUri.scheme == 'https')) {
@@ -805,7 +805,7 @@
Uri resource) async {
try {
if (tag == -1) {
- if (resource.scheme == 'file') {
+ if (resource.scheme == '' || resource.scheme == 'file') {
_findPackagesFile(sp, traceLoading, resource);
} else if ((resource.scheme == 'http') || (resource.scheme == 'https')) {
// Try to load the .packages file next to the resource.
@@ -825,7 +825,7 @@
if (traceLoading) {
_log("Handling load of packages map: '$resource'.");
}
- if (resource.scheme == 'file') {
+ if (resource.scheme == '' || resource.scheme == 'file') {
var exists = await new File.fromUri(resource).exists();
if (exists) {
_loadPackagesFile(sp, traceLoading, resource);
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 2736408..b7f4df4 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -342,8 +342,8 @@
return result;
}
if (tag == Dart_kImportTag) {
- // Embedder handles all requests for external libraries.
- return DartUtils::LibraryTagHandler(tag, library, url);
+ UNREACHABLE();
+ return Dart_Null();
}
ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl));
if (tag == Dart_kCanonicalizeUrl) {
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index 0387f80..28d4ef4 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -26,6 +26,7 @@
DartFrameIterator iterator;
iterator.NextFrame(); // Skip native call.
+ iterator.NextFrame(); // Skip _AssertionError._checkAssertion frame
const Script& script = Script::Handle(Exceptions::GetCallerScript(&iterator));
// Initialize argument 'failed_assertion' with source snippet.
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 8c995a4..faf342b 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -26,9 +26,13 @@
static _throwNew(int assertionStart, int assertionEnd)
native "AssertionError_throwNew";
- static _handleCondition(condition) {
- if (condition is Function) return condition();
- return condition;
+ static void _checkAssertion(condition, int start, int end) {
+ if (condition is Function) {
+ condition = condition();
+ }
+ if (!condition) {
+ _throwNew(start, end);
+ }
}
String toString() {
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index 351cbbf..5680037 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -146,7 +146,7 @@
const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1));
ASSERT(CheckInteger(right_int));
- ASSERT(CheckInteger(right_int));
+ ASSERT(CheckInteger(left_int));
if (FLAG_trace_intrinsified_natives) {
OS::Print("Integer_moduloFromInteger %s mod %s\n",
left_int.ToCString(), right_int.ToCString());
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 09ae531..4dd89c0 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -312,13 +312,12 @@
try {
// The VM will invoke [_startIsolate] with entryPoint as argument.
readyPort = new RawReceivePort();
- var packageRoot = null;
- var packageConfig = null;
- if (Isolate._packageSupported()) {
- packageRoot = (await Isolate.packageRoot)?.toString();
- packageConfig = (await Isolate.packageConfig)?.toString();
- }
+ // We do not inherit the package root or package config settings
+ // from the parent isolate, instead we use the values that were
+ // set on the command line.
+ var packageRoot = VMLibraryHooks.packageRootString;
+ var packageConfig = VMLibraryHooks.packageConfigString;
var script = VMLibraryHooks.platformScript;
if (script == null) {
// We do not have enough information to support spawning the new
diff --git a/runtime/observatory/.analysis_options b/runtime/observatory/.analysis_options
index fd7cfbf..fc9ab29 100644
--- a/runtime/observatory/.analysis_options
+++ b/runtime/observatory/.analysis_options
@@ -1,9 +1,6 @@
analyzer:
exclude:
-# Remove once Dart 1.13-dev is released
+ - tests/service/get_isolate_after_language_error_test.dart
- tests/service/developer_extension_test.dart
-# Remove once Dart 1.13-dev is released
- - tests/service/logging_test.dart
- - tests/ui/log.dart
-# Remove once Dart 1.13-dev is released
- - tests/service/get_stack_rpc_test.dart
+ - tests/service/address_mapper_test.dart
+ - tests/service/pause_on_unhandled_exceptions_test.dart
diff --git a/runtime/observatory/lib/src/debugger/debugger_location.dart b/runtime/observatory/lib/src/debugger/debugger_location.dart
index 7688712..ac3a9bf 100644
--- a/runtime/observatory/lib/src/debugger/debugger_location.dart
+++ b/runtime/observatory/lib/src/debugger/debugger_location.dart
@@ -256,7 +256,6 @@
return new DebuggerLocation.error(
"Function '${match.group(0)}' is ambiguous");
}
- return new DebuggerLocation.error('foo');
});
}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index a839728..18d29bf 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -46,6 +46,7 @@
static const kFileSystemAlreadyExists = 1001;
static const kFileSystemDoesNotExist = 1002;
static const kFileDoesNotExist = 1003;
+ static const kIsolateReloadFailed = 1004;
int code;
Map data;
@@ -1640,7 +1641,7 @@
}
Future<ObjectStore> getObjectStore() {
- return invokeRpc('_getObjectStore', {}).then((map) {
+ return invokeRpcNoUpgrade('_getObjectStore', {}).then((map) {
ObjectStore objectStore = new ObjectStore._empty(this);
objectStore._update(map, false);
return objectStore;
diff --git a/runtime/observatory/tests/service/dev_fs_test.dart b/runtime/observatory/tests/service/dev_fs_test.dart
index 9f23396..8855e13 100644
--- a/runtime/observatory/tests/service/dev_fs_test.dart
+++ b/runtime/observatory/tests/service/dev_fs_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--error_on_bad_type --error_on_bad_override
-import 'dart:async';
import 'dart:convert';
import 'package:observatory/service_io.dart';
import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/evaluate_activation_in_method_class_other.dart b/runtime/observatory/tests/service/evaluate_activation_in_method_class_other.dart
index 6cc5879..bf070a1 100644
--- a/runtime/observatory/tests/service/evaluate_activation_in_method_class_other.dart
+++ b/runtime/observatory/tests/service/evaluate_activation_in_method_class_other.dart
@@ -11,6 +11,7 @@
var instVar = 'Superclass';
method() => 'Superclass';
static staticMethod() => 'Superclass';
+ suppress_warning() => _instVar;
}
class Klass extends Superclass {
@@ -22,5 +23,7 @@
test() {
var _local = 'Klass';
debugger();
+ // Suppress unused variable warning.
+ print(_local);
}
}
diff --git a/runtime/observatory/tests/service/evaluate_activation_in_method_class_test.dart b/runtime/observatory/tests/service/evaluate_activation_in_method_class_test.dart
index cfe4315..d07b832 100644
--- a/runtime/observatory/tests/service/evaluate_activation_in_method_class_test.dart
+++ b/runtime/observatory/tests/service/evaluate_activation_in_method_class_test.dart
@@ -20,6 +20,7 @@
var instVar = 'Subclass';
method() => 'Subclass';
static staticMethod() => 'Subclass';
+ suppress_warning() => _instVar;
}
testeeDo() {
@@ -70,7 +71,7 @@
result = await isolate.evalFrame(topFrame, 'staticMethod()');
print(result);
expect(result.valueAsString, equals('Klass'));
-
+
// function.Owner verus function.Origin
// The mixin of Superclass is in _other.dart and the mixin
// application is in _test.dart.
diff --git a/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart b/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart
index dc763a0..ccb00fe 100644
--- a/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart
+++ b/runtime/observatory/tests/service/get_isolate_after_language_error_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--error_on_bad_type --error_on_bad_override
-import 'dart:async';
import 'package:observatory/service_io.dart';
import 'package:unittest/unittest.dart';
import 'test_helper.dart';
@@ -29,4 +28,4 @@
main(args) => runIsolateTestsSynchronous(args,
tests,
pause_on_exit: true,
- testeeConcurrent: doThrow);
\ No newline at end of file
+ testeeConcurrent: doThrow);
diff --git a/runtime/observatory/tests/service/get_isolate_after_stack_overflow_error_test.dart b/runtime/observatory/tests/service/get_isolate_after_stack_overflow_error_test.dart
new file mode 100644
index 0000000..0223218
--- /dev/null
+++ b/runtime/observatory/tests/service/get_isolate_after_stack_overflow_error_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// 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 'service_test_common.dart';
+
+// Non tailable recursive function that should trigger a Stack Overflow.
+num factorialGrowth([num n = 1]) {
+ return factorialGrowth(n + 1) * n;
+}
+
+void nonTailableRecursion() {
+ factorialGrowth();
+}
+
+var tests = [
+ hasStoppedAtExit,
+
+ (Isolate isolate) async {
+ await isolate.reload();
+ expect(isolate.error, isNotNull);
+ expect(isolate.error.message.contains('Stack Overflow'), isTrue);
+ }
+];
+
+main(args) async => runIsolateTests(args,
+ tests,
+ pause_on_exit: true,
+ testeeConcurrent: nonTailableRecursion);
diff --git a/runtime/observatory/tests/service/get_object_store_rpc_test.dart b/runtime/observatory/tests/service/get_object_store_rpc_test.dart
new file mode 100644
index 0000000..fb7f7f6
--- /dev/null
+++ b/runtime/observatory/tests/service/get_object_store_rpc_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer' as developer;
+
+void doDebugger() {
+ developer.debugger(message: "foo", when: true);
+}
+
+bool isClosureFunctionsList(NamedField field) {
+ return field.name == 'closure_functions_';
+}
+
+var tests = [
+
+// Initial data fetch and verify we've hit the breakpoint.
+(Isolate isolate) async {
+ await isolate.rootLibrary.load();
+ var script = isolate.rootLibrary.scripts[0];
+ await script.load();
+ await hasStoppedAtBreakpoint(isolate);
+ // Sanity check.
+ expect(isolate.pauseEvent.kind, equals(ServiceEvent.kPauseBreakpoint));
+},
+
+// Get object_store.
+(Isolate isolate) async {
+ var object_store = await isolate.getObjectStore();
+ expect(object_store.runtimeType, equals(ObjectStore));
+ // Sanity check.
+ expect(object_store.fields.length, greaterThanOrEqualTo(1));
+ // Checking Closures.
+ expect(object_store.fields.singleWhere(isClosureFunctionsList), isNotNull);
+ expect(object_store.fields.singleWhere(isClosureFunctionsList).value.isList, isTrue);
+}
+
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+ testeeConcurrent: doDebugger);
diff --git a/runtime/observatory/tests/service/instance_field_order_rpc_test.dart b/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
index 0323f8c..f39d324 100644
--- a/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
+++ b/runtime/observatory/tests/service/instance_field_order_rpc_test.dart
@@ -5,7 +5,6 @@
library get_object_rpc_test;
-import 'dart:typed_data';
import 'package:observatory/service_io.dart';
import 'package:unittest/unittest.dart';
import 'test_helper.dart';
diff --git a/runtime/observatory/tests/service/pause_idle_isolate_test.dart b/runtime/observatory/tests/service/pause_idle_isolate_test.dart
index a75dcd1..859291f 100644
--- a/runtime/observatory/tests/service/pause_idle_isolate_test.dart
+++ b/runtime/observatory/tests/service/pause_idle_isolate_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--error_on_bad_type --error_on_bad_override
-import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'dart:isolate' show ReceivePort;
diff --git a/runtime/observatory/tests/service/pause_on_exceptions_test.dart b/runtime/observatory/tests/service/pause_on_exceptions_test.dart
index 03d4731..da2e250 100644
--- a/runtime/observatory/tests/service/pause_on_exceptions_test.dart
+++ b/runtime/observatory/tests/service/pause_on_exceptions_test.dart
@@ -10,7 +10,6 @@
doThrow() {
throw "TheException"; // Line 13.
- return "end of doThrow";
}
doCaught() {
diff --git a/runtime/observatory/tests/service/set_name_rpc_test.dart b/runtime/observatory/tests/service/set_name_rpc_test.dart
new file mode 100644
index 0000000..bb3d8c8
--- /dev/null
+++ b/runtime/observatory/tests/service/set_name_rpc_test.dart
@@ -0,0 +1,36 @@
+// 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 --vm-name=Walter
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+var tests = [
+ (Isolate isolate) async {
+ expect(isolate.name, equals('set_name_rpc_test.dart\$main'));
+
+ Completer completer = new Completer();
+ var stream = await isolate.vm.getEventStream(VM.kIsolateStream);
+ var subscription;
+ subscription = stream.listen((ServiceEvent event) {
+ if (event.kind == ServiceEvent.kIsolateUpdate) {
+ expect(event.owner.type, equals('Isolate'));
+ expect(event.owner.name, equals('Barbara'));
+ subscription.cancel();
+ completer.complete();
+ }
+ });
+
+ var result = await isolate.setName('Barbara');
+ expect(result.type, equals('Success'));
+
+ await completer.future;
+ expect(isolate.name, equals('Barbara'));
+
+ }
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory/tests/service/string_escaping_test.dart b/runtime/observatory/tests/service/string_escaping_test.dart
index fd99cee..0f5dee4 100644
--- a/runtime/observatory/tests/service/string_escaping_test.dart
+++ b/runtime/observatory/tests/service/string_escaping_test.dart
@@ -48,44 +48,47 @@
malformedWithTrailSurrogate = "before" + "𝄞"[1] + "after";
}
+testStrings(Isolate isolate) async {
+ Library lib = isolate.rootLibrary;
+ await lib.load();
+ for (var variable in lib.variables) {
+ await variable.load();
+ }
+
+ expectFullString(String varName, String varValueAsString) {
+ Field field = lib.variables.singleWhere((v) => v.name == varName);
+ Instance value = field.staticValue;
+ expect(value.valueAsString, equals(varValueAsString));
+ expect(value.valueAsStringIsTruncated, isFalse);
+ }
+
+ expectTruncatedString(String varName, String varValueAsString) {
+ Field field = lib.variables.singleWhere((v) => v.name == varName);
+ Instance value = field.staticValue;
+ print(value.valueAsString);
+ expect(varValueAsString, startsWith(value.valueAsString));
+ expect(value.valueAsStringIsTruncated, isTrue);
+ }
+
+ script(); // Need to initialize variables in the testing isolate.
+ expectFullString('ascii', ascii);
+ expectFullString('latin1', latin1);
+ expectFullString('unicode', unicode);
+ expectFullString('hebrew', hebrew);
+ expectFullString('singleQuotes', singleQuotes);
+ expectFullString('doubleQuotes', doubleQuotes);
+ expectFullString('newLines', newLines);
+ expectFullString('tabs', tabs);
+ expectFullString('suggrogatePairs', suggrogatePairs);
+ expectFullString('nullInTheMiddle', nullInTheMiddle);
+ expectTruncatedString('longStringEven', longStringEven);
+ expectTruncatedString('longStringOdd', longStringOdd);
+ expectFullString('malformedWithLeadSurrogate', malformedWithLeadSurrogate);
+ expectFullString('malformedWithTrailSurrogate', malformedWithTrailSurrogate);
+}
+
var tests = [
-
-(Isolate isolate) =>
- isolate.rootLibrary.load().then((Library lib) {
- expectFullString(String varName, String varValueAsString) {
- Field field = lib.variables.singleWhere((v) => v.name == varName);
- field.load().then((_) {
- Instance value = field.staticValue;
- expect(value.valueAsString, equals(varValueAsString));
- expect(value.valueAsStringIsTruncated, isFalse);
- });
- }
- expectTruncatedString(String varName, String varValueAsString) {
- Field field = lib.variables.singleWhere((v) => v.name == varName);
- field.load().then((_) {
- Instance value = field.staticValue;
- expect(varValueAsString, startsWith(value.valueAsString));
- expect(value.valueAsStringIsTruncated, isTrue);
- });
- }
-
- script(); // Need to initialize variables in the testing isolate.
- expectFullString('ascii', ascii);
- expectFullString('latin1', latin1);
- expectFullString('unicode', unicode);
- expectFullString('hebrew', hebrew);
- expectFullString('singleQuotes', singleQuotes);
- expectFullString('doubleQuotes', doubleQuotes);
- expectFullString('newLines', newLines);
- expectFullString('tabs', tabs);
- expectFullString('suggrogatePairs', suggrogatePairs);
- expectFullString('nullInTheMiddle', nullInTheMiddle);
- expectTruncatedString('longStringEven', longStringEven);
- expectTruncatedString('longStringOdd', longStringOdd);
- expectFullString('malformedWithLeadSurrogate', malformedWithLeadSurrogate);
- expectFullString('malformedWithTrailSurrogate', malformedWithTrailSurrogate);
- }),
-
+ testStrings,
];
main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index e22cbb2..1d2ea9d 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -36,7 +36,7 @@
return Platform.environment[_SKY_SHELL_ENV_KEY];
}
-class _SerivceTesteeRunner {
+class _ServiceTesteeRunner {
Future run({testeeBefore(): null,
testeeConcurrent(): null,
bool pause_on_start: false,
@@ -335,7 +335,7 @@
bool pause_on_unhandled_exceptions: false}) async {
assert(!pause_on_start || testeeBefore == null);
if (_isTestee()) {
- new _SerivceTesteeRunner().run(testeeBefore: testeeBefore,
+ new _ServiceTesteeRunner().run(testeeBefore: testeeBefore,
testeeConcurrent: testeeConcurrent,
pause_on_start: pause_on_start,
pause_on_exit: pause_on_exit);
@@ -373,7 +373,7 @@
bool pause_on_unhandled_exceptions: false}) {
assert(!pause_on_start || testeeBefore == null);
if (_isTestee()) {
- new _SerivceTesteeRunner().runSync(testeeBeforeSync: testeeBefore,
+ new _ServiceTesteeRunner().runSync(testeeBeforeSync: testeeBefore,
testeeConcurrentSync: testeeConcurrent,
pause_on_start: pause_on_start,
pause_on_exit: pause_on_exit);
@@ -406,7 +406,7 @@
bool verbose_vm: false,
bool pause_on_unhandled_exceptions: false}) async {
if (_isTestee()) {
- new _SerivceTesteeRunner().run(testeeBefore: testeeBefore,
+ new _ServiceTesteeRunner().run(testeeBefore: testeeBefore,
testeeConcurrent: testeeConcurrent,
pause_on_start: pause_on_start,
pause_on_exit: pause_on_exit);
diff --git a/runtime/platform/assert.cc b/runtime/platform/assert.cc
index e9d1c4f..c5b91e7 100644
--- a/runtime/platform/assert.cc
+++ b/runtime/platform/assert.cc
@@ -4,9 +4,6 @@
#include "platform/assert.h"
-#include <sstream>
-#include <string>
-
#include "platform/globals.h"
#include "vm/os.h"
@@ -18,19 +15,27 @@
}
void DynamicAssertionHelper::Fail(const char* format, ...) {
- std::ostringstream stream;
- stream << file_ << ":" << line_ << ": error: ";
+ // Take only the last 1KB of the file name if it is longer.
+ const intptr_t file_len = strlen(file_);
+ const intptr_t file_offset = (file_len > (1 * KB)) ? file_len - (1 * KB) : 0;
+ const char* file = file_ + file_offset;
+ // Print the file and line number into the buffer.
+ char buffer[4 * KB];
+ intptr_t file_and_line_length =
+ snprintf(buffer, sizeof(buffer), "%s: %d: error: ", file, line_);
+
+ // Print the error message into the buffer.
va_list arguments;
va_start(arguments, format);
- char buffer[4 * KB];
- vsnprintf(buffer, sizeof(buffer), format, arguments);
+ vsnprintf(buffer + file_and_line_length,
+ sizeof(buffer) - file_and_line_length,
+ format,
+ arguments);
va_end(arguments);
- stream << buffer << std::endl;
- // Get the message from the string stream and dump it on stderr.
- std::string message = stream.str();
- fprintf(stderr, "%s", message.c_str());
+ // Print the buffer on stderr.
+ fprintf(stderr, "%s\n", buffer);
fflush(stderr);
// In case of failed assertions, abort right away. Otherwise, wait
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 2313aab..1faa41c 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -13,6 +13,9 @@
cc/ArrayNew_Overflow_Crash: Crash, Timeout
cc/AllocGeneric_Overflow: Crash, Timeout
cc/CodeImmutability: Crash
+cc/Fail0: Fail
+cc/Fail1: Fail
+cc/Fail2: Fail
cc/SNPrint_BadArgs: Skip
@@ -85,8 +88,8 @@
[ $builder_tag == asan ]
cc/CodeImmutability: Fail,OK # Address Sanitizer turns a crash into a failure.
-[ $noopt ]
-dart/byte_array_test: Crash # Incompatible flag --disable_alloc_stubs_after_gc
+[ $noopt || $compiler == precompiler ]
+dart/byte_array_test: Skip # Incompatible flag --disable_alloc_stubs_after_gc
[ $noopt || $compiler == precompiler || $mode == product ]
dart/redirection_type_shuffling_test: SkipByDesign # Imports dart:mirrors
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index 7cae460..89d6b09 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -1949,7 +1949,8 @@
// If type tests specified by 'ic_data' do not depend on type arguments,
// return mapping cid->result in 'results' (i : cid; i + 1: result).
// If all tests yield the same result, return it otherwise return Bool::null.
-// If no mapping is possible, 'results' is empty.
+// If no mapping is possible, 'results' has less than
+// (ic_data.NumberOfChecks() * 2) entries
// An instance-of test returning all same results can be converted to a class
// check.
RawBool* AotOptimizer::InstanceOfAsBool(
@@ -2078,7 +2079,7 @@
// TODO(srdjan): Do also for other than 'int' type.
static bool TryExpandTestCidsResult(ZoneGrowableArray<intptr_t>* results,
const AbstractType& type) {
- ASSERT(results->length() >= 2); // At least on eentry.
+ ASSERT(results->length() >= 2); // At least on entry.
const ClassTable& class_table = *Isolate::Current()->class_table();
if ((*results)[0] != kSmiCid) {
const Class& cls = Class::Handle(class_table.At(kSmiCid));
@@ -2100,14 +2101,26 @@
ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded());
ASSERT(results->length() >= 2);
- if (type.IsIntType()) {
+ if (type.IsSmiType()) {
+ ASSERT((*results)[0] == kSmiCid);
+ return false;
+ } else if (type.IsIntType()) {
ASSERT((*results)[0] == kSmiCid);
TryAddTest(results, kMintCid, true);
TryAddTest(results, kBigintCid, true);
// Cannot deoptimize since all tests returning true have been added.
return false;
+ } else if (type.IsNumberType()) {
+ ASSERT((*results)[0] == kSmiCid);
+ TryAddTest(results, kMintCid, true);
+ TryAddTest(results, kBigintCid, true);
+ TryAddTest(results, kDoubleCid, true);
+ return false;
+ } else if (type.IsDoubleType()) {
+ ASSERT((*results)[0] == kSmiCid);
+ TryAddTest(results, kDoubleCid, true);
+ return false;
}
-
return true; // May deoptimize since we have not identified all 'true' tests.
}
@@ -2115,11 +2128,6 @@
// TODO(srdjan): Use ICData to check if always true or false.
void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
ASSERT(Token::IsTypeTestOperator(call->token_kind()));
- // Guard against repeated speculative inlining.
- if (!use_speculative_inlining_ ||
- IsBlackListedForInlining(call->deopt_id())) {
- return;
- }
Definition* left = call->ArgumentAt(0);
Definition* type_args = NULL;
AbstractType& type = AbstractType::ZoneHandle(Z);
@@ -2152,46 +2160,6 @@
negate = Bool::Cast(call->ArgumentAt(3)->OriginalDefinition()
->AsConstant()->value()).value();
}
- const ICData& unary_checks =
- ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
- if ((unary_checks.NumberOfChecks() > 0) &&
- (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
- ZoneGrowableArray<intptr_t>* results =
- new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
- Bool& as_bool =
- Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results));
- if (as_bool.IsNull()) {
- if (results->length() == unary_checks.NumberOfChecks() * 2) {
- const bool can_deopt = TryExpandTestCidsResult(results, type);
- TestCidsInstr* test_cids = new(Z) TestCidsInstr(
- call->token_pos(),
- negate ? Token::kISNOT : Token::kIS,
- new(Z) Value(left),
- *results,
- can_deopt ? call->deopt_id() : Thread::kNoDeoptId);
- // Remove type.
- ReplaceCall(call, test_cids);
- return;
- }
- } else {
- // TODO(srdjan): Use TestCidsInstr also for this case.
- // One result only.
- AddReceiverCheck(call);
- if (negate) {
- as_bool = Bool::Get(!as_bool.value()).raw();
- }
- ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool);
- for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
- PushArgumentInstr* push = call->PushArgumentAt(i);
- push->ReplaceUsesWith(push->value()->definition());
- push->RemoveFromGraph();
- }
- call->ReplaceUsesWith(bool_const);
- ASSERT(current_iterator()->Current() == call);
- current_iterator()->RemoveCurrentFromGraph();
- return;
- }
- }
if (TypeCheckAsClassEquality(type)) {
LoadClassIdInstr* left_cid = new(Z) LoadClassIdInstr(new(Z) Value(left));
@@ -2214,6 +2182,31 @@
return;
}
+ const ICData& unary_checks =
+ ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
+ if ((unary_checks.NumberOfChecks() > 0) &&
+ (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
+ ZoneGrowableArray<intptr_t>* results =
+ new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
+ InstanceOfAsBool(unary_checks, type, results);
+ if (results->length() == unary_checks.NumberOfChecks() * 2) {
+ const bool can_deopt = TryExpandTestCidsResult(results, type);
+ if (can_deopt && !IsAllowedForInlining(call->deopt_id())) {
+ // Guard against repeated speculative inlining.
+ return;
+ }
+ TestCidsInstr* test_cids = new(Z) TestCidsInstr(
+ call->token_pos(),
+ negate ? Token::kISNOT : Token::kIS,
+ new(Z) Value(left),
+ *results,
+ can_deopt ? call->deopt_id() : Thread::kNoDeoptId);
+ // Remove type.
+ ReplaceCall(call, test_cids);
+ return;
+ }
+ }
+
InstanceOfInstr* instance_of =
new(Z) InstanceOfInstr(call->token_pos(),
new(Z) Value(left),
@@ -2228,11 +2221,6 @@
// TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids).
void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
ASSERT(Token::IsTypeCastOperator(call->token_kind()));
- // Guard against repeated speculative inlining.
- if (!use_speculative_inlining_ ||
- IsBlackListedForInlining(call->deopt_id())) {
- return;
- }
Definition* left = call->ArgumentAt(0);
Definition* type_args = call->ArgumentAt(1);
const AbstractType& type =
@@ -2247,6 +2235,10 @@
const Bool& as_bool = Bool::ZoneHandle(Z,
InstanceOfAsBool(unary_checks, type, results));
if (as_bool.raw() == Bool::True().raw()) {
+ // Guard against repeated speculative inlining.
+ if (!IsAllowedForInlining(call->deopt_id())) {
+ return;
+ }
AddReceiverCheck(call);
// Remove the original push arguments.
for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
@@ -2272,11 +2264,12 @@
}
-bool AotOptimizer::IsBlackListedForInlining(intptr_t call_deopt_id) {
+bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) {
+ if (!use_speculative_inlining_) return false;
for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) {
- if ((*inlining_black_list_)[i] == call_deopt_id) return true;
+ if ((*inlining_black_list_)[i] == call_deopt_id) return false;
}
- return false;
+ return true;
}
@@ -2329,8 +2322,7 @@
return;
}
- if (use_speculative_inlining_ &&
- !IsBlackListedForInlining(instr->deopt_id()) &&
+ if (IsAllowedForInlining(instr->deopt_id()) &&
(unary_checks.NumberOfChecks() > 0)) {
if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) {
return;
diff --git a/runtime/vm/aot_optimizer.h b/runtime/vm/aot_optimizer.h
index d608442..6902552 100644
--- a/runtime/vm/aot_optimizer.h
+++ b/runtime/vm/aot_optimizer.h
@@ -163,7 +163,7 @@
const Function& function() const { return flow_graph_->function(); }
- bool IsBlackListedForInlining(intptr_t deopt_id);
+ bool IsAllowedForInlining(intptr_t deopt_id);
FlowGraph* flow_graph_;
diff --git a/runtime/vm/assembler_dbc_test.cc b/runtime/vm/assembler_dbc_test.cc
index 5baa5d6..9e4e2cd 100644
--- a/runtime/vm/assembler_dbc_test.cc
+++ b/runtime/vm/assembler_dbc_test.cc
@@ -119,6 +119,22 @@
}
+ASSEMBLER_TEST_GENERATE(Nop, assembler) {
+ __ PushConstant(Smi::Handle(Smi::New(42)));
+ __ Nop();
+ __ Nop();
+ __ Nop();
+ __ Nop();
+ __ Nop();
+ __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(Nop, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
// Called from assembler_test.cc.
// FP[-kParamEndSlotFromFp - 1]: growable array
// FP[-kParamEndSlotFromFp - 2]: value
@@ -484,6 +500,413 @@
}
+// - Add, Sub, Mul, Div, Mod, Shl, Shr rA, rB, rC
+//
+// Arithmetic operations on Smis. FP[rA] <- FP[rB] op FP[rC].
+// If these instructions can trigger a deoptimization, the following
+// instruction should be Deopt. If no deoptimization should be triggered,
+// the immediately following instruction is skipped.
+ASSEMBLER_TEST_GENERATE(AddNoOverflow, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(20)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(22)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Add(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(AddNoOverflow, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddOverflow, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Add(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(AddOverflow, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(SubNoOverflow, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(64)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(22)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Sub(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(SubNoOverflow, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(SubOverflow, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Sub(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(SubOverflow, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(MulNoOverflow, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(-6)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(-7)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Mul(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(MulNoOverflow, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(MulOverflow, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(-8)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Mul(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(MulOverflow, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DivNoDeopt, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(27)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(3)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Div(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DivNoDeopt, test) {
+ EXPECT_EQ(9, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DivZero, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(3)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(0)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Div(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DivZero, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(DivCornerCase, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Div(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(DivCornerCase, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ModPosPos, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(4)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Mod(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ModPosPos, test) {
+ EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ModNegPos, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(-42)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(4)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Mod(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ModNegPos, test) {
+ EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ModPosNeg, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(-4)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Mod(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ModPosNeg, test) {
+ EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ModZero, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(3)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(0)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Mod(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ModZero, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ShlNoDeopt, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(21)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Shl(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ShlNoDeopt, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ShlOverflow, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Shl(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ShlOverflow, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ShlNegShift, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(21)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Shl(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ShlNegShift, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ShrNoDeopt, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(84)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(1)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Shr(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ShrNoDeopt, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(ShrNegShift, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(21)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ Shr(2, 0, 1);
+ __ LoadConstant(2, Smi::Handle(Smi::New(42)));
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(ShrNegShift, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+// - Neg rA , rD
+//
+// FP[rA] <- -FP[rD]. Assumes FP[rD] is a Smi. If there is no overflow the
+// immediately following instruction is skipped.
+ASSEMBLER_TEST_GENERATE(NegPos, assembler) {
+ __ Frame(2);
+ __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+ __ Neg(1, 0);
+ __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+ __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(NegPos, test) {
+ EXPECT_EQ(-42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(NegNeg, assembler) {
+ __ Frame(2);
+ __ LoadConstant(0, Smi::Handle(Smi::New(-42)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+ __ Neg(1, 0);
+ __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+ __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(NegNeg, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(NegOverflow, assembler) {
+ __ Frame(2);
+ __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+ __ Neg(1, 0);
+ __ LoadConstant(1, Smi::Handle(Smi::New(42)));
+ __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(NegOverflow, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+// - BitOr, BitAnd, BitXor rA, rB, rC
+//
+// FP[rA] <- FP[rB] op FP[rC]
+ASSEMBLER_TEST_GENERATE(BitOr, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(0x2)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(0x28)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ BitOr(2, 0, 1);
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(BitOr, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(BitAnd, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(0x2b)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(0x6a)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ BitAnd(2, 0, 1);
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(BitAnd, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(BitXor, assembler) {
+ __ Frame(3);
+ __ LoadConstant(0, Smi::Handle(Smi::New(0x37)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(0x1d)));
+ __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
+ __ BitXor(2, 0, 1);
+ __ Return(2);
+}
+
+
+ASSEMBLER_TEST_RUN(BitXor, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+// - BitNot rA, rD
+//
+// FP[rA] <- ~FP[rD]. As above, assumes FP[rD] is a Smi.
+ASSEMBLER_TEST_GENERATE(BitNot, assembler) {
+ __ Frame(2);
+ __ LoadConstant(0, Smi::Handle(Smi::New(~42)));
+ __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
+ __ BitNot(1, 0);
+ __ Return(1);
+}
+
+
+ASSEMBLER_TEST_RUN(BitNot, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
// - IfNeStrictTOS; IfEqStrictTOS; IfNeStrictNumTOS; IfEqStrictNumTOS
//
// Skips the next instruction unless the given condition holds. 'Num'
@@ -1166,6 +1589,52 @@
EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
}
+
+// - CheckClassId rA, D
+//
+// If the object at FP[rA]'s class id matches hthe class id in PP[D], then
+// skip the following instruction.
+ASSEMBLER_TEST_GENERATE(CheckClassIdSmiPass, assembler) {
+ __ Frame(1);
+ __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+ __ CheckClassId(0, __ AddConstant(Smi::Handle(Smi::New(kSmiCid))));
+ __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+ __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(CheckClassIdSmiPass, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(CheckClassIdNonSmiPass, assembler) {
+ __ Frame(1);
+ __ LoadConstant(0, Bool::True());
+ __ CheckClassId(0, __ AddConstant(Smi::Handle(Smi::New(kBoolCid))));
+ __ LoadConstant(0, Bool::False());
+ __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(CheckClassIdNonSmiPass, test) {
+ EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(CheckClassIdFail, assembler) {
+ __ Frame(1);
+ __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
+ __ CheckClassId(0, __ AddConstant(Smi::Handle(Smi::New(kBoolCid))));
+ __ LoadConstant(0, Smi::Handle(Smi::New(42)));
+ __ Return(0);
+}
+
+
+ASSEMBLER_TEST_RUN(CheckClassIdFail, test) {
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
} // namespace dart
#endif // defined(TARGET_ARCH_DBC)
diff --git a/runtime/vm/assert_test.cc b/runtime/vm/assert_test.cc
index 625f23b..dc935f1 100644
--- a/runtime/vm/assert_test.cc
+++ b/runtime/vm/assert_test.cc
@@ -46,3 +46,18 @@
EXPECT_FLOAT_EQ(15.43, 15.44, 0.01);
EXPECT_FLOAT_EQ(1.43, 1.43, 0.00);
}
+
+
+UNIT_TEST_CASE(Fail0) {
+ FAIL("This test fails");
+}
+
+
+UNIT_TEST_CASE(Fail1) {
+ FAIL1("This test fails with one argument: %d", 4);
+}
+
+
+UNIT_TEST_CASE(Fail2) {
+ FAIL2("This test fails with two arguments: %d, %d", -100, 42);
+}
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 5d4e3cb..683834b 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1297,7 +1297,7 @@
DeoptimizeFunctionsOnStack();
}
if (do_reload) {
- NOT_IN_PRODUCT(isolate->OnStackReload();)
+ NOT_IN_PRODUCT(isolate->ReloadSources();)
}
if (FLAG_support_debugger && do_stacktrace) {
String& var_name = String::Handle();
diff --git a/runtime/vm/constant_propagator.cc b/runtime/vm/constant_propagator.cc
index 4409f3f..6b97f7d 100644
--- a/runtime/vm/constant_propagator.cc
+++ b/runtime/vm/constant_propagator.cc
@@ -1514,8 +1514,9 @@
changed = true;
- if (FLAG_trace_constant_propagation) {
- OS::Print("Eliminated branch in B%" Pd " common target B%" Pd "\n",
+ if (FLAG_trace_constant_propagation &&
+ FlowGraphPrinter::ShouldPrint(graph_->function())) {
+ THR_Print("Eliminated branch in B%" Pd " common target B%" Pd "\n",
block->block_id(), join->block_id());
}
}
@@ -1533,7 +1534,8 @@
void ConstantPropagator::Transform() {
- if (FLAG_trace_constant_propagation) {
+ if (FLAG_trace_constant_propagation &&
+ FlowGraphPrinter::ShouldPrint(graph_->function())) {
FlowGraphPrinter::PrintGraph("Before CP", graph_);
}
@@ -1546,8 +1548,9 @@
b.Advance()) {
BlockEntryInstr* block = b.Current();
if (!reachable_->Contains(block->preorder_number())) {
- if (FLAG_trace_constant_propagation) {
- OS::Print("Unreachable B%" Pd "\n", block->block_id());
+ if (FLAG_trace_constant_propagation &&
+ FlowGraphPrinter::ShouldPrint(graph_->function())) {
+ THR_Print("Unreachable B%" Pd "\n", block->block_id());
}
// Remove all uses in unreachable blocks.
block->ClearAllInstructions();
@@ -1618,8 +1621,9 @@
!defn->IsStoreIndexed() &&
!defn->IsStoreInstanceField() &&
!defn->IsStoreStaticField()) {
- if (FLAG_trace_constant_propagation) {
- OS::Print("Constant v%" Pd " = %s\n",
+ if (FLAG_trace_constant_propagation &&
+ FlowGraphPrinter::ShouldPrint(graph_->function())) {
+ THR_Print("Constant v%" Pd " = %s\n",
defn->ssa_temp_index(),
defn->constant_value().ToCString());
}
@@ -1681,7 +1685,8 @@
GrowableArray<BitVector*> dominance_frontier;
graph_->ComputeDominators(&dominance_frontier);
- if (FLAG_trace_constant_propagation) {
+ if (FLAG_trace_constant_propagation &&
+ FlowGraphPrinter::ShouldPrint(graph_->function())) {
FlowGraphPrinter::PrintGraph("After CP", graph_);
}
}
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index 1518bfa..4f8aab9 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -83,6 +83,10 @@
//
// Unreachable instruction.
//
+// - Nop
+//
+// This instuction does nothing.
+//
// - Compile
//
// Compile current function and start executing newly produced code
@@ -160,7 +164,29 @@
// then pops operands and pushes result on the stack and skips the next
// instruction (which implements a slow path fallback).
//
-// - StoreStaticTOS D
+// - Add, Sub, Mul, Div, Mod, Shl, Shr rA, rB, rC
+//
+// Arithmetic operations on Smis. FP[rA] <- FP[rB] op FP[rC].
+// If these instructions can trigger a deoptimization, the following
+// instruction should be Deopt. If no deoptimization should be triggered,
+// the immediately following instruction is skipped. These instructions
+// expect their operands to be Smis, but don't check that they are.
+//
+// - Neg rA , rD
+//
+// FP[rA] <- -FP[rD]. Assumes FP[rD] is a Smi. If there is no overflow the
+// immediately following instruction is skipped.
+//
+// - BitOr, BitAnd, BitXor rA, rB, rC
+//
+// FP[rA] <- FP[rB] op FP[rC]. These instructions expect their operands to be
+// Smis, but don't check that they are.
+//
+// - BitNot rA, rD
+//
+// FP[rA] <- ~FP[rD]. As above, assumes FP[rD] is a Smi.
+//
+// - StoreStaticT`OS D
//
// Stores TOS into the static field PP[D].
//
@@ -327,6 +353,11 @@
//
// If FP[rA] is a Smi, then skip the next instruction.
//
+// - CheckClassId rA, D
+//
+// If the object at FP[rA]'s class id matches hthe class id in PP[D], then
+// skip the following instruction.
+//
// - CheckStack
//
// Compare SP against isolate stack limit and call StackOverflow handler if
@@ -389,6 +420,7 @@
//
#define BYTECODES_LIST(V) \
V(Trap, 0, ___, ___, ___) \
+ V(Nop, 0, ___, ___, ___) \
V(Compile, 0, ___, ___, ___) \
V(HotCheck, A_D, num, num, ___) \
V(Intrinsic, A, num, ___, ___) \
@@ -422,6 +454,18 @@
V(EqualTOS, 0, ___, ___, ___) \
V(LessThanTOS, 0, ___, ___, ___) \
V(GreaterThanTOS, 0, ___, ___, ___) \
+ V(Add, A_B_C, reg, reg, reg) \
+ V(Sub, A_B_C, reg, reg, reg) \
+ V(Mul, A_B_C, reg, reg, reg) \
+ V(Div, A_B_C, reg, reg, reg) \
+ V(Mod, A_B_C, reg, reg, reg) \
+ V(Shl, A_B_C, reg, reg, reg) \
+ V(Shr, A_B_C, reg, reg, reg) \
+ V(Neg, A_D, reg, reg, ___) \
+ V(BitOr, A_B_C, reg, reg, reg) \
+ V(BitAnd, A_B_C, reg, reg, reg) \
+ V(BitXor, A_B_C, reg, reg, reg) \
+ V(BitNot, A_D, reg, reg, ___) \
V(StoreStaticTOS, D, lit, ___, ___) \
V(PushStatic, D, lit, ___, ___) \
V(InitStaticTOS, 0, ___, ___, ___) \
@@ -458,6 +502,7 @@
V(AssertAssignable, D, num, lit, ___) \
V(AssertBoolean, A, num, ___, ___) \
V(CheckSmi, A, reg, ___, ___) \
+ V(CheckClassId, A_D, reg, lit, ___) \
V(CheckStack, 0, ___, ___, ___) \
V(DebugStep, 0, ___, ___, ___) \
V(DebugBreak, A, num, ___, ___) \
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 4778d7a..009e500 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -441,6 +441,10 @@
intptr_t to) {
if (loc.IsRegister()) {
BlockRegisterLocation(loc, from, to, blocked_cpu_registers_, cpu_regs_);
+#if defined(TARGET_ARCH_DBC)
+ last_used_register_ = Utils::Maximum(last_used_register_,
+ loc.register_code());
+#endif
} else if (loc.IsFpuRegister()) {
BlockRegisterLocation(loc, from, to, blocked_fpu_registers_, fpu_regs_);
} else {
@@ -2742,10 +2746,6 @@
registers_[reg]->Add(range);
}
}
-
-#if defined(TARGET_ARCH_DBC)
- last_used_register_ = -1;
-#endif
}
@@ -3010,6 +3010,10 @@
DiscoverLoops();
+#if defined(TARGET_ARCH_DBC)
+ last_used_register_ = -1;
+#endif
+
BuildLiveRanges();
if (FLAG_print_ssa_liveranges) {
@@ -3038,6 +3042,7 @@
AllocateUnallocatedRanges();
#if defined(TARGET_ARCH_DBC)
const intptr_t last_used_cpu_register = last_used_register_;
+ last_used_register_ = -1;
#endif
cpu_spill_slot_count_ = spill_slots_.length();
diff --git a/runtime/vm/flow_graph_compiler_dbc.cc b/runtime/vm/flow_graph_compiler_dbc.cc
index eae97e2..81c639e8 100644
--- a/runtime/vm/flow_graph_compiler_dbc.cc
+++ b/runtime/vm/flow_graph_compiler_dbc.cc
@@ -233,14 +233,22 @@
__ PushConstant(dst_type);
__ PushConstant(dst_name);
__ AssertAssignable(__ AddConstant(test_cache));
+ if (is_optimizing()) {
+ // Register allocator does not think that our first input (also used as
+ // output) needs to be kept alive across the call because that is how code
+ // is written on other platforms (where registers are always spilled across
+ // the call): inputs are consumed by operation and output is produced so
+ // neither are alive at the safepoint.
+ // We have to mark the slot alive manually to ensure that GC
+ // visits it.
+ locs->SetStackBit(locs->out(0).reg());
+ }
RecordSafepoint(locs);
AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos);
if (is_optimizing()) {
// Assert assignable keeps the instance on the stack as the result,
// all other arguments are popped.
- // In optimized code we need to drop it because optimized code
- // expects the result in the register and it is already there
- // because locs()->in(0).reg() == locs()->out(0).reg().
+ ASSERT(locs->out(0).reg() == locs->in(0).reg());
__ Drop1();
}
}
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index b51cfe8..bba04b4 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -863,7 +863,7 @@
}
}
- if (FLAG_support_il_printer && FLAG_trace_inlining &&
+ if (FLAG_support_il_printer && trace_inlining() &&
(FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
THR_Print("Callee graph for inlining %s\n",
function.ToFullyQualifiedCString());
diff --git a/runtime/vm/flow_graph_range_analysis.cc b/runtime/vm/flow_graph_range_analysis.cc
index 18eaa36..9b7eb8b 100644
--- a/runtime/vm/flow_graph_range_analysis.cc
+++ b/runtime/vm/flow_graph_range_analysis.cc
@@ -1569,7 +1569,8 @@
target->PredecessorAt(0)->last_instruction()->AsBranch();
if (target == branch->true_successor()) {
// True unreachable.
- if (FLAG_trace_constant_propagation) {
+ if (FLAG_trace_constant_propagation &&
+ FlowGraphPrinter::ShouldPrint(flow_graph_->function())) {
THR_Print("Range analysis: True unreachable (B%" Pd ")\n",
branch->true_successor()->block_id());
}
@@ -1577,7 +1578,8 @@
} else {
ASSERT(target == branch->false_successor());
// False unreachable.
- if (FLAG_trace_constant_propagation) {
+ if (FLAG_trace_constant_propagation &&
+ FlowGraphPrinter::ShouldPrint(flow_graph_->function())) {
THR_Print("Range analysis: False unreachable (B%" Pd ")\n",
branch->false_successor()->block_id());
}
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 1763877..85bae29 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -3045,26 +3045,38 @@
return;
}
if (name.raw() == Symbols::Plus().raw()) {
- __ AddTOS();
+ if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+ __ AddTOS();
+ }
} else if (name.raw() == Symbols::Minus().raw()) {
- __ SubTOS();
+ if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+ __ SubTOS();
+ }
} else if (name.raw() == Symbols::EqualOperator().raw()) {
- __ EqualTOS();
+ if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+ __ EqualTOS();
+ }
} else if (name.raw() == Symbols::LAngleBracket().raw()) {
- __ LessThanTOS();
+ if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+ __ LessThanTOS();
+ }
} else if (name.raw() == Symbols::RAngleBracket().raw()) {
- __ GreaterThanTOS();
+ if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+ __ GreaterThanTOS();
+ }
} else if (name.raw() == Symbols::BitAnd().raw()) {
- __ BitAndTOS();
+ if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+ __ BitAndTOS();
+ }
} else if (name.raw() == Symbols::BitOr().raw()) {
- __ BitOrTOS();
+ if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+ __ BitOrTOS();
+ }
} else if (name.raw() == Symbols::Star().raw()) {
- __ MulTOS();
- } else {
- return;
+ if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
+ __ MulTOS();
+ }
}
- bool is_smi_two_args_op = call_ic_data->AddSmiSmiCheckForFastSmiStubs();
- ASSERT(is_smi_two_args_op);
}
#endif
@@ -3298,9 +3310,6 @@
// DBC does not use LocationSummaries in the same way as other architectures.
#if !defined(TARGET_ARCH_DBC)
ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
-#else
- ASSERT(!compiler->is_optimizing() ||
- (locs()->in(0).reg() == locs()->out(0).reg()));
#endif // !defined(TARGET_ARCH_DBC)
}
@@ -3312,7 +3321,11 @@
void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if !defined(TARGET_ARCH_DBC)
__ Jump(compiler->AddDeoptStub(deopt_id(), deopt_reason_));
+#else
+ compiler->EmitDeopt(deopt_id(), deopt_reason_);
+#endif
}
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
index 0e1afc6..d28bbb2 100644
--- a/runtime/vm/intermediate_language_dbc.cc
+++ b/runtime/vm/intermediate_language_dbc.cc
@@ -29,15 +29,13 @@
DECLARE_FLAG(int, optimization_counter_threshold);
// List of instructions that are still unimplemented by DBC backend.
-#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \
- M(Stop) \
+#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \
M(IndirectGoto) \
M(LoadCodeUnits) \
M(InstanceOf) \
M(LoadUntagged) \
M(AllocateUninitializedContext) \
M(BinaryInt32Op) \
- M(UnarySmiOp) \
M(UnaryDoubleOp) \
M(SmiToDouble) \
M(Int32ToDouble) \
@@ -48,7 +46,6 @@
M(DoubleToFloat) \
M(FloatToDouble) \
M(UnboxedConstant) \
- M(CheckEitherNonSmi) \
M(BinaryDoubleOp) \
M(MathUnary) \
M(MathMinMax) \
@@ -108,9 +105,7 @@
M(UnboxInteger32) \
M(CheckedSmiOp) \
M(CheckArrayBound) \
- M(CheckClassId) \
M(CheckClass) \
- M(BinarySmiOp) \
M(TestSmi) \
M(RelationalOp) \
M(EqualityCompare) \
@@ -184,7 +179,9 @@
DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare)
-DEFINE_MAKE_LOCATION_SUMMARY(AssertAssignable, 2, Location::SameAsFirstInput());
+DEFINE_MAKE_LOCATION_SUMMARY(AssertAssignable, 2,
+ Location::SameAsFirstInput(),
+ LocationSummary::kCall);
EMIT_NATIVE_CODE(AssertBoolean,
@@ -219,6 +216,11 @@
}
+EMIT_NATIVE_CODE(Stop, 0) {
+ __ Stop(message());
+}
+
+
EMIT_NATIVE_CODE(CheckStackOverflow,
0, Location::NoLocation(),
LocationSummary::kCall) {
@@ -913,6 +915,109 @@
licm_hoisted_ ? ICData::kHoisted : 0);
}
+
+EMIT_NATIVE_CODE(CheckEitherNonSmi, 2) {
+ intptr_t left_cid = left()->Type()->ToCid();
+ intptr_t right_cid = right()->Type()->ToCid();
+ const Register left = locs()->in(0).reg();
+ const Register right = locs()->in(1).reg();
+ if (this->left()->definition() == this->right()->definition()) {
+ __ CheckSmi(left);
+ } else if (left_cid == kSmiCid) {
+ __ CheckSmi(right);
+ } else if (right_cid == kSmiCid) {
+ __ CheckSmi(left);
+ } else {
+ __ CheckSmi(left);
+ compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp,
+ licm_hoisted_ ? ICData::kHoisted : 0);
+ __ CheckSmi(right);
+ }
+ compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp,
+ licm_hoisted_ ? ICData::kHoisted : 0);
+}
+
+
+EMIT_NATIVE_CODE(CheckClassId, 1) {
+ intptr_t cid = __ AddConstant(Smi::Handle(Smi::New(cid_)));
+ __ CheckClassId(locs()->in(0).reg(), cid);
+ compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass);
+}
+
+
+EMIT_NATIVE_CODE(BinarySmiOp, 2, Location::RequiresRegister()) {
+ const Register left = locs()->in(0).reg();
+ const Register right = locs()->in(1).reg();
+ const Register out = locs()->out(0).reg();
+ const bool can_deopt = CanDeoptimize();
+ bool needs_nop = false;
+ switch (op_kind()) {
+ case Token::kADD:
+ __ Add(out, left, right);
+ needs_nop = true;
+ break;
+ case Token::kSUB:
+ __ Sub(out, left, right);
+ needs_nop = true;
+ break;
+ case Token::kMUL:
+ __ Mul(out, left, right);
+ needs_nop = true;
+ break;
+ case Token::kTRUNCDIV:
+ ASSERT(can_deopt);
+ __ Div(out, left, right);
+ break;
+ case Token::kBIT_AND:
+ ASSERT(!can_deopt);
+ __ BitAnd(out, left, right);
+ break;
+ case Token::kBIT_OR:
+ ASSERT(!can_deopt);
+ __ BitOr(out, left, right);
+ break;
+ case Token::kBIT_XOR:
+ ASSERT(!can_deopt);
+ __ BitXor(out, left, right);
+ break;
+ case Token::kMOD:
+ __ Mod(out, left, right);
+ needs_nop = true;
+ break;
+ case Token::kSHR:
+ __ Shr(out, left, right);
+ needs_nop = true;
+ break;
+ case Token::kSHL:
+ __ Shl(out, left, right);
+ needs_nop = true;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ if (can_deopt) {
+ compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinarySmiOp);
+ } else if (needs_nop) {
+ __ Nop();
+ }
+}
+
+
+EMIT_NATIVE_CODE(UnarySmiOp, 1, Location::RequiresRegister()) {
+ switch (op_kind()) {
+ case Token::kNEGATE: {
+ __ Neg(locs()->out(0).reg(), locs()->in(0).reg());
+ compiler->EmitDeopt(deopt_id(), ICData::kDeoptUnaryOp);
+ break;
+ }
+ case Token::kBIT_NOT:
+ __ BitNot(locs()->out(0).reg(), locs()->in(0).reg());
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 69578c9..5369226 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -813,6 +813,7 @@
tag_table_(GrowableObjectArray::null()),
deoptimized_code_array_(GrowableObjectArray::null()),
sticky_error_(Error::null()),
+ sticky_reload_error_(Error::null()),
background_compiler_(NULL),
background_compiler_disabled_depth_(0),
pending_service_extension_calls_(GrowableObjectArray::null()),
@@ -1066,11 +1067,6 @@
}
-void Isolate::OnStackReload() {
- ReloadSources();
-}
-
-
void Isolate::ReloadSources(bool test_mode) {
ASSERT(!IsReloading());
has_attempted_reload_ = true;
@@ -1090,6 +1086,10 @@
// context on the isolate so that it can be used by unit tests.
return;
}
+ if (reload_context_->has_error()) {
+ // Remember the reload error.
+ sticky_reload_error_ = reload_context_->error();
+ }
if (!reload_context_->has_error()) {
reload_context_->ReportSuccess();
}
@@ -1752,6 +1752,9 @@
visitor->VisitPointer(
reinterpret_cast<RawObject**>(&sticky_error_));
+ visitor->VisitPointer(
+ reinterpret_cast<RawObject**>(&sticky_reload_error_));
+
// Visit the pending service extension calls.
visitor->VisitPointer(
reinterpret_cast<RawObject**>(&pending_service_extension_calls_));
@@ -2005,6 +2008,11 @@
}
+void Isolate::clear_sticky_reload_error() {
+ sticky_reload_error_ = Error::null();
+}
+
+
void Isolate::set_pending_service_extension_calls(
const GrowableObjectArray& value) {
pending_service_extension_calls_ = value.raw();
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 5c219cc..701579c 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -255,7 +255,6 @@
void DoneLoading();
void DoneFinalizing();
- void OnStackReload();
void ReloadSources(bool test_mode = false);
bool MakeRunnable();
@@ -532,6 +531,9 @@
RawError* sticky_error() const { return sticky_error_; }
void clear_sticky_error();
+ RawError* sticky_reload_error() const { return sticky_reload_error_; }
+ void clear_sticky_reload_error();
+
bool compilation_allowed() const { return compilation_allowed_; }
void set_compilation_allowed(bool allowed) {
compilation_allowed_ = allowed;
@@ -751,6 +753,8 @@
RawError* sticky_error_;
+ RawError* sticky_reload_error_;
+
// Background compilation.
BackgroundCompiler* background_compiler_;
intptr_t background_compiler_disabled_depth_;
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 9b45046..aa8f188 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -228,6 +228,38 @@
}
+TEST_CASE(IsolateReload_ClassFieldAdded2) {
+ const char* kScript =
+ "class Foo {\n"
+ " var x;\n"
+ " var y;\n"
+ "}\n"
+ "main() {\n"
+ " new Foo();\n"
+ " return 44;\n"
+ "}\n";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+
+ EXPECT_EQ(44, SimpleInvoke(lib, "main"));
+
+ const char* kReloadScript =
+ "class Foo {\n"
+ " var x;\n"
+ " var y;\n"
+ " var z;\n"
+ "}\n"
+ "main() {\n"
+ " new Foo();\n"
+ " return 44;\n"
+ "}\n";
+
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_ERROR(lib, "Number of instance fields changed");
+}
+
+
TEST_CASE(IsolateReload_ClassFieldRemoved) {
const char* kScript =
"class Foo {\n"
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index c367f2e..f1a0d87 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -146,6 +146,8 @@
return "File system does not exist";
case kFileDoesNotExist:
return "File does not exist";
+ case kIsolateReloadFailed:
+ return "Isolate reload failed";
default:
return "Extension error";
}
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index 1dec0db..eec69b0 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -59,6 +59,7 @@
kFileSystemAlreadyExists = 1001,
kFileSystemDoesNotExist = 1002,
kFileDoesNotExist = 1003,
+ kIsolateReloadFailed = 1004,
};
// Expected that user_data is a JSONStream*.
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index ba5098a..f9c5ad9 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -444,13 +444,22 @@
const Array& replacement_fields =
Array::Handle(replacement.OffsetToFieldMap());
- // Check that we have the same number of fields.
+ // Check that the size of the instance is the same.
if (fields.Length() != replacement_fields.Length()) {
IRC->ReportError(String::Handle(String::NewFormatted(
"Number of instance fields changed in %s", ToCString())));
return false;
}
+ // Check that we have the same next field offset. This check is not
+ // redundant with the one above because the instance OffsetToFieldMap
+ // array length is based on the instance size (which may be aligned up).
+ if (next_field_offset() != replacement.next_field_offset()) {
+ IRC->ReportError(String::Handle(String::NewFormatted(
+ "Number of instance fields changed in %s", ToCString())));
+ return false;
+ }
+
if (NumTypeArguments() != replacement.NumTypeArguments()) {
IRC->ReportError(String::Handle(String::NewFormatted(
"Number of type arguments changed in %s", ToCString())));
@@ -483,7 +492,8 @@
} else if (is_prefinalized()) {
if (!replacement.is_prefinalized()) {
IRC->ReportError(String::Handle(String::NewFormatted(
- "Original class ('%s') is prefinalized and replacement class ('%s')",
+ "Original class ('%s') is prefinalized and replacement class "
+ "('%s') is not ",
ToCString(), replacement.ToCString())));
return false;
}
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index b8fa54b..4619602 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -2648,17 +2648,18 @@
AstNode* Parser::ParseExternalInitializedField(const Field& field) {
// Only use this function if the initialized field originates
- // from a different class. We need to save and restore current
- // class, library, and token stream (script).
+ // from a different class. We need to save and restore the
+ // library and token stream (script).
+ // The current_class remains unchanged, so that type arguments
+ // are resolved in the correct scope class.
ASSERT(current_class().raw() != field.Origin());
- const Class& saved_class = Class::Handle(Z, current_class().raw());
const Library& saved_library = Library::Handle(Z, library().raw());
const Script& saved_script = Script::Handle(Z, script().raw());
const TokenPosition saved_token_pos = TokenPos();
- set_current_class(Class::Handle(Z, field.Origin()));
- set_library(Library::Handle(Z, current_class().library()));
- SetScript(Script::Handle(Z, current_class().script()), field.token_pos());
+ const Class& origin_class = Class::Handle(Z, field.Origin());
+ set_library(Library::Handle(Z, origin_class.library()));
+ SetScript(Script::Handle(Z, origin_class.script()), field.token_pos());
ASSERT(IsIdentifier());
ConsumeToken();
@@ -2678,7 +2679,6 @@
init_expr = new(Z) LiteralNode(field.token_pos(), expr_value);
}
}
- set_current_class(saved_class);
set_library(saved_library);
SetScript(saved_script, saved_token_pos);
return init_expr;
@@ -6062,6 +6062,9 @@
void Parser::ParseLibraryPart() {
const TokenPosition source_pos = TokenPos();
ConsumeToken(); // Consume "part".
+ if (IsSymbol(Symbols::Of())) {
+ ReportError("part of declarations are not allowed in script files");
+ }
CheckToken(Token::kSTRING, "url expected");
AstNode* url_literal = ParseStringLiteral(false);
ASSERT(url_literal->IsLiteralNode());
@@ -9175,28 +9178,6 @@
}
-AstNode* Parser::MakeAssertCall(TokenPosition begin, TokenPosition end) {
- ArgumentListNode* arguments = new(Z) ArgumentListNode(begin);
- arguments->Add(new(Z) LiteralNode(begin,
- Integer::ZoneHandle(Z, Integer::New(begin.value(), Heap::kOld))));
- arguments->Add(new(Z) LiteralNode(end,
- Integer::ZoneHandle(Z, Integer::New(end.value(), Heap::kOld))));
- return MakeStaticCall(Symbols::AssertionError(),
- Library::PrivateCoreLibName(Symbols::ThrowNew()),
- arguments);
-}
-
-
-AstNode* Parser::HandleAssertCondition(AstNode* condition) {
- const TokenPosition pos = condition->token_pos();
- ArgumentListNode* arguments = new(Z) ArgumentListNode(pos);
- arguments->Add(condition);
- return MakeStaticCall(Symbols::AssertionError(),
- Library::PrivateCoreLibName(Symbols::HandleCondition()),
- arguments);
-}
-
-
AstNode* Parser::ParseAssertStatement() {
TRACE_PARSER("ParseAssertStatement");
ConsumeToken(); // Consume assert keyword.
@@ -9210,14 +9191,16 @@
AstNode* condition = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
const TokenPosition condition_end = TokenPos();
ExpectToken(Token::kRPAREN);
- condition = HandleAssertCondition(condition);
- condition = new(Z) UnaryOpNode(condition_pos, Token::kNOT, condition);
- AstNode* assert_throw = MakeAssertCall(condition_pos, condition_end);
- return new(Z) IfNode(
- condition_pos,
- condition,
- NodeAsSequenceNode(condition_pos, assert_throw, NULL),
- NULL);
+
+ ArgumentListNode* arguments = new(Z) ArgumentListNode(condition_pos);
+ arguments->Add(condition);
+ arguments->Add(new(Z) LiteralNode(condition_pos,
+ Integer::ZoneHandle(Z, Integer::New(condition_pos.value(), Heap::kOld))));
+ arguments->Add(new(Z) LiteralNode(condition_end,
+ Integer::ZoneHandle(Z, Integer::New(condition_end.value(), Heap::kOld))));
+ return MakeStaticCall(Symbols::AssertionError(),
+ Library::PrivateCoreLibName(Symbols::CheckAssertion()),
+ arguments);
}
@@ -10256,8 +10239,13 @@
// Rethrow of current exception.
ConsumeToken();
ExpectSemicolon();
- // Check if it is ok to do a rethrow.
- if ((try_stack_ == NULL) || !try_stack_->inside_catch()) {
+ // Check if it is ok to do a rethrow. Find the inntermost enclosing
+ // catch block.
+ TryStack* try_statement = try_stack_;
+ while ((try_statement != NULL) && !try_statement->inside_catch()) {
+ try_statement = try_statement->outer_try();
+ }
+ if (try_statement == NULL) {
ReportError(statement_pos, "rethrow of an exception is not valid here");
}
@@ -10265,7 +10253,7 @@
// instead of :exception_var and :stack_trace_var.
// These variables are bound in the block containing the try.
// Look in the try scope directly.
- LocalScope* scope = try_stack_->try_block()->scope->parent();
+ LocalScope* scope = try_statement->try_block()->scope->parent();
ASSERT(scope != NULL);
LocalVariable* excp_var;
LocalVariable* trace_var;
@@ -13639,6 +13627,12 @@
}
ASSERT(!constructor.IsNull());
+ // It is a compile time error to instantiate a const instance of an
+ // abstract class. Factory methods are ok.
+ if (is_const && type_class.is_abstract() && !constructor.IsFactory()) {
+ ReportError(new_pos, "cannot instantiate abstract class");
+ }
+
// It is ok to call a factory method of an abstract class, but it is
// a dynamic error to instantiate an abstract class.
if (type_class.is_abstract() && !constructor.IsFactory()) {
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 31c6ec0..815f978 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -874,7 +874,6 @@
const String& func_name,
ArgumentListNode* arguments);
String& Interpolate(const GrowableArray<AstNode*>& values);
- AstNode* MakeAssertCall(TokenPosition begin, TokenPosition end);
AstNode* ThrowTypeError(TokenPosition type_pos,
const AbstractType& type,
LibraryPrefix* prefix = NULL);
@@ -898,7 +897,6 @@
const String* left_ident,
TokenPosition left_pos,
bool is_compound = false);
- AstNode* HandleAssertCondition(AstNode* condition);
ConstructorCallNode* CreateConstructorCallNode(
TokenPosition token_pos,
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 8f6f624..286a5f9 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -2281,10 +2281,7 @@
kTwoByteStringCid == kStringCid + 2 &&
kExternalOneByteStringCid == kStringCid + 3 &&
kExternalTwoByteStringCid == kStringCid + 4);
- return (index == kOneByteStringCid ||
- index == kTwoByteStringCid ||
- index == kExternalOneByteStringCid ||
- index == kExternalTwoByteStringCid);
+ return (index == kTwoByteStringCid || index == kExternalTwoByteStringCid);
}
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 087e47e..09da5f3 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2484,19 +2484,24 @@
"This isolate is being reloaded.");
return true;
}
- DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
- ASSERT(isolate->CanReload());
-
- if (stack->Length() > 0) {
- // TODO(turnidge): We need to support this case.
+ if (!isolate->CanReload()) {
js->PrintError(kFeatureDisabled,
- "Source can only be reloaded when stack is empty.");
+ "This isolate cannot reload sources right now.");
return true;
- } else {
- isolate->ReloadSources();
}
- PrintSuccess(js);
+ isolate->ReloadSources();
+
+ const Error& error = Error::Handle(isolate->sticky_reload_error());
+
+ if (error.IsNull()) {
+ PrintSuccess(js);
+ } else {
+ // Clear the sticky error.
+ isolate->clear_sticky_reload_error();
+ js->PrintError(kIsolateReloadFailed,
+ "Isolate reload failed: %s", error.ToErrorCString());
+ }
return true;
}
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 499f604..1938950 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -442,7 +442,7 @@
: "r"(rhs), "r"(out)
: "cc", "r12");
#elif defined(HOST_ARCH_ARM64)
- int64_t prod_lo;
+ int64_t prod_lo = 0;
asm volatile(
"mul %1, %2, %3\n"
"smulh %2, %2, %3\n"
@@ -451,7 +451,7 @@
"mov %0, #0;\n"
"str %1, [%4, #0]\n"
"1:"
- : "+r"(res), "=r"(prod_lo), "+r"(lhs)
+ : "=r"(res), "+r"(prod_lo), "+r"(lhs)
: "r"(rhs), "r"(out)
: "cc");
#else
@@ -477,6 +477,7 @@
#define SMI_GT(lhs, rhs, pres) SMI_COND(>, lhs, rhs, pres)
#define SMI_BITOR(lhs, rhs, pres) ((*(pres) = (lhs | rhs)), false)
#define SMI_BITAND(lhs, rhs, pres) ((*(pres) = ((lhs) & (rhs))), false)
+#define SMI_BITXOR(lhs, rhs, pres) ((*(pres) = ((lhs) ^ (rhs))), false)
void Simulator::CallRuntime(Thread* thread,
@@ -786,6 +787,28 @@
} \
}
+// Skip the next instruction if there is no overflow.
+#define SMI_OP_CHECK(ResultT, Func) \
+ { \
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); \
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); \
+ ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]); \
+ if (LIKELY(!Func(lhs, rhs, slot))) { \
+ /* Success. Skip the instruction that follows. */ \
+ pc++; \
+ } \
+ }
+
+// Do not check for overflow.
+#define SMI_OP_NOCHECK(ResultT, Func) \
+ { \
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]); \
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]); \
+ ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]); \
+ Func(lhs, rhs, slot); \
+ } \
+
+
// Exception handling helper. Gets handler FP and PC from the Simulator where
// they were stored by Simulator::Longjmp and proceeds to execute the handler.
// Corner case: handler PC can be a fake marker that marks entry frame, which
@@ -1541,6 +1564,112 @@
SMI_FASTPATH_TOS(RawObject*, SMI_GT);
DISPATCH();
}
+ {
+ BYTECODE(Add, A_B_C);
+ SMI_OP_CHECK(intptr_t, SignedAddWithOverflow);
+ DISPATCH();
+ }
+ {
+ BYTECODE(Sub, A_B_C);
+ SMI_OP_CHECK(intptr_t, SignedSubWithOverflow);
+ DISPATCH();
+ }
+ {
+ BYTECODE(Mul, A_B_C);
+ SMI_OP_CHECK(intptr_t, SMI_MUL);
+ DISPATCH();
+ }
+ {
+ BYTECODE(Neg, A_D);
+ const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]);
+ intptr_t* out = reinterpret_cast<intptr_t*>(&FP[rA]);
+ if (LIKELY(!SignedSubWithOverflow(0, value, out))) {
+ pc++;
+ }
+ DISPATCH();
+ }
+ {
+ BYTECODE(BitOr, A_B_C);
+ SMI_OP_NOCHECK(intptr_t, SMI_BITOR);
+ DISPATCH();
+ }
+ {
+ BYTECODE(BitAnd, A_B_C);
+ SMI_OP_NOCHECK(intptr_t, SMI_BITAND);
+ DISPATCH();
+ }
+ {
+ BYTECODE(BitXor, A_B_C);
+ SMI_OP_NOCHECK(intptr_t, SMI_BITXOR);
+ DISPATCH();
+ }
+ {
+ BYTECODE(BitNot, A_D);
+ const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]);
+ *reinterpret_cast<intptr_t*>(&FP[rA]) = ~value & (~kSmiTagMask);
+ DISPATCH();
+ }
+
+ {
+ BYTECODE(Div, A_B_C);
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);
+ if (rhs != 0) {
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+ const intptr_t res = (lhs >> kSmiTagSize) / (rhs >> kSmiTagSize);
+#if defined(ARCH_IS_64_BIT)
+ const intptr_t untaggable = 0x4000000000000000LL;
+#else
+ const intptr_t untaggable = 0x40000000L;
+#endif // defined(ARCH_IS_64_BIT)
+ if (res != untaggable) {
+ *reinterpret_cast<intptr_t*>(&FP[rA]) = res << kSmiTagSize;
+ pc++;
+ }
+ }
+ DISPATCH();
+ }
+
+ {
+ BYTECODE(Mod, A_B_C);
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);
+ if (rhs != 0) {
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+ const intptr_t res =
+ ((lhs >> kSmiTagSize) % (rhs >> kSmiTagSize)) << kSmiTagSize;
+ *reinterpret_cast<intptr_t*>(&FP[rA]) =
+ (res < 0) ? ((rhs < 0) ? (res - rhs) : (res + rhs)) : res;
+ pc++;
+ }
+ DISPATCH();
+ }
+
+ {
+ BYTECODE(Shl, A_B_C);
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
+ if (rhs >= 0) {
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+ const intptr_t res = lhs << rhs;
+ if (lhs == (res >> rhs)) {
+ *reinterpret_cast<intptr_t*>(&FP[rA]) = res;
+ pc++;
+ }
+ }
+ DISPATCH();
+ }
+
+ {
+ BYTECODE(Shr, A_B_C);
+ const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
+ if (rhs >= 0) {
+ const intptr_t shift_amount =
+ (rhs >= kBitsPerWord) ? (kBitsPerWord - 1) : rhs;
+ const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize;
+ *reinterpret_cast<intptr_t*>(&FP[rA]) =
+ (lhs >> shift_amount) << kSmiTagSize;
+ pc++;
+ }
+ DISPATCH();
+ }
// Return and return like instructions (Instrinsic).
{
@@ -1735,8 +1864,8 @@
SP[2] = args[3]; // name.
SP[3] = args[2]; // type.
Exit(thread, FP, SP + 4, pc);
- NativeArguments args(thread, 3, SP + 1, SP - 3);
- INVOKE_RUNTIME(DRT_BadTypeError, args);
+ NativeArguments native_args(thread, 3, SP + 1, SP - 3);
+ INVOKE_RUNTIME(DRT_BadTypeError, native_args);
UNREACHABLE();
}
@@ -1796,8 +1925,8 @@
SP[4] = args[3]; // name
SP[5] = cache;
Exit(thread, FP, SP + 6, pc);
- NativeArguments args(thread, 5, SP + 1, SP - 3);
- INVOKE_RUNTIME(DRT_TypeCheck, args);
+ NativeArguments native_args(thread, 5, SP + 1, SP - 3);
+ INVOKE_RUNTIME(DRT_TypeCheck, native_args);
}
AssertAssignableOk:
@@ -1838,6 +1967,17 @@
}
{
+ BYTECODE(CheckClassId, A_D);
+ const RawSmi* actual_cid =
+ SimulatorHelpers::GetClassIdAsSmi(static_cast<RawObject*>(FP[rA]));
+ const RawSmi* desired_cid = RAW_CAST(Smi, LOAD_CONSTANT(rD));
+ if (actual_cid == desired_cid) {
+ pc++;
+ }
+ DISPATCH();
+ }
+
+ {
BYTECODE(IfEqStrictTOS, 0);
SP -= 2;
if (SP[1] != SP[2]) {
@@ -2042,6 +2182,11 @@
}
{
+ BYTECODE(Nop, 0);
+ DISPATCH();
+ }
+
+ {
BYTECODE(Trap, 0);
UNIMPLEMENTED();
DISPATCH();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 96b4eba..547c2e5 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -71,7 +71,7 @@
V(CyclicInitializationError, "CyclicInitializationError") \
V(ThrowNew, "_throwNew") \
V(ThrowNewIfNotLoaded, "_throwNewIfNotLoaded") \
- V(HandleCondition, "_handleCondition") \
+ V(CheckAssertion, "_checkAssertion") \
V(Symbol, "Symbol") \
V(SymbolCtor, "Symbol.") \
V(List, "List") \
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 6cfcda8..6f5cf9d 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -2456,8 +2456,9 @@
*
* V8 will share the underlying function code objects when the same string is
* passed to "new Function". Shared function code objects can lead to
- * sub-optimal performance due to polymorhism, and can be prevented by
- * ensuring the strings are different.
+ * sub-optimal performance due to polymorphism, and can be prevented by
+ * ensuring the strings are different, for example, by generating a local
+ * variable with a name dependent on [functionCounter].
*/
static int functionCounter = 0;
@@ -2559,8 +2560,9 @@
: isCsp
? JS('', 'function(a,b,c,d) {this.\$initialize(a,b,c,d)}')
: JS('',
- 'new Function("a,b,c,d", "this.\$initialize(a,b,c,d);" + #)',
- functionCounter++);
+ 'new Function("a,b,c,d" + #,'
+ ' "this.\$initialize(a,b,c,d" + # + ")")',
+ functionCounter, functionCounter++);
// It is necessary to set the constructor property, otherwise it will be
// "Object".
@@ -2722,12 +2724,14 @@
}
if (arity == 0) {
+ // Incorporate functionCounter into a local.
+ String selfName = 'self${functionCounter++}';
return JS(
'',
'(new Function(#))()',
'return function(){'
- 'return this.${BoundClosure.selfFieldName()}.$stubName();'
- '${functionCounter++}'
+ 'var $selfName = this.${BoundClosure.selfFieldName()};'
+ 'return $selfName.$stubName();'
'}');
}
assert (1 <= arity && arity < 27);
@@ -2735,12 +2739,12 @@
'String',
'"abcdefghijklmnopqrstuvwxyz".split("").splice(0,#).join(",")',
arity);
+ arguments += '${functionCounter++}';
return JS(
'',
'(new Function(#))()',
'return function($arguments){'
'return this.${BoundClosure.selfFieldName()}.$stubName($arguments);'
- '${functionCounter++}'
'}');
}
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 948470b..d531a08 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -28,6 +28,9 @@
Language/Classes/same_name_type_variable_t04: Pass, MissingCompileTimeError, Fail # Issue 14513,25525
Language/Classes/same_name_type_variable_t07: Pass, MissingCompileTimeError, Fail # Issue 14513,25525
+Language/Expressions/Instance_Creation/Const/abstract_class_t01: Pass, Fail # co19 issue 66
+Language/Expressions/Instance_Creation/Const/abstract_class_t03: Pass, Fail # co19 issue 66
+
LibTest/math/acos_A01_t01: PASS, FAIL, OK # Issue 26261
LibTest/math/asin_A01_t01: PASS, FAIL, OK # Issue 26261
LibTest/math/atan_A01_t01: PASS, FAIL, OK # Issue 26261
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index c4c30e7..4dbd24a 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -72,8 +72,6 @@
Language/Expressions/Identifier_Reference/built_in_not_dynamic_t15: MissingCompileTimeError # Issue 26581
Language/Expressions/Identifier_Reference/built_in_not_dynamic_t19: MissingCompileTimeError # Issue 25732
Language/Expressions/Identifier_Reference/syntax_built_in_t01: fail # Issue 21154
-Language/Expressions/Instance_Creation/Const/abstract_class_t01: CompileTimeError # Please triage this failure
-Language/Expressions/Instance_Creation/Const/abstract_class_t03: CompileTimeError # Please triage this failure
Language/Expressions/Instance_Creation/New/evaluation_t19: RuntimeError # Please triage this failure
Language/Expressions/Instance_Creation/New/evaluation_t20: RuntimeError # Please triage this failure
Language/Expressions/Maps/key_value_equals_operator_t02: CompileTimeError # Please triage this failure
@@ -632,6 +630,7 @@
LayoutTests/fast/dom/cssTarget-crash_t01: Skip # Test reloads itself. Issue 18558.
LayoutTests/fast/dom/empty-hash-and-search_t01: Skip # Test reloads itself. Issue 18558.
LayoutTests/fast/dom/shadow/form-in-shadow_t01: Skip # Test reloads itself. Issue 18558.
+LayoutTests/fast/forms/date/date-interactive-validation-required_t01: Skip # Test reloads itself. Issue 18558.
LayoutTests/fast/forms/datetimelocal/datetimelocal-interactive-validation-required_t01: Skip # Test reloads itself. Issue 18558.
LayoutTests/fast/forms/form-submission-create-crash_t01: Skip # Test reloads itself. Issue 18558.
LayoutTests/fast/forms/formmethod-attribute-button-html_t01: Skip # Test reloads itself. Issue 18558.
@@ -771,6 +770,8 @@
LayoutTests/fast/animation/request-animation-frame-timestamps-advance_t01: Skip # Times out. Please triage this failure
LayoutTests/fast/animation/request-animation-frame-timestamps_t01: Skip # Times out. Please triage this failure
LayoutTests/fast/animation/request-animation-frame-within-callback_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/backgrounds/background-position-parsing-2_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/backgrounds/background-shorthand-with-backgroundSize-style_t01: RuntimeError # Please triage this failure
LayoutTests/fast/backgrounds/repeat/parsing-background-repeat_t01: RuntimeError # Please triage this failure
LayoutTests/fast/borders/border-width-percent_t01: RuntimeError # Issue 25155
LayoutTests/fast/canvas/2d.fillText.gradient_t01: RuntimeError # Please triage this failure
@@ -868,7 +869,6 @@
LayoutTests/fast/css/aspect-ratio-parsing-tests_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/css/auto-min-size_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/checked-pseudo-selector_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/computed-offset-with-zoom_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/content/content-none_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/content/content-normal_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/content/content-quotes-01_t01: RuntimeError # Issue https://github.com/dart-lang/co19/issues/46
@@ -888,11 +888,13 @@
LayoutTests/fast/css/font-face-unicode-range-load_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/css/font-face-unicode-range-monospace_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/css/font-face-unicode-range-overlap-load_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/css/font-family-trailing-bracket-gunk_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/font-shorthand-from-longhands_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/fontfaceset-events_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/css/fontfaceset-loadingdone_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/css/getComputedStyle/computed-style-border-image_t01: RuntimeError # co19 issue 14
LayoutTests/fast/css/getComputedStyle/computed-style-cross-fade_t01: RuntimeError # co19 issue 14
+LayoutTests/fast/css/getComputedStyle/font-family-fallback-reset_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/html-attr-case-sensitivity_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/id-or-class-before-stylesheet_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/implicit-attach-marking_t01: Skip # Times out. Please triage this failure
@@ -992,6 +994,7 @@
LayoutTests/fast/dom/HTMLScriptElement/remove-in-beforeload_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLScriptElement/remove-source_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLScriptElement/script-set-src_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/dom/HTMLSelectElement/change-multiple-preserve-selection_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLTemplateElement/custom-element-wrapper-gc_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLTemplateElement/innerHTML_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLTemplateElement/ownerDocumentXHTML_t01: RuntimeError # Please triage this failure
@@ -1055,6 +1058,11 @@
LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/host-context-pseudo-class-css-text_t01: RuntimeError # https://github.com/dart-lang/co19/issues/49
LayoutTests/fast/dom/shadow/host-pseudo-class-css-text_t01: RuntimeError # https://github.com/dart-lang/co19/issues/49
+LayoutTests/fast/dom/shadow/olderShadowRoot_t01: RuntimeError # Issue 26729
+LayoutTests/fast/dom/shadow/shadowdom-for-input-spellcheck_t01: RuntimeError # Issue 26729
+LayoutTests/fast/dom/shadow/shadowdom-for-input-type-change_t01: RuntimeError # Issue 26729
+LayoutTests/fast/dom/shadow/shadowroot-clonenode_t01: RuntimeError # Issue 26729
+LayoutTests/fast/dom/shadow/shadowroot-host_t01: RuntimeError # Issue 26729
LayoutTests/fast/dom/shadow/no-renderers-for-light-children_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/pseudoclass-update-checked-option_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/pseudoclass-update-disabled-optgroup_t01: RuntimeError # Please triage this failure
@@ -1238,7 +1246,6 @@
LayoutTests/fast/table/col-width-span-expand_t01: RuntimeError # Please triage this failure
LayoutTests/fast/table/css-table-max-height_t01: RuntimeError # Please triage this failure
LayoutTests/fast/table/css-table-max-width_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/table/css-table-width-with-border-padding_t01: RuntimeError # Please triage this failure
LayoutTests/fast/table/hittest-tablecell-bottom-edge_t01: RuntimeError # Please triage this failure
LayoutTests/fast/table/hittest-tablecell-right-edge_t01: RuntimeError # Please triage this failure
LayoutTests/fast/table/hittest-tablecell-with-borders-bottom-edge_t01: RuntimeError # Please triage this failure
@@ -1291,7 +1298,6 @@
LayoutTests/fast/url/segments-from-data-url_t01: RuntimeError # Please triage this failure
LayoutTests/fast/url/segments_t01: RuntimeError # Please triage this failure
LayoutTests/fast/url/standard-url_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/writing-mode/auto-sizing-orthogonal-flows_t01: RuntimeError # Please triage this failure
LayoutTests/fast/writing-mode/flipped-blocks-hit-test-overflow-scroll_t01: RuntimeError # Please triage this failure
LayoutTests/fast/writing-mode/flipped-blocks-hit-test-overflow_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/writing-mode/positionForPoint_t01: RuntimeError # Please triage this failure
@@ -1315,6 +1321,7 @@
LayoutTests/fast/xpath/node-name-case-sensitivity_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/node-name-case-sensitivity_t02: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/position_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Issue 24398
LayoutTests/fast/xpath/py-dom-xpath/axes_t01: RuntimeError # Dartium JSInterop failure
LayoutTests/fast/xpath/py-dom-xpath/data_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/py-dom-xpath/expressions_t01: RuntimeError # Please triage this failure
@@ -1512,7 +1519,6 @@
WebPlatformTest/html/semantics/scripting-1/the-script-element/async_t11: RuntimeError # Please triage this failure
WebPlatformTest/html/semantics/scripting-1/the-script-element/script-text_t02: RuntimeError # Please triage this failure
WebPlatformTest/html/semantics/selectors/pseudo-classes/checked_t01: RuntimeError # Please triage this failure
-WebPlatformTest/html/semantics/selectors/pseudo-classes/default_t01: RuntimeError # Please triage this failure
WebPlatformTest/html/semantics/selectors/pseudo-classes/dir_t01: RuntimeError # Please triage this failure
WebPlatformTest/html/semantics/selectors/pseudo-classes/disabled_t01: RuntimeError # Please triage this failure
WebPlatformTest/html/semantics/selectors/pseudo-classes/enabled_t01: RuntimeError # Please triage this failure
@@ -1564,11 +1570,12 @@
WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t05: Skip # Times out. Please triage this failure
WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t06: Skip # Times out. Please triage this failure
WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-002_t01: Pass, RuntimeError, Timeout # Please triage this failure
-WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-003_t01: Pass, RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-003_t01: Skip # Times out. Please triage this failure
WebPlatformTest/shadow-dom/events/retargeting-relatedtarget/test-003_t01: RuntimeError # Please triage this failure
WebPlatformTest/shadow-dom/html-elements-and-their-shadow-trees/test-001_t01: RuntimeError # Please triage this failure
WebPlatformTest/shadow-dom/html-elements-and-their-shadow-trees/test-002_t01: RuntimeError # Please triage this failure
WebPlatformTest/shadow-dom/html-elements-and-their-shadow-trees/test-003_t01: RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/html-elements-and-their-shadow-trees/test-004_t01: RuntimeError # Issue 26729
WebPlatformTest/shadow-dom/shadow-trees/custom-pseudo-elements/test-001_t01: RuntimeError # Please triage this failure
WebPlatformTest/shadow-dom/shadow-trees/distributed-pseudo-element/test-001_t01: RuntimeError # Please triage this failure
WebPlatformTest/shadow-dom/shadow-trees/distributed-pseudo-element/test-002_t01: RuntimeError # Please triage this failure
@@ -1657,6 +1664,7 @@
Language/Expressions/Function_Invocation/async_invokation_t04: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/webgl/canvas-test_t01: Skip # Times out. Please triage this failure
LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/oes-vertex-array-object_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLOutputElement/htmloutputelement_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/MutationObserver/observe-attributes_t01: Skip # Times out. Please triage this failure
LayoutTests/fast/multicol/newmulticol/balance_t04: RuntimeError # Please triage this failure
@@ -1768,7 +1776,6 @@
LayoutTests/fast/canvas/webgl/webgl-texture-binding-preserved_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/webgl/webgl-unprefixed-context-id_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/webgl/webgl-viewport-parameters-preserved_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/Element/getBoundingClientRect-getClientRects-relative-to-viewport_t01: RuntimeError # Please triage this failure
LayoutTests/fast/multicol/newmulticol/balance_t04: RuntimeError # Please triage this failure
LayoutTests/fast/multicol/vertical-rl/image-inside-nested-blocks-with-border_t01: RuntimeError # co19 issue #65
LayoutTests/fast/shapes/shape-outside-floats/shape-outside-floats-inset-rounded-different-writing-modes-left_t01: RuntimeError # Please triage this failure
@@ -1781,13 +1788,8 @@
Language/Expressions/Bitwise_Expressions/method_invocation_super_t01: Pass, Slow # Issue 25940
Language/Classes/Constructors/Generative_Constructors/execution_of_an_initializer_t04: Pass, Slow # Issue 25940
-[ $compiler == dart2js && $runtime == chrome && $system != linux ]
-LayoutTests/fast/multicol/hit-test-gap-between-pages-flipped_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Issue 24398
-
[ $compiler == dart2js && $runtime == chrome && $system == linux]
LayoutTests/fast/text/international/combining-marks-position_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Dartium JSInterop failure
[ $compiler == dart2js && $runtime == ff ]
Language/Expressions/Postfix_Expressions/property_decrement_t02: Skip # Times out. Please triage this failure
@@ -1871,6 +1873,7 @@
LayoutTests/fast/canvas/webgl/context-lost_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/webgl/oes-vertex-array-object_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/webgl/renderer-and-vendor-strings_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-array-buffer-view_t01: Skip # Times out.
LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgb565_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba4444_t01: RuntimeError # Please triage this failure
@@ -1954,7 +1957,6 @@
LayoutTests/fast/css/box-sizing-backwards-compat-prefix_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/checked-pseudo-selector_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/child-selector-implicit-tbody_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/computed-offset-with-zoom_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/content/content-none_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/content/content-normal_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/content/content-quotes-01_t01: RuntimeError # co19 issue 61
@@ -2298,6 +2300,7 @@
LayoutTests/fast/dom/horizontal-scrollbar-in-rtl_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/horizontal-scrollbar-when-dir-change_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLDialogElement/dialog-return-value_t01: RuntimeError # Dartium JSInterop failure
+LayoutTests/fast/dom/icon-size-property_t01: RuntimeError # Issue 26714
LayoutTests/fast/dom/importNode-unsupported-node-type_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/insert-span-into-long-text-bug-28245_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/insertBefore-refChild-crash_t01: RuntimeError # Please triage this failure
@@ -2515,7 +2518,6 @@
LayoutTests/fast/forms/date/ValidityState-stepMismatch-date_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/ValidityState-typeMismatch-date_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/date-input-type_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/date-pseudo-classes_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/input-date-validation-message_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/input-valueasdate-date_t01: RuntimeError # Please triage this failure
@@ -3182,106 +3184,19 @@
Language/Classes/Constructors/Factories/return_type_t03: Pass, Slow # Issue 25940
Language/Classes/Constructors/Factories/return_wrong_type_t02: Pass, Slow # Issue 25940
Language/Classes/Constructors/Factories/return_type_t05: Pass, Slow # Issue 25940
-LayoutTests/fast/canvas/webgl/array-bounds-clamping_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/attrib-location-length-limits_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/buffer-bind-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/buffer-data-array-buffer_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-2d-webgl-texture_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-resize-crash_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/canvas-zero-size_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/css-webkit-canvas_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/compressed-tex-image_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/copy-tex-image-and-sub-image-2d_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/draw-arrays-out-of-bounds_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/draw-elements-out-of-bounds_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/drawingbuffer-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/error-reporting_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-bindings-unaffected-on-resize_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/functions-returning-strings_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/get-active-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-enable-enum-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-enum-tests_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-get-calls_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-getshadersource_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-getstring_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-object-get-calls_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-pixelstorei_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-teximage_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-uniformmatrix4fv_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-vertex-attrib-zero-issues_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-vertex-attrib_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/gl-vertexattribpointer_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/glsl-conformance_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/incorrect-context-object-behaviour_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation-copies-indices_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation-crash-with-buffer-sub-data_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation-verifies-too-many-indices_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation-with-resized-buffer_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/index-validation_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/invalid-UTF-16_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/invalid-passed-params_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/is-object_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/null-object-behaviour_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/null-uniform-location_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/object-deletion-behaviour_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/oes-element-index-uint_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/point-size_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/premultiplyalpha-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/program-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/read-pixels-pack-alignment_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/read-pixels-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/renderbuffer-initialization_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/shader-precision-format_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-array-buffer-view_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgb565_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgba4444_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgba5551_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgb565_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba4444_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba5551_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgb565_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba4444_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba5551_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-uniform-binding-bugs_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-webgl_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-sub-image-2d_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-sub-image-cube-maps_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texImage2DImageDataTest_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texImageTest_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-active-bind_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-bindings-uneffected-on-resize_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-complete_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-color-profile_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/texture-npot_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/triangle_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/uniform-location-length-limits_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/viewport-unchanged-upon-resize_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-composite-modes-repaint_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-composite-modes_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-exceptions_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-layer-update_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-specific_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-texture-binding-preserved_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-unprefixed-context-id_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/webgl-viewport-parameters-preserved_t01: RuntimeError # Please triage this failure
[ $compiler == dart2js && $runtime == ff && $system != windows ]
LayoutTests/fast/xpath/4XPath/Core/test_parser_t01: RuntimeError # Dartium JSInterop failure
LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Dartium JSInterop failure
[ $compiler == dart2js && $runtime == ff && $system == linux]
+LayoutTests/fast/canvas/webgl/*: Timeout, Pass # Issue 26725
LayoutTests/fast/canvas/canvas-composite-text-alpha_t01: RuntimeError # co19 issue 16
LayoutTests/fast/text/whitespace/nowrap-line-break-after-white-space_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/oes-element-index-uint_t01: Skip # Times out always
+LayoutTests/fast/canvas/webgl/texture-complete_t01: Skip # Times out sometimes
+LayoutTests/fast/canvas/webgl/texture-npot_t01: Skip # Times out sometimes
+LayoutTests/fast/dom/HTMLOutputElement/htmloutputelement_t01: RuntimeError # Issue 26714
[ $compiler == dart2js && $runtime == safari ]
Language/Statements/Yield_and_Yield_Each/Yield/execution_async_t01: RuntimeError # Issue 26615
@@ -3820,7 +3735,6 @@
LayoutTests/fast/forms/date/ValidityState-stepMismatch-date_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/ValidityState-typeMismatch-date_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/date-input-type_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/date-pseudo-classes_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/date-setrangetext_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/input-date-validation-message_t01: RuntimeError # Please triage this failure
@@ -3875,7 +3789,6 @@
LayoutTests/fast/inline/positioned-element-padding-contributes-width_t01: RuntimeError # Please triage this failure
LayoutTests/fast/innerHTML/innerHTML-svg-write_t01: RuntimeError # Issue 25941
LayoutTests/fast/innerHTML/javascript-url_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/layers/normal-flow-hit-test_t01: RuntimeError # Please triage this failure
LayoutTests/fast/loader/about-blank-hash-change_t01: Skip # Times out. Please triage this failure
LayoutTests/fast/loader/about-blank-hash-kept_t01: Skip # Times out. Please triage this failure
LayoutTests/fast/loader/hashchange-event-properties_t01: RuntimeError # Please triage this failure
@@ -3952,7 +3865,6 @@
LayoutTests/fast/storage/disallowed-storage_t01: RuntimeError # Please triage this failure
LayoutTests/fast/storage/storage-disallowed-in-data-url_t01: RuntimeError # Please triage this failure
LayoutTests/fast/sub-pixel/cssom-subpixel-precision_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/sub-pixel/float-containing-block-with-margin_t01: RuntimeError # Please triage this failure
LayoutTests/fast/sub-pixel/shadows-computed-style_t01: RuntimeError # Please triage this failure
LayoutTests/fast/svg/tabindex-focus_t01: RuntimeError # Please triage this failure
LayoutTests/fast/svg/whitespace-angle_t01: RuntimeError # Please triage this failure
@@ -3965,7 +3877,6 @@
LayoutTests/fast/table/col-width-span-expand_t01: RuntimeError # Please triage this failure
LayoutTests/fast/table/css-table-max-height_t01: RuntimeError # Please triage this failure
LayoutTests/fast/table/css-table-max-width_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/table/css-table-width-with-border-padding_t01: RuntimeError # Please triage this failure
LayoutTests/fast/table/fixed-table-layout-width-change_t01: RuntimeError # Please triage this failure
LayoutTests/fast/table/hittest-tablecell-bottom-edge_t01: RuntimeError # Please triage this failure
LayoutTests/fast/table/hittest-tablecell-right-edge_t01: RuntimeError # Please triage this failure
@@ -4036,7 +3947,6 @@
LayoutTests/fast/url/segments-from-data-url_t01: RuntimeError # Please triage this failure
LayoutTests/fast/url/segments_t01: RuntimeError # Please triage this failure
LayoutTests/fast/url/standard-url_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/writing-mode/auto-sizing-orthogonal-flows_t01: RuntimeError # Please triage this failure
LayoutTests/fast/writing-mode/positionForPoint_t01: RuntimeError # Please triage this failure
LayoutTests/fast/writing-mode/table-hit-test_t01: RuntimeError # Please triage this failure
LayoutTests/fast/writing-mode/vertical-font-vmtx-units-per-em_t01: RuntimeError # Please triage this failure
@@ -4433,15 +4343,10 @@
LayoutTests/fast/canvas/webgl/context-lost_t01: Skip
-LayoutTests/fast/canvas/canvas-strokePath-gradient-shadow_t01: RuntimeError # Fails 10 out of 10.
-LayoutTests/fast/canvas/canvas-strokeRect-gradient-shadow_t01: RuntimeError # Fails 10 out of 10.
-LayoutTests/fast/css/css-selector-text_t01: RuntimeError # Fails 10 out of 10.
-LayoutTests/fast/css/ex-unit-with-no-x-height_t01: RuntimeError # Fails 10 out of 10.
LayoutTests/fast/css/font-property-priority_t01: RuntimeError # Fails 10 out of 10.
LayoutTests/fast/css/inherited-properties-rare-text_t01: RuntimeError # Fails 10 out of 10.
LayoutTests/fast/css/invalid-not-with-simple-selector-sequence_t01: RuntimeError # Fails 10 out of 10.
LayoutTests/fast/css/parsing-font-variant-ligatures_t01: RuntimeError # Fails 10 out of 10.
-LayoutTests/fast/css/pseudo-valid-unapplied_t01: RuntimeError # Fails 10 out of 10.
LayoutTests/fast/dom/HTMLLinkElement/resolve-url-on-insertion_t01: RuntimeError # Fails 10 out of 10.
LayoutTests/fast/dom/css-selectorText_t01: RuntimeError # Fails 10 out of 10.
LayoutTests/fast/forms/datalist/datalist-child-validation_t01: RuntimeError # Fails 10 out of 10.
@@ -5131,7 +5036,6 @@
LayoutTests/fast/forms/datalist/input-list_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-change-layout-by-value_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-onblur-setvalue-onfocusremoved_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/input-date-validation-message_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/input-valueasdate-date_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/input-valueasnumber-date_t01: RuntimeError # Please triage this failure
@@ -6164,7 +6068,7 @@
LayoutTests/fast/css/link-alternate-stylesheet-3_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/link-alternate-stylesheet-4_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/link-alternate-stylesheet-5_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/link-disabled-attr-parser_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/link-disabled-attr-parser_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/css/list-item-text-align_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/margin-start-end_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/max-device-aspect-ratio_t01: Pass, RuntimeError # Please triage this failure
@@ -6798,7 +6702,6 @@
LayoutTests/fast/forms/date/ValidityState-stepMismatch-date_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/ValidityState-typeMismatch-date_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/date-input-type_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/date-pseudo-classes_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/input-date-validation-message_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/input-valueasdate-date_t01: RuntimeError # Please triage this failure
@@ -8074,7 +7977,7 @@
LayoutTests/fast/css/dynamic-class-backdrop-pseudo_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/dynamic-class-pseudo-elements_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/first-child-display-change-inverse_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/font-face-cache-bug_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/font-face-cache-bug_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/css/font-face-insert-link_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/css/font-face-multiple-ranges-for-unicode-range_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/font-face-unicode-range-load_t01: RuntimeError # Please triage this failure
@@ -8580,7 +8483,7 @@
LayoutTests/fast/dom/shadow/remove-styles-in-shadow-crash_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/shadow-aware-shadow-root_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/shadow-content-crash_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/shadow/shadow-disable_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/shadow/shadow-disable_t01: Skip # Issue 26737. Makes next test time out.
LayoutTests/fast/dom/shadow/shadow-element-inactive_t01: Skip # Times out. Please triage this failure
LayoutTests/fast/dom/shadow/shadow-element_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/shadow-hierarchy-exception_t01: RuntimeError # Please triage this failure
@@ -8749,7 +8652,6 @@
LayoutTests/fast/forms/date/ValidityState-stepMismatch-date_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/ValidityState-typeMismatch-date_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/date-input-type_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/forms/date/date-interactive-validation-required_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/date-pseudo-classes_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/input-date-validation-message_t01: RuntimeError # Please triage this failure
LayoutTests/fast/forms/date/input-valueasdate-date_t01: RuntimeError # Please triage this failure
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 5a12788..b5bdadc 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -54,7 +54,7 @@
[ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && $system == windows ]
Language/Expressions/Function_Invocation/async_invokation_t04: Pass, RuntimeError # co19 issue 54
-[ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && ($arch != x64 && $arch != simarm64 && $arch != arm64) ]
+[ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && ($arch != x64 && $arch != simarm64 && $arch != arm64 && $arch != simdbc && $arch != simdbc64) ]
LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch == mips || $arch == arm64) ]
@@ -64,7 +64,7 @@
LibTest/collection/ListMixin/ListMixin_class_A01_t02: Skip # co19 issue 673
LibTest/collection/ListBase/ListBase_class_A01_t02: Skip # co19 issue 673
-[ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && ($arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simmips || $arch == simarm64) ]
+[ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) && ($arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simmips || $arch == simarm64 || $arch == simdbc || $arch == simdbc64) ]
LibTest/core/Uri/Uri_A06_t03: Skip # Timeout
LibTest/collection/ListMixin/ListMixin_class_A01_t01: Skip # Timeout
LibTest/collection/ListBase/ListBase_class_A01_t01: Skip # Timeout
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index dffab8a..fc08b6b 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -127,18 +127,22 @@
});
}
- // There should at least be one metadata constant:
- // 1. The constructed constant for 'MirrorsUsed'.
- Expect.isTrue(backend.metadataConstants.length >= 1);
-
+ int metadataCount = 0;
Set<ConstantValue> compiledConstants = backend.constants.compiledConstants;
// Make sure that most of the metadata constants aren't included in the
// generated code.
- for (var dependency in backend.metadataConstants) {
- ConstantValue constant = dependency.constant;
+ backend.processMetadata(
+ compiler.enqueuer.resolution.processedElements, (metadata) {
+ ConstantValue constant =
+ backend.constants.getConstantValueForMetadata(metadata);
Expect.isFalse(compiledConstants.contains(constant),
constant.toStructuredText());
- }
+ metadataCount++;
+ });
+
+ // There should at least be one metadata constant:
+ // 1. The constructed constant for 'MirrorsUsed'.
+ Expect.isTrue(metadataCount >= 1);
// The type literal 'Foo' is both used as metadata, and as a plain value in
// the program. Make sure that it isn't duplicated.
diff --git a/tests/compiler/dart2js/serialization/compilation_test.dart b/tests/compiler/dart2js/serialization/compilation_test.dart
index b770f51..9889bf4 100644
--- a/tests/compiler/dart2js/serialization/compilation_test.dart
+++ b/tests/compiler/dart2js/serialization/compilation_test.dart
@@ -38,10 +38,6 @@
int index,
Test test,
bool verbose: false}) async {
- if (test != null && test.name == 'Disable tree shaking through reflection') {
- // TODO(johnniwinther): Support serialization of native element data.
- return;
- }
String testDescription = test != null ? test.name : '${entryPoint}';
String id = index != null ? '$index: ' : '';
print('------------------------------------------------------------------');
diff --git a/tests/compiler/dart2js/serialization/equivalence_test.dart b/tests/compiler/dart2js/serialization/equivalence_test.dart
index bd903da..e6ae2d4 100644
--- a/tests/compiler/dart2js/serialization/equivalence_test.dart
+++ b/tests/compiler/dart2js/serialization/equivalence_test.dart
@@ -248,6 +248,16 @@
list1, list2, checkElementProperties);
}
+/// Check the equivalence of the two metadata annotations, [metadata1] and
+/// [metadata2].
+///
+/// Uses [object1], [object2] and [property] to provide context for failures.
+checkMetadata(Object object1, Object object2, String property,
+ MetadataAnnotation metadata1, MetadataAnnotation metadata2) {
+ check(object1, object2, property,
+ metadata1, metadata2, areMetadataAnnotationsEquivalent);
+}
+
/// Visitor that checks for equivalence of [Element] properties.
class ElementPropertyEquivalence extends BaseElementVisitor<dynamic, Element> {
const ElementPropertyEquivalence();
@@ -277,6 +287,18 @@
element1.isClassMember, element2.isClassMember);
check(element1, element2, 'isInstanceMember',
element1.isInstanceMember, element2.isInstanceMember);
+ List<MetadataAnnotation> metadata1 = <MetadataAnnotation>[];
+ metadata1.addAll(element1.metadata);
+ if (element1.isPatched) {
+ metadata1.addAll(element1.implementation.metadata);
+ }
+ List<MetadataAnnotation> metadata2 = <MetadataAnnotation>[];
+ metadata2.addAll(element2.metadata);
+ if (element2.isPatched) {
+ metadata2.addAll(element2.implementation.metadata);
+ }
+ checkListEquivalence(element1, element2, 'metadata',
+ metadata1, metadata2, checkMetadata);
}
@override
@@ -382,7 +404,7 @@
throw message;
}
}
- currentCheck = new Check(currentCheck, element1, element1,
+ currentCheck = new Check(currentCheck, element1, element2,
'member:$name', member1, member2);
visit(member1, member2);
currentCheck = currentCheck.parent;
@@ -430,6 +452,10 @@
element1.isAbstract, element2.isAbstract);
check(element1, element2, 'isUnnamedMixinApplication',
element1.isUnnamedMixinApplication, element2.isUnnamedMixinApplication);
+ check(element1, element2, 'isProxy',
+ element1.isProxy, element2.isProxy);
+ check(element1, element2, 'isInjected',
+ element1.isInjected, element2.isInjected);
check(element1, element2, 'isEnumClass',
element1.isEnumClass, element2.isEnumClass);
if (element1.isEnumClass) {
@@ -515,6 +541,8 @@
element1.isStatic, element2.isStatic);
check(element1, element2, 'isInstanceMember',
element1.isInstanceMember, element2.isInstanceMember);
+ check(element1, element2, 'isInjected',
+ element1.isInjected, element2.isInjected);
checkElementIdentities(
element1, element2, 'library',
@@ -548,6 +576,8 @@
element1, element2, 'asyncMarker',
element1.asyncMarker,
element2.asyncMarker);
+ check(element1, element2, 'isInjected',
+ element1.isInjected, element2.isInjected);
checkElementIdentities(
element1, element2, 'library',
@@ -652,6 +682,8 @@
element2.immediateRedirectionTarget);
checkElementIdentities(element1, element2, 'redirectionDeferredPrefix',
element1.redirectionDeferredPrefix, element2.redirectionDeferredPrefix);
+ check(element1, element2, 'isInjected',
+ element1.isInjected, element2.isInjected);
}
@override
diff --git a/tests/compiler/dart2js/serialization/helper.dart b/tests/compiler/dart2js/serialization/helper.dart
index 3f2b429..e70b2ac 100644
--- a/tests/compiler/dart2js/serialization/helper.dart
+++ b/tests/compiler/dart2js/serialization/helper.dart
@@ -127,25 +127,39 @@
print('Loading data from $file');
serializedData = new SerializedData(uri, file.readAsStringSync());
}
+ } else {
+ SerializationResult result = await serialize(Uris.dart_core, uri);
+ serializedData = result.serializedData;
}
- if (serializedData == null) {
- Compiler compiler = compilerFor(
- options: [Flags.analyzeAll]);
- compiler.serialization.supportSerialization = true;
- await compiler.run(Uris.dart_core);
- BufferedEventSink sink = new BufferedEventSink();
- compiler.serialization.serializeToSink(
- sink, compiler.libraryLoader.libraries);
- serializedData = new SerializedData(uri, sink.text);
- if (arguments.saveSerializedData) {
- File file = new File(arguments.serializedDataFileName);
- print('Saving data to $file');
- file.writeAsStringSync(serializedData.data);
- }
+ if (arguments.saveSerializedData) {
+ File file = new File(arguments.serializedDataFileName);
+ print('Saving data to $file');
+ file.writeAsStringSync(serializedData.data);
}
return serializedData;
}
+class SerializationResult {
+ final Compiler compiler;
+ final SerializedData serializedData;
+
+ SerializationResult(this.compiler, this.serializedData);
+}
+
+Future<SerializationResult> serialize(Uri entryPoint, [Uri dataUri]) async {
+ if (dataUri == null) {
+ dataUri = Uri.parse('memory:${DEFAULT_DATA_FILE_NAME}');
+ }
+ Compiler compiler = compilerFor(options: [Flags.analyzeAll]);
+ compiler.serialization.supportSerialization = true;
+ await compiler.run(entryPoint);
+ BufferedEventSink sink = new BufferedEventSink();
+ compiler.serialization.serializeToSink(
+ sink, compiler.libraryLoader.libraries);
+ SerializedData serializedData = new SerializedData(dataUri, sink.text);
+ return new SerializationResult(compiler, serializedData);
+}
+
class SerializedData {
final Uri uri;
final String data;
diff --git a/tests/compiler/dart2js/serialization/model_test.dart b/tests/compiler/dart2js/serialization/model_test.dart
index d7eeed6..37b99df 100644
--- a/tests/compiler/dart2js/serialization/model_test.dart
+++ b/tests/compiler/dart2js/serialization/model_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
library dart2js.serialization_model_test;
-
import 'dart:async';
import 'dart:io';
import 'package:async_helper/async_helper.dart';
@@ -13,6 +12,7 @@
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/filenames.dart';
+import 'package:compiler/src/js_backend/js_backend.dart';
import 'package:compiler/src/serialization/equivalence.dart';
import 'package:compiler/src/tree/nodes.dart';
import 'package:compiler/src/universe/class_set.dart';
@@ -33,7 +33,7 @@
resolutionInputs: serializedData.toUris());
} else {
Uri entryPoint = Uri.parse('memory:main.dart');
- arguments.forEachTest(serializedData, TESTS, checkModels);
+ await arguments.forEachTest(serializedData, TESTS, checkModels);
}
});
}
@@ -45,11 +45,6 @@
int index,
Test test,
bool verbose: false}) async {
- if (test != null && test.name == 'Disable tree shaking through reflection') {
- // TODO(johnniwinther): Support serialization of metadata.
- return;
- }
-
String testDescription = test != null ? test.name : '${entryPoint}';
String id = index != null ? '$index: ' : '';
print('------------------------------------------------------------------');
@@ -121,6 +116,19 @@
compilerDeserialized.world.getClassHierarchyNode(
compilerDeserialized.coreClasses.objectClass),
verbose: verbose);
+
+ Expect.equals(compilerNormal.enabledInvokeOn,
+ compilerDeserialized.enabledInvokeOn,
+ "Compiler.enabledInvokeOn mismatch");
+ Expect.equals(compilerNormal.enabledFunctionApply,
+ compilerDeserialized.enabledFunctionApply,
+ "Compiler.enabledFunctionApply mismatch");
+ Expect.equals(compilerNormal.enabledRuntimeType,
+ compilerDeserialized.enabledRuntimeType,
+ "Compiler.enabledRuntimeType mismatch");
+ Expect.equals(compilerNormal.hasIsolateSupport,
+ compilerDeserialized.hasIsolateSupport,
+ "Compiler.hasIsolateSupport mismatch");
}
void checkElements(
@@ -133,11 +141,11 @@
AstElement astElement1 = element1;
AstElement astElement2 = element2;
ClosureClassMap closureData1 =
- compiler1.closureToClassMapper.computeClosureToClassMapping(
- astElement1.resolvedAst);
+ compiler1.closureToClassMapper.computeClosureToClassMapping(
+ astElement1.resolvedAst);
ClosureClassMap closureData2 =
- compiler2.closureToClassMapper.computeClosureToClassMapping(
- astElement2.resolvedAst);
+ compiler2.closureToClassMapper.computeClosureToClassMapping(
+ astElement2.resolvedAst);
checkElementIdentities(closureData1, closureData2,
'$element1.closureElement',
@@ -174,6 +182,12 @@
areLocalsEquivalent,
verbose: verbose);
}
+ JavaScriptBackend backend1 = compiler1.backend;
+ JavaScriptBackend backend2 = compiler2.backend;
+ Expect.equals(
+ backend1.inlineCache.getCurrentCacheDecisionForTesting(element1),
+ backend2.inlineCache.getCurrentCacheDecisionForTesting(element2),
+ "Inline cache decision mismatch for $element1 vs $element2");
}
void checkMixinUses(
@@ -240,128 +254,6 @@
checkMixinUses(compiler1, compiler2, node1.cls, node2.cls, verbose: verbose);
}
-void checkSets(
- Iterable set1,
- Iterable set2,
- String messagePrefix,
- bool sameElement(a, b),
- {bool failOnUnfound: true,
- bool verbose: false,
- void onSameElement(a, b)}) {
- List common = [];
- List unfound = [];
- Set remaining = computeSetDifference(
- set1, set2, common, unfound,
- sameElement: sameElement,
- checkElements: onSameElement);
- StringBuffer sb = new StringBuffer();
- sb.write("$messagePrefix:");
- if (verbose) {
- sb.write("\n Common:\n ${common.join('\n ')}");
- }
- if (unfound.isNotEmpty || verbose) {
- sb.write("\n Unfound:\n ${unfound.join('\n ')}");
- }
- if (remaining.isNotEmpty || verbose) {
- sb.write("\n Extra: \n ${remaining.join('\n ')}");
- }
- String message = sb.toString();
- if (unfound.isNotEmpty || remaining.isNotEmpty) {
-
- if (failOnUnfound || remaining.isNotEmpty) {
- Expect.fail(message);
- } else {
- print(message);
- }
- } else if (verbose) {
- print(message);
- }
-}
-
-String defaultToString(obj) => '$obj';
-
-void checkMaps(
- Map map1,
- Map map2,
- String messagePrefix,
- bool sameKey(a, b),
- bool sameValue(a, b),
- {bool failOnUnfound: true,
- bool failOnMismatch: true,
- bool verbose: false,
- String keyToString(key): defaultToString,
- String valueToString(key): defaultToString}) {
- List common = [];
- List unfound = [];
- List<List> mismatch = <List>[];
- Set remaining = computeSetDifference(
- map1.keys, map2.keys, common, unfound,
- sameElement: sameKey,
- checkElements: (k1, k2) {
- var v1 = map1[k1];
- var v2 = map2[k2];
- if (!sameValue(v1, v2)) {
- mismatch.add([k1, k2]);
- }
- });
- StringBuffer sb = new StringBuffer();
- sb.write("$messagePrefix:");
- if (verbose) {
- sb.write("\n Common: \n");
- for (List pair in common) {
- var k1 = pair[0];
- var k2 = pair[1];
- var v1 = map1[k1];
- var v2 = map2[k2];
- sb.write(" key1 =${keyToString(k1)}\n");
- sb.write(" key2 =${keyToString(k2)}\n");
- sb.write(" value1=${valueToString(v1)}\n");
- sb.write(" value2=${valueToString(v2)}\n");
- }
- }
- if (unfound.isNotEmpty || verbose) {
- sb.write("\n Unfound: \n");
- for (var k1 in unfound) {
- var v1 = map1[k1];
- sb.write(" key1 =${keyToString(k1)}\n");
- sb.write(" value1=${valueToString(v1)}\n");
- }
- }
- if (remaining.isNotEmpty || verbose) {
- sb.write("\n Extra: \n");
- for (var k2 in remaining) {
- var v2 = map2[k2];
- sb.write(" key2 =${keyToString(k2)}\n");
- sb.write(" value2=${valueToString(v2)}\n");
- }
- }
- if (mismatch.isNotEmpty || verbose) {
- sb.write("\n Mismatch: \n");
- for (List pair in mismatch) {
- var k1 = pair[0];
- var k2 = pair[1];
- var v1 = map1[k1];
- var v2 = map2[k2];
- sb.write(" key1 =${keyToString(k1)}\n");
- sb.write(" key2 =${keyToString(k2)}\n");
- sb.write(" value1=${valueToString(v1)}\n");
- sb.write(" value2=${valueToString(v2)}\n");
- }
- }
- String message = sb.toString();
- if (unfound.isNotEmpty || mismatch.isNotEmpty || remaining.isNotEmpty) {
- if ((unfound.isNotEmpty && failOnUnfound) ||
- (mismatch.isNotEmpty && failOnMismatch) ||
- remaining.isNotEmpty) {
- Expect.fail(message);
- } else {
- print(message);
- }
- } else if (verbose) {
- print(message);
- }
-}
-
bool areLocalsEquivalent(Local a, Local b) {
if (a == b) return true;
if (a == null || b == null) return false;
diff --git a/tests/compiler/dart2js/serialization/native_data_test.dart b/tests/compiler/dart2js/serialization/native_data_test.dart
new file mode 100644
index 0000000..d2a9173
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/native_data_test.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.serialization.native_data_test;
+
+import 'dart:async';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/common/names.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/js_backend/js_backend.dart';
+import 'package:compiler/src/js_backend/native_data.dart';
+import 'package:compiler/src/filenames.dart';
+import 'package:compiler/src/serialization/equivalence.dart';
+import '../memory_compiler.dart';
+import 'helper.dart';
+import 'test_helper.dart';
+
+main(List<String> args) {
+ asyncTest(() async {
+ Arguments arguments = new Arguments.from(args);
+ Uri uri = Uris.dart_html;
+ if (arguments.filename != null) {
+ uri = Uri.base.resolve(nativeToUriPath(arguments.filename));
+ }
+ await checkNativeData(uri, verbose: arguments.verbose);
+ });
+}
+
+Future checkNativeData(Uri uri, {bool verbose: false}) async {
+ print('------------------------------------------------------------------');
+ print('analyze normal: $uri');
+ print('------------------------------------------------------------------');
+ SerializationResult result = await serialize(uri);
+ Compiler compiler1 = result.compiler;
+ SerializedData serializedData = result.serializedData;
+
+ print('------------------------------------------------------------------');
+ print('analyze deserialized: $uri');
+ print('------------------------------------------------------------------');
+ Compiler compiler2 = compilerFor(
+ memorySourceFiles: serializedData.toMemorySourceFiles(),
+ resolutionInputs: serializedData.toUris(),
+ options: [Flags.analyzeAll]);
+ await compiler2.run(uri);
+
+ JavaScriptBackend backend1 = compiler1.backend;
+ JavaScriptBackend backend2 = compiler2.backend;
+ NativeData nativeData1 = backend1.nativeData;
+ NativeData nativeData2 = backend2.nativeData;
+
+ checkMaps(
+ nativeData1.jsInteropNames,
+ nativeData2.jsInteropNames,
+ "NativeData.jsInteropNames",
+ areElementsEquivalent,
+ equality,
+ verbose: verbose);
+
+ checkMaps(
+ nativeData1.nativeMemberName,
+ nativeData2.nativeMemberName,
+ "NativeData.nativeMemberName",
+ areElementsEquivalent,
+ equality,
+ verbose: verbose);
+
+ checkMaps(
+ nativeData1.nativeClassTagInfo,
+ nativeData2.nativeClassTagInfo,
+ "NativeData.nativeClassTagInfo",
+ areElementsEquivalent,
+ equality,
+ verbose: verbose);
+
+ checkMaps(
+ nativeData1.nativeMethodBehavior,
+ nativeData2.nativeMethodBehavior,
+ "NativeData.nativeMethodBehavior",
+ areElementsEquivalent,
+ testNativeBehavior,
+ verbose: verbose);
+
+ checkMaps(
+ nativeData1.nativeFieldLoadBehavior,
+ nativeData2.nativeFieldLoadBehavior,
+ "NativeData.nativeFieldLoadBehavior",
+ areElementsEquivalent,
+ testNativeBehavior,
+ verbose: verbose);
+
+ checkMaps(
+ nativeData1.nativeFieldStoreBehavior,
+ nativeData2.nativeFieldStoreBehavior,
+ "NativeData.nativeFieldStoreBehavior",
+ areElementsEquivalent,
+ testNativeBehavior,
+ verbose: verbose);
+}
diff --git a/tests/compiler/dart2js/serialization/test_helper.dart b/tests/compiler/dart2js/serialization/test_helper.dart
index 4bbed39..a6dddf9 100644
--- a/tests/compiler/dart2js/serialization/test_helper.dart
+++ b/tests/compiler/dart2js/serialization/test_helper.dart
@@ -12,6 +12,7 @@
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/serialization/equivalence.dart';
import 'package:compiler/src/tree/nodes.dart';
+import 'package:expect/expect.dart';
Check currentCheck;
@@ -185,7 +186,7 @@
Set computeSetDifference(
Iterable set1,
Iterable set2,
- List common,
+ List<List> common,
List unfound,
{bool sameElement(a, b): equality,
void checkElements(a, b)}) {
@@ -197,19 +198,19 @@
// set.difference would work)
Set remaining = set2.toSet();
for (var element1 in set1) {
- bool found = false;
+ var correspondingElement;
for (var element2 in remaining) {
if (sameElement(element1, element2)) {
if (checkElements != null) {
checkElements(element1, element2);
}
- found = true;
+ correspondingElement = element2;
remaining.remove(element2);
break;
}
}
- if (found) {
- common.add(element1);
+ if (correspondingElement != null) {
+ common.add([element1, correspondingElement]);
} else {
unfound.add(element1);
}
@@ -229,7 +230,7 @@
Iterable set2,
bool sameElement(a, b),
{void onSameElement(a, b)}) {
- List common = [];
+ List<List> common = <List>[];
List unfound = [];
Set remaining =
computeSetDifference(set1, set2, common, unfound,
@@ -428,3 +429,127 @@
testResolutionImpactEquivalence(impact1, impact2, const CheckStrategy());
}
+
+void checkSets(
+ Iterable set1,
+ Iterable set2,
+ String messagePrefix,
+ bool sameElement(a, b),
+ {bool failOnUnfound: true,
+ bool failOnExtra: true,
+ bool verbose: false,
+ void onSameElement(a, b)}) {
+ List<List> common = <List>[];
+ List unfound = [];
+ Set remaining = computeSetDifference(
+ set1, set2, common, unfound,
+ sameElement: sameElement,
+ checkElements: onSameElement);
+ StringBuffer sb = new StringBuffer();
+ sb.write("$messagePrefix:");
+ if (verbose) {
+ sb.write("\n Common:\n ${common.join('\n ')}");
+ }
+ if (unfound.isNotEmpty || verbose) {
+ sb.write("\n Unfound:\n ${unfound.join('\n ')}");
+ }
+ if (remaining.isNotEmpty || verbose) {
+ sb.write("\n Extra: \n ${remaining.join('\n ')}");
+ }
+ String message = sb.toString();
+ if (unfound.isNotEmpty || remaining.isNotEmpty) {
+
+ if ((failOnUnfound && unfound.isNotEmpty) ||
+ (failOnExtra && remaining.isNotEmpty)) {
+ Expect.fail(message);
+ } else {
+ print(message);
+ }
+ } else if (verbose) {
+ print(message);
+ }
+}
+
+String defaultToString(obj) => '$obj';
+
+void checkMaps(
+ Map map1,
+ Map map2,
+ String messagePrefix,
+ bool sameKey(a, b),
+ bool sameValue(a, b),
+ {bool failOnUnfound: true,
+ bool failOnMismatch: true,
+ bool verbose: false,
+ String keyToString(key): defaultToString,
+ String valueToString(key): defaultToString}) {
+ List<List> common = <List>[];
+ List unfound = [];
+ List<List> mismatch = <List>[];
+ Set remaining = computeSetDifference(
+ map1.keys, map2.keys, common, unfound,
+ sameElement: sameKey,
+ checkElements: (k1, k2) {
+ var v1 = map1[k1];
+ var v2 = map2[k2];
+ if (!sameValue(v1, v2)) {
+ mismatch.add([k1, k2]);
+ }
+ });
+ StringBuffer sb = new StringBuffer();
+ sb.write("$messagePrefix:");
+ if (verbose) {
+ sb.write("\n Common: \n");
+ for (List pair in common) {
+ var k1 = pair[0];
+ var k2 = pair[1];
+ var v1 = map1[k1];
+ var v2 = map2[k2];
+ sb.write(" key1 =${keyToString(k1)}\n");
+ sb.write(" key2 =${keyToString(k2)}\n");
+ sb.write(" value1=${valueToString(v1)}\n");
+ sb.write(" value2=${valueToString(v2)}\n");
+ }
+ }
+ if (unfound.isNotEmpty || verbose) {
+ sb.write("\n Unfound: \n");
+ for (var k1 in unfound) {
+ var v1 = map1[k1];
+ sb.write(" key1 =${keyToString(k1)}\n");
+ sb.write(" value1=${valueToString(v1)}\n");
+ }
+ }
+ if (remaining.isNotEmpty || verbose) {
+ sb.write("\n Extra: \n");
+ for (var k2 in remaining) {
+ var v2 = map2[k2];
+ sb.write(" key2 =${keyToString(k2)}\n");
+ sb.write(" value2=${valueToString(v2)}\n");
+ }
+ }
+ if (mismatch.isNotEmpty || verbose) {
+ sb.write("\n Mismatch: \n");
+ for (List pair in mismatch) {
+ var k1 = pair[0];
+ var k2 = pair[1];
+ var v1 = map1[k1];
+ var v2 = map2[k2];
+ sb.write(" key1 =${keyToString(k1)}\n");
+ sb.write(" key2 =${keyToString(k2)}\n");
+ sb.write(" value1=${valueToString(v1)}\n");
+ sb.write(" value2=${valueToString(v2)}\n");
+ }
+ }
+ String message = sb.toString();
+ if (unfound.isNotEmpty || mismatch.isNotEmpty || remaining.isNotEmpty) {
+ if ((unfound.isNotEmpty && failOnUnfound) ||
+ (mismatch.isNotEmpty && failOnMismatch) ||
+ remaining.isNotEmpty) {
+ Expect.fail(message);
+ } else {
+ print(message);
+ }
+ } else if (verbose) {
+ print(message);
+ }
+}
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 897d5b3..df4de07 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -84,3 +84,6 @@
[ $compiler == dart2js && $runtime == ff && $system == windows ]
consistent_index_error_string_test: Pass, Slow # Issue 25940
+
+[ $compiler == dart2js && $runtime == ff && $system == linux ]
+mirror_printer_test: Pass, Slow # Issue 25940
diff --git a/tests/html/html.status b/tests/html/html.status
index c36e35a..670665a 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -104,6 +104,7 @@
element_types_test/supported_object: RuntimeError # Issue 25155
element_types_test/supported_embed: RuntimeError # Issue 25155
svgelement_test/PathElement: RuntimeError # Issue 25665
+element_animate_test/timing_dict: RuntimeError # Issue 26730
[ $runtime == chrome && $system == macos ]
canvasrenderingcontext2d_test/drawImage_video_element: Skip # Times out. Please triage this failure.
@@ -301,43 +302,6 @@
js_test/JsArray: RuntimeError # Fails 10 out of 10.
indexeddb_3_test: Skip # Times out 1 out of 10.
-[ $runtime == opera ]
-blob_constructor_test: Fail
-canvas_test: Fail
-canvas_test: Pass,Fail
-cssstyledeclaration_test: Fail
-document_test/document: Fail # Issue: 7413
-element_add_test: Fail
-element_constructor_1_test: Fail
-element_test/children: Fail # Issue: 7413
-element_test/constructors: Fail
-element_test/elements: Fail
-element_test/eventListening: Crash
-element_test/eventListening: Fail # Issue: 7413
-element_test/queryAll: Fail
-fileapi_test: Skip # Timeout.
-form_data_test: Fail # Issue: 7413
-htmlelement_test: Fail
-isolates_test: Skip # Timeout.
-keyboard_event_test: Fail # Issue: 7413
-serialized_script_value_test: Fail
-typed_arrays_arraybuffer_test: Fail
-url_test: Fail
-
-# Opera Feature support statuses-
-# All changes should be accompanied by platform support annotation changes.
-audiobuffersourcenode_test/supported: Fail
-audiocontext_test/supported: Fail
-crypto_test/supported: Fail
-css_test/supportsPointConversions: Fail
-element_types_test/supported_template: Fail
-indexeddb_1_test/supported: Fail
-indexeddb_1_test/supportsDatabaseNames: Fail
-mutationobserver_test/supported: Fail
-performance_api_test/supported: Fail
-speechrecognition_test/supported: Fail
-websql_test/supported: Fail
-
[ $compiler == dart2js && $runtime == ff ]
history_test/history: Skip # Issue 22050
xhr_test/xhr: Pass, Fail # Issue 11602
diff --git a/tests/language/const_constructor_super2_test.dart b/tests/language/const_constructor_super2_test.dart
new file mode 100644
index 0000000..8832d24
--- /dev/null
+++ b/tests/language/const_constructor_super2_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+class A {
+ final a;
+
+ const A(this.a);
+}
+
+class B extends A {
+ final b;
+
+ const B(a, this.b) : super(a);
+}
+
+@NoInline()
+foo() => const B(1, 2);
+
+@NoInline()
+bar() => const B(2, 2);
+
+void main() {
+ Expect.notEquals(foo(), bar());
+ Expect.notEquals(foo().a, bar().a);
+ Expect.equals(foo().b, bar().b);
+}
\ No newline at end of file
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index d80aae4..aec3d55 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -16,6 +16,8 @@
deep_nesting1_negative_test: Crash # Issue 25557
deep_nesting2_negative_test: Crash # Issue 25557
+regress_18713_test: Fail # Issue 26743
+
call_function_apply_test: RuntimeError # Issue 23873
mixin_supertype_subclass_test: CompileTimeError # Issue 23773
mixin_supertype_subclass2_test: CompileTimeError # Issue 23773
@@ -227,6 +229,9 @@
[ $compiler == dart2js && $runtime == ff ]
round_test: Pass, Fail, OK # Fixed in ff 35. Common JavaScript engine Math.round bug.
+[ $compiler == dart2js && $runtime == chrome && $system == macos ]
+await_future_test: Pass, Timeout # Issue 26735
+
[ $compiler == dart2js && ($runtime == safari || $runtime == safarimobilesim)]
# Safari codegen bug, fixed on some versions of Safari 7.1 (Version 7.1 (9537.85.10.17.1))
call_through_getter_test: Fail, OK
diff --git a/tests/language/regress_18713_test.dart b/tests/language/regress_18713_test.dart
new file mode 100644
index 0000000..b0d8736
--- /dev/null
+++ b/tests/language/regress_18713_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class T<X> {
+ final Type tType = X;
+ Type get getTType => X;
+}
+
+class S<Y> {
+ final Type sType = Y;
+ Type get getSType => Y;
+}
+
+class TS<A, B> = T<A> with S<B>;
+
+main() {
+ var ts = new TS<int, String>();
+ Expect.equals("String", ts.sType.toString());
+ Expect.equals("int", ts.tType.toString());
+ Expect.equals("String", ts.getSType.toString());
+ Expect.equals("int", ts.getTType.toString());
+}
diff --git a/tests/language/regress_26530_test.dart b/tests/language/regress_26530_test.dart
new file mode 100644
index 0000000..a41761a
--- /dev/null
+++ b/tests/language/regress_26530_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+var trace = "";
+
+main() {
+ var x = 0;
+ try {
+ try {
+ throw x++; // 1
+ } on int catch (e) {
+ trace += "$e";
+ trace += "-$x";
+ x++; // 2
+ try {
+ x++; // 3
+ rethrow;
+ } finally {
+ trace += "-f";
+ x++; // 4
+ }
+ }
+ } catch (e) {
+ trace += "-c";
+ trace += "-$e";
+ trace += "-$x";
+ }
+ Expect.equals("0-1-f-c-0-4", trace);
+}
diff --git a/tests/lib/async/timer_regress22626_test.dart b/tests/lib/async/timer_regress22626_test.dart
index 483b9338..810be7c 100644
--- a/tests/lib/async/timer_regress22626_test.dart
+++ b/tests/lib/async/timer_regress22626_test.dart
@@ -12,7 +12,7 @@
import 'dart:math';
import 'package:expect/expect.dart';
-int countdown = 10;
+int countdown = 5;
var rng = new Random(1234);
void test(int delay, int delta) {
@@ -31,5 +31,5 @@
}
void main() {
- test(50, 2);
+ test(200, 2);
}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 07ac39b..7a60549 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -229,6 +229,9 @@
# TODO(efortuna): Investigate.
async/timer_test: Fail, Pass
+[ $runtime == vm ]
+convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Infrequent timeouts.
+
[ ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) ]
async/timer_not_available_test: Fail, OK
mirrors/native_class_test: Fail, OK # This test is meant to run in a browser.
diff --git a/tests/standalone/packages_file_test.dart b/tests/standalone/packages_file_test.dart
index 9902d69..d41e46b 100644
--- a/tests/standalone/packages_file_test.dart
+++ b/tests/standalone/packages_file_test.dart
@@ -85,26 +85,11 @@
/// This should not change the expected results compared to running it
/// directly.
Configuration spawn(Configuration conf) {
- // TODO(26555): Clean up when fixed.
- // TEMPORARY FIX FOR ISSUE #26555 (http://dartbug.com/26555)
- if (conf.expect["iroot"] == null &&
- conf.expect["iconf"] == null &&
- conf.expect["pconf"] != null) {
- // The spawned isolate will do a search for a package file or root,
- // which is not what the original did. Skip test for now.
- return null;
- }
- // REMOVE WHEN ISSUE FIXED!
return conf.update(
description: conf.description + "/spawn",
main: "spawnMain",
newArgs: [conf.mainType],
- // TEMPORARY FIX FOR ISSUE #26555 (http://dartbug.com/26555)
- expect: {
- "proot": conf.expect["iroot"],
- "pconf": conf.expect["iconf"],
- }
- // REMOVE WHEN ISSUE FIXED!
+ expect: null
);
}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index c039aad..5c03bea 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -7,7 +7,7 @@
# listed in tests/lib/analyzer/analyze_tests.status without the "standalone"
# prefix.
-packages_file_test: Pass, Slow
+packages_file_test: Skip # Issue 26715
packages_file_test/none: Skip # contains no tests.
package/invalid_uri_test: Fail, OK # CompileTimeErrors intentionally
diff --git a/tools/VERSION b/tools/VERSION
index 4fd0654..67e5d05 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 1
MINOR 18
PATCH 0
-PRERELEASE 1
+PRERELEASE 2
PRERELEASE_PATCH 0