Version 1.14.0-dev.6.0
Merge commit 'dcb021c5d99ae5c1cd7dc96ba4f839101944f327' into dev
diff --git a/DEPS b/DEPS
index aa5c78c..e041804 100644
--- a/DEPS
+++ b/DEPS
@@ -7,13 +7,6 @@
# simply sdk, but if using special gclient specs it can be different.
"dart_root": "sdk",
- # The svn location to pull out dependencies from
- "third_party": "http://dart.googlecode.com/svn/third_party",
-
- # Use this googlecode_url variable only if there is an internal mirror for it.
- # If you do not know, use the full path while defining your new deps entry.
- "googlecode_url": "http://%s.googlecode.com/svn",
-
# We use mirrors of all github repos to guarantee reproducibility and
# consistency between what users see and what the bots see.
# We need the mirrors to not have 100+ bots pulling github constantly.
@@ -30,18 +23,15 @@
"gyp_rev": "@6ee91ad8659871916f9aa840d42e1513befdf638",
"co19_rev": "@3ed795ea02e022ef19c77cf1b6095b7c8f5584d0",
- "chromium_url": "http://src.chromium.org/svn",
"chromium_git": "https://chromium.googlesource.com",
# Revisions of /third_party/* dependencies.
- "7zip_rev" : "@19997",
"args_tag": "@0.13.0",
"async_tag": "@1.4.0",
"barback_tag" : "@0.15.2+7",
"boringssl_rev" : "@daeafc22c66ad48f6b32fc8d3362eb9ba31b774e",
"charcode_tag": "@1.1.0",
"chrome_rev" : "@19997",
- "clang_rev" : "@28450",
"cli_util_tag" : "@0.0.1+2",
"collection_rev": "@f6135e6350c63eb3f4dd12953b8d4363faff16fc",
"convert_tag": "@1.0.0",
@@ -52,11 +42,9 @@
"dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
"dart_style_tag": "@0.2.2",
"dev_compiler_rev": "@0.1.9",
- "firefox_jsshell_rev" : "@45554",
"glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
- "gsutil_rev" : "@33376",
"html_tag" : "@0.12.1+1",
- "http_rev" : "@9b93e1542c753090c50b46ef1592d44bc858bfe7",
+ "http_tag" : "@0.11.3+3",
"http_multi_server_tag" : "@2.0.0",
"http_parser_tag" : "@1.1.0",
"http_throttle_rev" : "@a81f08be942cdd608883c7b67795c12226abc235",
@@ -76,7 +64,6 @@
"observatory_pub_packages_rev": "@cf90eb9077177d3d6b3fd5e8289477c2385c026a",
"package_config_rev": "@0.1.3",
"path_tag": "@1.3.6",
- "petitparser_rev" : "@37878",
"ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
"plugin_tag": "@0.1.0",
"pool_tag": "@1.2.1",
@@ -86,7 +73,7 @@
"quiver_tag": "@0.21.4",
"root_certificates_rev": "@c3a41df63afacec62fcb8135196177e35fe72f71",
"scheduled_test_tag": "@0.12.4+2",
- "shelf_tag": "@0.6.2+1",
+ "shelf_tag": "@0.6.4+3",
"smoke_rev" : "@f3361191cc2a85ebc1e4d4c33aec672d7915aba9",
"source_maps_tag": "@0.10.1",
"shelf_static_tag": "@0.2.3+1",
@@ -105,7 +92,7 @@
"when_tag": "@0.2.0+2",
"which_tag": "@0.1.3+1",
"web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
- "WebCore_rev" : "@44061",
+ "WebCore_rev": "@4f90b41b0165f23f412cecdba07b7d81d3fbb5b5",
"yaml_tag": "@2.1.5",
"zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
"barback-0.13.0_rev": "@34853",
@@ -146,20 +133,8 @@
Var("chromium_git") + "/chromium/src/tools/idl_parser.git" +
Var("idl_parser_rev"),
- Var("dart_root") + "/third_party/7zip":
- Var("third_party") + "/7zip" + Var("7zip_rev"),
- Var("dart_root") + "/third_party/firefox_jsshell":
- Var("third_party") + "/firefox_jsshell" + Var("firefox_jsshell_rev"),
- Var("dart_root") + "/third_party/gsutil":
- Var("third_party") + "/gsutil" + Var("gsutil_rev"),
- Var("dart_root") + "/third_party/pkg/petitparser":
- Var("third_party") + "/petitparser" + Var("petitparser_rev"),
Var("dart_root") + "/third_party/WebCore":
- Var("third_party") + "/WebCore" + Var("WebCore_rev"),
-
- Var("dart_root") + "/third_party/dart-services":
- (Var("github_mirror") % "dart-services") +
- Var("dart_services_rev"),
+ "https://github.com/dart-lang/webcore.git" + Var("WebCore_rev"),
Var("dart_root") + "/third_party/pkg/args":
(Var("github_mirror") % "args") + Var("args_tag"),
@@ -179,6 +154,9 @@
(Var("github_mirror") % "crypto") + Var("crypto_rev"),
Var("dart_root") + "/third_party/pkg/csslib":
(Var("github_mirror") % "csslib") + Var("csslib_tag"),
+ Var("dart_root") + "/third_party/dart-services":
+ (Var("github_mirror") % "dart-services") +
+ Var("dart_services_rev"),
Var("dart_root") + "/third_party/pkg_tested/dart_style":
(Var("github_mirror") % "dart_style") + Var("dart_style_tag"),
Var("dart_root") + "/third_party/pkg/dart2js_info":
@@ -192,7 +170,7 @@
Var("dart_root") + "/third_party/pkg/html":
(Var("github_mirror") % "html") + Var("html_tag"),
Var("dart_root") + "/third_party/pkg/http":
- (Var("github_mirror") % "http") + Var("http_rev"),
+ (Var("github_mirror") % "http") + Var("http_tag"),
Var("dart_root") + "/third_party/pkg/http_multi_server":
(Var("github_mirror") % "http_multi_server") +
Var("http_multi_server_tag"),
@@ -307,13 +285,6 @@
Var("dart_root") + "/third_party/cygwin":
Var("chromium_git") + "/chromium/deps/cygwin.git" +
"@c89e446b273697fadf3a10ff1007a97c0b7de6df",
- Var("dart_root") + "/third_party/drt_resources":
- Var("chromium_url") +
- "/trunk/src/webkit/tools/test_shell/resources@157099",
- },
- "unix": {
- Var("dart_root") + "/third_party/clang":
- Var("third_party") + "/clang" + Var("clang_rev"),
},
}
@@ -368,4 +339,92 @@
Var('dart_root') + "/tools/sdks",
],
},
+ {
+ "name": "firefox_jsshell",
+ "pattern": ".",
+ "action": [
+ "download_from_google_storage",
+ "--no_auth",
+ "--no_resume",
+ "--bucket",
+ "dart-dependencies",
+ "--recursive",
+ "--auto_platform",
+ "--extract",
+ "--directory",
+ Var('dart_root') + "/third_party/firefox_jsshell",
+ ],
+ },
+ {
+ "name": "drt_resources",
+ "pattern": ".",
+ "action": [
+ "download_from_google_storage",
+ "--no_auth",
+ "--no_resume",
+ "--bucket",
+ "dart-dependencies",
+ "--platform=win32",
+ "--directory",
+ Var('dart_root') + "/third_party/drt_resources",
+ ],
+ },
+ {
+ "name": "petitparser",
+ "pattern": ".",
+ "action": [
+ "download_from_google_storage",
+ "--no_auth",
+ "--no_resume",
+ "--bucket",
+ "dart-dependencies",
+ "--extract",
+ "-s",
+ Var('dart_root') + "/third_party/pkg/petitparser.tar.gz.sha1",
+ ],
+ },
+ {
+ "name": "7zip",
+ "pattern": ".",
+ "action": [
+ "download_from_google_storage",
+ "--no_auth",
+ "--no_resume",
+ "--bucket",
+ "dart-dependencies",
+ "--platform=win32",
+ "--extract",
+ "-s",
+ Var('dart_root') + "/third_party/7zip.tar.gz.sha1",
+ ],
+ },
+ {
+ "name": "gsutil",
+ "pattern": ".",
+ "action": [
+ "download_from_google_storage",
+ "--no_auth",
+ "--no_resume",
+ "--bucket",
+ "dart-dependencies",
+ "--extract",
+ "-s",
+ Var('dart_root') + "/third_party/gsutil.tar.gz.sha1",
+ ],
+ },
+ {
+ "name": "clang",
+ "pattern": ".",
+ "action": [
+ "download_from_google_storage",
+ "--no_auth",
+ "--no_resume",
+ "--bucket",
+ "dart-dependencies",
+ "--platform=linux*",
+ "--extract",
+ "-s",
+ Var('dart_root') + "/third_party/clang.tar.gz.sha1",
+ ],
+ },
]
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 653d509..8810ff6 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -9,18 +9,12 @@
import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/constants.dart';
-import 'package:analysis_server/src/context_manager.dart';
-import 'package:analysis_server/src/provisional/completion/completion_core.dart'
- show CompletionRequest, CompletionResult;
+import 'package:analysis_server/src/provisional/completion/completion_core.dart';
import 'package:analysis_server/src/services/completion/completion_core.dart';
-import 'package:analysis_server/src/services/completion/completion_manager.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
-export 'package:analysis_server/src/services/completion/completion_manager.dart'
- show CompletionPerformance, CompletionRequest, OperationPerformance;
-
/**
* Instances of the class [CompletionDomainHandler] implement a [RequestHandler]
* that handles requests in the search domain.
@@ -37,27 +31,11 @@
final AnalysisServer server;
/**
- * The [SearchEngine] for this server.
- */
- SearchEngine searchEngine;
-
- /**
* The next completion response id.
*/
int _nextCompletionId = 0;
/**
- * The completion manager for most recent [Source] and [AnalysisContext],
- * or `null` if none.
- */
- CompletionManager _manager;
-
- /**
- * The subscription for the cached context's source change stream.
- */
- StreamSubscription<SourcesChangedEvent> _sourcesChangedSubscription;
-
- /**
* Code completion performance for the last completion operation.
*/
CompletionPerformance performance;
@@ -77,60 +55,44 @@
/**
* Initialize a new request handler for the given [server].
*/
- CompletionDomainHandler(this.server) {
- server.onContextsChanged.listen(contextsChanged);
- server.onPriorityChange.listen(priorityChanged);
- searchEngine = server.searchEngine;
- }
+ CompletionDomainHandler(this.server);
/**
- * Return the completion manager for most recent [Source] and [AnalysisContext],
- * or `null` if none.
+ * Compute completion results for the given reqeust and append them to the stream.
+ * Clients should not call this method directly as it is automatically called
+ * when a client listens to the stream returned by [results].
+ * Subclasses should override this method, append at least one result
+ * to the [controller], and close the controller stream once complete.
*/
- CompletionManager get manager => _manager;
+ Future<CompletionResult> computeSuggestions(
+ CompletionRequestImpl request) async {
+ Iterable<CompletionContributor> newContributors =
+ server.serverPlugin.completionContributors;
+ List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
- /**
- * Return the [CompletionManager] for the given [context] and [source],
- * creating a new manager or returning an existing manager as necessary.
- */
- CompletionManager completionManagerFor(
- AnalysisContext context, Source source) {
- if (_manager != null) {
- if (_manager.context == context && _manager.source == source) {
- return _manager;
- }
- _discardManager();
- }
- _manager = createCompletionManager(server, context, source);
- if (context != null) {
- _sourcesChangedSubscription =
- context.onSourcesChanged.listen(sourcesChanged);
- }
- return _manager;
- }
+ const COMPUTE_SUGGESTIONS_TAG = 'computeSuggestions';
+ performance.logStartTime(COMPUTE_SUGGESTIONS_TAG);
- /**
- * If the context associated with the cache has changed or been removed
- * then discard the cache.
- */
- void contextsChanged(ContextsChangedEvent event) {
- if (_manager != null) {
- AnalysisContext context = _manager.context;
- if (event.changed.contains(context) || event.removed.contains(context)) {
- _discardManager();
- }
+ for (CompletionContributor contributor in newContributors) {
+ String contributorTag = 'computeSuggestions - ${contributor.runtimeType}';
+ performance.logStartTime(contributorTag);
+ suggestions.addAll(await contributor.computeSuggestions(request));
+ performance.logElapseTime(contributorTag);
}
- }
- CompletionManager createCompletionManager(
- AnalysisServer server, AnalysisContext context, Source source) {
- return new CompletionManager.create(context, source, server.searchEngine,
- server.serverPlugin.completionContributors);
+ performance.logElapseTime(COMPUTE_SUGGESTIONS_TAG);
+
+ // TODO (danrubel) if request is obsolete
+ // (processAnalysisRequest returns false)
+ // then send empty results
+
+ return new CompletionResult(
+ request.replacementOffset, request.replacementLength, suggestions);
}
@override
Response handleRequest(Request request) {
- if (searchEngine == null) {
+ if (server.searchEngine == null) {
return new Response.noIndexGenerated(request);
}
return runZoned(() {
@@ -152,34 +114,9 @@
}
/**
- * If the set the priority files has changed, then pre-cache completion
- * information related to the first priority file.
- */
- void priorityChanged(PriorityChangeEvent event) {
- Source source = event.firstSource;
- CompletionPerformance performance = new CompletionPerformance();
- computeCachePerformance = performance;
- if (source == null) {
- performance.complete('priorityChanged caching: no source');
- return;
- }
- performance.source = source;
- AnalysisContext context = server.getAnalysisContextForSource(source);
- if (context != null) {
- String computeTag = 'computeCache';
- performance.logStartTime(computeTag);
- CompletionManager manager = completionManagerFor(context, source);
- manager.computeCache().catchError((_) => false).then((bool success) {
- performance.logElapseTime(computeTag);
- performance.complete('priorityChanged caching: $success');
- });
- }
- }
-
- /**
* Process a `completion.getSuggestions` request.
*/
- Response processRequest(Request request, [CompletionManager manager]) {
+ Response processRequest(Request request) {
performance = new CompletionPerformance();
// extract and validate params
@@ -200,32 +137,32 @@
' but found ${params.offset}');
}
- // schedule completion analysis
recordRequest(performance, context, source, params.offset);
- if (manager == null) {
- manager = completionManagerFor(context, source);
- }
- CompletionRequest completionRequest = new CompletionRequestImpl(context,
- server.resourceProvider, server.searchEngine, source, params.offset);
- int notificationCount = 0;
+
+ CompletionRequest completionRequest = new CompletionRequestImpl(
+ context,
+ server.resourceProvider,
+ server.searchEngine,
+ source,
+ params.offset,
+ performance);
String completionId = (_nextCompletionId++).toString();
- manager.results(completionRequest).listen((CompletionResult result) {
- ++notificationCount;
- bool isLast = result is CompletionResultImpl ? result.isLast : true;
- performance.logElapseTime("notification $notificationCount send", () {
- sendCompletionNotification(completionId, result.replacementOffset,
- result.replacementLength, result.suggestions, isLast);
- });
- if (notificationCount == 1) {
- performance.logFirstNotificationComplete('notification 1 complete');
- performance.suggestionCountFirst = result.suggestions.length;
- }
- if (isLast) {
- performance.notificationCount = notificationCount;
- performance.suggestionCountLast = result.suggestions.length;
- performance.complete();
- }
+
+ // Compute suggestions in the background
+ computeSuggestions(completionRequest).then((CompletionResult result) {
+ const SEND_NOTIFICATION_TAG = 'send notification';
+ performance.logStartTime(SEND_NOTIFICATION_TAG);
+ sendCompletionNotification(completionId, result.replacementOffset,
+ result.replacementLength, result.suggestions);
+ performance.logElapseTime(SEND_NOTIFICATION_TAG);
+
+ performance.notificationCount = 1;
+ performance.logFirstNotificationComplete('notification 1 complete');
+ performance.suggestionCountFirst = result.suggestions.length;
+ performance.suggestionCountLast = result.suggestions.length;
+ performance.complete();
});
+
// initial response without results
return new CompletionGetSuggestionsResult(completionId)
.toResponse(request.id);
@@ -255,51 +192,38 @@
/**
* Send completion notification results.
*/
- void sendCompletionNotification(
- String completionId,
- int replacementOffset,
- int replacementLength,
- Iterable<CompletionSuggestion> results,
- bool isLast) {
+ void sendCompletionNotification(String completionId, int replacementOffset,
+ int replacementLength, Iterable<CompletionSuggestion> results) {
server.sendNotification(new CompletionResultsParams(
- completionId, replacementOffset, replacementLength, results, isLast)
+ completionId, replacementOffset, replacementLength, results, true)
.toNotification());
}
+}
+
+/**
+ * The result of computing suggestions for code completion.
+ */
+class CompletionResult {
+ /**
+ * The length of the text to be replaced if the remainder of the identifier
+ * containing the cursor is to be replaced when the suggestion is applied
+ * (that is, the number of characters in the existing identifier).
+ */
+ final int replacementLength;
/**
- * Discard the cache if a source other than the source referenced by
- * the cache changes or if any source is added, removed, or deleted.
+ * The offset of the start of the text to be replaced. This will be different
+ * than the offset used to request the completion suggestions if there was a
+ * portion of an identifier before the original offset. In particular, the
+ * replacementOffset will be the offset of the beginning of said identifier.
*/
- void sourcesChanged(SourcesChangedEvent event) {
- bool shouldDiscardManager(SourcesChangedEvent event) {
- if (_manager == null) {
- return false;
- }
- if (event.wereSourcesAdded || event.wereSourcesRemovedOrDeleted) {
- return true;
- }
- var changedSources = event.changedSources;
- return changedSources.length > 2 ||
- (changedSources.length == 1 &&
- !changedSources.contains(_manager.source));
- }
-
- if (shouldDiscardManager(event)) {
- _discardManager();
- }
- }
+ final int replacementOffset;
/**
- * Discard the sourcesChanged subscription if any
+ * The suggested completions.
*/
- void _discardManager() {
- if (_sourcesChangedSubscription != null) {
- _sourcesChangedSubscription.cancel();
- _sourcesChangedSubscription = null;
- }
- if (_manager != null) {
- _manager.dispose();
- _manager = null;
- }
- }
+ final List<CompletionSuggestion> suggestions;
+
+ CompletionResult(
+ this.replacementOffset, this.replacementLength, this.suggestions);
}
diff --git a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
index bdebfcc..9a585dd 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
@@ -71,34 +71,3 @@
*/
Source get source;
}
-
-/**
- * The result of computing suggestions for code completion.
- *
- * Clients may implement this class when implementing plugins.
- */
-abstract class CompletionResult {
- /**
- * Return the length of the text to be replaced. This will be zero (0) if the
- * suggestion is to be inserted, otherwise it will be greater than zero. For
- * example, if the remainder of the identifier containing the cursor is to be
- * replaced when the suggestion is applied, in which case the length will be
- * the number of characters in the existing identifier.
- */
- int get replacementLength;
-
- /**
- * Return the offset of the start of the text to be replaced. This will be
- * different than the offset used to request the completion suggestions if
- * there was a portion of text that needs to be replaced. For example, if a
- * partial identifier is immediately before the original offset, in which case
- * the replacementOffset will be the offset of the beginning of the
- * identifier.
- */
- int get replacementOffset;
-
- /**
- * Return the list of suggestions being contributed by the contributor.
- */
- List<CompletionSuggestion> get suggestions;
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_core.dart b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
index 7048a6e..e0635aa 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -5,6 +5,7 @@
library analysis_server.src.services.completion.completion_core;
import 'package:analysis_server/src/provisional/completion/completion_core.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -25,9 +26,9 @@
/**
* The offset of the start of the text to be replaced.
- * This will be different than the offset used to request the completion
+ * This will be different than the [offset] used to request the completion
* suggestions if there was a portion of an identifier before the original
- * offset. In particular, the replacementOffset will be the offset of the
+ * [offset]. In particular, the [replacementOffset] will be the offset of the
* beginning of said identifier.
*/
int replacementOffset;
@@ -36,6 +37,8 @@
* The length of the text to be replaced if the remainder of the identifier
* containing the cursor is to be replaced when the suggestion is applied
* (that is, the number of characters in the existing identifier).
+ * This will be different than the [replacementOffset] - [offset]
+ * if the [offset] is in the middle of an existing identifier.
*/
int replacementLength;
@@ -45,11 +48,13 @@
@override
final SearchEngine searchEngine;
+ final CompletionPerformance performance;
+
/**
* Initialize a newly created completion request based on the given arguments.
*/
CompletionRequestImpl(this.context, this.resourceProvider, this.searchEngine,
- this.source, this.offset) {
+ this.source, this.offset, this.performance) {
replacementOffset = offset;
replacementLength = 0;
}
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/completion_manager.dart
deleted file mode 100644
index 5cb8bab..0000000
--- a/pkg/analysis_server/lib/src/services/completion/completion_manager.dart
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library services.completion.manager;
-
-import 'dart:async';
-
-import 'package:analysis_server/plugin/protocol/protocol.dart';
-import 'package:analysis_server/src/provisional/completion/completion_core.dart'
- show CompletionContributor, CompletionContributorFactory, CompletionRequest, CompletionResult;
-import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-/**
- * Manages completion contributors for a given completion request.
- */
-abstract class CompletionManager {
- /**
- * The context in which the completion was computed.
- */
- final AnalysisContext context;
-
- /**
- * The source in which the completion was computed.
- */
- final Source source;
-
- /**
- * The controller used for returning completion results.
- */
- StreamController<CompletionResult> controller;
-
- CompletionManager(this.context, this.source);
-
- /**
- * Create a manager for the given request.
- */
- factory CompletionManager.create(
- AnalysisContext context,
- Source source,
- SearchEngine searchEngine,
- Iterable<CompletionContributor> newContributors) {
- if (context != null) {
- if (AnalysisEngine.isDartFileName(source.shortName)) {
- return new DartCompletionManager.create(
- context, searchEngine, source, newContributors);
- }
- }
- return new NoOpCompletionManager(source);
- }
-
- /**
- * Compute and cache information in preparation for a possible code
- * completion request sometime in the future. The default implementation
- * of this method does nothing. Subclasses may override but should not
- * count on this method being called before [computeSuggestions].
- * Return a future that completes when the cache is computed with a bool
- * indicating success.
- */
- Future<bool> computeCache() {
- return new Future.value(true);
- }
-
- /**
- * Compute completion results for the given reqeust and append them to the stream.
- * Clients should not call this method directly as it is automatically called
- * when a client listens to the stream returned by [results].
- * Subclasses should override this method, append at least one result
- * to the [controller], and close the controller stream once complete.
- */
- void computeSuggestions(CompletionRequest request);
-
- /**
- * Discard any pending operations.
- * Subclasses may override but should call super.dispose
- */
- void dispose() {}
-
- /**
- * Generate a stream of code completion results.
- */
- Stream<CompletionResult> results(CompletionRequest request) {
- controller = new StreamController<CompletionResult>(onListen: () {
- scheduleMicrotask(() {
- computeSuggestions(request);
- });
- });
- return controller.stream;
- }
-}
-
-/**
- * Overall performance of a code completion operation.
- */
-class CompletionPerformance {
- final DateTime start = new DateTime.now();
- final Map<String, Duration> _startTimes = new Map<String, Duration>();
- final Stopwatch _stopwatch = new Stopwatch();
- final List<OperationPerformance> operations = <OperationPerformance>[];
-
- Source source;
- String snippet = '';
- int notificationCount = -1;
- int suggestionCountFirst = -1;
- int suggestionCountLast = -1;
- Duration _firstNotification;
-
- CompletionPerformance() {
- _stopwatch.start();
- }
-
- int get elapsedInMilliseconds =>
- operations.length > 0 ? operations.last.elapsed.inMilliseconds : 0;
-
- int get firstNotificationInMilliseconds =>
- _firstNotification != null ? _firstNotification.inMilliseconds : 0;
-
- String get startTimeAndMs => '${start.millisecondsSinceEpoch} - $start';
-
- String get suggestionCount {
- if (notificationCount < 1) return '';
- if (notificationCount == 1) return '$suggestionCountFirst';
- return '$suggestionCountFirst, $suggestionCountLast';
- }
-
- void complete([String tag = null]) {
- _stopwatch.stop();
- _logDuration(tag != null ? tag : 'total time', _stopwatch.elapsed);
- }
-
- logElapseTime(String tag, [f() = null]) {
- Duration start;
- Duration end = _stopwatch.elapsed;
- var result;
- if (f == null) {
- start = _startTimes[tag];
- if (start == null) {
- _logDuration(tag, null);
- return null;
- }
- } else {
- result = f();
- start = end;
- end = _stopwatch.elapsed;
- }
- _logDuration(tag, end - start);
- return result;
- }
-
- void logFirstNotificationComplete(String tag) {
- _firstNotification = _stopwatch.elapsed;
- _logDuration(tag, _firstNotification);
- }
-
- void logStartTime(String tag) {
- _startTimes[tag] = _stopwatch.elapsed;
- }
-
- void setContentsAndOffset(String contents, int offset) {
- snippet = _computeSnippet(contents, offset);
- }
-
- void _logDuration(String tag, Duration elapsed) {
- operations.add(new OperationPerformance(tag, elapsed));
- }
-
- static String _computeSnippet(String contents, int offset) {
- if (contents == null ||
- offset == null ||
- offset < 0 ||
- contents.length < offset) {
- return '???';
- }
- int start = offset;
- while (start > 0) {
- String ch = contents[start - 1];
- if (ch == '\r' || ch == '\n') {
- break;
- }
- --start;
- }
- int end = offset;
- while (end < contents.length) {
- String ch = contents[end];
- if (ch == '\r' || ch == '\n') {
- break;
- }
- ++end;
- }
- String prefix = contents.substring(start, offset);
- String suffix = contents.substring(offset, end);
- return '$prefix^$suffix';
- }
-}
-
-/**
- * Code completion result generated by an [CompletionManager].
- */
-class CompletionResultImpl implements CompletionResult {
- /**
- * The length of the text to be replaced if the remainder of the identifier
- * containing the cursor is to be replaced when the suggestion is applied
- * (that is, the number of characters in the existing identifier).
- */
- final int replacementLength;
-
- /**
- * The offset of the start of the text to be replaced. This will be different
- * than the offset used to request the completion suggestions if there was a
- * portion of an identifier before the original offset. In particular, the
- * replacementOffset will be the offset of the beginning of said identifier.
- */
- final int replacementOffset;
-
- /**
- * The suggested completions.
- */
- final List<CompletionSuggestion> suggestions;
-
- /**
- * `true` if this is that last set of results that will be returned
- * for the indicated completion.
- */
- final bool last;
-
- CompletionResultImpl(this.replacementOffset, this.replacementLength,
- this.suggestions, this.last);
-
- /**
- * Return `true` if this is the last completion result that will be produced.
- */
- bool get isLast => last;
-}
-
-class NoOpCompletionManager extends CompletionManager {
- NoOpCompletionManager(Source source) : super(null, source);
-
- @override
- void computeSuggestions(CompletionRequest request) {
- controller.add(new CompletionResultImpl(request.offset, 0, [], true));
- }
-}
-
-/**
- * The performance of an operation when computing code completion.
- */
-class OperationPerformance {
- /**
- * The name of the operation
- */
- final String name;
-
- /**
- * The elapse time or `null` if undefined.
- */
- final Duration elapsed;
-
- OperationPerformance(this.name, this.elapsed);
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
new file mode 100644
index 0000000..0272fb8
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library services.completion.manager;
+
+import 'package:analyzer/src/generated/source.dart';
+
+/**
+ * Overall performance of a code completion operation.
+ */
+class CompletionPerformance {
+ final DateTime start = new DateTime.now();
+ final Map<String, Duration> _startTimes = new Map<String, Duration>();
+ final Stopwatch _stopwatch = new Stopwatch();
+ final List<OperationPerformance> operations = <OperationPerformance>[];
+
+ Source source;
+ String snippet = '';
+ int notificationCount = -1;
+ int suggestionCountFirst = -1;
+ int suggestionCountLast = -1;
+ Duration _firstNotification;
+
+ CompletionPerformance() {
+ _stopwatch.start();
+ }
+
+ int get elapsedInMilliseconds =>
+ operations.length > 0 ? operations.last.elapsed.inMilliseconds : 0;
+
+ int get firstNotificationInMilliseconds =>
+ _firstNotification != null ? _firstNotification.inMilliseconds : 0;
+
+ String get startTimeAndMs => '${start.millisecondsSinceEpoch} - $start';
+
+ String get suggestionCount {
+ if (notificationCount < 1) return '';
+ if (notificationCount == 1) return '$suggestionCountFirst';
+ return '$suggestionCountFirst, $suggestionCountLast';
+ }
+
+ void complete([String tag = null]) {
+ _stopwatch.stop();
+ _logDuration(tag != null ? tag : 'total time', _stopwatch.elapsed);
+ }
+
+ void logElapseTime(String tag) {
+ Duration end = _stopwatch.elapsed;
+ Duration start = _startTimes[tag];
+ if (start == null) {
+ _logDuration(tag, null);
+ return null;
+ }
+ _logDuration(tag, end - start);
+ }
+
+ void logFirstNotificationComplete(String tag) {
+ _firstNotification = _stopwatch.elapsed;
+ _logDuration(tag, _firstNotification);
+ }
+
+ void logStartTime(String tag) {
+ _startTimes[tag] = _stopwatch.elapsed;
+ }
+
+ void setContentsAndOffset(String contents, int offset) {
+ snippet = _computeSnippet(contents, offset);
+ }
+
+ void _logDuration(String tag, Duration elapsed) {
+ operations.add(new OperationPerformance(tag, elapsed));
+ }
+
+ static String _computeSnippet(String contents, int offset) {
+ if (contents == null ||
+ offset == null ||
+ offset < 0 ||
+ contents.length < offset) {
+ return '???';
+ }
+ int start = offset;
+ while (start > 0) {
+ String ch = contents[start - 1];
+ if (ch == '\r' || ch == '\n') {
+ break;
+ }
+ --start;
+ }
+ int end = offset;
+ while (end < contents.length) {
+ String ch = contents[end];
+ if (ch == '\r' || ch == '\n') {
+ break;
+ }
+ ++end;
+ }
+ String prefix = contents.substring(start, offset);
+ String suffix = contents.substring(offset, end);
+ return '$prefix^$suffix';
+ }
+}
+
+/**
+ * The performance of an operation when computing code completion.
+ */
+class OperationPerformance {
+ /**
+ * The name of the operation
+ */
+ final String name;
+
+ /**
+ * The elapse time or `null` if undefined.
+ */
+ final Duration elapsed;
+
+ OperationPerformance(this.name, this.elapsed);
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 2289a92..cfe0ca7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -13,7 +13,10 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_plugin.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
import 'package:analysis_server/src/services/completion/completion_core.dart';
-import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
+import 'package:analysis_server/src/services/completion/dart/common_usage_sorter.dart';
+import 'package:analysis_server/src/services/completion/dart/contribution_sorter.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -22,12 +25,10 @@
show AnalysisFutureHelper, AnalysisContextImpl;
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl;
+import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/task/dart.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-import 'package:analysis_server/src/services/completion/dart/contribution_sorter.dart';
-import 'package:analysis_server/src/services/completion/dart/common_usage_sorter.dart';
/**
* [DartCompletionManager] determines if a completion request is Dart specific
@@ -47,26 +48,36 @@
return EMPTY_LIST;
}
+ CompletionPerformance performance =
+ (request as CompletionRequestImpl).performance;
+ const BUILD_REQUEST_TAG = 'build DartCompletionRequestImpl';
+ performance.logStartTime(BUILD_REQUEST_TAG);
DartCompletionRequestImpl dartRequest =
await DartCompletionRequestImpl.from(request);
- ReplacementRange range =
- new ReplacementRange.compute(dartRequest.offset, dartRequest.target);
- (request as CompletionRequestImpl)
- ..replacementOffset = range.offset
- ..replacementLength = range.length;
+ performance.logElapseTime(BUILD_REQUEST_TAG);
// Don't suggest in comments.
if (dartRequest.target.isCommentText) {
return EMPTY_LIST;
}
+ ReplacementRange range =
+ new ReplacementRange.compute(dartRequest.offset, dartRequest.target);
+ (request as CompletionRequestImpl)
+ ..replacementOffset = range.offset
+ ..replacementLength = range.length;
+
// Request Dart specific completions from each contributor
Map<String, CompletionSuggestion> suggestionMap =
<String, CompletionSuggestion>{};
for (DartCompletionContributor contributor
in dartCompletionPlugin.contributors) {
+ String contributorTag =
+ 'DartCompletionManager - ${contributor.runtimeType}';
+ performance.logStartTime(contributorTag);
List<CompletionSuggestion> contributorSuggestions =
await contributor.computeSuggestions(dartRequest);
+ performance.logElapseTime(contributorTag);
for (CompletionSuggestion newSuggestion in contributorSuggestions) {
var oldSuggestion = suggestionMap.putIfAbsent(
@@ -80,7 +91,10 @@
// Adjust suggestion relevance before returning
List<CompletionSuggestion> suggestions = suggestionMap.values.toList();
+ const SORT_TAG = 'DartCompletionManager - sort';
+ performance.logStartTime(SORT_TAG);
await contributionSorter.sort(dartRequest, suggestions);
+ performance.logElapseTime(SORT_TAG);
return suggestions;
}
}
@@ -88,8 +102,31 @@
/**
* The information about a requested list of completions within a Dart file.
*/
-class DartCompletionRequestImpl extends CompletionRequestImpl
- implements DartCompletionRequest {
+class DartCompletionRequestImpl implements DartCompletionRequest {
+ @override
+ final AnalysisContext context;
+
+ @override
+ final Source source;
+
+ @override
+ final int offset;
+
+ @override
+ Expression dotTarget;
+
+ @override
+ Source librarySource;
+
+ @override
+ final ResourceProvider resourceProvider;
+
+ @override
+ final SearchEngine searchEngine;
+
+ @override
+ CompletionTarget target;
+
/**
* The [LibraryElement] representing dart:core
*/
@@ -100,26 +137,19 @@
*/
InterfaceType _objectType;
- @override
- Expression dotTarget;
-
- @override
- Source librarySource;
-
OpType _opType;
- @override
- CompletionTarget target;
+ final CompletionPerformance performance;
DartCompletionRequestImpl._(
- AnalysisContext context,
- ResourceProvider resourceProvider,
- SearchEngine searchEngine,
+ this.context,
+ this.resourceProvider,
+ this.searchEngine,
this.librarySource,
- Source source,
- int offset,
- CompilationUnit unit)
- : super(context, resourceProvider, searchEngine, source, offset) {
+ this.source,
+ this.offset,
+ CompilationUnit unit,
+ this.performance) {
_updateTargets(unit);
}
@@ -178,11 +208,14 @@
libUnit = target.unit;
} else if (librarySource != null) {
// TODO(danrubel) only resolve the directives
+ const RESOLVE_DIRECTIVES_TAG = 'resolve directives';
+ performance.logStartTime(RESOLVE_DIRECTIVES_TAG);
libUnit = await new AnalysisFutureHelper<CompilationUnit>(
context,
new LibrarySpecificUnit(librarySource, librarySource),
RESOLVED_UNIT3)
.computeAsync();
+ performance.logElapseTime(RESOLVE_DIRECTIVES_TAG);
}
return libUnit?.directives;
}
@@ -202,10 +235,13 @@
// Resolve declarations in the target unit
// TODO(danrubel) resolve the expression or containing method
// rather than the entire complilation unit
+ const RESOLVE_EXPRESSION_TAG = 'resolve expression';
+ performance.logStartTime(RESOLVE_EXPRESSION_TAG);
CompilationUnit resolvedUnit =
await new AnalysisFutureHelper<CompilationUnit>(context,
new LibrarySpecificUnit(librarySource, source), RESOLVED_UNIT)
.computeAsync();
+ performance.logElapseTime(RESOLVE_EXPRESSION_TAG);
// TODO(danrubel) determine if the underlying source has been modified
// in a way that invalidates the completion request
@@ -254,9 +290,18 @@
* based on the given [request].
*/
static Future<DartCompletionRequest> from(CompletionRequest request) async {
+ CompletionPerformance performance =
+ (request as CompletionRequestImpl).performance;
+ const BUILD_REQUEST_TAG = 'build DartCompletionRequest';
+ performance.logStartTime(BUILD_REQUEST_TAG);
+
Source source = request.source;
AnalysisContext context = request.context;
+
+ const PARSE_TAG = 'parse unit';
+ performance.logStartTime(PARSE_TAG);
CompilationUnit unit = request.context.computeResult(source, PARSED_UNIT);
+ performance.logElapseTime(PARSE_TAG);
Source libSource;
if (unit.directives.any((d) => d is PartOfDirective)) {
@@ -270,9 +315,12 @@
// Most (all?) contributors need declarations in scope to be resolved
if (libSource != null) {
+ const RESOLVE_DECLARATIONS_TAG = 'resolve declarations';
+ performance.logStartTime(RESOLVE_DECLARATIONS_TAG);
unit = await new AnalysisFutureHelper<CompilationUnit>(context,
new LibrarySpecificUnit(libSource, source), RESOLVED_UNIT3)
.computeAsync();
+ performance.logElapseTime(RESOLVE_DECLARATIONS_TAG);
}
DartCompletionRequestImpl dartRequest = new DartCompletionRequestImpl._(
@@ -282,7 +330,8 @@
libSource,
request.source,
request.offset,
- unit);
+ unit,
+ performance);
// Resolve the expression in which the completion occurs
// to properly determine if identifiers should be suggested
@@ -290,10 +339,14 @@
if (dartRequest.target.maybeFunctionalArgument()) {
AstNode node = dartRequest.target.containingNode.parent;
if (node is Expression) {
+ const FUNCTIONAL_ARG_TAG = 'resolve expression for isFunctionalArg';
+ performance.logStartTime(FUNCTIONAL_ARG_TAG);
await dartRequest.resolveExpression(node);
+ performance.logElapseTime(FUNCTIONAL_ARG_TAG);
}
}
+ performance.logElapseTime(BUILD_REQUEST_TAG);
return dartRequest;
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
index e25dc18..736f2a0 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
@@ -9,7 +9,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
-import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
index 40f0af7..bf1633e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
@@ -9,8 +9,8 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analysis_server/src/services/completion/optype.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
index 296f03b..014d4ee 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
@@ -13,7 +13,7 @@
show DartCompletionRequestImpl;
import 'package:analysis_server/src/services/completion/dart/local_declaration_visitor.dart'
show LocalDeclarationVisitor;
-import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
index 9b4bca9..d8d4e36 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
@@ -13,8 +13,8 @@
show DartCompletionRequestImpl;
import 'package:analysis_server/src/services/completion/dart/local_declaration_visitor.dart'
show LocalDeclarationVisitor;
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analysis_server/src/services/completion/optype.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/scanner.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index 02878a0..9469154 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -8,9 +8,9 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart'
show createSuggestion, ElementSuggestionBuilder;
-import 'package:analysis_server/src/services/completion/optype.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
index 4fb7c97..966f1d9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -13,7 +13,7 @@
show DartCompletionRequestImpl;
import 'package:analysis_server/src/services/completion/dart/local_declaration_visitor.dart'
show LocalDeclarationVisitor;
-import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
import 'package:analysis_server/src/services/correction/strings.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/scanner.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/optype.dart b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
similarity index 100%
rename from pkg/analysis_server/lib/src/services/completion/optype.dart
rename to pkg/analysis_server/lib/src/services/completion/dart/optype.dart
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
deleted file mode 100644
index 92bd9b0..0000000
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library services.completion.dart;
-
-import 'dart:async';
-
-import 'package:analysis_server/plugin/protocol/protocol.dart';
-import 'package:analysis_server/src/provisional/completion/completion_core.dart'
- show AnalysisRequest, CompletionContributor, CompletionRequest;
-import 'package:analysis_server/src/services/completion/completion_core.dart';
-import 'package:analysis_server/src/services/completion/completion_manager.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-/**
- * The base class for contributing code completion suggestions.
- */
-abstract class DartCompletionContributor {
- /**
- * Computes the initial set of [CompletionSuggestion]s based on
- * the given completion context. The compilation unit and completion node
- * in the given completion context may not be resolved.
- * This method should execute quickly and not block waiting for any analysis.
- * Returns `true` if the contributor's work is complete
- * or `false` if [computeFull] should be called to complete the work.
- */
- bool computeFast(DartCompletionRequest request);
-
- /**
- * Computes the complete set of [CompletionSuggestion]s based on
- * the given completion context. The compilation unit and completion node
- * in the given completion context are resolved.
- * Returns `true` if the receiver modified the list of suggestions.
- */
- Future<bool> computeFull(DartCompletionRequest request);
-}
-
-/**
- * Manages code completion for a given Dart file completion request.
- */
-class DartCompletionManager extends CompletionManager {
- final SearchEngine searchEngine;
- Iterable<CompletionContributor> newContributors;
-
- DartCompletionManager(
- AnalysisContext context, this.searchEngine, Source source,
- [this.newContributors])
- : super(context, source) {
- if (newContributors == null) {
- newContributors = <CompletionContributor>[];
- }
- }
-
- /**
- * Create a new initialized Dart source completion manager
- */
- factory DartCompletionManager.create(
- AnalysisContext context,
- SearchEngine searchEngine,
- Source source,
- Iterable<CompletionContributor> newContributors) {
- return new DartCompletionManager(
- context, searchEngine, source, newContributors);
- }
-
- /**
- * Compute suggestions based upon cached information only
- * then send an initial response to the client.
- * Return a list of contributors for which [computeFull] should be called
- */
- List<DartCompletionContributor> computeFast(
- DartCompletionRequest request, CompletionPerformance performance) {
- return [];
- }
-
- /**
- * If there is remaining work to be done, then wait for the unit to be
- * resolved and request that each remaining contributor finish their work.
- * Return a [Future] that completes when the last notification has been sent.
- */
- Future computeFull(
- DartCompletionRequest request,
- CompletionPerformance performance,
- List<DartCompletionContributor> todo) async {
- // Compute suggestions using the new API
- performance.logStartTime('computeSuggestions');
- for (CompletionContributor contributor in newContributors) {
- String contributorTag = 'computeSuggestions - ${contributor.runtimeType}';
- performance.logStartTime(contributorTag);
- List<CompletionSuggestion> newSuggestions =
- await contributor.computeSuggestions(request);
- for (CompletionSuggestion suggestion in newSuggestions) {
- request.addSuggestion(suggestion);
- }
- performance.logElapseTime(contributorTag);
- }
- performance.logElapseTime('computeSuggestions');
- performance.logStartTime('waitForAnalysis');
-
- // TODO (danrubel) if request is obsolete
- // (processAnalysisRequest returns false)
- // then send empty results
- sendResults(request, true);
- return new Future.value();
- }
-
- @override
- void computeSuggestions(CompletionRequest completionRequest) {
- DartCompletionRequest request =
- new DartCompletionRequest.from(completionRequest);
- CompletionPerformance performance = new CompletionPerformance();
- performance.logElapseTime('compute', () {
- List<DartCompletionContributor> todo = computeFast(request, performance);
- computeFull(request, performance, todo);
- });
- }
-
- /**
- * Send the current list of suggestions to the client.
- */
- void sendResults(DartCompletionRequest request, bool last) {
- if (controller == null || controller.isClosed) {
- return;
- }
- controller.add(new CompletionResultImpl(request.replacementOffset,
- request.replacementLength, request.suggestions, last));
- if (last) {
- controller.close();
- }
- }
-
- /**
- * Return a future that either (a) completes with the resolved compilation
- * unit when analysis is complete, or (b) completes with null if the
- * compilation unit is never going to be resolved.
- */
- Future<CompilationUnit> waitForAnalysis() {
- List<Source> libraries = context.getLibrariesContaining(source);
- assert(libraries != null);
- if (libraries.length == 0) {
- return new Future.value(null);
- }
- Source libSource = libraries[0];
- assert(libSource != null);
- return context
- .computeResolvedCompilationUnitAsync(source, libSource)
- .catchError((_) {
- // This source file is not scheduled for analysis, so a resolved
- // compilation unit is never going to get computed.
- return null;
- }, test: (e) => e is AnalysisNotScheduledError);
- }
-}
-
-/**
- * The context in which the completion is requested.
- */
-class DartCompletionRequest extends CompletionRequestImpl {
- /**
- * The list of suggestions to be sent to the client.
- */
- final List<CompletionSuggestion> _suggestions = <CompletionSuggestion>[];
-
- /**
- * The set of completions used to prevent duplicates
- */
- final Set<String> _completions = new Set<String>();
-
- DartCompletionRequest(
- AnalysisContext context,
- ResourceProvider resourceProvider,
- SearchEngine searchEngine,
- Source source,
- int offset)
- : super(context, resourceProvider, searchEngine, source, offset);
-
- factory DartCompletionRequest.from(CompletionRequestImpl request) =>
- new DartCompletionRequest(request.context, request.resourceProvider,
- request.searchEngine, request.source, request.offset);
-
- /**
- * The list of suggestions to be sent to the client.
- */
- Iterable<CompletionSuggestion> get suggestions => _suggestions;
-
- /**
- * Add the given suggestion to the list that is returned to the client as long
- * as a suggestion with an identical completion has not already been added.
- */
- void addSuggestion(CompletionSuggestion suggestion) {
- if (_completions.add(suggestion.completion)) {
- _suggestions.add(suggestion);
- }
- }
-}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index a9c4918..7525b74f 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -169,6 +169,8 @@
const FixKind('MAKE_CLASS_ABSTRACT', 50, "Make class '{0}' abstract");
static const REMOVE_DEAD_CODE =
const FixKind('REMOVE_DEAD_CODE', 50, "Remove dead code");
+ static const MAKE_FIELD_NOT_FINAL =
+ const FixKind('MAKE_FIELD_NOT_FINAL', 50, "Make field '{0}' not final");
static const REMOVE_PARAMETERS_IN_GETTER_DECLARATION = const FixKind(
'REMOVE_PARAMETERS_IN_GETTER_DECLARATION',
50,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 50d437c..fa16435 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -230,6 +230,9 @@
if (errorCode == ParserErrorCode.VAR_AS_TYPE_NAME) {
_addFix_replaceVarWithDynamic();
}
+ if (errorCode == StaticWarningCode.ASSIGNMENT_TO_FINAL) {
+ _addFix_makeFieldNotFinal();
+ }
if (errorCode == StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER) {
_addFix_makeEnclosingClassAbstract();
}
@@ -1590,6 +1593,41 @@
_addFix(DartFixKind.MAKE_CLASS_ABSTRACT, [className]);
}
+ void _addFix_makeFieldNotFinal() {
+ AstNode node = this.node;
+ if (node is SimpleIdentifier &&
+ node.bestElement is PropertyAccessorElement) {
+ PropertyAccessorElement getter = node.bestElement;
+ if (getter.isGetter &&
+ getter.isSynthetic &&
+ !getter.variable.isSynthetic &&
+ getter.variable.setter == null &&
+ getter.enclosingElement is ClassElement) {
+ AstNode variable = getter.variable.computeNode();
+ if (variable is VariableDeclaration &&
+ variable.parent is VariableDeclarationList &&
+ variable.parent.parent is FieldDeclaration) {
+ VariableDeclarationList declarationList = variable.parent;
+ Token keywordToken = declarationList.keyword;
+ if (declarationList.variables.length == 1 &&
+ keywordToken is KeywordToken &&
+ keywordToken.keyword == Keyword.FINAL) {
+ if (declarationList.type != null) {
+ SourceRange range =
+ rf.rangeStartStart(keywordToken, declarationList.type);
+ _addRemoveEdit(range);
+ } else {
+ SourceRange range = rf.rangeStartStart(keywordToken, variable);
+ _addReplaceEdit(range, 'var ');
+ }
+ String fieldName = getter.variable.displayName;
+ _addFix(DartFixKind.MAKE_FIELD_NOT_FINAL, [fieldName]);
+ }
+ }
+ }
+ }
+ }
+
void _addFix_nonBoolCondition_addNotNull() {
_addInsertEdit(error.offset + error.length, ' != null');
_addFix(DartFixKind.ADD_NE_NULL, []);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
index ca90fd2..a17bfda 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -230,10 +230,30 @@
new NodeLocator(selectionRange.offset, selectionRange.end)
.searchWithin(unit);
// compute covering expressions
- for (AstNode node = coveringNode;
- node is Expression || node is ArgumentList;
- node = node.parent) {
+ for (AstNode node = coveringNode; node != null; node = node.parent) {
AstNode parent = node.parent;
+ // skip some nodes
+ if (node is ArgumentList ||
+ node is AssignmentExpression ||
+ node is NamedExpression ||
+ node is TypeArgumentList) {
+ continue;
+ }
+ if (node is ConstructorName || node is Label || node is TypeName) {
+ rootExpression = null;
+ coveringExpressionOffsets.clear();
+ coveringExpressionLengths.clear();
+ continue;
+ }
+ // cannot extract the name part of a property access
+ if (parent is PrefixedIdentifier && parent.identifier == node ||
+ parent is PropertyAccess && parent.propertyName == node) {
+ continue;
+ }
+ // stop if not an Expression
+ if (node is! Expression) {
+ break;
+ }
// stop at void method invocations
if (node is MethodInvocation) {
MethodInvocation invocation = node;
@@ -249,19 +269,6 @@
break;
}
}
- // skip ArgumentList
- if (node is ArgumentList) {
- continue;
- }
- // skip AssignmentExpression
- if (node is AssignmentExpression) {
- continue;
- }
- // cannot extract the name part of a property access
- if (parent is PrefixedIdentifier && parent.identifier == node ||
- parent is PropertyAccess && parent.propertyName == node) {
- continue;
- }
// fatal selection problems
if (coveringExpressionOffsets.isEmpty) {
if (node is SimpleIdentifier) {
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index 360ad0d..0f4fc15 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -18,6 +18,7 @@
import 'package:analysis_server/src/operation/operation.dart';
import 'package:analysis_server/src/operation/operation_analysis.dart';
import 'package:analysis_server/src/operation/operation_queue.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
import 'package:analysis_server/src/services/index/index.dart';
import 'package:analysis_server/src/services/index/local_index.dart';
import 'package:analysis_server/src/services/index/store/split_store.dart';
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index e9a1663..14d9fd6 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -337,7 +337,7 @@
channel.notificationsReceived.clear();
server.updateContent(
'0', {bar.path: new AddContentOverlay('library bar; void f() {}')});
- await pumpEventQueue(500);
+ await pumpEventQueue(1000);
expect(server.statusAnalyzing, isFalse);
expect(channel.notificationsReceived, isNotEmpty);
Set<String> notificationTypesReceived = new Set<String>();
diff --git a/pkg/analysis_server/test/completion_test_support.dart b/pkg/analysis_server/test/completion_test_support.dart
index 0f00d1e..c2fb7a1 100644
--- a/pkg/analysis_server/test/completion_test_support.dart
+++ b/pkg/analysis_server/test/completion_test_support.dart
@@ -16,7 +16,7 @@
/**
* A base class for classes containing completion tests.
*/
-class CompletionTestCase extends CompletionTest {
+class CompletionTestCase extends CompletionDomainHandlerTest {
static const String CURSOR_MARKER = '!';
List get suggestedCompletions => suggestions
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index a3e956a..acff007 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -7,277 +7,26 @@
import 'dart:async';
import 'package:analysis_server/plugin/protocol/protocol.dart';
-import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/channel/channel.dart';
-import 'package:analysis_server/src/constants.dart';
-import 'package:analysis_server/src/context_manager.dart';
-import 'package:analysis_server/src/domain_analysis.dart';
import 'package:analysis_server/src/domain_completion.dart';
-import 'package:analysis_server/src/plugin/server_plugin.dart';
-import 'package:analysis_server/src/provisional/completion/completion_core.dart'
- show AnalysisRequest, CompletionRequest, CompletionResult;
+import 'package:analysis_server/src/provisional/completion/completion_core.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
-import 'package:analysis_server/src/services/completion/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart/contribution_sorter.dart';
-import 'package:analysis_server/src/services/index/index.dart' show Index;
-import 'package:analysis_server/src/services/index/local_memory_index.dart';
-import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/source/pub_package_map_provider.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:unittest/unittest.dart';
import 'analysis_abstract.dart';
import 'domain_completion_util.dart';
-import 'mock_sdk.dart';
-import 'mocks.dart';
import 'utils.dart';
main() {
initializeTestEnvironment();
- defineReflectiveTests(CompletionManagerTest);
- defineReflectiveTests(CompletionTest);
+ defineReflectiveTests(CompletionDomainHandlerTest);
defineReflectiveTests(_NoSearchEngine);
}
@reflectiveTest
-class CompletionManagerTest extends AbstractAnalysisTest {
- AnalysisDomainHandler analysisDomain;
- Test_CompletionDomainHandler completionDomain;
- Request request;
- int requestCount = 0;
- String testFile2 = '/project/bin/test2.dart';
-
- AnalysisServer createAnalysisServer(Index index) {
- //
- // Collect plugins
- //
- ServerPlugin serverPlugin = new ServerPlugin();
- List<Plugin> plugins = <Plugin>[];
- plugins.addAll(AnalysisEngine.instance.requiredPlugins);
- plugins.add(serverPlugin);
- addServerPlugins(plugins);
- //
- // Process plugins
- //
- ExtensionManager manager = new ExtensionManager();
- manager.processPlugins(plugins);
- //
- // Create the server
- //
- return new Test_AnalysisServer(
- super.serverChannel,
- super.resourceProvider,
- super.packageMapProvider,
- index,
- serverPlugin,
- new AnalysisServerOptions(),
- new MockSdk(),
- InstrumentationService.NULL_SERVICE);
- }
-
- @override
- Index createIndex() {
- return createLocalMemoryIndex();
- }
-
- void sendRequest(String path) {
- String id = (++requestCount).toString();
- request = new CompletionGetSuggestionsParams(path, 0).toRequest(id);
- Response response = handler.handleRequest(request);
- expect(response, isResponseSuccess(id));
- }
-
- @override
- void setUp() {
- super.setUp();
- createProject();
- analysisDomain = handler;
- completionDomain = new Test_CompletionDomainHandler(server);
- handler = completionDomain;
- addTestFile('^library A; cl');
- addFile(testFile2, 'library B; cl');
- }
-
- void tearDown() {
- super.tearDown();
- analysisDomain = null;
- completionDomain = null;
- }
-
- /**
- * Assert different managers are used for different sources
- */
- test_2_requests_different_sources() {
- expect(completionDomain.manager, isNull);
- sendRequest(testFile);
- expect(completionDomain.manager, isNotNull);
- MockCompletionManager expectedManager = completionDomain.manager;
- expect(expectedManager.disposeCallCount, 0);
- expect(completionDomain.mockContext.mockStream.listenCount, 1);
- expect(completionDomain.mockContext.mockStream.cancelCount, 0);
- return pumpEventQueue().then((_) {
- expect(completionDomain.manager, expectedManager);
- expect(completionDomain.mockManager.computeCallCount, 1);
- sendRequest(testFile2);
- expect(completionDomain.manager, isNotNull);
- expect(completionDomain.manager, isNot(expectedManager));
- expect(expectedManager.disposeCallCount, 1);
- expectedManager = completionDomain.manager;
- expect(completionDomain.mockContext.mockStream.listenCount, 2);
- expect(completionDomain.mockContext.mockStream.cancelCount, 1);
- return pumpEventQueue();
- }).then((_) {
- expect(completionDomain.manager, expectedManager);
- expect(completionDomain.mockContext.mockStream.listenCount, 2);
- expect(completionDomain.mockContext.mockStream.cancelCount, 1);
- expect(completionDomain.mockManager.computeCallCount, 1);
- });
- }
-
- /**
- * Assert same manager is used for multiple requests on same source
- */
- test_2_requests_same_source() {
- expect(completionDomain.manager, isNull);
- sendRequest(testFile);
- expect(completionDomain.manager, isNotNull);
- expect(completionDomain.manager.source, isNotNull);
- CompletionManager expectedManager = completionDomain.manager;
- expect(completionDomain.mockContext.mockStream.listenCount, 1);
- expect(completionDomain.mockContext.mockStream.cancelCount, 0);
- return pumpEventQueue().then((_) {
- expect(completionDomain.manager, expectedManager);
- expect(completionDomain.mockManager.computeCallCount, 1);
- sendRequest(testFile);
- expect(completionDomain.manager, expectedManager);
- expect(completionDomain.mockContext.mockStream.listenCount, 1);
- expect(completionDomain.mockContext.mockStream.cancelCount, 0);
- return pumpEventQueue();
- }).then((_) {
- expect(completionDomain.manager, expectedManager);
- expect(completionDomain.mockContext.mockStream.listenCount, 1);
- expect(completionDomain.mockContext.mockStream.cancelCount, 0);
- expect(completionDomain.mockManager.computeCallCount, 2);
- });
- }
-
- /**
- * Assert manager is NOT cleared when context NOT associated with manager changes.
- */
- test_contextsChanged_different() {
- sendRequest(testFile);
- CompletionManager expectedManager;
- return pumpEventQueue().then((_) {
- expect(completionDomain.manager, isNotNull);
- expectedManager = completionDomain.manager;
- completionDomain.contextsChangedRaw(
- new ContextsChangedEvent(changed: [new MockContext()]));
- return pumpEventQueue();
- }).then((_) {
- expect(completionDomain.manager, expectedManager);
- });
- }
-
- /**
- * Assert manager is cleared when context associated with manager changes.
- */
- test_contextsChanged_same() {
- sendRequest(testFile);
- return pumpEventQueue().then((_) {
- expect(completionDomain.manager, isNotNull);
- completionDomain.contextsChangedRaw(
- new ContextsChangedEvent(changed: [completionDomain.mockContext]));
- return pumpEventQueue();
- }).then((_) {
- expect(completionDomain.manager, isNull);
- });
- }
-
- /**
- * Assert manager is cleared when analysis roots are set
- */
- test_setAnalysisRoots() {
- sendRequest(testFile);
- return pumpEventQueue().then((_) {
- expect(completionDomain.manager, isNotNull);
- request = new AnalysisSetAnalysisRootsParams([], []).toRequest('7');
- Response response = analysisDomain.handleRequest(request);
- expect(response, isResponseSuccess('7'));
- return pumpEventQueue();
- }).then((_) {
- expect(completionDomain.manager, isNull);
- });
- }
-
- /**
- * Assert manager is cleared when source NOT associated with manager is changed.
- */
- test_sourcesChanged_different_source_changed() {
- sendRequest(testFile);
- return pumpEventQueue().then((_) {
- expect(completionDomain.manager, isNotNull);
- ContextSourcePair contextSource = server.getContextSourcePair(testFile2);
- ChangeSet changeSet = new ChangeSet();
- changeSet.changedSource(contextSource.source);
- completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
- expect(completionDomain.manager, isNull);
- });
- }
-
- /**
- * Assert manager is NOT cleared when source associated with manager is changed.
- */
- test_sourcesChanged_same_source_changed() {
- sendRequest(testFile);
- return pumpEventQueue().then((_) {
- expect(completionDomain.manager, isNotNull);
- CompletionManager expectedManager = completionDomain.manager;
- ChangeSet changeSet = new ChangeSet();
- changeSet.changedSource(completionDomain.manager.source);
- completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
- expect(completionDomain.manager, expectedManager);
- });
- }
-
- /**
- * Assert manager is cleared when source is deleted
- */
- test_sourcesChanged_source_deleted() {
- sendRequest(testFile);
- return pumpEventQueue().then((_) {
- expect(completionDomain.manager, isNotNull);
- ChangeSet changeSet = new ChangeSet();
- changeSet.deletedSource(completionDomain.manager.source);
- completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
- expect(completionDomain.manager, isNull);
- });
- }
-
- /**
- * Assert manager is cleared when source is removed
- */
- test_sourcesChanged_source_removed() {
- sendRequest(testFile);
- return pumpEventQueue().then((_) {
- expect(completionDomain.manager, isNotNull);
- ChangeSet changeSet = new ChangeSet();
- changeSet.removedSource(completionDomain.manager.source);
- completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
- expect(completionDomain.manager, isNull);
- });
- }
-}
-
-@reflectiveTest
-class CompletionTest extends AbstractCompletionDomainTest {
+class CompletionDomainHandlerTest extends AbstractCompletionDomainTest {
test_html() {
testFile = '/project/web/test.html';
addTestFile('''
@@ -694,74 +443,6 @@
}
}
-class MockCompletionManager implements CompletionManager {
- final AnalysisContext context;
- final Source source;
- final SearchEngine searchEngine;
- StreamController<CompletionResult> controller;
- int computeCallCount = 0;
- int disposeCallCount = 0;
-
- MockCompletionManager(this.context, this.source, this.searchEngine);
-
- @override
- Future<bool> computeCache() {
- return new Future.value(true);
- }
-
- @override
- void computeSuggestions(CompletionRequest request) {
- ++computeCallCount;
- CompletionResult result = new CompletionResultImpl(0, 0, [], true);
- controller.add(result);
- }
-
- @override
- void dispose() {
- ++disposeCallCount;
- }
-
- @override
- Stream<CompletionResult> results(CompletionRequest request) {
- controller = new StreamController<CompletionResult>(onListen: () {
- scheduleMicrotask(() {
- computeSuggestions(request);
- });
- });
- return controller.stream;
- }
-}
-
-/**
- * Mock [AnaysisContext] for tracking usage of onSourcesChanged.
- */
-class MockContext implements AnalysisContext {
- static final SourceFactory DEFAULT_SOURCE_FACTORY = new SourceFactory([]);
-
- MockStream<SourcesChangedEvent> mockStream;
-
- SourceFactory sourceFactory = DEFAULT_SOURCE_FACTORY;
-
- MockContext() {
- mockStream = new MockStream<SourcesChangedEvent>();
- }
-
- @override
- Stream<SourcesChangedEvent> get onSourcesChanged => mockStream;
-
- @override
- bool exists(Source source) {
- return source != null && source.exists();
- }
-
- @override
- TimestampedData<String> getContents(Source source) {
- return source.contents;
- }
-
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
class MockRelevancySorter implements DartContributionSorter {
bool enabled = true;
@@ -775,101 +456,6 @@
}
}
-/**
- * Mock stream for tracking calls to listen and subscription.cancel.
- */
-class MockStream<E> implements Stream<E> {
- MockSubscription<E> mockSubscription = new MockSubscription<E>();
- int listenCount = 0;
-
- int get cancelCount => mockSubscription.cancelCount;
-
- @override
- StreamSubscription<E> listen(void onData(E event),
- {Function onError, void onDone(), bool cancelOnError}) {
- ++listenCount;
- return mockSubscription;
- }
-
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/**
- * Mock subscription for tracking calls to subscription.cancel.
- */
-class MockSubscription<E> implements StreamSubscription<E> {
- int cancelCount = 0;
-
- Future cancel() {
- ++cancelCount;
- return new Future.value(true);
- }
-
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-class Test_AnalysisServer extends AnalysisServer {
- final MockContext mockContext = new MockContext();
-
- Test_AnalysisServer(
- ServerCommunicationChannel channel,
- ResourceProvider resourceProvider,
- PubPackageMapProvider packageMapProvider,
- Index index,
- ServerPlugin serverPlugin,
- AnalysisServerOptions analysisServerOptions,
- DartSdk defaultSdk,
- InstrumentationService instrumentationService)
- : super(
- channel,
- resourceProvider,
- packageMapProvider,
- index,
- serverPlugin,
- analysisServerOptions,
- defaultSdk,
- instrumentationService);
-
- @override
- AnalysisContext getAnalysisContext(String path) {
- return mockContext;
- }
-
- @override
- ContextSourcePair getContextSourcePair(String path) {
- ContextSourcePair pair = super.getContextSourcePair(path);
- return new ContextSourcePair(mockContext, pair.source);
- }
-}
-
-/**
- * A [CompletionDomainHandler] subclass that returns a mock completion manager
- * so that the domain handler cache management can be tested.
- */
-class Test_CompletionDomainHandler extends CompletionDomainHandler {
- Test_CompletionDomainHandler(Test_AnalysisServer server) : super(server);
-
- MockContext get mockContext => (server as Test_AnalysisServer).mockContext;
-
- MockCompletionManager get mockManager => manager;
-
- void contextsChanged(ContextsChangedEvent event) {
- contextsChangedRaw(new ContextsChangedEvent(
- added: event.added.length > 0 ? [mockContext] : [],
- changed: event.changed.length > 0 ? [mockContext] : [],
- removed: event.removed.length > 0 ? [mockContext] : []));
- }
-
- void contextsChangedRaw(ContextsChangedEvent newEvent) {
- super.contextsChanged(newEvent);
- }
-
- CompletionManager createCompletionManager(
- AnalysisServer server, AnalysisContext context, Source source) {
- return new MockCompletionManager(mockContext, source, searchEngine);
- }
-}
-
@reflectiveTest
class _NoSearchEngine extends AbstractAnalysisTest {
@override
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index d76f15c1..28c6a09 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -23,6 +23,7 @@
import 'package:unittest/unittest.dart';
import '../../../abstract_context.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
int suggestionComparator(CompletionSuggestion s1, CompletionSuggestion s2) {
String c1 = s1.completion.toLowerCase();
@@ -436,7 +437,12 @@
Future computeSuggestions([int times = 200]) async {
CompletionRequestImpl baseRequest = new CompletionRequestImpl(
- context, provider, searchEngine, testSource, completionOffset);
+ context,
+ provider,
+ searchEngine,
+ testSource,
+ completionOffset,
+ new CompletionPerformance());
// Build the request
Completer<DartCompletionRequest> requestCompleter =
diff --git a/pkg/analysis_server/test/services/completion/optype_test.dart b/pkg/analysis_server/test/services/completion/dart/optype_test.dart
similarity index 99%
rename from pkg/analysis_server/test/services/completion/optype_test.dart
rename to pkg/analysis_server/test/services/completion/dart/optype_test.dart
index 8fb29bf..9ed569e 100644
--- a/pkg/analysis_server/test/services/completion/optype_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/optype_test.dart
@@ -4,8 +4,9 @@
library test.services.completion.contributor.dart.optype;
+import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
-import 'package:analysis_server/src/services/completion/optype.dart';
+import 'package:analysis_server/src/services/completion/dart/optype.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -13,9 +14,8 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:unittest/unittest.dart';
-import '../../abstract_context.dart';
-import '../../utils.dart';
-import 'package:analysis_server/src/protocol_server.dart';
+import '../../../abstract_context.dart';
+import '../../../utils.dart';
main() {
initializeTestEnvironment();
diff --git a/pkg/analysis_server/test/services/completion/dart/test_all.dart b/pkg/analysis_server/test/services/completion/dart/test_all.dart
index 482780f..c12f8de 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -22,6 +22,7 @@
import 'local_library_contributor_test.dart' as local_lib_test;
import 'local_reference_contributor_test.dart' as local_ref_test;
import 'named_constructor_contributor_test.dart' as named_contributor_test;
+import 'optype_test.dart' as optype_test;
import 'override_contributor_test.dart' as override_contributor_test;
import 'static_member_contributor_test.dart' as static_contributor_test;
import 'type_member_contributor_test.dart' as type_member_contributor_test;
@@ -46,6 +47,7 @@
local_lib_test.main();
local_ref_test.main();
named_contributor_test.main();
+ optype_test.main();
override_contributor_test.main();
static_contributor_test.main();
type_member_contributor_test.main();
diff --git a/pkg/analysis_server/test/services/completion/test_all.dart b/pkg/analysis_server/test/services/completion/test_all.dart
index d6b119e..f219dda 100644
--- a/pkg/analysis_server/test/services/completion/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/test_all.dart
@@ -9,7 +9,6 @@
import '../../utils.dart';
import 'completion_target_test.dart' as completion_target_test;
import 'dart/test_all.dart' as dart_contributor_tests;
-import 'optype_test.dart' as optype_test;
/// Utility for manually running all tests.
main() {
@@ -17,6 +16,5 @@
group('completion', () {
completion_target_test.main();
dart_contributor_tests.main();
- optype_test.main();
});
}
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index a6ec27a..7ce9b90 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -3278,6 +3278,48 @@
''');
}
+ test_makeFieldNotFinal_hasType() async {
+ resolveTestUnit('''
+class A {
+ final int fff = 1;
+ main() {
+ fff = 2;
+ }
+}
+''');
+ await assertHasFix(
+ DartFixKind.MAKE_FIELD_NOT_FINAL,
+ '''
+class A {
+ int fff = 1;
+ main() {
+ fff = 2;
+ }
+}
+''');
+ }
+
+ test_makeFieldNotFinal_noType() async {
+ resolveTestUnit('''
+class A {
+ final fff = 1;
+ main() {
+ fff = 2;
+ }
+}
+''');
+ await assertHasFix(
+ DartFixKind.MAKE_FIELD_NOT_FINAL,
+ '''
+class A {
+ var fff = 1;
+ main() {
+ fff = 2;
+ }
+}
+''');
+ }
+
test_noException_1() async {
resolveTestUnit('''
main(p) {
diff --git a/pkg/analysis_server/test/services/refactoring/extract_local_test.dart b/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
index cac1c16..0ced288 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
@@ -426,7 +426,21 @@
expect(subExpressions, ['111', '111 + 222']);
}
- test_coveringExpressions_skipAssignments() async {
+ test_coveringExpressions_namedExpression_value() async {
+ indexTestUnit('''
+main() {
+ foo(ppp: 42);
+}
+int foo({int ppp: 0}) => ppp + 1;
+''');
+ _createRefactoring(testCode.indexOf('42'), 0);
+ // check conditions
+ await refactoring.checkInitialConditions();
+ List<String> subExpressions = _getCoveringExpressions();
+ expect(subExpressions, ['42', 'foo(ppp: 42)']);
+ }
+
+ test_coveringExpressions_skip_assignment() async {
indexTestUnit('''
main() {
int v;
@@ -441,6 +455,80 @@
expect(subExpressions, ['111', '111 + 222', 'foo(v = 111 + 222)']);
}
+ test_coveringExpressions_skip_constructorName() async {
+ indexTestUnit('''
+class AAA {
+ AAA.name() {}
+}
+main() {
+ int v = new AAA.name();
+}
+''');
+ _createRefactoring(testCode.indexOf('AA.name();'), 5);
+ // check conditions
+ await refactoring.checkInitialConditions();
+ List<String> subExpressions = _getCoveringExpressions();
+ expect(subExpressions, ['new AAA.name()']);
+ }
+
+ test_coveringExpressions_skip_constructorName_name() async {
+ indexTestUnit('''
+class A {
+ A.name() {}
+}
+main() {
+ int v = new A.name();
+}
+''');
+ _createRefactoring(testCode.indexOf('ame();'), 0);
+ // check conditions
+ await refactoring.checkInitialConditions();
+ List<String> subExpressions = _getCoveringExpressions();
+ expect(subExpressions, ['new A.name()']);
+ }
+
+ test_coveringExpressions_skip_constructorName_type() async {
+ indexTestUnit('''
+class A {}
+main() {
+ int v = new A();
+}
+''');
+ _createRefactoring(testCode.indexOf('A();'), 0);
+ // check conditions
+ await refactoring.checkInitialConditions();
+ List<String> subExpressions = _getCoveringExpressions();
+ expect(subExpressions, ['new A()']);
+ }
+
+ test_coveringExpressions_skip_constructorName_typeArgument() async {
+ indexTestUnit('''
+class A<T> {}
+main() {
+ int v = new A<String>();
+}
+''');
+ _createRefactoring(testCode.indexOf('ring>'), 0);
+ // check conditions
+ await refactoring.checkInitialConditions();
+ List<String> subExpressions = _getCoveringExpressions();
+ expect(subExpressions, ['new A<String>()']);
+ }
+
+ test_coveringExpressions_skip_namedExpression() async {
+ indexTestUnit('''
+main() {
+ foo(ppp: 42);
+}
+int foo({int ppp: 0}) => ppp + 1;
+''');
+ _createRefactoring(testCode.indexOf('pp: 42'), 0);
+ // check conditions
+ await refactoring.checkInitialConditions();
+ List<String> subExpressions = _getCoveringExpressions();
+ expect(subExpressions, ['foo(ppp: 42)']);
+ }
+
test_fragmentExpression() {
indexTestUnit('''
main() {
diff --git a/pkg/analysis_server/tool/spec/generate_files b/pkg/analysis_server/tool/spec/generate_files
index 0c992fa..85092ea 100755
--- a/pkg/analysis_server/tool/spec/generate_files
+++ b/pkg/analysis_server/tool/spec/generate_files
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
new file mode 100644
index 0000000..c9b345a
--- /dev/null
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -0,0 +1,1884 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.dart.ast.visitor;
+
+import 'dart:collection';
+
+import 'package:analyzer/src/generated/ast.dart';
+
+/**
+ * An AST visitor that will recursively visit all of the nodes in an AST
+ * structure, similar to [GeneralizingAstVisitor]. This visitor uses a
+ * breadth-first ordering rather than the depth-first ordering of
+ * [GeneralizingAstVisitor].
+ *
+ * Subclasses that override a visit method must either invoke the overridden
+ * visit method or explicitly invoke the more general visit method. Failure to
+ * do so will cause the visit methods for superclasses of the node to not be
+ * invoked and will cause the children of the visited node to not be visited.
+ *
+ * In addition, subclasses should <b>not</b> explicitly visit the children of a
+ * node, but should ensure that the method [visitNode] is used to visit the
+ * children (either directly or indirectly). Failure to do will break the order
+ * in which nodes are visited.
+ *
+ * Note that, unlike other visitors that begin to visit a structure of nodes by
+ * asking the root node in the structure to accept the visitor, this visitor
+ * requires that clients start the visit by invoking the method [visitAllNodes]
+ * defined on the visitor with the root node as the argument:
+ *
+ * visitor.visitAllNodes(rootNode);
+ *
+ * Clients may extend or implement this class.
+ */
+class BreadthFirstVisitor<R> extends GeneralizingAstVisitor<R> {
+ /**
+ * A queue holding the nodes that have not yet been visited in the order in
+ * which they ought to be visited.
+ */
+ Queue<AstNode> _queue = new Queue<AstNode>();
+
+ /**
+ * A visitor, used to visit the children of the current node, that will add
+ * the nodes it visits to the [_queue].
+ */
+ _BreadthFirstChildVisitor _childVisitor;
+
+ /**
+ * Initialize a newly created visitor.
+ */
+ BreadthFirstVisitor() {
+ _childVisitor = new _BreadthFirstChildVisitor(this);
+ }
+
+ /**
+ * Visit all nodes in the tree starting at the given [root] node, in
+ * breadth-first order.
+ */
+ void visitAllNodes(AstNode root) {
+ _queue.add(root);
+ while (!_queue.isEmpty) {
+ AstNode next = _queue.removeFirst();
+ next.accept(this);
+ }
+ }
+
+ @override
+ R visitNode(AstNode node) {
+ node.visitChildren(_childVisitor);
+ return null;
+ }
+}
+
+/**
+ * An AST visitor that will recursively visit all of the nodes in an AST
+ * structure (like instances of the class [RecursiveAstVisitor]). In addition,
+ * when a node of a specific type is visited not only will the visit method for
+ * that specific type of node be invoked, but additional methods for the
+ * superclasses of that node will also be invoked. For example, using an
+ * instance of this class to visit a [Block] will cause the method [visitBlock]
+ * to be invoked but will also cause the methods [visitStatement] and
+ * [visitNode] to be subsequently invoked. This allows visitors to be written
+ * that visit all statements without needing to override the visit method for
+ * each of the specific subclasses of [Statement].
+ *
+ * Subclasses that override a visit method must either invoke the overridden
+ * visit method or explicitly invoke the more general visit method. Failure to
+ * do so will cause the visit methods for superclasses of the node to not be
+ * invoked and will cause the children of the visited node to not be visited.
+ *
+ * Clients may extend or implement this class.
+ */
+class GeneralizingAstVisitor<R> implements AstVisitor<R> {
+ @override
+ R visitAdjacentStrings(AdjacentStrings node) => visitStringLiteral(node);
+
+ R visitAnnotatedNode(AnnotatedNode node) => visitNode(node);
+
+ @override
+ R visitAnnotation(Annotation node) => visitNode(node);
+
+ @override
+ R visitArgumentList(ArgumentList node) => visitNode(node);
+
+ @override
+ R visitAsExpression(AsExpression node) => visitExpression(node);
+
+ @override
+ R visitAssertStatement(AssertStatement node) => visitStatement(node);
+
+ @override
+ R visitAssignmentExpression(AssignmentExpression node) =>
+ visitExpression(node);
+
+ @override
+ R visitAwaitExpression(AwaitExpression node) => visitExpression(node);
+
+ @override
+ R visitBinaryExpression(BinaryExpression node) => visitExpression(node);
+
+ @override
+ R visitBlock(Block node) => visitStatement(node);
+
+ @override
+ R visitBlockFunctionBody(BlockFunctionBody node) => visitFunctionBody(node);
+
+ @override
+ R visitBooleanLiteral(BooleanLiteral node) => visitLiteral(node);
+
+ @override
+ R visitBreakStatement(BreakStatement node) => visitStatement(node);
+
+ @override
+ R visitCascadeExpression(CascadeExpression node) => visitExpression(node);
+
+ @override
+ R visitCatchClause(CatchClause node) => visitNode(node);
+
+ @override
+ R visitClassDeclaration(ClassDeclaration node) =>
+ visitNamedCompilationUnitMember(node);
+
+ R visitClassMember(ClassMember node) => visitDeclaration(node);
+
+ @override
+ R visitClassTypeAlias(ClassTypeAlias node) => visitTypeAlias(node);
+
+ R visitCombinator(Combinator node) => visitNode(node);
+
+ @override
+ R visitComment(Comment node) => visitNode(node);
+
+ @override
+ R visitCommentReference(CommentReference node) => visitNode(node);
+
+ @override
+ R visitCompilationUnit(CompilationUnit node) => visitNode(node);
+
+ R visitCompilationUnitMember(CompilationUnitMember node) =>
+ visitDeclaration(node);
+
+ @override
+ R visitConditionalExpression(ConditionalExpression node) =>
+ visitExpression(node);
+
+ @override
+ R visitConfiguration(Configuration node) => visitNode(node);
+
+ @override
+ R visitConstructorDeclaration(ConstructorDeclaration node) =>
+ visitClassMember(node);
+
+ @override
+ R visitConstructorFieldInitializer(ConstructorFieldInitializer node) =>
+ visitConstructorInitializer(node);
+
+ R visitConstructorInitializer(ConstructorInitializer node) => visitNode(node);
+
+ @override
+ R visitConstructorName(ConstructorName node) => visitNode(node);
+
+ @override
+ R visitContinueStatement(ContinueStatement node) => visitStatement(node);
+
+ R visitDeclaration(Declaration node) => visitAnnotatedNode(node);
+
+ @override
+ R visitDeclaredIdentifier(DeclaredIdentifier node) => visitDeclaration(node);
+
+ @override
+ R visitDefaultFormalParameter(DefaultFormalParameter node) =>
+ visitFormalParameter(node);
+
+ R visitDirective(Directive node) => visitAnnotatedNode(node);
+
+ @override
+ R visitDoStatement(DoStatement node) => visitStatement(node);
+
+ @override
+ R visitDottedName(DottedName node) => visitNode(node);
+
+ @override
+ R visitDoubleLiteral(DoubleLiteral node) => visitLiteral(node);
+
+ @override
+ R visitEmptyFunctionBody(EmptyFunctionBody node) => visitFunctionBody(node);
+
+ @override
+ R visitEmptyStatement(EmptyStatement node) => visitStatement(node);
+
+ @override
+ R visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
+ visitDeclaration(node);
+
+ @override
+ R visitEnumDeclaration(EnumDeclaration node) =>
+ visitNamedCompilationUnitMember(node);
+
+ @override
+ R visitExportDirective(ExportDirective node) => visitNamespaceDirective(node);
+
+ R visitExpression(Expression node) => visitNode(node);
+
+ @override
+ R visitExpressionFunctionBody(ExpressionFunctionBody node) =>
+ visitFunctionBody(node);
+
+ @override
+ R visitExpressionStatement(ExpressionStatement node) => visitStatement(node);
+
+ @override
+ R visitExtendsClause(ExtendsClause node) => visitNode(node);
+
+ @override
+ R visitFieldDeclaration(FieldDeclaration node) => visitClassMember(node);
+
+ @override
+ R visitFieldFormalParameter(FieldFormalParameter node) =>
+ visitNormalFormalParameter(node);
+
+ @override
+ R visitForEachStatement(ForEachStatement node) => visitStatement(node);
+
+ R visitFormalParameter(FormalParameter node) => visitNode(node);
+
+ @override
+ R visitFormalParameterList(FormalParameterList node) => visitNode(node);
+
+ @override
+ R visitForStatement(ForStatement node) => visitStatement(node);
+
+ R visitFunctionBody(FunctionBody node) => visitNode(node);
+
+ @override
+ R visitFunctionDeclaration(FunctionDeclaration node) =>
+ visitNamedCompilationUnitMember(node);
+
+ @override
+ R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
+ visitStatement(node);
+
+ @override
+ R visitFunctionExpression(FunctionExpression node) => visitExpression(node);
+
+ @override
+ R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
+ visitExpression(node);
+
+ @override
+ R visitFunctionTypeAlias(FunctionTypeAlias node) => visitTypeAlias(node);
+
+ @override
+ R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
+ visitNormalFormalParameter(node);
+
+ @override
+ R visitHideCombinator(HideCombinator node) => visitCombinator(node);
+
+ R visitIdentifier(Identifier node) => visitExpression(node);
+
+ @override
+ R visitIfStatement(IfStatement node) => visitStatement(node);
+
+ @override
+ R visitImplementsClause(ImplementsClause node) => visitNode(node);
+
+ @override
+ R visitImportDirective(ImportDirective node) => visitNamespaceDirective(node);
+
+ @override
+ R visitIndexExpression(IndexExpression node) => visitExpression(node);
+
+ @override
+ R visitInstanceCreationExpression(InstanceCreationExpression node) =>
+ visitExpression(node);
+
+ @override
+ R visitIntegerLiteral(IntegerLiteral node) => visitLiteral(node);
+
+ R visitInterpolationElement(InterpolationElement node) => visitNode(node);
+
+ @override
+ R visitInterpolationExpression(InterpolationExpression node) =>
+ visitInterpolationElement(node);
+
+ @override
+ R visitInterpolationString(InterpolationString node) =>
+ visitInterpolationElement(node);
+
+ @override
+ R visitIsExpression(IsExpression node) => visitExpression(node);
+
+ @override
+ R visitLabel(Label node) => visitNode(node);
+
+ @override
+ R visitLabeledStatement(LabeledStatement node) => visitStatement(node);
+
+ @override
+ R visitLibraryDirective(LibraryDirective node) => visitDirective(node);
+
+ @override
+ R visitLibraryIdentifier(LibraryIdentifier node) => visitIdentifier(node);
+
+ @override
+ R visitListLiteral(ListLiteral node) => visitTypedLiteral(node);
+
+ R visitLiteral(Literal node) => visitExpression(node);
+
+ @override
+ R visitMapLiteral(MapLiteral node) => visitTypedLiteral(node);
+
+ @override
+ R visitMapLiteralEntry(MapLiteralEntry node) => visitNode(node);
+
+ @override
+ R visitMethodDeclaration(MethodDeclaration node) => visitClassMember(node);
+
+ @override
+ R visitMethodInvocation(MethodInvocation node) => visitExpression(node);
+
+ R visitNamedCompilationUnitMember(NamedCompilationUnitMember node) =>
+ visitCompilationUnitMember(node);
+
+ @override
+ R visitNamedExpression(NamedExpression node) => visitExpression(node);
+
+ R visitNamespaceDirective(NamespaceDirective node) =>
+ visitUriBasedDirective(node);
+
+ @override
+ R visitNativeClause(NativeClause node) => visitNode(node);
+
+ @override
+ R visitNativeFunctionBody(NativeFunctionBody node) => visitFunctionBody(node);
+
+ R visitNode(AstNode node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ R visitNormalFormalParameter(NormalFormalParameter node) =>
+ visitFormalParameter(node);
+
+ @override
+ R visitNullLiteral(NullLiteral node) => visitLiteral(node);
+
+ @override
+ R visitParenthesizedExpression(ParenthesizedExpression node) =>
+ visitExpression(node);
+
+ @override
+ R visitPartDirective(PartDirective node) => visitUriBasedDirective(node);
+
+ @override
+ R visitPartOfDirective(PartOfDirective node) => visitDirective(node);
+
+ @override
+ R visitPostfixExpression(PostfixExpression node) => visitExpression(node);
+
+ @override
+ R visitPrefixedIdentifier(PrefixedIdentifier node) => visitIdentifier(node);
+
+ @override
+ R visitPrefixExpression(PrefixExpression node) => visitExpression(node);
+
+ @override
+ R visitPropertyAccess(PropertyAccess node) => visitExpression(node);
+
+ @override
+ R visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) =>
+ visitConstructorInitializer(node);
+
+ @override
+ R visitRethrowExpression(RethrowExpression node) => visitExpression(node);
+
+ @override
+ R visitReturnStatement(ReturnStatement node) => visitStatement(node);
+
+ @override
+ R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
+
+ @override
+ R visitShowCombinator(ShowCombinator node) => visitCombinator(node);
+
+ @override
+ R visitSimpleFormalParameter(SimpleFormalParameter node) =>
+ visitNormalFormalParameter(node);
+
+ @override
+ R visitSimpleIdentifier(SimpleIdentifier node) => visitIdentifier(node);
+
+ @override
+ R visitSimpleStringLiteral(SimpleStringLiteral node) =>
+ visitSingleStringLiteral(node);
+
+ R visitSingleStringLiteral(SingleStringLiteral node) =>
+ visitStringLiteral(node);
+
+ R visitStatement(Statement node) => visitNode(node);
+
+ @override
+ R visitStringInterpolation(StringInterpolation node) =>
+ visitSingleStringLiteral(node);
+
+ R visitStringLiteral(StringLiteral node) => visitLiteral(node);
+
+ @override
+ R visitSuperConstructorInvocation(SuperConstructorInvocation node) =>
+ visitConstructorInitializer(node);
+
+ @override
+ R visitSuperExpression(SuperExpression node) => visitExpression(node);
+
+ @override
+ R visitSwitchCase(SwitchCase node) => visitSwitchMember(node);
+
+ @override
+ R visitSwitchDefault(SwitchDefault node) => visitSwitchMember(node);
+
+ R visitSwitchMember(SwitchMember node) => visitNode(node);
+
+ @override
+ R visitSwitchStatement(SwitchStatement node) => visitStatement(node);
+
+ @override
+ R visitSymbolLiteral(SymbolLiteral node) => visitLiteral(node);
+
+ @override
+ R visitThisExpression(ThisExpression node) => visitExpression(node);
+
+ @override
+ R visitThrowExpression(ThrowExpression node) => visitExpression(node);
+
+ @override
+ R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) =>
+ visitCompilationUnitMember(node);
+
+ @override
+ R visitTryStatement(TryStatement node) => visitStatement(node);
+
+ R visitTypeAlias(TypeAlias node) => visitNamedCompilationUnitMember(node);
+
+ @override
+ R visitTypeArgumentList(TypeArgumentList node) => visitNode(node);
+
+ R visitTypedLiteral(TypedLiteral node) => visitLiteral(node);
+
+ @override
+ R visitTypeName(TypeName node) => visitNode(node);
+
+ @override
+ R visitTypeParameter(TypeParameter node) => visitNode(node);
+
+ @override
+ R visitTypeParameterList(TypeParameterList node) => visitNode(node);
+
+ R visitUriBasedDirective(UriBasedDirective node) => visitDirective(node);
+
+ @override
+ R visitVariableDeclaration(VariableDeclaration node) =>
+ visitDeclaration(node);
+
+ @override
+ R visitVariableDeclarationList(VariableDeclarationList node) =>
+ visitNode(node);
+
+ @override
+ R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
+ visitStatement(node);
+
+ @override
+ R visitWhileStatement(WhileStatement node) => visitStatement(node);
+
+ @override
+ R visitWithClause(WithClause node) => visitNode(node);
+
+ @override
+ R visitYieldStatement(YieldStatement node) => visitStatement(node);
+}
+
+/**
+ * An AST visitor that will recursively visit all of the nodes in an AST
+ * structure. For example, using an instance of this class to visit a [Block]
+ * will also cause all of the statements in the block to be visited.
+ *
+ * Subclasses that override a visit method must either invoke the overridden
+ * visit method or must explicitly ask the visited node to visit its children.
+ * Failure to do so will cause the children of the visited node to not be
+ * visited.
+ *
+ * Clients may extend or implement this class.
+ */
+class RecursiveAstVisitor<R> implements AstVisitor<R> {
+ @override
+ R visitAdjacentStrings(AdjacentStrings node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAnnotation(Annotation node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitArgumentList(ArgumentList node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAsExpression(AsExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAssertStatement(AssertStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAssignmentExpression(AssignmentExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitAwaitExpression(AwaitExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitBinaryExpression(BinaryExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitBlock(Block node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitBlockFunctionBody(BlockFunctionBody node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitBooleanLiteral(BooleanLiteral node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitBreakStatement(BreakStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitCascadeExpression(CascadeExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitCatchClause(CatchClause node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitClassDeclaration(ClassDeclaration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitClassTypeAlias(ClassTypeAlias node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitComment(Comment node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitCommentReference(CommentReference node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitCompilationUnit(CompilationUnit node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitConditionalExpression(ConditionalExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitConfiguration(Configuration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitConstructorDeclaration(ConstructorDeclaration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitConstructorName(ConstructorName node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitContinueStatement(ContinueStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitDeclaredIdentifier(DeclaredIdentifier node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitDefaultFormalParameter(DefaultFormalParameter node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitDoStatement(DoStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitDottedName(DottedName node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitDoubleLiteral(DoubleLiteral node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitEmptyFunctionBody(EmptyFunctionBody node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitEmptyStatement(EmptyStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitEnumDeclaration(EnumDeclaration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitExportDirective(ExportDirective node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitExpressionStatement(ExpressionStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitExtendsClause(ExtendsClause node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFieldDeclaration(FieldDeclaration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFieldFormalParameter(FieldFormalParameter node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitForEachStatement(ForEachStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFormalParameterList(FormalParameterList node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitForStatement(ForStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFunctionDeclaration(FunctionDeclaration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFunctionExpression(FunctionExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFunctionTypeAlias(FunctionTypeAlias node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitHideCombinator(HideCombinator node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitIfStatement(IfStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitImplementsClause(ImplementsClause node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitImportDirective(ImportDirective node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitIndexExpression(IndexExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitInstanceCreationExpression(InstanceCreationExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitIntegerLiteral(IntegerLiteral node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitInterpolationExpression(InterpolationExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitInterpolationString(InterpolationString node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitIsExpression(IsExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitLabel(Label node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitLabeledStatement(LabeledStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitLibraryDirective(LibraryDirective node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitLibraryIdentifier(LibraryIdentifier node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitListLiteral(ListLiteral node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitMapLiteral(MapLiteral node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitMapLiteralEntry(MapLiteralEntry node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitMethodDeclaration(MethodDeclaration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitMethodInvocation(MethodInvocation node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitNamedExpression(NamedExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitNativeClause(NativeClause node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitNativeFunctionBody(NativeFunctionBody node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitNullLiteral(NullLiteral node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitParenthesizedExpression(ParenthesizedExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitPartDirective(PartDirective node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitPartOfDirective(PartOfDirective node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitPostfixExpression(PostfixExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitPrefixedIdentifier(PrefixedIdentifier node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitPrefixExpression(PrefixExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitPropertyAccess(PropertyAccess node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitRethrowExpression(RethrowExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitReturnStatement(ReturnStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitScriptTag(ScriptTag node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitShowCombinator(ShowCombinator node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitSimpleFormalParameter(SimpleFormalParameter node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitSimpleIdentifier(SimpleIdentifier node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitSimpleStringLiteral(SimpleStringLiteral node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitStringInterpolation(StringInterpolation node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitSuperExpression(SuperExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitSwitchCase(SwitchCase node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitSwitchDefault(SwitchDefault node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitSwitchStatement(SwitchStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitSymbolLiteral(SymbolLiteral node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitThisExpression(ThisExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitThrowExpression(ThrowExpression node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitTryStatement(TryStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitTypeArgumentList(TypeArgumentList node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitTypeName(TypeName node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitTypeParameter(TypeParameter node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitTypeParameterList(TypeParameterList node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitVariableDeclaration(VariableDeclaration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitVariableDeclarationList(VariableDeclarationList node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitWhileStatement(WhileStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitWithClause(WithClause node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitYieldStatement(YieldStatement node) {
+ node.visitChildren(this);
+ return null;
+ }
+}
+
+/**
+ * An AST visitor that will do nothing when visiting an AST node. It is intended
+ * to be a superclass for classes that use the visitor pattern primarily as a
+ * dispatch mechanism (and hence don't need to recursively visit a whole
+ * structure) and that only need to visit a small number of node types.
+ *
+ * Clients may extend or implement this class.
+ */
+class SimpleAstVisitor<R> implements AstVisitor<R> {
+ @override
+ R visitAdjacentStrings(AdjacentStrings node) => null;
+
+ @override
+ R visitAnnotation(Annotation node) => null;
+
+ @override
+ R visitArgumentList(ArgumentList node) => null;
+
+ @override
+ R visitAsExpression(AsExpression node) => null;
+
+ @override
+ R visitAssertStatement(AssertStatement node) => null;
+
+ @override
+ R visitAssignmentExpression(AssignmentExpression node) => null;
+
+ @override
+ R visitAwaitExpression(AwaitExpression node) => null;
+
+ @override
+ R visitBinaryExpression(BinaryExpression node) => null;
+
+ @override
+ R visitBlock(Block node) => null;
+
+ @override
+ R visitBlockFunctionBody(BlockFunctionBody node) => null;
+
+ @override
+ R visitBooleanLiteral(BooleanLiteral node) => null;
+
+ @override
+ R visitBreakStatement(BreakStatement node) => null;
+
+ @override
+ R visitCascadeExpression(CascadeExpression node) => null;
+
+ @override
+ R visitCatchClause(CatchClause node) => null;
+
+ @override
+ R visitClassDeclaration(ClassDeclaration node) => null;
+
+ @override
+ R visitClassTypeAlias(ClassTypeAlias node) => null;
+
+ @override
+ R visitComment(Comment node) => null;
+
+ @override
+ R visitCommentReference(CommentReference node) => null;
+
+ @override
+ R visitCompilationUnit(CompilationUnit node) => null;
+
+ @override
+ R visitConditionalExpression(ConditionalExpression node) => null;
+
+ @override
+ R visitConfiguration(Configuration node) => null;
+
+ @override
+ R visitConstructorDeclaration(ConstructorDeclaration node) => null;
+
+ @override
+ R visitConstructorFieldInitializer(ConstructorFieldInitializer node) => null;
+
+ @override
+ R visitConstructorName(ConstructorName node) => null;
+
+ @override
+ R visitContinueStatement(ContinueStatement node) => null;
+
+ @override
+ R visitDeclaredIdentifier(DeclaredIdentifier node) => null;
+
+ @override
+ R visitDefaultFormalParameter(DefaultFormalParameter node) => null;
+
+ @override
+ R visitDoStatement(DoStatement node) => null;
+
+ @override
+ R visitDottedName(DottedName node) => null;
+
+ @override
+ R visitDoubleLiteral(DoubleLiteral node) => null;
+
+ @override
+ R visitEmptyFunctionBody(EmptyFunctionBody node) => null;
+
+ @override
+ R visitEmptyStatement(EmptyStatement node) => null;
+
+ @override
+ R visitEnumConstantDeclaration(EnumConstantDeclaration node) => null;
+
+ @override
+ R visitEnumDeclaration(EnumDeclaration node) => null;
+
+ @override
+ R visitExportDirective(ExportDirective node) => null;
+
+ @override
+ R visitExpressionFunctionBody(ExpressionFunctionBody node) => null;
+
+ @override
+ R visitExpressionStatement(ExpressionStatement node) => null;
+
+ @override
+ R visitExtendsClause(ExtendsClause node) => null;
+
+ @override
+ R visitFieldDeclaration(FieldDeclaration node) => null;
+
+ @override
+ R visitFieldFormalParameter(FieldFormalParameter node) => null;
+
+ @override
+ R visitForEachStatement(ForEachStatement node) => null;
+
+ @override
+ R visitFormalParameterList(FormalParameterList node) => null;
+
+ @override
+ R visitForStatement(ForStatement node) => null;
+
+ @override
+ R visitFunctionDeclaration(FunctionDeclaration node) => null;
+
+ @override
+ R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
+ null;
+
+ @override
+ R visitFunctionExpression(FunctionExpression node) => null;
+
+ @override
+ R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
+ null;
+
+ @override
+ R visitFunctionTypeAlias(FunctionTypeAlias node) => null;
+
+ @override
+ R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
+ null;
+
+ @override
+ R visitHideCombinator(HideCombinator node) => null;
+
+ @override
+ R visitIfStatement(IfStatement node) => null;
+
+ @override
+ R visitImplementsClause(ImplementsClause node) => null;
+
+ @override
+ R visitImportDirective(ImportDirective node) => null;
+
+ @override
+ R visitIndexExpression(IndexExpression node) => null;
+
+ @override
+ R visitInstanceCreationExpression(InstanceCreationExpression node) => null;
+
+ @override
+ R visitIntegerLiteral(IntegerLiteral node) => null;
+
+ @override
+ R visitInterpolationExpression(InterpolationExpression node) => null;
+
+ @override
+ R visitInterpolationString(InterpolationString node) => null;
+
+ @override
+ R visitIsExpression(IsExpression node) => null;
+
+ @override
+ R visitLabel(Label node) => null;
+
+ @override
+ R visitLabeledStatement(LabeledStatement node) => null;
+
+ @override
+ R visitLibraryDirective(LibraryDirective node) => null;
+
+ @override
+ R visitLibraryIdentifier(LibraryIdentifier node) => null;
+
+ @override
+ R visitListLiteral(ListLiteral node) => null;
+
+ @override
+ R visitMapLiteral(MapLiteral node) => null;
+
+ @override
+ R visitMapLiteralEntry(MapLiteralEntry node) => null;
+
+ @override
+ R visitMethodDeclaration(MethodDeclaration node) => null;
+
+ @override
+ R visitMethodInvocation(MethodInvocation node) => null;
+
+ @override
+ R visitNamedExpression(NamedExpression node) => null;
+
+ @override
+ R visitNativeClause(NativeClause node) => null;
+
+ @override
+ R visitNativeFunctionBody(NativeFunctionBody node) => null;
+
+ @override
+ R visitNullLiteral(NullLiteral node) => null;
+
+ @override
+ R visitParenthesizedExpression(ParenthesizedExpression node) => null;
+
+ @override
+ R visitPartDirective(PartDirective node) => null;
+
+ @override
+ R visitPartOfDirective(PartOfDirective node) => null;
+
+ @override
+ R visitPostfixExpression(PostfixExpression node) => null;
+
+ @override
+ R visitPrefixedIdentifier(PrefixedIdentifier node) => null;
+
+ @override
+ R visitPrefixExpression(PrefixExpression node) => null;
+
+ @override
+ R visitPropertyAccess(PropertyAccess node) => null;
+
+ @override
+ R visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) =>
+ null;
+
+ @override
+ R visitRethrowExpression(RethrowExpression node) => null;
+
+ @override
+ R visitReturnStatement(ReturnStatement node) => null;
+
+ @override
+ R visitScriptTag(ScriptTag node) => null;
+
+ @override
+ R visitShowCombinator(ShowCombinator node) => null;
+
+ @override
+ R visitSimpleFormalParameter(SimpleFormalParameter node) => null;
+
+ @override
+ R visitSimpleIdentifier(SimpleIdentifier node) => null;
+
+ @override
+ R visitSimpleStringLiteral(SimpleStringLiteral node) => null;
+
+ @override
+ R visitStringInterpolation(StringInterpolation node) => null;
+
+ @override
+ R visitSuperConstructorInvocation(SuperConstructorInvocation node) => null;
+
+ @override
+ R visitSuperExpression(SuperExpression node) => null;
+
+ @override
+ R visitSwitchCase(SwitchCase node) => null;
+
+ @override
+ R visitSwitchDefault(SwitchDefault node) => null;
+
+ @override
+ R visitSwitchStatement(SwitchStatement node) => null;
+
+ @override
+ R visitSymbolLiteral(SymbolLiteral node) => null;
+
+ @override
+ R visitThisExpression(ThisExpression node) => null;
+
+ @override
+ R visitThrowExpression(ThrowExpression node) => null;
+
+ @override
+ R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) => null;
+
+ @override
+ R visitTryStatement(TryStatement node) => null;
+
+ @override
+ R visitTypeArgumentList(TypeArgumentList node) => null;
+
+ @override
+ R visitTypeName(TypeName node) => null;
+
+ @override
+ R visitTypeParameter(TypeParameter node) => null;
+
+ @override
+ R visitTypeParameterList(TypeParameterList node) => null;
+
+ @override
+ R visitVariableDeclaration(VariableDeclaration node) => null;
+
+ @override
+ R visitVariableDeclarationList(VariableDeclarationList node) => null;
+
+ @override
+ R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
+ null;
+
+ @override
+ R visitWhileStatement(WhileStatement node) => null;
+
+ @override
+ R visitWithClause(WithClause node) => null;
+
+ @override
+ R visitYieldStatement(YieldStatement node) => null;
+}
+
+/**
+ * An AST visitor that will recursively visit all of the nodes in an AST
+ * structure (like instances of the class [RecursiveAstVisitor]). In addition,
+ * every node will also be visited by using a single unified [visitNode] method.
+ *
+ * Subclasses that override a visit method must either invoke the overridden
+ * visit method or explicitly invoke the more general [visitNode] method.
+ * Failure to do so will cause the children of the visited node to not be
+ * visited.
+ *
+ * Clients may extend or implement this class.
+ */
+class UnifyingAstVisitor<R> implements AstVisitor<R> {
+ @override
+ R visitAdjacentStrings(AdjacentStrings node) => visitNode(node);
+
+ @override
+ R visitAnnotation(Annotation node) => visitNode(node);
+
+ @override
+ R visitArgumentList(ArgumentList node) => visitNode(node);
+
+ @override
+ R visitAsExpression(AsExpression node) => visitNode(node);
+
+ @override
+ R visitAssertStatement(AssertStatement node) => visitNode(node);
+
+ @override
+ R visitAssignmentExpression(AssignmentExpression node) => visitNode(node);
+
+ @override
+ R visitAwaitExpression(AwaitExpression node) => visitNode(node);
+
+ @override
+ R visitBinaryExpression(BinaryExpression node) => visitNode(node);
+
+ @override
+ R visitBlock(Block node) => visitNode(node);
+
+ @override
+ R visitBlockFunctionBody(BlockFunctionBody node) => visitNode(node);
+
+ @override
+ R visitBooleanLiteral(BooleanLiteral node) => visitNode(node);
+
+ @override
+ R visitBreakStatement(BreakStatement node) => visitNode(node);
+
+ @override
+ R visitCascadeExpression(CascadeExpression node) => visitNode(node);
+
+ @override
+ R visitCatchClause(CatchClause node) => visitNode(node);
+
+ @override
+ R visitClassDeclaration(ClassDeclaration node) => visitNode(node);
+
+ @override
+ R visitClassTypeAlias(ClassTypeAlias node) => visitNode(node);
+
+ @override
+ R visitComment(Comment node) => visitNode(node);
+
+ @override
+ R visitCommentReference(CommentReference node) => visitNode(node);
+
+ @override
+ R visitCompilationUnit(CompilationUnit node) => visitNode(node);
+
+ @override
+ R visitConditionalExpression(ConditionalExpression node) => visitNode(node);
+
+ @override
+ R visitConfiguration(Configuration node) => visitNode(node);
+
+ @override
+ R visitConstructorDeclaration(ConstructorDeclaration node) => visitNode(node);
+
+ @override
+ R visitConstructorFieldInitializer(ConstructorFieldInitializer node) =>
+ visitNode(node);
+
+ @override
+ R visitConstructorName(ConstructorName node) => visitNode(node);
+
+ @override
+ R visitContinueStatement(ContinueStatement node) => visitNode(node);
+
+ @override
+ R visitDeclaredIdentifier(DeclaredIdentifier node) => visitNode(node);
+
+ @override
+ R visitDefaultFormalParameter(DefaultFormalParameter node) => visitNode(node);
+
+ @override
+ R visitDoStatement(DoStatement node) => visitNode(node);
+
+ @override
+ R visitDottedName(DottedName node) => visitNode(node);
+
+ @override
+ R visitDoubleLiteral(DoubleLiteral node) => visitNode(node);
+
+ @override
+ R visitEmptyFunctionBody(EmptyFunctionBody node) => visitNode(node);
+
+ @override
+ R visitEmptyStatement(EmptyStatement node) => visitNode(node);
+
+ @override
+ R visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
+ visitNode(node);
+
+ @override
+ R visitEnumDeclaration(EnumDeclaration node) => visitNode(node);
+
+ @override
+ R visitExportDirective(ExportDirective node) => visitNode(node);
+
+ @override
+ R visitExpressionFunctionBody(ExpressionFunctionBody node) => visitNode(node);
+
+ @override
+ R visitExpressionStatement(ExpressionStatement node) => visitNode(node);
+
+ @override
+ R visitExtendsClause(ExtendsClause node) => visitNode(node);
+
+ @override
+ R visitFieldDeclaration(FieldDeclaration node) => visitNode(node);
+
+ @override
+ R visitFieldFormalParameter(FieldFormalParameter node) => visitNode(node);
+
+ @override
+ R visitForEachStatement(ForEachStatement node) => visitNode(node);
+
+ @override
+ R visitFormalParameterList(FormalParameterList node) => visitNode(node);
+
+ @override
+ R visitForStatement(ForStatement node) => visitNode(node);
+
+ @override
+ R visitFunctionDeclaration(FunctionDeclaration node) => visitNode(node);
+
+ @override
+ R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
+ visitNode(node);
+
+ @override
+ R visitFunctionExpression(FunctionExpression node) => visitNode(node);
+
+ @override
+ R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
+ visitNode(node);
+
+ @override
+ R visitFunctionTypeAlias(FunctionTypeAlias node) => visitNode(node);
+
+ @override
+ R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
+ visitNode(node);
+
+ @override
+ R visitHideCombinator(HideCombinator node) => visitNode(node);
+
+ @override
+ R visitIfStatement(IfStatement node) => visitNode(node);
+
+ @override
+ R visitImplementsClause(ImplementsClause node) => visitNode(node);
+
+ @override
+ R visitImportDirective(ImportDirective node) => visitNode(node);
+
+ @override
+ R visitIndexExpression(IndexExpression node) => visitNode(node);
+
+ @override
+ R visitInstanceCreationExpression(InstanceCreationExpression node) =>
+ visitNode(node);
+
+ @override
+ R visitIntegerLiteral(IntegerLiteral node) => visitNode(node);
+
+ @override
+ R visitInterpolationExpression(InterpolationExpression node) =>
+ visitNode(node);
+
+ @override
+ R visitInterpolationString(InterpolationString node) => visitNode(node);
+
+ @override
+ R visitIsExpression(IsExpression node) => visitNode(node);
+
+ @override
+ R visitLabel(Label node) => visitNode(node);
+
+ @override
+ R visitLabeledStatement(LabeledStatement node) => visitNode(node);
+
+ @override
+ R visitLibraryDirective(LibraryDirective node) => visitNode(node);
+
+ @override
+ R visitLibraryIdentifier(LibraryIdentifier node) => visitNode(node);
+
+ @override
+ R visitListLiteral(ListLiteral node) => visitNode(node);
+
+ @override
+ R visitMapLiteral(MapLiteral node) => visitNode(node);
+
+ @override
+ R visitMapLiteralEntry(MapLiteralEntry node) => visitNode(node);
+
+ @override
+ R visitMethodDeclaration(MethodDeclaration node) => visitNode(node);
+
+ @override
+ R visitMethodInvocation(MethodInvocation node) => visitNode(node);
+
+ @override
+ R visitNamedExpression(NamedExpression node) => visitNode(node);
+
+ @override
+ R visitNativeClause(NativeClause node) => visitNode(node);
+
+ @override
+ R visitNativeFunctionBody(NativeFunctionBody node) => visitNode(node);
+
+ R visitNode(AstNode node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
+ R visitNullLiteral(NullLiteral node) => visitNode(node);
+
+ @override
+ R visitParenthesizedExpression(ParenthesizedExpression node) =>
+ visitNode(node);
+
+ @override
+ R visitPartDirective(PartDirective node) => visitNode(node);
+
+ @override
+ R visitPartOfDirective(PartOfDirective node) => visitNode(node);
+
+ @override
+ R visitPostfixExpression(PostfixExpression node) => visitNode(node);
+
+ @override
+ R visitPrefixedIdentifier(PrefixedIdentifier node) => visitNode(node);
+
+ @override
+ R visitPrefixExpression(PrefixExpression node) => visitNode(node);
+
+ @override
+ R visitPropertyAccess(PropertyAccess node) => visitNode(node);
+
+ @override
+ R visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) =>
+ visitNode(node);
+
+ @override
+ R visitRethrowExpression(RethrowExpression node) => visitNode(node);
+
+ @override
+ R visitReturnStatement(ReturnStatement node) => visitNode(node);
+
+ @override
+ R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
+
+ @override
+ R visitShowCombinator(ShowCombinator node) => visitNode(node);
+
+ @override
+ R visitSimpleFormalParameter(SimpleFormalParameter node) => visitNode(node);
+
+ @override
+ R visitSimpleIdentifier(SimpleIdentifier node) => visitNode(node);
+
+ @override
+ R visitSimpleStringLiteral(SimpleStringLiteral node) => visitNode(node);
+
+ @override
+ R visitStringInterpolation(StringInterpolation node) => visitNode(node);
+
+ @override
+ R visitSuperConstructorInvocation(SuperConstructorInvocation node) =>
+ visitNode(node);
+
+ @override
+ R visitSuperExpression(SuperExpression node) => visitNode(node);
+
+ @override
+ R visitSwitchCase(SwitchCase node) => visitNode(node);
+
+ @override
+ R visitSwitchDefault(SwitchDefault node) => visitNode(node);
+
+ @override
+ R visitSwitchStatement(SwitchStatement node) => visitNode(node);
+
+ @override
+ R visitSymbolLiteral(SymbolLiteral node) => visitNode(node);
+
+ @override
+ R visitThisExpression(ThisExpression node) => visitNode(node);
+
+ @override
+ R visitThrowExpression(ThrowExpression node) => visitNode(node);
+
+ @override
+ R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) =>
+ visitNode(node);
+
+ @override
+ R visitTryStatement(TryStatement node) => visitNode(node);
+
+ @override
+ R visitTypeArgumentList(TypeArgumentList node) => visitNode(node);
+
+ @override
+ R visitTypeName(TypeName node) => visitNode(node);
+
+ @override
+ R visitTypeParameter(TypeParameter node) => visitNode(node);
+
+ @override
+ R visitTypeParameterList(TypeParameterList node) => visitNode(node);
+
+ @override
+ R visitVariableDeclaration(VariableDeclaration node) => visitNode(node);
+
+ @override
+ R visitVariableDeclarationList(VariableDeclarationList node) =>
+ visitNode(node);
+
+ @override
+ R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
+ visitNode(node);
+
+ @override
+ R visitWhileStatement(WhileStatement node) => visitNode(node);
+
+ @override
+ R visitWithClause(WithClause node) => visitNode(node);
+
+ @override
+ R visitYieldStatement(YieldStatement node) => visitNode(node);
+}
+
+/**
+ * A helper class used to implement the correct order of visits for a
+ * [BreadthFirstVisitor].
+ */
+class _BreadthFirstChildVisitor extends UnifyingAstVisitor<Object> {
+ /**
+ * The [BreadthFirstVisitor] being helped by this visitor.
+ */
+ final BreadthFirstVisitor outerVisitor;
+
+ /**
+ * Initialize a newly created visitor to help the [outerVisitor].
+ */
+ _BreadthFirstChildVisitor(this.outerVisitor);
+
+ @override
+ Object visitNode(AstNode node) {
+ outerVisitor._queue.add(node);
+ return null;
+ }
+}
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index e0efffc..ab468ed 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -558,13 +558,6 @@
String get displayName;
/**
- * Return the content of the documentation comment (including delimiters) for
- * this element, or `null` if this element does not or cannot have
- * documentation.
- */
- String get documentationComment;
-
- /**
* Return the source range of the documentation comment for this element,
* or `null` if this element does not or cannot have a documentation.
*
@@ -574,6 +567,13 @@
SourceRange get docRange;
/**
+ * Return the content of the documentation comment (including delimiters) for
+ * this element, or `null` if this element does not or cannot have
+ * documentation.
+ */
+ String get documentationComment;
+
+ /**
* Return the element that either physically or logically encloses this
* element. This will be `null` if this element is a library because libraries
* are the top-level elements in the model.
@@ -1153,7 +1153,8 @@
*
* Clients may not extend, implement or mix-in this class.
*/
-abstract class FunctionTypeAliasElement implements FunctionTypedElement {
+abstract class FunctionTypeAliasElement
+ implements FunctionTypedElement, TypeDefiningElement {
/**
* An empty array of type alias elements.
*/
@@ -1177,8 +1178,7 @@
*
* Clients may not extend, implement or mix-in this class.
*/
-abstract class FunctionTypedElement
- implements TypeDefiningElement, TypeParameterizedElement {
+abstract class FunctionTypedElement implements TypeParameterizedElement {
/**
* Return a list containing all of the parameters defined by this executable
* element.
@@ -1192,7 +1192,9 @@
*/
DartType get returnType;
- @override
+ /**
+ * The type of this element, which will be a function type.
+ */
FunctionType get type;
}
diff --git a/pkg/analyzer/lib/source/error_processor.dart b/pkg/analyzer/lib/source/error_processor.dart
index b20716a..8e369aa 100644
--- a/pkg/analyzer/lib/source/error_processor.dart
+++ b/pkg/analyzer/lib/source/error_processor.dart
@@ -54,20 +54,16 @@
}
}
- ErrorSeverity _toSeverity(String severity) {
- switch (severity) {
- case 'error':
- return ErrorSeverity.ERROR;
- case 'info':
- return ErrorSeverity.INFO;
- case 'warning':
- return ErrorSeverity.WARNING;
- }
- return null;
- }
-
+ ErrorSeverity _toSeverity(String severity) => severityMap[severity];
}
+/// String identifiers mapped to associated severities.
+const Map<String, ErrorSeverity> severityMap = const {
+ 'error': ErrorSeverity.ERROR,
+ 'info': ErrorSeverity.INFO,
+ 'warning': ErrorSeverity.WARNING
+};
+
/// Process errors by filtering or changing associated [ErrorSeverity].
class ErrorProcessor {
/// The code name of the associated error.
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index c9604ef..ac3ace6 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -485,6 +485,31 @@
}
@override
+ bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
+ AnalysisTarget target = entry.target;
+ // TYPE_PROVIDER
+ if (target is AnalysisContextTarget && result == TYPE_PROVIDER) {
+ DartSdk dartSdk = sourceFactory.dartSdk;
+ if (dartSdk != null) {
+ AnalysisContext sdkContext = dartSdk.context;
+ if (!identical(sdkContext, this) &&
+ sdkContext is InternalAnalysisContext) {
+ return sdkContext.aboutToComputeResult(entry, result);
+ }
+ }
+ }
+ // A result for a Source.
+ Source source = target.source;
+ if (source != null) {
+ InternalAnalysisContext context = _cache.getContextFor(source);
+ if (!identical(context, this)) {
+ return context.aboutToComputeResult(entry, result);
+ }
+ }
+ return false;
+ }
+
+ @override
void addListener(AnalysisListener listener) {
if (!_listeners.contains(listener)) {
_listeners.add(listener);
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
new file mode 100644
index 0000000..f0435eb
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -0,0 +1,6272 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.src.generated.ast;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap;
+import 'package:analyzer/src/generated/utilities_dart.dart';
+
+/**
+ * An AST visitor that will clone any AST structure that it visits. The cloner
+ * will only clone the structure, it will not preserve any resolution results or
+ * properties associated with the nodes.
+ */
+class AstCloner implements AstVisitor<AstNode> {
+ /**
+ * A flag indicating whether tokens should be cloned while cloning an AST
+ * structure.
+ */
+ final bool cloneTokens;
+
+ /**
+ * Initialize a newly created AST cloner to optionally clone tokens while
+ * cloning AST nodes if [cloneTokens] is `true`.
+ */
+ AstCloner(
+ [this.cloneTokens =
+ false]); // TODO(brianwilkerson) Change this to be a named parameter.
+
+ /**
+ * Return a clone of the given [node].
+ */
+ AstNode cloneNode(AstNode node) {
+ if (node == null) {
+ return null;
+ }
+ return node.accept(this) as AstNode;
+ }
+
+ /**
+ * Return a list containing cloned versions of the nodes in the given list of
+ * [nodes].
+ */
+ List<AstNode> cloneNodeList(NodeList nodes) {
+ int count = nodes.length;
+ List clonedNodes = new List();
+ for (int i = 0; i < count; i++) {
+ clonedNodes.add((nodes[i]).accept(this) as AstNode);
+ }
+ return clonedNodes;
+ }
+
+ /**
+ * Clone the given [token] if tokens are supposed to be cloned.
+ */
+ Token cloneToken(Token token) {
+ if (cloneTokens) {
+ return (token == null ? null : token.copy());
+ } else {
+ return token;
+ }
+ }
+
+ /**
+ * Clone the given [tokens] if tokens are supposed to be cloned.
+ */
+ List<Token> cloneTokenList(List<Token> tokens) {
+ if (cloneTokens) {
+ return tokens.map((Token token) => token.copy()).toList();
+ }
+ return tokens;
+ }
+
+ @override
+ AdjacentStrings visitAdjacentStrings(AdjacentStrings node) =>
+ new AdjacentStrings(cloneNodeList(node.strings));
+
+ @override
+ Annotation visitAnnotation(Annotation node) => new Annotation(
+ cloneToken(node.atSign),
+ cloneNode(node.name),
+ cloneToken(node.period),
+ cloneNode(node.constructorName),
+ cloneNode(node.arguments));
+
+ @override
+ ArgumentList visitArgumentList(ArgumentList node) => new ArgumentList(
+ cloneToken(node.leftParenthesis),
+ cloneNodeList(node.arguments),
+ cloneToken(node.rightParenthesis));
+
+ @override
+ AsExpression visitAsExpression(AsExpression node) => new AsExpression(
+ cloneNode(node.expression),
+ cloneToken(node.asOperator),
+ cloneNode(node.type));
+
+ @override
+ AstNode visitAssertStatement(AssertStatement node) => new AssertStatement(
+ cloneToken(node.assertKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.condition),
+ cloneToken(node.comma),
+ cloneNode(node.message),
+ cloneToken(node.rightParenthesis),
+ cloneToken(node.semicolon));
+
+ @override
+ AssignmentExpression visitAssignmentExpression(AssignmentExpression node) =>
+ new AssignmentExpression(cloneNode(node.leftHandSide),
+ cloneToken(node.operator), cloneNode(node.rightHandSide));
+
+ @override
+ AwaitExpression visitAwaitExpression(AwaitExpression node) =>
+ new AwaitExpression(
+ cloneToken(node.awaitKeyword), cloneNode(node.expression));
+
+ @override
+ BinaryExpression visitBinaryExpression(BinaryExpression node) =>
+ new BinaryExpression(cloneNode(node.leftOperand),
+ cloneToken(node.operator), cloneNode(node.rightOperand));
+
+ @override
+ Block visitBlock(Block node) => new Block(cloneToken(node.leftBracket),
+ cloneNodeList(node.statements), cloneToken(node.rightBracket));
+
+ @override
+ BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
+ new BlockFunctionBody(cloneToken(node.keyword), cloneToken(node.star),
+ cloneNode(node.block));
+
+ @override
+ BooleanLiteral visitBooleanLiteral(BooleanLiteral node) =>
+ new BooleanLiteral(cloneToken(node.literal), node.value);
+
+ @override
+ BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement(
+ cloneToken(node.breakKeyword),
+ cloneNode(node.label),
+ cloneToken(node.semicolon));
+
+ @override
+ CascadeExpression visitCascadeExpression(CascadeExpression node) =>
+ new CascadeExpression(
+ cloneNode(node.target), cloneNodeList(node.cascadeSections));
+
+ @override
+ CatchClause visitCatchClause(CatchClause node) => new CatchClause(
+ cloneToken(node.onKeyword),
+ cloneNode(node.exceptionType),
+ cloneToken(node.catchKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.exceptionParameter),
+ cloneToken(node.comma),
+ cloneNode(node.stackTraceParameter),
+ cloneToken(node.rightParenthesis),
+ cloneNode(node.body));
+
+ @override
+ ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
+ ClassDeclaration copy = new ClassDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.abstractKeyword),
+ cloneToken(node.classKeyword),
+ cloneNode(node.name),
+ cloneNode(node.typeParameters),
+ cloneNode(node.extendsClause),
+ cloneNode(node.withClause),
+ cloneNode(node.implementsClause),
+ cloneToken(node.leftBracket),
+ cloneNodeList(node.members),
+ cloneToken(node.rightBracket));
+ copy.nativeClause = cloneNode(node.nativeClause);
+ return copy;
+ }
+
+ @override
+ ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.typedefKeyword),
+ cloneNode(node.name),
+ cloneNode(node.typeParameters),
+ cloneToken(node.equals),
+ cloneToken(node.abstractKeyword),
+ cloneNode(node.superclass),
+ cloneNode(node.withClause),
+ cloneNode(node.implementsClause),
+ cloneToken(node.semicolon));
+
+ @override
+ Comment visitComment(Comment node) {
+ if (node.isDocumentation) {
+ return Comment.createDocumentationCommentWithReferences(
+ cloneTokenList(node.tokens), cloneNodeList(node.references));
+ } else if (node.isBlock) {
+ return Comment.createBlockComment(cloneTokenList(node.tokens));
+ }
+ return Comment.createEndOfLineComment(cloneTokenList(node.tokens));
+ }
+
+ @override
+ CommentReference visitCommentReference(CommentReference node) =>
+ new CommentReference(
+ cloneToken(node.newKeyword), cloneNode(node.identifier));
+
+ @override
+ CompilationUnit visitCompilationUnit(CompilationUnit node) {
+ CompilationUnit clone = new CompilationUnit(
+ cloneToken(node.beginToken),
+ cloneNode(node.scriptTag),
+ cloneNodeList(node.directives),
+ cloneNodeList(node.declarations),
+ cloneToken(node.endToken));
+ clone.lineInfo = node.lineInfo;
+ return clone;
+ }
+
+ @override
+ ConditionalExpression visitConditionalExpression(
+ ConditionalExpression node) =>
+ new ConditionalExpression(
+ cloneNode(node.condition),
+ cloneToken(node.question),
+ cloneNode(node.thenExpression),
+ cloneToken(node.colon),
+ cloneNode(node.elseExpression));
+
+ @override
+ Configuration visitConfiguration(Configuration node) => new Configuration(
+ cloneToken(node.ifKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.name),
+ cloneToken(node.equalToken),
+ cloneNode(node.value),
+ cloneToken(node.rightParenthesis),
+ cloneNode(node.libraryUri));
+
+ @override
+ ConstructorDeclaration visitConstructorDeclaration(
+ ConstructorDeclaration node) =>
+ new ConstructorDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.externalKeyword),
+ cloneToken(node.constKeyword),
+ cloneToken(node.factoryKeyword),
+ cloneNode(node.returnType),
+ cloneToken(node.period),
+ cloneNode(node.name),
+ cloneNode(node.parameters),
+ cloneToken(node.separator),
+ cloneNodeList(node.initializers),
+ cloneNode(node.redirectedConstructor),
+ cloneNode(node.body));
+
+ @override
+ ConstructorFieldInitializer visitConstructorFieldInitializer(
+ ConstructorFieldInitializer node) =>
+ new ConstructorFieldInitializer(
+ cloneToken(node.thisKeyword),
+ cloneToken(node.period),
+ cloneNode(node.fieldName),
+ cloneToken(node.equals),
+ cloneNode(node.expression));
+
+ @override
+ ConstructorName visitConstructorName(ConstructorName node) =>
+ new ConstructorName(
+ cloneNode(node.type), cloneToken(node.period), cloneNode(node.name));
+
+ @override
+ ContinueStatement visitContinueStatement(ContinueStatement node) =>
+ new ContinueStatement(cloneToken(node.continueKeyword),
+ cloneNode(node.label), cloneToken(node.semicolon));
+
+ @override
+ DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
+ new DeclaredIdentifier(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.type),
+ cloneNode(node.identifier));
+
+ @override
+ DefaultFormalParameter visitDefaultFormalParameter(
+ DefaultFormalParameter node) =>
+ new DefaultFormalParameter(cloneNode(node.parameter), node.kind,
+ cloneToken(node.separator), cloneNode(node.defaultValue));
+
+ @override
+ DoStatement visitDoStatement(DoStatement node) => new DoStatement(
+ cloneToken(node.doKeyword),
+ cloneNode(node.body),
+ cloneToken(node.whileKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.condition),
+ cloneToken(node.rightParenthesis),
+ cloneToken(node.semicolon));
+
+ @override
+ DottedName visitDottedName(DottedName node) =>
+ new DottedName(cloneNodeList(node.components));
+
+ @override
+ DoubleLiteral visitDoubleLiteral(DoubleLiteral node) =>
+ new DoubleLiteral(cloneToken(node.literal), node.value);
+
+ @override
+ EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) =>
+ new EmptyFunctionBody(cloneToken(node.semicolon));
+
+ @override
+ EmptyStatement visitEmptyStatement(EmptyStatement node) =>
+ new EmptyStatement(cloneToken(node.semicolon));
+
+ @override
+ AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
+ new EnumConstantDeclaration(cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata), cloneNode(node.name));
+
+ @override
+ EnumDeclaration visitEnumDeclaration(EnumDeclaration node) =>
+ new EnumDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.enumKeyword),
+ cloneNode(node.name),
+ cloneToken(node.leftBracket),
+ cloneNodeList(node.constants),
+ cloneToken(node.rightBracket));
+
+ @override
+ ExportDirective visitExportDirective(ExportDirective node) {
+ ExportDirective directive = new ExportDirective(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.uri),
+ cloneNodeList(node.configurations),
+ cloneNodeList(node.combinators),
+ cloneToken(node.semicolon));
+ directive.source = node.source;
+ directive.uriContent = node.uriContent;
+ return directive;
+ }
+
+ @override
+ ExpressionFunctionBody visitExpressionFunctionBody(
+ ExpressionFunctionBody node) =>
+ new ExpressionFunctionBody(
+ cloneToken(node.keyword),
+ cloneToken(node.functionDefinition),
+ cloneNode(node.expression),
+ cloneToken(node.semicolon));
+
+ @override
+ ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
+ new ExpressionStatement(
+ cloneNode(node.expression), cloneToken(node.semicolon));
+
+ @override
+ ExtendsClause visitExtendsClause(ExtendsClause node) => new ExtendsClause(
+ cloneToken(node.extendsKeyword), cloneNode(node.superclass));
+
+ @override
+ FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
+ new FieldDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.staticKeyword),
+ cloneNode(node.fields),
+ cloneToken(node.semicolon));
+
+ @override
+ FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
+ new FieldFormalParameter(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.type),
+ cloneToken(node.thisKeyword),
+ cloneToken(node.period),
+ cloneNode(node.identifier),
+ cloneNode(node.typeParameters),
+ cloneNode(node.parameters));
+
+ @override
+ ForEachStatement visitForEachStatement(ForEachStatement node) {
+ DeclaredIdentifier loopVariable = node.loopVariable;
+ if (loopVariable == null) {
+ return new ForEachStatement.withReference(
+ cloneToken(node.awaitKeyword),
+ cloneToken(node.forKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.identifier),
+ cloneToken(node.inKeyword),
+ cloneNode(node.iterable),
+ cloneToken(node.rightParenthesis),
+ cloneNode(node.body));
+ }
+ return new ForEachStatement.withDeclaration(
+ cloneToken(node.awaitKeyword),
+ cloneToken(node.forKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(loopVariable),
+ cloneToken(node.inKeyword),
+ cloneNode(node.iterable),
+ cloneToken(node.rightParenthesis),
+ cloneNode(node.body));
+ }
+
+ @override
+ FormalParameterList visitFormalParameterList(FormalParameterList node) =>
+ new FormalParameterList(
+ cloneToken(node.leftParenthesis),
+ cloneNodeList(node.parameters),
+ cloneToken(node.leftDelimiter),
+ cloneToken(node.rightDelimiter),
+ cloneToken(node.rightParenthesis));
+
+ @override
+ ForStatement visitForStatement(ForStatement node) => new ForStatement(
+ cloneToken(node.forKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.variables),
+ cloneNode(node.initialization),
+ cloneToken(node.leftSeparator),
+ cloneNode(node.condition),
+ cloneToken(node.rightSeparator),
+ cloneNodeList(node.updaters),
+ cloneToken(node.rightParenthesis),
+ cloneNode(node.body));
+
+ @override
+ FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
+ new FunctionDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.externalKeyword),
+ cloneNode(node.returnType),
+ cloneToken(node.propertyKeyword),
+ cloneNode(node.name),
+ cloneNode(node.functionExpression));
+
+ @override
+ FunctionDeclarationStatement visitFunctionDeclarationStatement(
+ FunctionDeclarationStatement node) =>
+ new FunctionDeclarationStatement(cloneNode(node.functionDeclaration));
+
+ @override
+ FunctionExpression visitFunctionExpression(FunctionExpression node) =>
+ new FunctionExpression(cloneNode(node.typeParameters),
+ cloneNode(node.parameters), cloneNode(node.body));
+
+ @override
+ FunctionExpressionInvocation visitFunctionExpressionInvocation(
+ FunctionExpressionInvocation node) =>
+ new FunctionExpressionInvocation(cloneNode(node.function),
+ cloneNode(node.typeArguments), cloneNode(node.argumentList));
+
+ @override
+ FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
+ new FunctionTypeAlias(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.typedefKeyword),
+ cloneNode(node.returnType),
+ cloneNode(node.name),
+ cloneNode(node.typeParameters),
+ cloneNode(node.parameters),
+ cloneToken(node.semicolon));
+
+ @override
+ FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
+ FunctionTypedFormalParameter node) =>
+ new FunctionTypedFormalParameter(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneNode(node.returnType),
+ cloneNode(node.identifier),
+ cloneNode(node.typeParameters),
+ cloneNode(node.parameters));
+
+ @override
+ HideCombinator visitHideCombinator(HideCombinator node) => new HideCombinator(
+ cloneToken(node.keyword), cloneNodeList(node.hiddenNames));
+
+ @override
+ IfStatement visitIfStatement(IfStatement node) => new IfStatement(
+ cloneToken(node.ifKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.condition),
+ cloneToken(node.rightParenthesis),
+ cloneNode(node.thenStatement),
+ cloneToken(node.elseKeyword),
+ cloneNode(node.elseStatement));
+
+ @override
+ ImplementsClause visitImplementsClause(ImplementsClause node) =>
+ new ImplementsClause(
+ cloneToken(node.implementsKeyword), cloneNodeList(node.interfaces));
+
+ @override
+ ImportDirective visitImportDirective(ImportDirective node) {
+ ImportDirective directive = new ImportDirective(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.uri),
+ cloneNodeList(node.configurations),
+ cloneToken(node.deferredKeyword),
+ cloneToken(node.asKeyword),
+ cloneNode(node.prefix),
+ cloneNodeList(node.combinators),
+ cloneToken(node.semicolon));
+ directive.source = node.source;
+ directive.uriContent = node.uriContent;
+ return directive;
+ }
+
+ @override
+ IndexExpression visitIndexExpression(IndexExpression node) {
+ Token period = node.period;
+ if (period == null) {
+ return new IndexExpression.forTarget(
+ cloneNode(node.target),
+ cloneToken(node.leftBracket),
+ cloneNode(node.index),
+ cloneToken(node.rightBracket));
+ } else {
+ return new IndexExpression.forCascade(
+ cloneToken(period),
+ cloneToken(node.leftBracket),
+ cloneNode(node.index),
+ cloneToken(node.rightBracket));
+ }
+ }
+
+ @override
+ InstanceCreationExpression visitInstanceCreationExpression(
+ InstanceCreationExpression node) =>
+ new InstanceCreationExpression(cloneToken(node.keyword),
+ cloneNode(node.constructorName), cloneNode(node.argumentList));
+
+ @override
+ IntegerLiteral visitIntegerLiteral(IntegerLiteral node) =>
+ new IntegerLiteral(cloneToken(node.literal), node.value);
+
+ @override
+ InterpolationExpression visitInterpolationExpression(
+ InterpolationExpression node) =>
+ new InterpolationExpression(cloneToken(node.leftBracket),
+ cloneNode(node.expression), cloneToken(node.rightBracket));
+
+ @override
+ InterpolationString visitInterpolationString(InterpolationString node) =>
+ new InterpolationString(cloneToken(node.contents), node.value);
+
+ @override
+ IsExpression visitIsExpression(IsExpression node) => new IsExpression(
+ cloneNode(node.expression),
+ cloneToken(node.isOperator),
+ cloneToken(node.notOperator),
+ cloneNode(node.type));
+
+ @override
+ Label visitLabel(Label node) =>
+ new Label(cloneNode(node.label), cloneToken(node.colon));
+
+ @override
+ LabeledStatement visitLabeledStatement(LabeledStatement node) =>
+ new LabeledStatement(
+ cloneNodeList(node.labels), cloneNode(node.statement));
+
+ @override
+ LibraryDirective visitLibraryDirective(LibraryDirective node) =>
+ new LibraryDirective(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.libraryKeyword),
+ cloneNode(node.name),
+ cloneToken(node.semicolon));
+
+ @override
+ LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) =>
+ new LibraryIdentifier(cloneNodeList(node.components));
+
+ @override
+ ListLiteral visitListLiteral(ListLiteral node) => new ListLiteral(
+ cloneToken(node.constKeyword),
+ cloneNode(node.typeArguments),
+ cloneToken(node.leftBracket),
+ cloneNodeList(node.elements),
+ cloneToken(node.rightBracket));
+
+ @override
+ MapLiteral visitMapLiteral(MapLiteral node) => new MapLiteral(
+ cloneToken(node.constKeyword),
+ cloneNode(node.typeArguments),
+ cloneToken(node.leftBracket),
+ cloneNodeList(node.entries),
+ cloneToken(node.rightBracket));
+
+ @override
+ MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
+ new MapLiteralEntry(cloneNode(node.key), cloneToken(node.separator),
+ cloneNode(node.value));
+
+ @override
+ MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
+ new MethodDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.externalKeyword),
+ cloneToken(node.modifierKeyword),
+ cloneNode(node.returnType),
+ cloneToken(node.propertyKeyword),
+ cloneToken(node.operatorKeyword),
+ cloneNode(node.name),
+ cloneNode(node.typeParameters),
+ cloneNode(node.parameters),
+ cloneNode(node.body));
+
+ @override
+ MethodInvocation visitMethodInvocation(MethodInvocation node) =>
+ new MethodInvocation(
+ cloneNode(node.target),
+ cloneToken(node.operator),
+ cloneNode(node.methodName),
+ cloneNode(node.typeArguments),
+ cloneNode(node.argumentList));
+
+ @override
+ NamedExpression visitNamedExpression(NamedExpression node) =>
+ new NamedExpression(cloneNode(node.name), cloneNode(node.expression));
+
+ @override
+ AstNode visitNativeClause(NativeClause node) =>
+ new NativeClause(cloneToken(node.nativeKeyword), cloneNode(node.name));
+
+ @override
+ NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) =>
+ new NativeFunctionBody(cloneToken(node.nativeKeyword),
+ cloneNode(node.stringLiteral), cloneToken(node.semicolon));
+
+ @override
+ NullLiteral visitNullLiteral(NullLiteral node) =>
+ new NullLiteral(cloneToken(node.literal));
+
+ @override
+ ParenthesizedExpression visitParenthesizedExpression(
+ ParenthesizedExpression node) =>
+ new ParenthesizedExpression(cloneToken(node.leftParenthesis),
+ cloneNode(node.expression), cloneToken(node.rightParenthesis));
+
+ @override
+ PartDirective visitPartDirective(PartDirective node) {
+ PartDirective directive = new PartDirective(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.partKeyword),
+ cloneNode(node.uri),
+ cloneToken(node.semicolon));
+ directive.source = node.source;
+ directive.uriContent = node.uriContent;
+ return directive;
+ }
+
+ @override
+ PartOfDirective visitPartOfDirective(PartOfDirective node) =>
+ new PartOfDirective(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.partKeyword),
+ cloneToken(node.ofKeyword),
+ cloneNode(node.libraryName),
+ cloneToken(node.semicolon));
+
+ @override
+ PostfixExpression visitPostfixExpression(PostfixExpression node) =>
+ new PostfixExpression(cloneNode(node.operand), cloneToken(node.operator));
+
+ @override
+ PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) =>
+ new PrefixedIdentifier(cloneNode(node.prefix), cloneToken(node.period),
+ cloneNode(node.identifier));
+
+ @override
+ PrefixExpression visitPrefixExpression(PrefixExpression node) =>
+ new PrefixExpression(cloneToken(node.operator), cloneNode(node.operand));
+
+ @override
+ PropertyAccess visitPropertyAccess(PropertyAccess node) => new PropertyAccess(
+ cloneNode(node.target),
+ cloneToken(node.operator),
+ cloneNode(node.propertyName));
+
+ @override
+ RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) =>
+ new RedirectingConstructorInvocation(
+ cloneToken(node.thisKeyword),
+ cloneToken(node.period),
+ cloneNode(node.constructorName),
+ cloneNode(node.argumentList));
+
+ @override
+ RethrowExpression visitRethrowExpression(RethrowExpression node) =>
+ new RethrowExpression(cloneToken(node.rethrowKeyword));
+
+ @override
+ ReturnStatement visitReturnStatement(ReturnStatement node) =>
+ new ReturnStatement(cloneToken(node.returnKeyword),
+ cloneNode(node.expression), cloneToken(node.semicolon));
+
+ @override
+ ScriptTag visitScriptTag(ScriptTag node) =>
+ new ScriptTag(cloneToken(node.scriptTag));
+
+ @override
+ ShowCombinator visitShowCombinator(ShowCombinator node) => new ShowCombinator(
+ cloneToken(node.keyword), cloneNodeList(node.shownNames));
+
+ @override
+ SimpleFormalParameter visitSimpleFormalParameter(
+ SimpleFormalParameter node) =>
+ new SimpleFormalParameter(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.type),
+ cloneNode(node.identifier));
+
+ @override
+ SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) =>
+ new SimpleIdentifier(cloneToken(node.token));
+
+ @override
+ SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) =>
+ new SimpleStringLiteral(cloneToken(node.literal), node.value);
+
+ @override
+ StringInterpolation visitStringInterpolation(StringInterpolation node) =>
+ new StringInterpolation(cloneNodeList(node.elements));
+
+ @override
+ SuperConstructorInvocation visitSuperConstructorInvocation(
+ SuperConstructorInvocation node) =>
+ new SuperConstructorInvocation(
+ cloneToken(node.superKeyword),
+ cloneToken(node.period),
+ cloneNode(node.constructorName),
+ cloneNode(node.argumentList));
+
+ @override
+ SuperExpression visitSuperExpression(SuperExpression node) =>
+ new SuperExpression(cloneToken(node.superKeyword));
+
+ @override
+ SwitchCase visitSwitchCase(SwitchCase node) => new SwitchCase(
+ cloneNodeList(node.labels),
+ cloneToken(node.keyword),
+ cloneNode(node.expression),
+ cloneToken(node.colon),
+ cloneNodeList(node.statements));
+
+ @override
+ SwitchDefault visitSwitchDefault(SwitchDefault node) => new SwitchDefault(
+ cloneNodeList(node.labels),
+ cloneToken(node.keyword),
+ cloneToken(node.colon),
+ cloneNodeList(node.statements));
+
+ @override
+ SwitchStatement visitSwitchStatement(SwitchStatement node) =>
+ new SwitchStatement(
+ cloneToken(node.switchKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.expression),
+ cloneToken(node.rightParenthesis),
+ cloneToken(node.leftBracket),
+ cloneNodeList(node.members),
+ cloneToken(node.rightBracket));
+
+ @override
+ SymbolLiteral visitSymbolLiteral(SymbolLiteral node) => new SymbolLiteral(
+ cloneToken(node.poundSign), cloneTokenList(node.components));
+
+ @override
+ ThisExpression visitThisExpression(ThisExpression node) =>
+ new ThisExpression(cloneToken(node.thisKeyword));
+
+ @override
+ ThrowExpression visitThrowExpression(ThrowExpression node) =>
+ new ThrowExpression(
+ cloneToken(node.throwKeyword), cloneNode(node.expression));
+
+ @override
+ TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
+ TopLevelVariableDeclaration node) =>
+ new TopLevelVariableDeclaration(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneNode(node.variables),
+ cloneToken(node.semicolon));
+
+ @override
+ TryStatement visitTryStatement(TryStatement node) => new TryStatement(
+ cloneToken(node.tryKeyword),
+ cloneNode(node.body),
+ cloneNodeList(node.catchClauses),
+ cloneToken(node.finallyKeyword),
+ cloneNode(node.finallyBlock));
+
+ @override
+ TypeArgumentList visitTypeArgumentList(TypeArgumentList node) =>
+ new TypeArgumentList(cloneToken(node.leftBracket),
+ cloneNodeList(node.arguments), cloneToken(node.rightBracket));
+
+ @override
+ TypeName visitTypeName(TypeName node) =>
+ new TypeName(cloneNode(node.name), cloneNode(node.typeArguments));
+
+ @override
+ TypeParameter visitTypeParameter(TypeParameter node) => new TypeParameter(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneNode(node.name),
+ cloneToken(node.extendsKeyword),
+ cloneNode(node.bound));
+
+ @override
+ TypeParameterList visitTypeParameterList(TypeParameterList node) =>
+ new TypeParameterList(cloneToken(node.leftBracket),
+ cloneNodeList(node.typeParameters), cloneToken(node.rightBracket));
+
+ @override
+ VariableDeclaration visitVariableDeclaration(VariableDeclaration node) =>
+ new VariableDeclaration(cloneNode(node.name), cloneToken(node.equals),
+ cloneNode(node.initializer));
+
+ @override
+ VariableDeclarationList visitVariableDeclarationList(
+ VariableDeclarationList node) =>
+ new VariableDeclarationList(
+ cloneNode(node.documentationComment),
+ cloneNodeList(node.metadata),
+ cloneToken(node.keyword),
+ cloneNode(node.type),
+ cloneNodeList(node.variables));
+
+ @override
+ VariableDeclarationStatement visitVariableDeclarationStatement(
+ VariableDeclarationStatement node) =>
+ new VariableDeclarationStatement(
+ cloneNode(node.variables), cloneToken(node.semicolon));
+
+ @override
+ WhileStatement visitWhileStatement(WhileStatement node) => new WhileStatement(
+ cloneToken(node.whileKeyword),
+ cloneToken(node.leftParenthesis),
+ cloneNode(node.condition),
+ cloneToken(node.rightParenthesis),
+ cloneNode(node.body));
+
+ @override
+ WithClause visitWithClause(WithClause node) => new WithClause(
+ cloneToken(node.withKeyword), cloneNodeList(node.mixinTypes));
+
+ @override
+ YieldStatement visitYieldStatement(YieldStatement node) => new YieldStatement(
+ cloneToken(node.yieldKeyword),
+ cloneToken(node.star),
+ cloneNode(node.expression),
+ cloneToken(node.semicolon));
+
+ /**
+ * Return a clone of the given [node].
+ */
+ static AstNode clone(AstNode node) {
+ return node.accept(new AstCloner());
+ }
+}
+
+/**
+ * An AstVisitor that compares the structure of two AstNodes to see whether they
+ * are equal.
+ */
+class AstComparator implements AstVisitor<bool> {
+ /**
+ * The AST node with which the node being visited is to be compared. This is
+ * only valid at the beginning of each visit method (until [isEqualNodes] is
+ * invoked).
+ */
+ AstNode _other;
+
+ /**
+ * Return `true` if the [first] node and the [second] node have the same
+ * structure.
+ *
+ * *Note:* This method is only visible for testing purposes and should not be
+ * used by clients.
+ */
+ bool isEqualNodes(AstNode first, AstNode second) {
+ if (first == null) {
+ return second == null;
+ } else if (second == null) {
+ return false;
+ } else if (first.runtimeType != second.runtimeType) {
+ return false;
+ }
+ _other = second;
+ return first.accept(this);
+ }
+
+ /**
+ * Return `true` if the [first] token and the [second] token have the same
+ * structure.
+ *
+ * *Note:* This method is only visible for testing purposes and should not be
+ * used by clients.
+ */
+ bool isEqualTokens(Token first, Token second) {
+ if (first == null) {
+ return second == null;
+ } else if (second == null) {
+ return false;
+ } else if (identical(first, second)) {
+ return true;
+ }
+ return first.offset == second.offset &&
+ first.length == second.length &&
+ first.lexeme == second.lexeme;
+ }
+
+ @override
+ bool visitAdjacentStrings(AdjacentStrings node) {
+ AdjacentStrings other = _other as AdjacentStrings;
+ return _isEqualNodeLists(node.strings, other.strings);
+ }
+
+ @override
+ bool visitAnnotation(Annotation node) {
+ Annotation other = _other as Annotation;
+ return isEqualTokens(node.atSign, other.atSign) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualTokens(node.period, other.period) &&
+ isEqualNodes(node.constructorName, other.constructorName) &&
+ isEqualNodes(node.arguments, other.arguments);
+ }
+
+ @override
+ bool visitArgumentList(ArgumentList node) {
+ ArgumentList other = _other as ArgumentList;
+ return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ _isEqualNodeLists(node.arguments, other.arguments) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis);
+ }
+
+ @override
+ bool visitAsExpression(AsExpression node) {
+ AsExpression other = _other as AsExpression;
+ return isEqualNodes(node.expression, other.expression) &&
+ isEqualTokens(node.asOperator, other.asOperator) &&
+ isEqualNodes(node.type, other.type);
+ }
+
+ @override
+ bool visitAssertStatement(AssertStatement node) {
+ AssertStatement other = _other as AssertStatement;
+ return isEqualTokens(node.assertKeyword, other.assertKeyword) &&
+ isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ isEqualNodes(node.condition, other.condition) &&
+ isEqualTokens(node.comma, other.comma) &&
+ isEqualNodes(node.message, other.message) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitAssignmentExpression(AssignmentExpression node) {
+ AssignmentExpression other = _other as AssignmentExpression;
+ return isEqualNodes(node.leftHandSide, other.leftHandSide) &&
+ isEqualTokens(node.operator, other.operator) &&
+ isEqualNodes(node.rightHandSide, other.rightHandSide);
+ }
+
+ @override
+ bool visitAwaitExpression(AwaitExpression node) {
+ AwaitExpression other = _other as AwaitExpression;
+ return isEqualTokens(node.awaitKeyword, other.awaitKeyword) &&
+ isEqualNodes(node.expression, other.expression);
+ }
+
+ @override
+ bool visitBinaryExpression(BinaryExpression node) {
+ BinaryExpression other = _other as BinaryExpression;
+ return isEqualNodes(node.leftOperand, other.leftOperand) &&
+ isEqualTokens(node.operator, other.operator) &&
+ isEqualNodes(node.rightOperand, other.rightOperand);
+ }
+
+ @override
+ bool visitBlock(Block node) {
+ Block other = _other as Block;
+ return isEqualTokens(node.leftBracket, other.leftBracket) &&
+ _isEqualNodeLists(node.statements, other.statements) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
+ bool visitBlockFunctionBody(BlockFunctionBody node) {
+ BlockFunctionBody other = _other as BlockFunctionBody;
+ return isEqualNodes(node.block, other.block);
+ }
+
+ @override
+ bool visitBooleanLiteral(BooleanLiteral node) {
+ BooleanLiteral other = _other as BooleanLiteral;
+ return isEqualTokens(node.literal, other.literal) &&
+ node.value == other.value;
+ }
+
+ @override
+ bool visitBreakStatement(BreakStatement node) {
+ BreakStatement other = _other as BreakStatement;
+ return isEqualTokens(node.breakKeyword, other.breakKeyword) &&
+ isEqualNodes(node.label, other.label) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitCascadeExpression(CascadeExpression node) {
+ CascadeExpression other = _other as CascadeExpression;
+ return isEqualNodes(node.target, other.target) &&
+ _isEqualNodeLists(node.cascadeSections, other.cascadeSections);
+ }
+
+ @override
+ bool visitCatchClause(CatchClause node) {
+ CatchClause other = _other as CatchClause;
+ return isEqualTokens(node.onKeyword, other.onKeyword) &&
+ isEqualNodes(node.exceptionType, other.exceptionType) &&
+ isEqualTokens(node.catchKeyword, other.catchKeyword) &&
+ isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ isEqualNodes(node.exceptionParameter, other.exceptionParameter) &&
+ isEqualTokens(node.comma, other.comma) &&
+ isEqualNodes(node.stackTraceParameter, other.stackTraceParameter) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+ isEqualNodes(node.body, other.body);
+ }
+
+ @override
+ bool visitClassDeclaration(ClassDeclaration node) {
+ ClassDeclaration other = _other as ClassDeclaration;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.abstractKeyword, other.abstractKeyword) &&
+ isEqualTokens(node.classKeyword, other.classKeyword) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualNodes(node.typeParameters, other.typeParameters) &&
+ isEqualNodes(node.extendsClause, other.extendsClause) &&
+ isEqualNodes(node.withClause, other.withClause) &&
+ isEqualNodes(node.implementsClause, other.implementsClause) &&
+ isEqualTokens(node.leftBracket, other.leftBracket) &&
+ _isEqualNodeLists(node.members, other.members) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
+ bool visitClassTypeAlias(ClassTypeAlias node) {
+ ClassTypeAlias other = _other as ClassTypeAlias;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.typedefKeyword, other.typedefKeyword) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualNodes(node.typeParameters, other.typeParameters) &&
+ isEqualTokens(node.equals, other.equals) &&
+ isEqualTokens(node.abstractKeyword, other.abstractKeyword) &&
+ isEqualNodes(node.superclass, other.superclass) &&
+ isEqualNodes(node.withClause, other.withClause) &&
+ isEqualNodes(node.implementsClause, other.implementsClause) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitComment(Comment node) {
+ Comment other = _other as Comment;
+ return _isEqualNodeLists(node.references, other.references);
+ }
+
+ @override
+ bool visitCommentReference(CommentReference node) {
+ CommentReference other = _other as CommentReference;
+ return isEqualTokens(node.newKeyword, other.newKeyword) &&
+ isEqualNodes(node.identifier, other.identifier);
+ }
+
+ @override
+ bool visitCompilationUnit(CompilationUnit node) {
+ CompilationUnit other = _other as CompilationUnit;
+ return isEqualTokens(node.beginToken, other.beginToken) &&
+ isEqualNodes(node.scriptTag, other.scriptTag) &&
+ _isEqualNodeLists(node.directives, other.directives) &&
+ _isEqualNodeLists(node.declarations, other.declarations) &&
+ isEqualTokens(node.endToken, other.endToken);
+ }
+
+ @override
+ bool visitConditionalExpression(ConditionalExpression node) {
+ ConditionalExpression other = _other as ConditionalExpression;
+ return isEqualNodes(node.condition, other.condition) &&
+ isEqualTokens(node.question, other.question) &&
+ isEqualNodes(node.thenExpression, other.thenExpression) &&
+ isEqualTokens(node.colon, other.colon) &&
+ isEqualNodes(node.elseExpression, other.elseExpression);
+ }
+
+ @override
+ bool visitConfiguration(Configuration node) {
+ Configuration other = _other as Configuration;
+ return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
+ isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualTokens(node.equalToken, other.equalToken) &&
+ isEqualNodes(node.value, other.value) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+ isEqualNodes(node.libraryUri, other.libraryUri);
+ }
+
+ @override
+ bool visitConstructorDeclaration(ConstructorDeclaration node) {
+ ConstructorDeclaration other = _other as ConstructorDeclaration;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.externalKeyword, other.externalKeyword) &&
+ isEqualTokens(node.constKeyword, other.constKeyword) &&
+ isEqualTokens(node.factoryKeyword, other.factoryKeyword) &&
+ isEqualNodes(node.returnType, other.returnType) &&
+ isEqualTokens(node.period, other.period) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualNodes(node.parameters, other.parameters) &&
+ isEqualTokens(node.separator, other.separator) &&
+ _isEqualNodeLists(node.initializers, other.initializers) &&
+ isEqualNodes(node.redirectedConstructor, other.redirectedConstructor) &&
+ isEqualNodes(node.body, other.body);
+ }
+
+ @override
+ bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+ ConstructorFieldInitializer other = _other as ConstructorFieldInitializer;
+ return isEqualTokens(node.thisKeyword, other.thisKeyword) &&
+ isEqualTokens(node.period, other.period) &&
+ isEqualNodes(node.fieldName, other.fieldName) &&
+ isEqualTokens(node.equals, other.equals) &&
+ isEqualNodes(node.expression, other.expression);
+ }
+
+ @override
+ bool visitConstructorName(ConstructorName node) {
+ ConstructorName other = _other as ConstructorName;
+ return isEqualNodes(node.type, other.type) &&
+ isEqualTokens(node.period, other.period) &&
+ isEqualNodes(node.name, other.name);
+ }
+
+ @override
+ bool visitContinueStatement(ContinueStatement node) {
+ ContinueStatement other = _other as ContinueStatement;
+ return isEqualTokens(node.continueKeyword, other.continueKeyword) &&
+ isEqualNodes(node.label, other.label) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitDeclaredIdentifier(DeclaredIdentifier node) {
+ DeclaredIdentifier other = _other as DeclaredIdentifier;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.keyword, other.keyword) &&
+ isEqualNodes(node.type, other.type) &&
+ isEqualNodes(node.identifier, other.identifier);
+ }
+
+ @override
+ bool visitDefaultFormalParameter(DefaultFormalParameter node) {
+ DefaultFormalParameter other = _other as DefaultFormalParameter;
+ return isEqualNodes(node.parameter, other.parameter) &&
+ node.kind == other.kind &&
+ isEqualTokens(node.separator, other.separator) &&
+ isEqualNodes(node.defaultValue, other.defaultValue);
+ }
+
+ @override
+ bool visitDoStatement(DoStatement node) {
+ DoStatement other = _other as DoStatement;
+ return isEqualTokens(node.doKeyword, other.doKeyword) &&
+ isEqualNodes(node.body, other.body) &&
+ isEqualTokens(node.whileKeyword, other.whileKeyword) &&
+ isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ isEqualNodes(node.condition, other.condition) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitDottedName(DottedName node) {
+ DottedName other = _other as DottedName;
+ return _isEqualNodeLists(node.components, other.components);
+ }
+
+ @override
+ bool visitDoubleLiteral(DoubleLiteral node) {
+ DoubleLiteral other = _other as DoubleLiteral;
+ return isEqualTokens(node.literal, other.literal) &&
+ node.value == other.value;
+ }
+
+ @override
+ bool visitEmptyFunctionBody(EmptyFunctionBody node) {
+ EmptyFunctionBody other = _other as EmptyFunctionBody;
+ return isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitEmptyStatement(EmptyStatement node) {
+ EmptyStatement other = _other as EmptyStatement;
+ return isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ EnumConstantDeclaration other = _other as EnumConstantDeclaration;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualNodes(node.name, other.name);
+ }
+
+ @override
+ bool visitEnumDeclaration(EnumDeclaration node) {
+ EnumDeclaration other = _other as EnumDeclaration;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.enumKeyword, other.enumKeyword) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualTokens(node.leftBracket, other.leftBracket) &&
+ _isEqualNodeLists(node.constants, other.constants) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
+ bool visitExportDirective(ExportDirective node) {
+ ExportDirective other = _other as ExportDirective;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.keyword, other.keyword) &&
+ isEqualNodes(node.uri, other.uri) &&
+ _isEqualNodeLists(node.combinators, other.combinators) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ ExpressionFunctionBody other = _other as ExpressionFunctionBody;
+ return isEqualTokens(node.functionDefinition, other.functionDefinition) &&
+ isEqualNodes(node.expression, other.expression) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitExpressionStatement(ExpressionStatement node) {
+ ExpressionStatement other = _other as ExpressionStatement;
+ return isEqualNodes(node.expression, other.expression) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitExtendsClause(ExtendsClause node) {
+ ExtendsClause other = _other as ExtendsClause;
+ return isEqualTokens(node.extendsKeyword, other.extendsKeyword) &&
+ isEqualNodes(node.superclass, other.superclass);
+ }
+
+ @override
+ bool visitFieldDeclaration(FieldDeclaration node) {
+ FieldDeclaration other = _other as FieldDeclaration;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.staticKeyword, other.staticKeyword) &&
+ isEqualNodes(node.fields, other.fields) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitFieldFormalParameter(FieldFormalParameter node) {
+ FieldFormalParameter other = _other as FieldFormalParameter;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.keyword, other.keyword) &&
+ isEqualNodes(node.type, other.type) &&
+ isEqualTokens(node.thisKeyword, other.thisKeyword) &&
+ isEqualTokens(node.period, other.period) &&
+ isEqualNodes(node.identifier, other.identifier);
+ }
+
+ @override
+ bool visitForEachStatement(ForEachStatement node) {
+ ForEachStatement other = _other as ForEachStatement;
+ return isEqualTokens(node.forKeyword, other.forKeyword) &&
+ isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ isEqualNodes(node.loopVariable, other.loopVariable) &&
+ isEqualTokens(node.inKeyword, other.inKeyword) &&
+ isEqualNodes(node.iterable, other.iterable) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+ isEqualNodes(node.body, other.body);
+ }
+
+ @override
+ bool visitFormalParameterList(FormalParameterList node) {
+ FormalParameterList other = _other as FormalParameterList;
+ return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ _isEqualNodeLists(node.parameters, other.parameters) &&
+ isEqualTokens(node.leftDelimiter, other.leftDelimiter) &&
+ isEqualTokens(node.rightDelimiter, other.rightDelimiter) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis);
+ }
+
+ @override
+ bool visitForStatement(ForStatement node) {
+ ForStatement other = _other as ForStatement;
+ return isEqualTokens(node.forKeyword, other.forKeyword) &&
+ isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ isEqualNodes(node.variables, other.variables) &&
+ isEqualNodes(node.initialization, other.initialization) &&
+ isEqualTokens(node.leftSeparator, other.leftSeparator) &&
+ isEqualNodes(node.condition, other.condition) &&
+ isEqualTokens(node.rightSeparator, other.rightSeparator) &&
+ _isEqualNodeLists(node.updaters, other.updaters) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+ isEqualNodes(node.body, other.body);
+ }
+
+ @override
+ bool visitFunctionDeclaration(FunctionDeclaration node) {
+ FunctionDeclaration other = _other as FunctionDeclaration;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.externalKeyword, other.externalKeyword) &&
+ isEqualNodes(node.returnType, other.returnType) &&
+ isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualNodes(node.functionExpression, other.functionExpression);
+ }
+
+ @override
+ bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+ FunctionDeclarationStatement other = _other as FunctionDeclarationStatement;
+ return isEqualNodes(node.functionDeclaration, other.functionDeclaration);
+ }
+
+ @override
+ bool visitFunctionExpression(FunctionExpression node) {
+ FunctionExpression other = _other as FunctionExpression;
+ return isEqualNodes(node.parameters, other.parameters) &&
+ isEqualNodes(node.body, other.body);
+ }
+
+ @override
+ bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ FunctionExpressionInvocation other = _other as FunctionExpressionInvocation;
+ return isEqualNodes(node.function, other.function) &&
+ isEqualNodes(node.argumentList, other.argumentList);
+ }
+
+ @override
+ bool visitFunctionTypeAlias(FunctionTypeAlias node) {
+ FunctionTypeAlias other = _other as FunctionTypeAlias;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.typedefKeyword, other.typedefKeyword) &&
+ isEqualNodes(node.returnType, other.returnType) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualNodes(node.typeParameters, other.typeParameters) &&
+ isEqualNodes(node.parameters, other.parameters) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+ FunctionTypedFormalParameter other = _other as FunctionTypedFormalParameter;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualNodes(node.returnType, other.returnType) &&
+ isEqualNodes(node.identifier, other.identifier) &&
+ isEqualNodes(node.parameters, other.parameters);
+ }
+
+ @override
+ bool visitHideCombinator(HideCombinator node) {
+ HideCombinator other = _other as HideCombinator;
+ return isEqualTokens(node.keyword, other.keyword) &&
+ _isEqualNodeLists(node.hiddenNames, other.hiddenNames);
+ }
+
+ @override
+ bool visitIfStatement(IfStatement node) {
+ IfStatement other = _other as IfStatement;
+ return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
+ isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ isEqualNodes(node.condition, other.condition) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+ isEqualNodes(node.thenStatement, other.thenStatement) &&
+ isEqualTokens(node.elseKeyword, other.elseKeyword) &&
+ isEqualNodes(node.elseStatement, other.elseStatement);
+ }
+
+ @override
+ bool visitImplementsClause(ImplementsClause node) {
+ ImplementsClause other = _other as ImplementsClause;
+ return isEqualTokens(node.implementsKeyword, other.implementsKeyword) &&
+ _isEqualNodeLists(node.interfaces, other.interfaces);
+ }
+
+ @override
+ bool visitImportDirective(ImportDirective node) {
+ ImportDirective other = _other as ImportDirective;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.keyword, other.keyword) &&
+ isEqualNodes(node.uri, other.uri) &&
+ isEqualTokens(node.deferredKeyword, other.deferredKeyword) &&
+ isEqualTokens(node.asKeyword, other.asKeyword) &&
+ isEqualNodes(node.prefix, other.prefix) &&
+ _isEqualNodeLists(node.combinators, other.combinators) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitIndexExpression(IndexExpression node) {
+ IndexExpression other = _other as IndexExpression;
+ return isEqualNodes(node.target, other.target) &&
+ isEqualTokens(node.leftBracket, other.leftBracket) &&
+ isEqualNodes(node.index, other.index) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
+ bool visitInstanceCreationExpression(InstanceCreationExpression node) {
+ InstanceCreationExpression other = _other as InstanceCreationExpression;
+ return isEqualTokens(node.keyword, other.keyword) &&
+ isEqualNodes(node.constructorName, other.constructorName) &&
+ isEqualNodes(node.argumentList, other.argumentList);
+ }
+
+ @override
+ bool visitIntegerLiteral(IntegerLiteral node) {
+ IntegerLiteral other = _other as IntegerLiteral;
+ return isEqualTokens(node.literal, other.literal) &&
+ (node.value == other.value);
+ }
+
+ @override
+ bool visitInterpolationExpression(InterpolationExpression node) {
+ InterpolationExpression other = _other as InterpolationExpression;
+ return isEqualTokens(node.leftBracket, other.leftBracket) &&
+ isEqualNodes(node.expression, other.expression) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
+ bool visitInterpolationString(InterpolationString node) {
+ InterpolationString other = _other as InterpolationString;
+ return isEqualTokens(node.contents, other.contents) &&
+ node.value == other.value;
+ }
+
+ @override
+ bool visitIsExpression(IsExpression node) {
+ IsExpression other = _other as IsExpression;
+ return isEqualNodes(node.expression, other.expression) &&
+ isEqualTokens(node.isOperator, other.isOperator) &&
+ isEqualTokens(node.notOperator, other.notOperator) &&
+ isEqualNodes(node.type, other.type);
+ }
+
+ @override
+ bool visitLabel(Label node) {
+ Label other = _other as Label;
+ return isEqualNodes(node.label, other.label) &&
+ isEqualTokens(node.colon, other.colon);
+ }
+
+ @override
+ bool visitLabeledStatement(LabeledStatement node) {
+ LabeledStatement other = _other as LabeledStatement;
+ return _isEqualNodeLists(node.labels, other.labels) &&
+ isEqualNodes(node.statement, other.statement);
+ }
+
+ @override
+ bool visitLibraryDirective(LibraryDirective node) {
+ LibraryDirective other = _other as LibraryDirective;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.libraryKeyword, other.libraryKeyword) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitLibraryIdentifier(LibraryIdentifier node) {
+ LibraryIdentifier other = _other as LibraryIdentifier;
+ return _isEqualNodeLists(node.components, other.components);
+ }
+
+ @override
+ bool visitListLiteral(ListLiteral node) {
+ ListLiteral other = _other as ListLiteral;
+ return isEqualTokens(node.constKeyword, other.constKeyword) &&
+ isEqualNodes(node.typeArguments, other.typeArguments) &&
+ isEqualTokens(node.leftBracket, other.leftBracket) &&
+ _isEqualNodeLists(node.elements, other.elements) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
+ bool visitMapLiteral(MapLiteral node) {
+ MapLiteral other = _other as MapLiteral;
+ return isEqualTokens(node.constKeyword, other.constKeyword) &&
+ isEqualNodes(node.typeArguments, other.typeArguments) &&
+ isEqualTokens(node.leftBracket, other.leftBracket) &&
+ _isEqualNodeLists(node.entries, other.entries) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
+ bool visitMapLiteralEntry(MapLiteralEntry node) {
+ MapLiteralEntry other = _other as MapLiteralEntry;
+ return isEqualNodes(node.key, other.key) &&
+ isEqualTokens(node.separator, other.separator) &&
+ isEqualNodes(node.value, other.value);
+ }
+
+ @override
+ bool visitMethodDeclaration(MethodDeclaration node) {
+ MethodDeclaration other = _other as MethodDeclaration;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.externalKeyword, other.externalKeyword) &&
+ isEqualTokens(node.modifierKeyword, other.modifierKeyword) &&
+ isEqualNodes(node.returnType, other.returnType) &&
+ isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
+ isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualNodes(node.parameters, other.parameters) &&
+ isEqualNodes(node.body, other.body);
+ }
+
+ @override
+ bool visitMethodInvocation(MethodInvocation node) {
+ MethodInvocation other = _other as MethodInvocation;
+ return isEqualNodes(node.target, other.target) &&
+ isEqualTokens(node.operator, other.operator) &&
+ isEqualNodes(node.methodName, other.methodName) &&
+ isEqualNodes(node.argumentList, other.argumentList);
+ }
+
+ @override
+ bool visitNamedExpression(NamedExpression node) {
+ NamedExpression other = _other as NamedExpression;
+ return isEqualNodes(node.name, other.name) &&
+ isEqualNodes(node.expression, other.expression);
+ }
+
+ @override
+ bool visitNativeClause(NativeClause node) {
+ NativeClause other = _other as NativeClause;
+ return isEqualTokens(node.nativeKeyword, other.nativeKeyword) &&
+ isEqualNodes(node.name, other.name);
+ }
+
+ @override
+ bool visitNativeFunctionBody(NativeFunctionBody node) {
+ NativeFunctionBody other = _other as NativeFunctionBody;
+ return isEqualTokens(node.nativeKeyword, other.nativeKeyword) &&
+ isEqualNodes(node.stringLiteral, other.stringLiteral) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitNullLiteral(NullLiteral node) {
+ NullLiteral other = _other as NullLiteral;
+ return isEqualTokens(node.literal, other.literal);
+ }
+
+ @override
+ bool visitParenthesizedExpression(ParenthesizedExpression node) {
+ ParenthesizedExpression other = _other as ParenthesizedExpression;
+ return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ isEqualNodes(node.expression, other.expression) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis);
+ }
+
+ @override
+ bool visitPartDirective(PartDirective node) {
+ PartDirective other = _other as PartDirective;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.partKeyword, other.partKeyword) &&
+ isEqualNodes(node.uri, other.uri) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitPartOfDirective(PartOfDirective node) {
+ PartOfDirective other = _other as PartOfDirective;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.partKeyword, other.partKeyword) &&
+ isEqualTokens(node.ofKeyword, other.ofKeyword) &&
+ isEqualNodes(node.libraryName, other.libraryName) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitPostfixExpression(PostfixExpression node) {
+ PostfixExpression other = _other as PostfixExpression;
+ return isEqualNodes(node.operand, other.operand) &&
+ isEqualTokens(node.operator, other.operator);
+ }
+
+ @override
+ bool visitPrefixedIdentifier(PrefixedIdentifier node) {
+ PrefixedIdentifier other = _other as PrefixedIdentifier;
+ return isEqualNodes(node.prefix, other.prefix) &&
+ isEqualTokens(node.period, other.period) &&
+ isEqualNodes(node.identifier, other.identifier);
+ }
+
+ @override
+ bool visitPrefixExpression(PrefixExpression node) {
+ PrefixExpression other = _other as PrefixExpression;
+ return isEqualTokens(node.operator, other.operator) &&
+ isEqualNodes(node.operand, other.operand);
+ }
+
+ @override
+ bool visitPropertyAccess(PropertyAccess node) {
+ PropertyAccess other = _other as PropertyAccess;
+ return isEqualNodes(node.target, other.target) &&
+ isEqualTokens(node.operator, other.operator) &&
+ isEqualNodes(node.propertyName, other.propertyName);
+ }
+
+ @override
+ bool visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
+ RedirectingConstructorInvocation other =
+ _other as RedirectingConstructorInvocation;
+ return isEqualTokens(node.thisKeyword, other.thisKeyword) &&
+ isEqualTokens(node.period, other.period) &&
+ isEqualNodes(node.constructorName, other.constructorName) &&
+ isEqualNodes(node.argumentList, other.argumentList);
+ }
+
+ @override
+ bool visitRethrowExpression(RethrowExpression node) {
+ RethrowExpression other = _other as RethrowExpression;
+ return isEqualTokens(node.rethrowKeyword, other.rethrowKeyword);
+ }
+
+ @override
+ bool visitReturnStatement(ReturnStatement node) {
+ ReturnStatement other = _other as ReturnStatement;
+ return isEqualTokens(node.returnKeyword, other.returnKeyword) &&
+ isEqualNodes(node.expression, other.expression) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitScriptTag(ScriptTag node) {
+ ScriptTag other = _other as ScriptTag;
+ return isEqualTokens(node.scriptTag, other.scriptTag);
+ }
+
+ @override
+ bool visitShowCombinator(ShowCombinator node) {
+ ShowCombinator other = _other as ShowCombinator;
+ return isEqualTokens(node.keyword, other.keyword) &&
+ _isEqualNodeLists(node.shownNames, other.shownNames);
+ }
+
+ @override
+ bool visitSimpleFormalParameter(SimpleFormalParameter node) {
+ SimpleFormalParameter other = _other as SimpleFormalParameter;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.keyword, other.keyword) &&
+ isEqualNodes(node.type, other.type) &&
+ isEqualNodes(node.identifier, other.identifier);
+ }
+
+ @override
+ bool visitSimpleIdentifier(SimpleIdentifier node) {
+ SimpleIdentifier other = _other as SimpleIdentifier;
+ return isEqualTokens(node.token, other.token);
+ }
+
+ @override
+ bool visitSimpleStringLiteral(SimpleStringLiteral node) {
+ SimpleStringLiteral other = _other as SimpleStringLiteral;
+ return isEqualTokens(node.literal, other.literal) &&
+ (node.value == other.value);
+ }
+
+ @override
+ bool visitStringInterpolation(StringInterpolation node) {
+ StringInterpolation other = _other as StringInterpolation;
+ return _isEqualNodeLists(node.elements, other.elements);
+ }
+
+ @override
+ bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ SuperConstructorInvocation other = _other as SuperConstructorInvocation;
+ return isEqualTokens(node.superKeyword, other.superKeyword) &&
+ isEqualTokens(node.period, other.period) &&
+ isEqualNodes(node.constructorName, other.constructorName) &&
+ isEqualNodes(node.argumentList, other.argumentList);
+ }
+
+ @override
+ bool visitSuperExpression(SuperExpression node) {
+ SuperExpression other = _other as SuperExpression;
+ return isEqualTokens(node.superKeyword, other.superKeyword);
+ }
+
+ @override
+ bool visitSwitchCase(SwitchCase node) {
+ SwitchCase other = _other as SwitchCase;
+ return _isEqualNodeLists(node.labels, other.labels) &&
+ isEqualTokens(node.keyword, other.keyword) &&
+ isEqualNodes(node.expression, other.expression) &&
+ isEqualTokens(node.colon, other.colon) &&
+ _isEqualNodeLists(node.statements, other.statements);
+ }
+
+ @override
+ bool visitSwitchDefault(SwitchDefault node) {
+ SwitchDefault other = _other as SwitchDefault;
+ return _isEqualNodeLists(node.labels, other.labels) &&
+ isEqualTokens(node.keyword, other.keyword) &&
+ isEqualTokens(node.colon, other.colon) &&
+ _isEqualNodeLists(node.statements, other.statements);
+ }
+
+ @override
+ bool visitSwitchStatement(SwitchStatement node) {
+ SwitchStatement other = _other as SwitchStatement;
+ return isEqualTokens(node.switchKeyword, other.switchKeyword) &&
+ isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ isEqualNodes(node.expression, other.expression) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+ isEqualTokens(node.leftBracket, other.leftBracket) &&
+ _isEqualNodeLists(node.members, other.members) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
+ bool visitSymbolLiteral(SymbolLiteral node) {
+ SymbolLiteral other = _other as SymbolLiteral;
+ return isEqualTokens(node.poundSign, other.poundSign) &&
+ _isEqualTokenLists(node.components, other.components);
+ }
+
+ @override
+ bool visitThisExpression(ThisExpression node) {
+ ThisExpression other = _other as ThisExpression;
+ return isEqualTokens(node.thisKeyword, other.thisKeyword);
+ }
+
+ @override
+ bool visitThrowExpression(ThrowExpression node) {
+ ThrowExpression other = _other as ThrowExpression;
+ return isEqualTokens(node.throwKeyword, other.throwKeyword) &&
+ isEqualNodes(node.expression, other.expression);
+ }
+
+ @override
+ bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ TopLevelVariableDeclaration other = _other as TopLevelVariableDeclaration;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualNodes(node.variables, other.variables) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitTryStatement(TryStatement node) {
+ TryStatement other = _other as TryStatement;
+ return isEqualTokens(node.tryKeyword, other.tryKeyword) &&
+ isEqualNodes(node.body, other.body) &&
+ _isEqualNodeLists(node.catchClauses, other.catchClauses) &&
+ isEqualTokens(node.finallyKeyword, other.finallyKeyword) &&
+ isEqualNodes(node.finallyBlock, other.finallyBlock);
+ }
+
+ @override
+ bool visitTypeArgumentList(TypeArgumentList node) {
+ TypeArgumentList other = _other as TypeArgumentList;
+ return isEqualTokens(node.leftBracket, other.leftBracket) &&
+ _isEqualNodeLists(node.arguments, other.arguments) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
+ bool visitTypeName(TypeName node) {
+ TypeName other = _other as TypeName;
+ return isEqualNodes(node.name, other.name) &&
+ isEqualNodes(node.typeArguments, other.typeArguments);
+ }
+
+ @override
+ bool visitTypeParameter(TypeParameter node) {
+ TypeParameter other = _other as TypeParameter;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualTokens(node.extendsKeyword, other.extendsKeyword) &&
+ isEqualNodes(node.bound, other.bound);
+ }
+
+ @override
+ bool visitTypeParameterList(TypeParameterList node) {
+ TypeParameterList other = _other as TypeParameterList;
+ return isEqualTokens(node.leftBracket, other.leftBracket) &&
+ _isEqualNodeLists(node.typeParameters, other.typeParameters) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
+ bool visitVariableDeclaration(VariableDeclaration node) {
+ VariableDeclaration other = _other as VariableDeclaration;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualTokens(node.equals, other.equals) &&
+ isEqualNodes(node.initializer, other.initializer);
+ }
+
+ @override
+ bool visitVariableDeclarationList(VariableDeclarationList node) {
+ VariableDeclarationList other = _other as VariableDeclarationList;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.keyword, other.keyword) &&
+ isEqualNodes(node.type, other.type) &&
+ _isEqualNodeLists(node.variables, other.variables);
+ }
+
+ @override
+ bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+ VariableDeclarationStatement other = _other as VariableDeclarationStatement;
+ return isEqualNodes(node.variables, other.variables) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ @override
+ bool visitWhileStatement(WhileStatement node) {
+ WhileStatement other = _other as WhileStatement;
+ return isEqualTokens(node.whileKeyword, other.whileKeyword) &&
+ isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+ isEqualNodes(node.condition, other.condition) &&
+ isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+ isEqualNodes(node.body, other.body);
+ }
+
+ @override
+ bool visitWithClause(WithClause node) {
+ WithClause other = _other as WithClause;
+ return isEqualTokens(node.withKeyword, other.withKeyword) &&
+ _isEqualNodeLists(node.mixinTypes, other.mixinTypes);
+ }
+
+ @override
+ bool visitYieldStatement(YieldStatement node) {
+ YieldStatement other = _other as YieldStatement;
+ return isEqualTokens(node.yieldKeyword, other.yieldKeyword) &&
+ isEqualNodes(node.expression, other.expression) &&
+ isEqualTokens(node.semicolon, other.semicolon);
+ }
+
+ /**
+ * Return `true` if the [first] and [second] lists of AST nodes have the same
+ * size and corresponding elements are equal.
+ */
+ bool _isEqualNodeLists(NodeList first, NodeList second) {
+ if (first == null) {
+ return second == null;
+ } else if (second == null) {
+ return false;
+ }
+ int size = first.length;
+ if (second.length != size) {
+ return false;
+ }
+ for (int i = 0; i < size; i++) {
+ if (!isEqualNodes(first[i], second[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Return `true` if the [first] and [second] lists of tokens have the same
+ * length and corresponding elements are equal.
+ */
+ bool _isEqualTokenLists(List<Token> first, List<Token> second) {
+ int length = first.length;
+ if (second.length != length) {
+ return false;
+ }
+ for (int i = 0; i < length; i++) {
+ if (!isEqualTokens(first[i], second[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Return `true` if the [first] and [second] nodes are equal.
+ */
+ static bool equalNodes(AstNode first, AstNode second) {
+ AstComparator comparator = new AstComparator();
+ return comparator.isEqualNodes(first, second);
+ }
+}
+
+/**
+ * Instances of the class [ConstantEvaluator] evaluate constant expressions to
+ * produce their compile-time value.
+ *
+ * According to the Dart Language Specification:
+ *
+ * > A constant expression is one of the following:
+ * >
+ * > * A literal number.
+ * > * A literal boolean.
+ * > * A literal string where any interpolated expression is a compile-time
+ * > constant that evaluates to a numeric, string or boolean value or to
+ * > **null**.
+ * > * A literal symbol.
+ * > * **null**.
+ * > * A qualified reference to a static constant variable.
+ * > * An identifier expression that denotes a constant variable, class or type
+ * > alias.
+ * > * A constant constructor invocation.
+ * > * A constant list literal.
+ * > * A constant map literal.
+ * > * A simple or qualified identifier denoting a top-level function or a
+ * > static method.
+ * > * A parenthesized expression _(e)_ where _e_ is a constant expression.
+ * > * <span>
+ * > An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
+ * > where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * > expressions and <i>identical()</i> is statically bound to the predefined
+ * > dart function <i>identical()</i> discussed above.
+ * > </span>
+ * > * <span>
+ * > An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i>
+ * > or <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
+ * > <i>e<sub>2</sub></i> are constant expressions that evaluate to a
+ * > numeric, string or boolean value.
+ * > </span>
+ * > * <span>
+ * > An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &&
+ * > e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where
+ * > <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * > expressions that evaluate to a boolean value.
+ * > </span>
+ * > * <span>
+ * > An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
+ * > e<sub>2</sub></i>, <i>e<sub>1</sub> & e<sub>2</sub></i>,
+ * > <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> >>
+ * > e<sub>2</sub></i> or <i>e<sub>1</sub> << e<sub>2</sub></i>, where
+ * > <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * > expressions that evaluate to an integer value or to <b>null</b>.
+ * > </span>
+ * > * <span>
+ * > An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
+ * > e<sub>2</sub></i>, <i>e<sub>1</sub> -e<sub>2</sub></i>,
+ * > <i>e<sub>1</sub> * e<sub>2</sub></i>, <i>e<sub>1</sub> /
+ * > e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ e<sub>2</sub></i>,
+ * > <i>e<sub>1</sub> > e<sub>2</sub></i>, <i>e<sub>1</sub> <
+ * > e<sub>2</sub></i>, <i>e<sub>1</sub> >= e<sub>2</sub></i>,
+ * > <i>e<sub>1</sub> <= e<sub>2</sub></i> or <i>e<sub>1</sub> %
+ * > e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i> and
+ * > <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric
+ * > value or to <b>null</b>.
+ * > </span>
+ * > * <span>
+ * > An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
+ * > e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
+ * > <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
+ * > evaluates to a boolean value.
+ * > </span>
+ *
+ * The values returned by instances of this class are therefore `null` and
+ * instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and
+ * `DartObject`.
+ *
+ * In addition, this class defines several values that can be returned to
+ * indicate various conditions encountered during evaluation. These are
+ * documented with the static fields that define those values.
+ */
+class ConstantEvaluator extends GeneralizingAstVisitor<Object> {
+ /**
+ * The value returned for expressions (or non-expression nodes) that are not
+ * compile-time constant expressions.
+ */
+ static Object NOT_A_CONSTANT = new Object();
+
+ @override
+ Object visitAdjacentStrings(AdjacentStrings node) {
+ StringBuffer buffer = new StringBuffer();
+ for (StringLiteral string in node.strings) {
+ Object value = string.accept(this);
+ if (identical(value, NOT_A_CONSTANT)) {
+ return value;
+ }
+ buffer.write(value);
+ }
+ return buffer.toString();
+ }
+
+ @override
+ Object visitBinaryExpression(BinaryExpression node) {
+ Object leftOperand = node.leftOperand.accept(this);
+ if (identical(leftOperand, NOT_A_CONSTANT)) {
+ return leftOperand;
+ }
+ Object rightOperand = node.rightOperand.accept(this);
+ if (identical(rightOperand, NOT_A_CONSTANT)) {
+ return rightOperand;
+ }
+ while (true) {
+ if (node.operator.type == TokenType.AMPERSAND) {
+ // integer or {@code null}
+ if (leftOperand is int && rightOperand is int) {
+ return leftOperand & rightOperand;
+ }
+ } else if (node.operator.type == TokenType.AMPERSAND_AMPERSAND) {
+ // boolean or {@code null}
+ if (leftOperand is bool && rightOperand is bool) {
+ return leftOperand && rightOperand;
+ }
+ } else if (node.operator.type == TokenType.BANG_EQ) {
+ // numeric, string, boolean, or {@code null}
+ if (leftOperand is bool && rightOperand is bool) {
+ return leftOperand != rightOperand;
+ } else if (leftOperand is num && rightOperand is num) {
+ return leftOperand != rightOperand;
+ } else if (leftOperand is String && rightOperand is String) {
+ return leftOperand != rightOperand;
+ }
+ } else if (node.operator.type == TokenType.BAR) {
+ // integer or {@code null}
+ if (leftOperand is int && rightOperand is int) {
+ return leftOperand | rightOperand;
+ }
+ } else if (node.operator.type == TokenType.BAR_BAR) {
+ // boolean or {@code null}
+ if (leftOperand is bool && rightOperand is bool) {
+ return leftOperand || rightOperand;
+ }
+ } else if (node.operator.type == TokenType.CARET) {
+ // integer or {@code null}
+ if (leftOperand is int && rightOperand is int) {
+ return leftOperand ^ rightOperand;
+ }
+ } else if (node.operator.type == TokenType.EQ_EQ) {
+ // numeric, string, boolean, or {@code null}
+ if (leftOperand is bool && rightOperand is bool) {
+ return leftOperand == rightOperand;
+ } else if (leftOperand is num && rightOperand is num) {
+ return leftOperand == rightOperand;
+ } else if (leftOperand is String && rightOperand is String) {
+ return leftOperand == rightOperand;
+ }
+ } else if (node.operator.type == TokenType.GT) {
+ // numeric or {@code null}
+ if (leftOperand is num && rightOperand is num) {
+ return leftOperand.compareTo(rightOperand) > 0;
+ }
+ } else if (node.operator.type == TokenType.GT_EQ) {
+ // numeric or {@code null}
+ if (leftOperand is num && rightOperand is num) {
+ return leftOperand.compareTo(rightOperand) >= 0;
+ }
+ } else if (node.operator.type == TokenType.GT_GT) {
+ // integer or {@code null}
+ if (leftOperand is int && rightOperand is int) {
+ return leftOperand >> rightOperand;
+ }
+ } else if (node.operator.type == TokenType.LT) {
+ // numeric or {@code null}
+ if (leftOperand is num && rightOperand is num) {
+ return leftOperand.compareTo(rightOperand) < 0;
+ }
+ } else if (node.operator.type == TokenType.LT_EQ) {
+ // numeric or {@code null}
+ if (leftOperand is num && rightOperand is num) {
+ return leftOperand.compareTo(rightOperand) <= 0;
+ }
+ } else if (node.operator.type == TokenType.LT_LT) {
+ // integer or {@code null}
+ if (leftOperand is int && rightOperand is int) {
+ return leftOperand << rightOperand;
+ }
+ } else if (node.operator.type == TokenType.MINUS) {
+ // numeric or {@code null}
+ if (leftOperand is num && rightOperand is num) {
+ return leftOperand - rightOperand;
+ }
+ } else if (node.operator.type == TokenType.PERCENT) {
+ // numeric or {@code null}
+ if (leftOperand is num && rightOperand is num) {
+ return leftOperand.remainder(rightOperand);
+ }
+ } else if (node.operator.type == TokenType.PLUS) {
+ // numeric or {@code null}
+ if (leftOperand is num && rightOperand is num) {
+ return leftOperand + rightOperand;
+ }
+ } else if (node.operator.type == TokenType.STAR) {
+ // numeric or {@code null}
+ if (leftOperand is num && rightOperand is num) {
+ return leftOperand * rightOperand;
+ }
+ } else if (node.operator.type == TokenType.SLASH) {
+ // numeric or {@code null}
+ if (leftOperand is num && rightOperand is num) {
+ return leftOperand / rightOperand;
+ }
+ } else if (node.operator.type == TokenType.TILDE_SLASH) {
+ // numeric or {@code null}
+ if (leftOperand is num && rightOperand is num) {
+ return leftOperand ~/ rightOperand;
+ }
+ } else {}
+ break;
+ }
+ // TODO(brianwilkerson) This doesn't handle numeric conversions.
+ return visitExpression(node);
+ }
+
+ @override
+ Object visitBooleanLiteral(BooleanLiteral node) => node.value ? true : false;
+
+ @override
+ Object visitDoubleLiteral(DoubleLiteral node) => node.value;
+
+ @override
+ Object visitIntegerLiteral(IntegerLiteral node) => node.value;
+
+ @override
+ Object visitInterpolationExpression(InterpolationExpression node) {
+ Object value = node.expression.accept(this);
+ if (value == null || value is bool || value is String || value is num) {
+ return value;
+ }
+ return NOT_A_CONSTANT;
+ }
+
+ @override
+ Object visitInterpolationString(InterpolationString node) => node.value;
+
+ @override
+ Object visitListLiteral(ListLiteral node) {
+ List<Object> list = new List<Object>();
+ for (Expression element in node.elements) {
+ Object value = element.accept(this);
+ if (identical(value, NOT_A_CONSTANT)) {
+ return value;
+ }
+ list.add(value);
+ }
+ return list;
+ }
+
+ @override
+ Object visitMapLiteral(MapLiteral node) {
+ HashMap<String, Object> map = new HashMap<String, Object>();
+ for (MapLiteralEntry entry in node.entries) {
+ Object key = entry.key.accept(this);
+ Object value = entry.value.accept(this);
+ if (key is! String || identical(value, NOT_A_CONSTANT)) {
+ return NOT_A_CONSTANT;
+ }
+ map[(key as String)] = value;
+ }
+ return map;
+ }
+
+ @override
+ Object visitMethodInvocation(MethodInvocation node) => visitNode(node);
+
+ @override
+ Object visitNode(AstNode node) => NOT_A_CONSTANT;
+
+ @override
+ Object visitNullLiteral(NullLiteral node) => null;
+
+ @override
+ Object visitParenthesizedExpression(ParenthesizedExpression node) =>
+ node.expression.accept(this);
+
+ @override
+ Object visitPrefixedIdentifier(PrefixedIdentifier node) =>
+ _getConstantValue(null);
+
+ @override
+ Object visitPrefixExpression(PrefixExpression node) {
+ Object operand = node.operand.accept(this);
+ if (identical(operand, NOT_A_CONSTANT)) {
+ return operand;
+ }
+ while (true) {
+ if (node.operator.type == TokenType.BANG) {
+ if (identical(operand, true)) {
+ return false;
+ } else if (identical(operand, false)) {
+ return true;
+ }
+ } else if (node.operator.type == TokenType.TILDE) {
+ if (operand is int) {
+ return ~operand;
+ }
+ } else if (node.operator.type == TokenType.MINUS) {
+ if (operand == null) {
+ return null;
+ } else if (operand is num) {
+ return -operand;
+ }
+ } else {}
+ break;
+ }
+ return NOT_A_CONSTANT;
+ }
+
+ @override
+ Object visitPropertyAccess(PropertyAccess node) => _getConstantValue(null);
+
+ @override
+ Object visitSimpleIdentifier(SimpleIdentifier node) =>
+ _getConstantValue(null);
+
+ @override
+ Object visitSimpleStringLiteral(SimpleStringLiteral node) => node.value;
+
+ @override
+ Object visitStringInterpolation(StringInterpolation node) {
+ StringBuffer buffer = new StringBuffer();
+ for (InterpolationElement element in node.elements) {
+ Object value = element.accept(this);
+ if (identical(value, NOT_A_CONSTANT)) {
+ return value;
+ }
+ buffer.write(value);
+ }
+ return buffer.toString();
+ }
+
+ @override
+ Object visitSymbolLiteral(SymbolLiteral node) {
+ // TODO(brianwilkerson) This isn't optimal because a Symbol is not a String.
+ StringBuffer buffer = new StringBuffer();
+ for (Token component in node.components) {
+ if (buffer.length > 0) {
+ buffer.writeCharCode(0x2E);
+ }
+ buffer.write(component.lexeme);
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Return the constant value of the static constant represented by the given
+ * [element].
+ */
+ Object _getConstantValue(Element element) {
+ // TODO(brianwilkerson) Implement this
+ if (element is FieldElement) {
+ FieldElement field = element;
+ if (field.isStatic && field.isConst) {
+ //field.getConstantValue();
+ }
+ // } else if (element instanceof VariableElement) {
+ // VariableElement variable = (VariableElement) element;
+ // if (variable.isStatic() && variable.isConst()) {
+ // //variable.getConstantValue();
+ // }
+ }
+ return NOT_A_CONSTANT;
+ }
+}
+
+/**
+ * A recursive AST visitor that is used to run over [Expression]s to determine
+ * whether the expression is composed by at least one deferred
+ * [PrefixedIdentifier].
+ *
+ * See [PrefixedIdentifier.isDeferred].
+ */
+class DeferredLibraryReferenceDetector extends RecursiveAstVisitor<Object> {
+ /**
+ * A flag indicating whether an identifier from a deferred library has been
+ * found.
+ */
+ bool _result = false;
+
+ /**
+ * Return `true` if the visitor found a [PrefixedIdentifier] that returned
+ * `true` to the [PrefixedIdentifier.isDeferred] query.
+ */
+ bool get result => _result;
+
+ @override
+ Object visitPrefixedIdentifier(PrefixedIdentifier node) {
+ if (!_result) {
+ if (node.isDeferred) {
+ _result = true;
+ }
+ }
+ return null;
+ }
+}
+
+/**
+ * An object used to locate the [Element] associated with a given [AstNode].
+ */
+class ElementLocator {
+ /**
+ * Return the element associated with the given [node], or `null` if there is
+ * no element associated with the node.
+ */
+ static Element locate(AstNode node) {
+ if (node == null) {
+ return null;
+ }
+ ElementLocator_ElementMapper mapper = new ElementLocator_ElementMapper();
+ return node.accept(mapper);
+ }
+}
+
+/**
+ * Visitor that maps nodes to elements.
+ */
+class ElementLocator_ElementMapper extends GeneralizingAstVisitor<Element> {
+ @override
+ Element visitAnnotation(Annotation node) => node.element;
+
+ @override
+ Element visitAssignmentExpression(AssignmentExpression node) =>
+ node.bestElement;
+
+ @override
+ Element visitBinaryExpression(BinaryExpression node) => node.bestElement;
+
+ @override
+ Element visitClassDeclaration(ClassDeclaration node) => node.element;
+
+ @override
+ Element visitCompilationUnit(CompilationUnit node) => node.element;
+
+ @override
+ Element visitConstructorDeclaration(ConstructorDeclaration node) =>
+ node.element;
+
+ @override
+ Element visitFunctionDeclaration(FunctionDeclaration node) => node.element;
+
+ @override
+ Element visitIdentifier(Identifier node) {
+ AstNode parent = node.parent;
+ // Type name in Annotation
+ if (parent is Annotation) {
+ Annotation annotation = parent;
+ if (identical(annotation.name, node) &&
+ annotation.constructorName == null) {
+ return annotation.element;
+ }
+ }
+ // Extra work to map Constructor Declarations to their associated
+ // Constructor Elements
+ if (parent is ConstructorDeclaration) {
+ Identifier returnType = parent.returnType;
+ if (identical(returnType, node)) {
+ SimpleIdentifier name = parent.name;
+ if (name != null) {
+ return name.bestElement;
+ }
+ Element element = node.bestElement;
+ if (element is ClassElement) {
+ return element.unnamedConstructor;
+ }
+ }
+ }
+ if (parent is LibraryIdentifier) {
+ AstNode grandParent = parent.parent;
+ if (grandParent is PartOfDirective) {
+ Element element = grandParent.element;
+ if (element is LibraryElement) {
+ return element.definingCompilationUnit;
+ }
+ }
+ }
+ return node.bestElement;
+ }
+
+ @override
+ Element visitImportDirective(ImportDirective node) => node.element;
+
+ @override
+ Element visitIndexExpression(IndexExpression node) => node.bestElement;
+
+ @override
+ Element visitInstanceCreationExpression(InstanceCreationExpression node) =>
+ node.staticElement;
+
+ @override
+ Element visitLibraryDirective(LibraryDirective node) => node.element;
+
+ @override
+ Element visitMethodDeclaration(MethodDeclaration node) => node.element;
+
+ @override
+ Element visitMethodInvocation(MethodInvocation node) =>
+ node.methodName.bestElement;
+
+ @override
+ Element visitPartOfDirective(PartOfDirective node) => node.element;
+
+ @override
+ Element visitPostfixExpression(PostfixExpression node) => node.bestElement;
+
+ @override
+ Element visitPrefixedIdentifier(PrefixedIdentifier node) => node.bestElement;
+
+ @override
+ Element visitPrefixExpression(PrefixExpression node) => node.bestElement;
+
+ @override
+ Element visitStringLiteral(StringLiteral node) {
+ AstNode parent = node.parent;
+ if (parent is UriBasedDirective) {
+ return parent.uriElement;
+ }
+ return null;
+ }
+
+ @override
+ Element visitVariableDeclaration(VariableDeclaration node) => node.element;
+}
+
+/**
+ * An object that will clone any AST structure that it visits. The cloner will
+ * clone the structure, replacing the specified ASTNode with a new ASTNode,
+ * mapping the old token stream to a new token stream, and preserving resolution
+ * results.
+ */
+class IncrementalAstCloner implements AstVisitor<AstNode> {
+ /**
+ * The node to be replaced during the cloning process.
+ */
+ final AstNode _oldNode;
+
+ /**
+ * The replacement node used during the cloning process.
+ */
+ final AstNode _newNode;
+
+ /**
+ * A mapping of old tokens to new tokens used during the cloning process.
+ */
+ final TokenMap _tokenMap;
+
+ /**
+ * Construct a new instance that will replace the [oldNode] with the [newNode]
+ * in the process of cloning an existing AST structure. The [tokenMap] is a
+ * mapping of old tokens to new tokens.
+ */
+ IncrementalAstCloner(this._oldNode, this._newNode, this._tokenMap);
+
+ @override
+ AdjacentStrings visitAdjacentStrings(AdjacentStrings node) =>
+ new AdjacentStrings(_cloneNodeList(node.strings));
+
+ @override
+ Annotation visitAnnotation(Annotation node) {
+ Annotation copy = new Annotation(
+ _mapToken(node.atSign),
+ _cloneNode(node.name),
+ _mapToken(node.period),
+ _cloneNode(node.constructorName),
+ _cloneNode(node.arguments));
+ copy.element = node.element;
+ return copy;
+ }
+
+ @override
+ ArgumentList visitArgumentList(ArgumentList node) => new ArgumentList(
+ _mapToken(node.leftParenthesis),
+ _cloneNodeList(node.arguments),
+ _mapToken(node.rightParenthesis));
+
+ @override
+ AsExpression visitAsExpression(AsExpression node) {
+ AsExpression copy = new AsExpression(_cloneNode(node.expression),
+ _mapToken(node.asOperator), _cloneNode(node.type));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ AstNode visitAssertStatement(AssertStatement node) => new AssertStatement(
+ _mapToken(node.assertKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.condition),
+ _mapToken(node.comma),
+ _cloneNode(node.message),
+ _mapToken(node.rightParenthesis),
+ _mapToken(node.semicolon));
+
+ @override
+ AssignmentExpression visitAssignmentExpression(AssignmentExpression node) {
+ AssignmentExpression copy = new AssignmentExpression(
+ _cloneNode(node.leftHandSide),
+ _mapToken(node.operator),
+ _cloneNode(node.rightHandSide));
+ copy.propagatedElement = node.propagatedElement;
+ copy.propagatedType = node.propagatedType;
+ copy.staticElement = node.staticElement;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ AwaitExpression visitAwaitExpression(AwaitExpression node) =>
+ new AwaitExpression(
+ _mapToken(node.awaitKeyword), _cloneNode(node.expression));
+
+ @override
+ BinaryExpression visitBinaryExpression(BinaryExpression node) {
+ BinaryExpression copy = new BinaryExpression(_cloneNode(node.leftOperand),
+ _mapToken(node.operator), _cloneNode(node.rightOperand));
+ copy.propagatedElement = node.propagatedElement;
+ copy.propagatedType = node.propagatedType;
+ copy.staticElement = node.staticElement;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ Block visitBlock(Block node) => new Block(_mapToken(node.leftBracket),
+ _cloneNodeList(node.statements), _mapToken(node.rightBracket));
+
+ @override
+ BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
+ new BlockFunctionBody(_mapToken(node.keyword), _mapToken(node.star),
+ _cloneNode(node.block));
+
+ @override
+ BooleanLiteral visitBooleanLiteral(BooleanLiteral node) {
+ BooleanLiteral copy =
+ new BooleanLiteral(_mapToken(node.literal), node.value);
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement(
+ _mapToken(node.breakKeyword),
+ _cloneNode(node.label),
+ _mapToken(node.semicolon));
+
+ @override
+ CascadeExpression visitCascadeExpression(CascadeExpression node) {
+ CascadeExpression copy = new CascadeExpression(
+ _cloneNode(node.target), _cloneNodeList(node.cascadeSections));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ CatchClause visitCatchClause(CatchClause node) => new CatchClause(
+ _mapToken(node.onKeyword),
+ _cloneNode(node.exceptionType),
+ _mapToken(node.catchKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.exceptionParameter),
+ _mapToken(node.comma),
+ _cloneNode(node.stackTraceParameter),
+ _mapToken(node.rightParenthesis),
+ _cloneNode(node.body));
+
+ @override
+ ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
+ ClassDeclaration copy = new ClassDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.abstractKeyword),
+ _mapToken(node.classKeyword),
+ _cloneNode(node.name),
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.extendsClause),
+ _cloneNode(node.withClause),
+ _cloneNode(node.implementsClause),
+ _mapToken(node.leftBracket),
+ _cloneNodeList(node.members),
+ _mapToken(node.rightBracket));
+ copy.nativeClause = _cloneNode(node.nativeClause);
+ return copy;
+ }
+
+ @override
+ ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.typedefKeyword),
+ _cloneNode(node.name),
+ _cloneNode(node.typeParameters),
+ _mapToken(node.equals),
+ _mapToken(node.abstractKeyword),
+ _cloneNode(node.superclass),
+ _cloneNode(node.withClause),
+ _cloneNode(node.implementsClause),
+ _mapToken(node.semicolon));
+
+ @override
+ Comment visitComment(Comment node) {
+ if (node.isDocumentation) {
+ return Comment.createDocumentationCommentWithReferences(
+ _mapTokens(node.tokens), _cloneNodeList(node.references));
+ } else if (node.isBlock) {
+ return Comment.createBlockComment(_mapTokens(node.tokens));
+ }
+ return Comment.createEndOfLineComment(_mapTokens(node.tokens));
+ }
+
+ @override
+ CommentReference visitCommentReference(CommentReference node) =>
+ new CommentReference(
+ _mapToken(node.newKeyword), _cloneNode(node.identifier));
+
+ @override
+ CompilationUnit visitCompilationUnit(CompilationUnit node) {
+ CompilationUnit copy = new CompilationUnit(
+ _mapToken(node.beginToken),
+ _cloneNode(node.scriptTag),
+ _cloneNodeList(node.directives),
+ _cloneNodeList(node.declarations),
+ _mapToken(node.endToken));
+ copy.lineInfo = node.lineInfo;
+ copy.element = node.element;
+ return copy;
+ }
+
+ @override
+ ConditionalExpression visitConditionalExpression(ConditionalExpression node) {
+ ConditionalExpression copy = new ConditionalExpression(
+ _cloneNode(node.condition),
+ _mapToken(node.question),
+ _cloneNode(node.thenExpression),
+ _mapToken(node.colon),
+ _cloneNode(node.elseExpression));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ Configuration visitConfiguration(Configuration node) => new Configuration(
+ _mapToken(node.ifKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.name),
+ _mapToken(node.equalToken),
+ _cloneNode(node.value),
+ _mapToken(node.rightParenthesis),
+ _cloneNode(node.libraryUri));
+
+ @override
+ ConstructorDeclaration visitConstructorDeclaration(
+ ConstructorDeclaration node) {
+ ConstructorDeclaration copy = new ConstructorDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.externalKeyword),
+ _mapToken(node.constKeyword),
+ _mapToken(node.factoryKeyword),
+ _cloneNode(node.returnType),
+ _mapToken(node.period),
+ _cloneNode(node.name),
+ _cloneNode(node.parameters),
+ _mapToken(node.separator),
+ _cloneNodeList(node.initializers),
+ _cloneNode(node.redirectedConstructor),
+ _cloneNode(node.body));
+ copy.element = node.element;
+ return copy;
+ }
+
+ @override
+ ConstructorFieldInitializer visitConstructorFieldInitializer(
+ ConstructorFieldInitializer node) =>
+ new ConstructorFieldInitializer(
+ _mapToken(node.thisKeyword),
+ _mapToken(node.period),
+ _cloneNode(node.fieldName),
+ _mapToken(node.equals),
+ _cloneNode(node.expression));
+
+ @override
+ ConstructorName visitConstructorName(ConstructorName node) {
+ ConstructorName copy = new ConstructorName(
+ _cloneNode(node.type), _mapToken(node.period), _cloneNode(node.name));
+ copy.staticElement = node.staticElement;
+ return copy;
+ }
+
+ @override
+ ContinueStatement visitContinueStatement(ContinueStatement node) =>
+ new ContinueStatement(_mapToken(node.continueKeyword),
+ _cloneNode(node.label), _mapToken(node.semicolon));
+
+ @override
+ DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
+ new DeclaredIdentifier(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.type),
+ _cloneNode(node.identifier));
+
+ @override
+ DefaultFormalParameter visitDefaultFormalParameter(
+ DefaultFormalParameter node) =>
+ new DefaultFormalParameter(_cloneNode(node.parameter), node.kind,
+ _mapToken(node.separator), _cloneNode(node.defaultValue));
+
+ @override
+ DoStatement visitDoStatement(DoStatement node) => new DoStatement(
+ _mapToken(node.doKeyword),
+ _cloneNode(node.body),
+ _mapToken(node.whileKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.condition),
+ _mapToken(node.rightParenthesis),
+ _mapToken(node.semicolon));
+
+ @override
+ DottedName visitDottedName(DottedName node) =>
+ new DottedName(_cloneNodeList(node.components));
+
+ @override
+ DoubleLiteral visitDoubleLiteral(DoubleLiteral node) {
+ DoubleLiteral copy = new DoubleLiteral(_mapToken(node.literal), node.value);
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) =>
+ new EmptyFunctionBody(_mapToken(node.semicolon));
+
+ @override
+ EmptyStatement visitEmptyStatement(EmptyStatement node) =>
+ new EmptyStatement(_mapToken(node.semicolon));
+
+ @override
+ AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
+ new EnumConstantDeclaration(_cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata), _cloneNode(node.name));
+
+ @override
+ AstNode visitEnumDeclaration(EnumDeclaration node) => new EnumDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.enumKeyword),
+ _cloneNode(node.name),
+ _mapToken(node.leftBracket),
+ _cloneNodeList(node.constants),
+ _mapToken(node.rightBracket));
+
+ @override
+ ExportDirective visitExportDirective(ExportDirective node) {
+ ExportDirective copy = new ExportDirective(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.uri),
+ _cloneNodeList(node.configurations),
+ _cloneNodeList(node.combinators),
+ _mapToken(node.semicolon));
+ copy.element = node.element;
+ return copy;
+ }
+
+ @override
+ ExpressionFunctionBody visitExpressionFunctionBody(
+ ExpressionFunctionBody node) =>
+ new ExpressionFunctionBody(
+ _mapToken(node.keyword),
+ _mapToken(node.functionDefinition),
+ _cloneNode(node.expression),
+ _mapToken(node.semicolon));
+
+ @override
+ ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
+ new ExpressionStatement(
+ _cloneNode(node.expression), _mapToken(node.semicolon));
+
+ @override
+ ExtendsClause visitExtendsClause(ExtendsClause node) => new ExtendsClause(
+ _mapToken(node.extendsKeyword), _cloneNode(node.superclass));
+
+ @override
+ FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
+ new FieldDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.staticKeyword),
+ _cloneNode(node.fields),
+ _mapToken(node.semicolon));
+
+ @override
+ FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
+ new FieldFormalParameter(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.type),
+ _mapToken(node.thisKeyword),
+ _mapToken(node.period),
+ _cloneNode(node.identifier),
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.parameters));
+
+ @override
+ ForEachStatement visitForEachStatement(ForEachStatement node) {
+ DeclaredIdentifier loopVariable = node.loopVariable;
+ if (loopVariable == null) {
+ return new ForEachStatement.withReference(
+ _mapToken(node.awaitKeyword),
+ _mapToken(node.forKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.identifier),
+ _mapToken(node.inKeyword),
+ _cloneNode(node.iterable),
+ _mapToken(node.rightParenthesis),
+ _cloneNode(node.body));
+ }
+ return new ForEachStatement.withDeclaration(
+ _mapToken(node.awaitKeyword),
+ _mapToken(node.forKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(loopVariable),
+ _mapToken(node.inKeyword),
+ _cloneNode(node.iterable),
+ _mapToken(node.rightParenthesis),
+ _cloneNode(node.body));
+ }
+
+ @override
+ FormalParameterList visitFormalParameterList(FormalParameterList node) =>
+ new FormalParameterList(
+ _mapToken(node.leftParenthesis),
+ _cloneNodeList(node.parameters),
+ _mapToken(node.leftDelimiter),
+ _mapToken(node.rightDelimiter),
+ _mapToken(node.rightParenthesis));
+
+ @override
+ ForStatement visitForStatement(ForStatement node) => new ForStatement(
+ _mapToken(node.forKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.variables),
+ _cloneNode(node.initialization),
+ _mapToken(node.leftSeparator),
+ _cloneNode(node.condition),
+ _mapToken(node.rightSeparator),
+ _cloneNodeList(node.updaters),
+ _mapToken(node.rightParenthesis),
+ _cloneNode(node.body));
+
+ @override
+ FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
+ new FunctionDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.externalKeyword),
+ _cloneNode(node.returnType),
+ _mapToken(node.propertyKeyword),
+ _cloneNode(node.name),
+ _cloneNode(node.functionExpression));
+
+ @override
+ FunctionDeclarationStatement visitFunctionDeclarationStatement(
+ FunctionDeclarationStatement node) =>
+ new FunctionDeclarationStatement(_cloneNode(node.functionDeclaration));
+
+ @override
+ FunctionExpression visitFunctionExpression(FunctionExpression node) {
+ FunctionExpression copy = new FunctionExpression(
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.parameters),
+ _cloneNode(node.body));
+ copy.element = node.element;
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ FunctionExpressionInvocation visitFunctionExpressionInvocation(
+ FunctionExpressionInvocation node) {
+ FunctionExpressionInvocation copy = new FunctionExpressionInvocation(
+ _cloneNode(node.function),
+ _cloneNode(node.typeArguments),
+ _cloneNode(node.argumentList));
+ copy.propagatedElement = node.propagatedElement;
+ copy.propagatedType = node.propagatedType;
+ copy.staticElement = node.staticElement;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
+ new FunctionTypeAlias(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.typedefKeyword),
+ _cloneNode(node.returnType),
+ _cloneNode(node.name),
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.parameters),
+ _mapToken(node.semicolon));
+
+ @override
+ FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
+ FunctionTypedFormalParameter node) =>
+ new FunctionTypedFormalParameter(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _cloneNode(node.returnType),
+ _cloneNode(node.identifier),
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.parameters));
+
+ @override
+ HideCombinator visitHideCombinator(HideCombinator node) => new HideCombinator(
+ _mapToken(node.keyword), _cloneNodeList(node.hiddenNames));
+
+ @override
+ IfStatement visitIfStatement(IfStatement node) => new IfStatement(
+ _mapToken(node.ifKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.condition),
+ _mapToken(node.rightParenthesis),
+ _cloneNode(node.thenStatement),
+ _mapToken(node.elseKeyword),
+ _cloneNode(node.elseStatement));
+
+ @override
+ ImplementsClause visitImplementsClause(ImplementsClause node) =>
+ new ImplementsClause(
+ _mapToken(node.implementsKeyword), _cloneNodeList(node.interfaces));
+
+ @override
+ ImportDirective visitImportDirective(ImportDirective node) =>
+ new ImportDirective(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.uri),
+ _cloneNodeList(node.configurations),
+ _mapToken(node.deferredKeyword),
+ _mapToken(node.asKeyword),
+ _cloneNode(node.prefix),
+ _cloneNodeList(node.combinators),
+ _mapToken(node.semicolon));
+
+ @override
+ IndexExpression visitIndexExpression(IndexExpression node) {
+ Token period = _mapToken(node.period);
+ IndexExpression copy;
+ if (period == null) {
+ copy = new IndexExpression.forTarget(
+ _cloneNode(node.target),
+ _mapToken(node.leftBracket),
+ _cloneNode(node.index),
+ _mapToken(node.rightBracket));
+ } else {
+ copy = new IndexExpression.forCascade(period, _mapToken(node.leftBracket),
+ _cloneNode(node.index), _mapToken(node.rightBracket));
+ }
+ copy.auxiliaryElements = node.auxiliaryElements;
+ copy.propagatedElement = node.propagatedElement;
+ copy.propagatedType = node.propagatedType;
+ copy.staticElement = node.staticElement;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ InstanceCreationExpression visitInstanceCreationExpression(
+ InstanceCreationExpression node) {
+ InstanceCreationExpression copy = new InstanceCreationExpression(
+ _mapToken(node.keyword),
+ _cloneNode(node.constructorName),
+ _cloneNode(node.argumentList));
+ copy.propagatedType = node.propagatedType;
+ copy.staticElement = node.staticElement;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ IntegerLiteral visitIntegerLiteral(IntegerLiteral node) {
+ IntegerLiteral copy =
+ new IntegerLiteral(_mapToken(node.literal), node.value);
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ InterpolationExpression visitInterpolationExpression(
+ InterpolationExpression node) =>
+ new InterpolationExpression(_mapToken(node.leftBracket),
+ _cloneNode(node.expression), _mapToken(node.rightBracket));
+
+ @override
+ InterpolationString visitInterpolationString(InterpolationString node) =>
+ new InterpolationString(_mapToken(node.contents), node.value);
+
+ @override
+ IsExpression visitIsExpression(IsExpression node) {
+ IsExpression copy = new IsExpression(
+ _cloneNode(node.expression),
+ _mapToken(node.isOperator),
+ _mapToken(node.notOperator),
+ _cloneNode(node.type));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ Label visitLabel(Label node) =>
+ new Label(_cloneNode(node.label), _mapToken(node.colon));
+
+ @override
+ LabeledStatement visitLabeledStatement(LabeledStatement node) =>
+ new LabeledStatement(
+ _cloneNodeList(node.labels), _cloneNode(node.statement));
+
+ @override
+ LibraryDirective visitLibraryDirective(LibraryDirective node) =>
+ new LibraryDirective(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.libraryKeyword),
+ _cloneNode(node.name),
+ _mapToken(node.semicolon));
+
+ @override
+ LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) {
+ LibraryIdentifier copy =
+ new LibraryIdentifier(_cloneNodeList(node.components));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ ListLiteral visitListLiteral(ListLiteral node) {
+ ListLiteral copy = new ListLiteral(
+ _mapToken(node.constKeyword),
+ _cloneNode(node.typeArguments),
+ _mapToken(node.leftBracket),
+ _cloneNodeList(node.elements),
+ _mapToken(node.rightBracket));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ MapLiteral visitMapLiteral(MapLiteral node) {
+ MapLiteral copy = new MapLiteral(
+ _mapToken(node.constKeyword),
+ _cloneNode(node.typeArguments),
+ _mapToken(node.leftBracket),
+ _cloneNodeList(node.entries),
+ _mapToken(node.rightBracket));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
+ new MapLiteralEntry(_cloneNode(node.key), _mapToken(node.separator),
+ _cloneNode(node.value));
+
+ @override
+ MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
+ new MethodDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.externalKeyword),
+ _mapToken(node.modifierKeyword),
+ _cloneNode(node.returnType),
+ _mapToken(node.propertyKeyword),
+ _mapToken(node.operatorKeyword),
+ _cloneNode(node.name),
+ _cloneNode(node.typeParameters),
+ _cloneNode(node.parameters),
+ _cloneNode(node.body));
+
+ @override
+ MethodInvocation visitMethodInvocation(MethodInvocation node) {
+ MethodInvocation copy = new MethodInvocation(
+ _cloneNode(node.target),
+ _mapToken(node.operator),
+ _cloneNode(node.methodName),
+ _cloneNode(node.typeArguments),
+ _cloneNode(node.argumentList));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ NamedExpression visitNamedExpression(NamedExpression node) {
+ NamedExpression copy =
+ new NamedExpression(_cloneNode(node.name), _cloneNode(node.expression));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ AstNode visitNativeClause(NativeClause node) =>
+ new NativeClause(_mapToken(node.nativeKeyword), _cloneNode(node.name));
+
+ @override
+ NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) =>
+ new NativeFunctionBody(_mapToken(node.nativeKeyword),
+ _cloneNode(node.stringLiteral), _mapToken(node.semicolon));
+
+ @override
+ NullLiteral visitNullLiteral(NullLiteral node) {
+ NullLiteral copy = new NullLiteral(_mapToken(node.literal));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ ParenthesizedExpression visitParenthesizedExpression(
+ ParenthesizedExpression node) {
+ ParenthesizedExpression copy = new ParenthesizedExpression(
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.expression),
+ _mapToken(node.rightParenthesis));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ PartDirective visitPartDirective(PartDirective node) {
+ PartDirective copy = new PartDirective(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.partKeyword),
+ _cloneNode(node.uri),
+ _mapToken(node.semicolon));
+ copy.element = node.element;
+ return copy;
+ }
+
+ @override
+ PartOfDirective visitPartOfDirective(PartOfDirective node) {
+ PartOfDirective copy = new PartOfDirective(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.partKeyword),
+ _mapToken(node.ofKeyword),
+ _cloneNode(node.libraryName),
+ _mapToken(node.semicolon));
+ copy.element = node.element;
+ return copy;
+ }
+
+ @override
+ PostfixExpression visitPostfixExpression(PostfixExpression node) {
+ PostfixExpression copy = new PostfixExpression(
+ _cloneNode(node.operand), _mapToken(node.operator));
+ copy.propagatedElement = node.propagatedElement;
+ copy.propagatedType = node.propagatedType;
+ copy.staticElement = node.staticElement;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) {
+ PrefixedIdentifier copy = new PrefixedIdentifier(_cloneNode(node.prefix),
+ _mapToken(node.period), _cloneNode(node.identifier));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ PrefixExpression visitPrefixExpression(PrefixExpression node) {
+ PrefixExpression copy = new PrefixExpression(
+ _mapToken(node.operator), _cloneNode(node.operand));
+ copy.propagatedElement = node.propagatedElement;
+ copy.propagatedType = node.propagatedType;
+ copy.staticElement = node.staticElement;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ PropertyAccess visitPropertyAccess(PropertyAccess node) {
+ PropertyAccess copy = new PropertyAccess(_cloneNode(node.target),
+ _mapToken(node.operator), _cloneNode(node.propertyName));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
+ RedirectingConstructorInvocation copy =
+ new RedirectingConstructorInvocation(
+ _mapToken(node.thisKeyword),
+ _mapToken(node.period),
+ _cloneNode(node.constructorName),
+ _cloneNode(node.argumentList));
+ copy.staticElement = node.staticElement;
+ return copy;
+ }
+
+ @override
+ RethrowExpression visitRethrowExpression(RethrowExpression node) {
+ RethrowExpression copy =
+ new RethrowExpression(_mapToken(node.rethrowKeyword));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ ReturnStatement visitReturnStatement(ReturnStatement node) =>
+ new ReturnStatement(_mapToken(node.returnKeyword),
+ _cloneNode(node.expression), _mapToken(node.semicolon));
+
+ @override
+ ScriptTag visitScriptTag(ScriptTag node) =>
+ new ScriptTag(_mapToken(node.scriptTag));
+
+ @override
+ ShowCombinator visitShowCombinator(ShowCombinator node) => new ShowCombinator(
+ _mapToken(node.keyword), _cloneNodeList(node.shownNames));
+
+ @override
+ SimpleFormalParameter visitSimpleFormalParameter(
+ SimpleFormalParameter node) =>
+ new SimpleFormalParameter(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.type),
+ _cloneNode(node.identifier));
+
+ @override
+ SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
+ Token mappedToken = _mapToken(node.token);
+ if (mappedToken == null) {
+ // This only happens for SimpleIdentifiers created by the parser as part
+ // of scanning documentation comments (the tokens for those identifiers
+ // are not in the original token stream and hence do not get copied).
+ // This extra check can be removed if the scanner is changed to scan
+ // documentation comments for the parser.
+ mappedToken = node.token;
+ }
+ SimpleIdentifier copy = new SimpleIdentifier(mappedToken);
+ copy.auxiliaryElements = node.auxiliaryElements;
+ copy.propagatedElement = node.propagatedElement;
+ copy.propagatedType = node.propagatedType;
+ copy.staticElement = node.staticElement;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) {
+ SimpleStringLiteral copy =
+ new SimpleStringLiteral(_mapToken(node.literal), node.value);
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ StringInterpolation visitStringInterpolation(StringInterpolation node) {
+ StringInterpolation copy =
+ new StringInterpolation(_cloneNodeList(node.elements));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ SuperConstructorInvocation visitSuperConstructorInvocation(
+ SuperConstructorInvocation node) {
+ SuperConstructorInvocation copy = new SuperConstructorInvocation(
+ _mapToken(node.superKeyword),
+ _mapToken(node.period),
+ _cloneNode(node.constructorName),
+ _cloneNode(node.argumentList));
+ copy.staticElement = node.staticElement;
+ return copy;
+ }
+
+ @override
+ SuperExpression visitSuperExpression(SuperExpression node) {
+ SuperExpression copy = new SuperExpression(_mapToken(node.superKeyword));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ SwitchCase visitSwitchCase(SwitchCase node) => new SwitchCase(
+ _cloneNodeList(node.labels),
+ _mapToken(node.keyword),
+ _cloneNode(node.expression),
+ _mapToken(node.colon),
+ _cloneNodeList(node.statements));
+
+ @override
+ SwitchDefault visitSwitchDefault(SwitchDefault node) => new SwitchDefault(
+ _cloneNodeList(node.labels),
+ _mapToken(node.keyword),
+ _mapToken(node.colon),
+ _cloneNodeList(node.statements));
+
+ @override
+ SwitchStatement visitSwitchStatement(SwitchStatement node) =>
+ new SwitchStatement(
+ _mapToken(node.switchKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.expression),
+ _mapToken(node.rightParenthesis),
+ _mapToken(node.leftBracket),
+ _cloneNodeList(node.members),
+ _mapToken(node.rightBracket));
+
+ @override
+ AstNode visitSymbolLiteral(SymbolLiteral node) {
+ SymbolLiteral copy = new SymbolLiteral(
+ _mapToken(node.poundSign), _mapTokens(node.components));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ ThisExpression visitThisExpression(ThisExpression node) {
+ ThisExpression copy = new ThisExpression(_mapToken(node.thisKeyword));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ ThrowExpression visitThrowExpression(ThrowExpression node) {
+ ThrowExpression copy = new ThrowExpression(
+ _mapToken(node.throwKeyword), _cloneNode(node.expression));
+ copy.propagatedType = node.propagatedType;
+ copy.staticType = node.staticType;
+ return copy;
+ }
+
+ @override
+ TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
+ TopLevelVariableDeclaration node) =>
+ new TopLevelVariableDeclaration(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _cloneNode(node.variables),
+ _mapToken(node.semicolon));
+
+ @override
+ TryStatement visitTryStatement(TryStatement node) => new TryStatement(
+ _mapToken(node.tryKeyword),
+ _cloneNode(node.body),
+ _cloneNodeList(node.catchClauses),
+ _mapToken(node.finallyKeyword),
+ _cloneNode(node.finallyBlock));
+
+ @override
+ TypeArgumentList visitTypeArgumentList(TypeArgumentList node) =>
+ new TypeArgumentList(_mapToken(node.leftBracket),
+ _cloneNodeList(node.arguments), _mapToken(node.rightBracket));
+
+ @override
+ TypeName visitTypeName(TypeName node) {
+ TypeName copy =
+ new TypeName(_cloneNode(node.name), _cloneNode(node.typeArguments));
+ copy.type = node.type;
+ return copy;
+ }
+
+ @override
+ TypeParameter visitTypeParameter(TypeParameter node) => new TypeParameter(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _cloneNode(node.name),
+ _mapToken(node.extendsKeyword),
+ _cloneNode(node.bound));
+
+ @override
+ TypeParameterList visitTypeParameterList(TypeParameterList node) =>
+ new TypeParameterList(_mapToken(node.leftBracket),
+ _cloneNodeList(node.typeParameters), _mapToken(node.rightBracket));
+
+ @override
+ VariableDeclaration visitVariableDeclaration(VariableDeclaration node) =>
+ new VariableDeclaration(_cloneNode(node.name), _mapToken(node.equals),
+ _cloneNode(node.initializer));
+
+ @override
+ VariableDeclarationList visitVariableDeclarationList(
+ VariableDeclarationList node) =>
+ new VariableDeclarationList(
+ null,
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.type),
+ _cloneNodeList(node.variables));
+
+ @override
+ VariableDeclarationStatement visitVariableDeclarationStatement(
+ VariableDeclarationStatement node) =>
+ new VariableDeclarationStatement(
+ _cloneNode(node.variables), _mapToken(node.semicolon));
+
+ @override
+ WhileStatement visitWhileStatement(WhileStatement node) => new WhileStatement(
+ _mapToken(node.whileKeyword),
+ _mapToken(node.leftParenthesis),
+ _cloneNode(node.condition),
+ _mapToken(node.rightParenthesis),
+ _cloneNode(node.body));
+
+ @override
+ WithClause visitWithClause(WithClause node) => new WithClause(
+ _mapToken(node.withKeyword), _cloneNodeList(node.mixinTypes));
+
+ @override
+ YieldStatement visitYieldStatement(YieldStatement node) => new YieldStatement(
+ _mapToken(node.yieldKeyword),
+ _mapToken(node.star),
+ _cloneNode(node.expression),
+ _mapToken(node.semicolon));
+
+ AstNode _cloneNode(AstNode node) {
+ if (node == null) {
+ return null;
+ }
+ if (identical(node, _oldNode)) {
+ return _newNode;
+ }
+ return node.accept(this) as AstNode;
+ }
+
+ List _cloneNodeList(NodeList nodes) {
+ List clonedNodes = new List();
+ for (AstNode node in nodes) {
+ clonedNodes.add(_cloneNode(node));
+ }
+ return clonedNodes;
+ }
+
+ Token _mapToken(Token oldToken) {
+ if (oldToken == null) {
+ return null;
+ }
+ return _tokenMap.get(oldToken);
+ }
+
+ List<Token> _mapTokens(List<Token> oldTokens) {
+ List<Token> newTokens = new List<Token>(oldTokens.length);
+ for (int index = 0; index < newTokens.length; index++) {
+ newTokens[index] = _mapToken(oldTokens[index]);
+ }
+ return newTokens;
+ }
+}
+
+/**
+ * An object used to locate the [AstNode] associated with a source range, given
+ * the AST structure built from the source. More specifically, they will return
+ * the [AstNode] with the shortest length whose source range completely
+ * encompasses the specified range.
+ */
+class NodeLocator extends UnifyingAstVisitor<Object> {
+ /**
+ * The start offset of the range used to identify the node.
+ */
+ int _startOffset = 0;
+
+ /**
+ * The end offset of the range used to identify the node.
+ */
+ int _endOffset = 0;
+
+ /**
+ * The element that was found that corresponds to the given source range, or
+ * `null` if there is no such element.
+ */
+ AstNode _foundNode;
+
+ /**
+ * Initialize a newly created locator to locate an [AstNode] by locating the
+ * node within an AST structure that corresponds to the given range of
+ * characters (between the [startOffset] and [endOffset] in the source.
+ */
+ NodeLocator(int startOffset, [int endOffset])
+ : this._startOffset = startOffset,
+ this._endOffset = endOffset == null ? startOffset : endOffset;
+
+ /**
+ * Return the node that was found that corresponds to the given source range
+ * or `null` if there is no such node.
+ */
+ AstNode get foundNode => _foundNode;
+
+ /**
+ * Search within the given AST [node] for an identifier representing an
+ * element in the specified source range. Return the element that was found,
+ * or `null` if no element was found.
+ */
+ AstNode searchWithin(AstNode node) {
+ if (node == null) {
+ return null;
+ }
+ try {
+ node.accept(this);
+ } on NodeLocator_NodeFoundException {
+ // A node with the right source position was found.
+ } catch (exception, stackTrace) {
+ AnalysisEngine.instance.logger.logInformation(
+ "Unable to locate element at offset ($_startOffset - $_endOffset)",
+ new CaughtException(exception, stackTrace));
+ return null;
+ }
+ return _foundNode;
+ }
+
+ @override
+ Object visitNode(AstNode node) {
+ Token beginToken = node.beginToken;
+ Token endToken = node.endToken;
+ // Don't include synthetic tokens.
+ while (endToken != beginToken) {
+ if (endToken.type == TokenType.EOF || !endToken.isSynthetic) {
+ break;
+ }
+ endToken = endToken.previous;
+ }
+ int end = endToken.end;
+ int start = node.offset;
+ if (end < _startOffset) {
+ return null;
+ }
+ if (start > _endOffset) {
+ return null;
+ }
+ try {
+ node.visitChildren(this);
+ } on NodeLocator_NodeFoundException {
+ rethrow;
+ } catch (exception, stackTrace) {
+ // Ignore the exception and proceed in order to visit the rest of the
+ // structure.
+ AnalysisEngine.instance.logger.logInformation(
+ "Exception caught while traversing an AST structure.",
+ new CaughtException(exception, stackTrace));
+ }
+ if (start <= _startOffset && _endOffset <= end) {
+ _foundNode = node;
+ throw new NodeLocator_NodeFoundException();
+ }
+ return null;
+ }
+}
+
+/**
+ * An object used to locate the [AstNode] associated with a source range.
+ * More specifically, they will return the deepest [AstNode] which completely
+ * encompasses the specified range.
+ */
+class NodeLocator2 extends UnifyingAstVisitor<Object> {
+ /**
+ * The inclusive start offset of the range used to identify the node.
+ */
+ int _startOffset = 0;
+
+ /**
+ * The inclusive end offset of the range used to identify the node.
+ */
+ int _endOffset = 0;
+
+ /**
+ * The found node or `null` if there is no such node.
+ */
+ AstNode _foundNode;
+
+ /**
+ * Initialize a newly created locator to locate the deepest [AstNode] for
+ * which `node.offset <= [startOffset]` and `[endOffset] < node.end`.
+ *
+ * If [endOffset] is not provided, then it is considered the same as the
+ * given [startOffset].
+ */
+ NodeLocator2(int startOffset, [int endOffset])
+ : this._startOffset = startOffset,
+ this._endOffset = endOffset == null ? startOffset : endOffset;
+
+ /**
+ * Search within the given AST [node] and return the node that was found,
+ * or `null` if no node was found.
+ */
+ AstNode searchWithin(AstNode node) {
+ if (node == null) {
+ return null;
+ }
+ try {
+ node.accept(this);
+ } on NodeLocator_NodeFoundException {} catch (exception, stackTrace) {
+ AnalysisEngine.instance.logger.logInformation(
+ "Unable to locate element at offset ($_startOffset - $_endOffset)",
+ new CaughtException(exception, stackTrace));
+ return null;
+ }
+ return _foundNode;
+ }
+
+ @override
+ Object visitNode(AstNode node) {
+ Token beginToken = node.beginToken;
+ Token endToken = node.endToken;
+ // Don't include synthetic tokens.
+ while (endToken != beginToken) {
+ if (endToken.type == TokenType.EOF || !endToken.isSynthetic) {
+ break;
+ }
+ endToken = endToken.previous;
+ }
+ int end = endToken.end;
+ int start = node.offset;
+ if (end <= _startOffset) {
+ return null;
+ }
+ if (start > _endOffset) {
+ return null;
+ }
+ try {
+ node.visitChildren(this);
+ } on NodeLocator_NodeFoundException {
+ rethrow;
+ } catch (exception, stackTrace) {
+ // Ignore the exception and proceed in order to visit the rest of the
+ // structure.
+ AnalysisEngine.instance.logger.logInformation(
+ "Exception caught while traversing an AST structure.",
+ new CaughtException(exception, stackTrace));
+ }
+ if (start <= _startOffset && _endOffset < end) {
+ _foundNode = node;
+ throw new NodeLocator_NodeFoundException();
+ }
+ return null;
+ }
+}
+
+/**
+ * An exception used by [NodeLocator] to cancel visiting after a node has been
+ * found.
+ */
+class NodeLocator_NodeFoundException extends RuntimeException {}
+
+/**
+ * An object that will replace one child node in an AST node with another node.
+ */
+class NodeReplacer implements AstVisitor<bool> {
+ /**
+ * The node being replaced.
+ */
+ final AstNode _oldNode;
+
+ /**
+ * The node that is replacing the old node.
+ */
+ final AstNode _newNode;
+
+ /**
+ * Initialize a newly created node locator to replace the [_oldNode] with the
+ * [_newNode].
+ */
+ NodeReplacer(this._oldNode, this._newNode);
+
+ @override
+ bool visitAdjacentStrings(AdjacentStrings node) {
+ if (_replaceInList(node.strings)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ bool visitAnnotatedNode(AnnotatedNode node) {
+ if (identical(node.documentationComment, _oldNode)) {
+ node.documentationComment = _newNode as Comment;
+ return true;
+ } else if (_replaceInList(node.metadata)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitAnnotation(Annotation node) {
+ if (identical(node.arguments, _oldNode)) {
+ node.arguments = _newNode as ArgumentList;
+ return true;
+ } else if (identical(node.constructorName, _oldNode)) {
+ node.constructorName = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.name, _oldNode)) {
+ node.name = _newNode as Identifier;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitArgumentList(ArgumentList node) {
+ if (_replaceInList(node.arguments)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitAsExpression(AsExpression node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ } else if (identical(node.type, _oldNode)) {
+ node.type = _newNode as TypeName;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitAssertStatement(AssertStatement node) {
+ if (identical(node.condition, _oldNode)) {
+ node.condition = _newNode as Expression;
+ return true;
+ }
+ if (identical(node.message, _oldNode)) {
+ node.message = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitAssignmentExpression(AssignmentExpression node) {
+ if (identical(node.leftHandSide, _oldNode)) {
+ node.leftHandSide = _newNode as Expression;
+ return true;
+ } else if (identical(node.rightHandSide, _oldNode)) {
+ node.rightHandSide = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitAwaitExpression(AwaitExpression node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitBinaryExpression(BinaryExpression node) {
+ if (identical(node.leftOperand, _oldNode)) {
+ node.leftOperand = _newNode as Expression;
+ return true;
+ } else if (identical(node.rightOperand, _oldNode)) {
+ node.rightOperand = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitBlock(Block node) {
+ if (_replaceInList(node.statements)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitBlockFunctionBody(BlockFunctionBody node) {
+ if (identical(node.block, _oldNode)) {
+ node.block = _newNode as Block;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitBooleanLiteral(BooleanLiteral node) => visitNode(node);
+
+ @override
+ bool visitBreakStatement(BreakStatement node) {
+ if (identical(node.label, _oldNode)) {
+ node.label = _newNode as SimpleIdentifier;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitCascadeExpression(CascadeExpression node) {
+ if (identical(node.target, _oldNode)) {
+ node.target = _newNode as Expression;
+ return true;
+ } else if (_replaceInList(node.cascadeSections)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitCatchClause(CatchClause node) {
+ if (identical(node.exceptionType, _oldNode)) {
+ node.exceptionType = _newNode as TypeName;
+ return true;
+ } else if (identical(node.exceptionParameter, _oldNode)) {
+ node.exceptionParameter = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.stackTraceParameter, _oldNode)) {
+ node.stackTraceParameter = _newNode as SimpleIdentifier;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitClassDeclaration(ClassDeclaration node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.typeParameters, _oldNode)) {
+ node.typeParameters = _newNode as TypeParameterList;
+ return true;
+ } else if (identical(node.extendsClause, _oldNode)) {
+ node.extendsClause = _newNode as ExtendsClause;
+ return true;
+ } else if (identical(node.withClause, _oldNode)) {
+ node.withClause = _newNode as WithClause;
+ return true;
+ } else if (identical(node.implementsClause, _oldNode)) {
+ node.implementsClause = _newNode as ImplementsClause;
+ return true;
+ } else if (identical(node.nativeClause, _oldNode)) {
+ node.nativeClause = _newNode as NativeClause;
+ return true;
+ } else if (_replaceInList(node.members)) {
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitClassTypeAlias(ClassTypeAlias node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.typeParameters, _oldNode)) {
+ node.typeParameters = _newNode as TypeParameterList;
+ return true;
+ } else if (identical(node.superclass, _oldNode)) {
+ node.superclass = _newNode as TypeName;
+ return true;
+ } else if (identical(node.withClause, _oldNode)) {
+ node.withClause = _newNode as WithClause;
+ return true;
+ } else if (identical(node.implementsClause, _oldNode)) {
+ node.implementsClause = _newNode as ImplementsClause;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitComment(Comment node) {
+ if (_replaceInList(node.references)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitCommentReference(CommentReference node) {
+ if (identical(node.identifier, _oldNode)) {
+ node.identifier = _newNode as Identifier;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitCompilationUnit(CompilationUnit node) {
+ if (identical(node.scriptTag, _oldNode)) {
+ node.scriptTag = _newNode as ScriptTag;
+ return true;
+ } else if (_replaceInList(node.directives)) {
+ return true;
+ } else if (_replaceInList(node.declarations)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitConditionalExpression(ConditionalExpression node) {
+ if (identical(node.condition, _oldNode)) {
+ node.condition = _newNode as Expression;
+ return true;
+ } else if (identical(node.thenExpression, _oldNode)) {
+ node.thenExpression = _newNode as Expression;
+ return true;
+ } else if (identical(node.elseExpression, _oldNode)) {
+ node.elseExpression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitConfiguration(Configuration node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as DottedName;
+ return true;
+ } else if (identical(node.value, _oldNode)) {
+ node.value = _newNode as StringLiteral;
+ return true;
+ } else if (identical(node.libraryUri, _oldNode)) {
+ node.libraryUri = _newNode as StringLiteral;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitConstructorDeclaration(ConstructorDeclaration node) {
+ if (identical(node.returnType, _oldNode)) {
+ node.returnType = _newNode as Identifier;
+ return true;
+ } else if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.parameters, _oldNode)) {
+ node.parameters = _newNode as FormalParameterList;
+ return true;
+ } else if (identical(node.redirectedConstructor, _oldNode)) {
+ node.redirectedConstructor = _newNode as ConstructorName;
+ return true;
+ } else if (identical(node.body, _oldNode)) {
+ node.body = _newNode as FunctionBody;
+ return true;
+ } else if (_replaceInList(node.initializers)) {
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+ if (identical(node.fieldName, _oldNode)) {
+ node.fieldName = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitConstructorName(ConstructorName node) {
+ if (identical(node.type, _oldNode)) {
+ node.type = _newNode as TypeName;
+ return true;
+ } else if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitContinueStatement(ContinueStatement node) {
+ if (identical(node.label, _oldNode)) {
+ node.label = _newNode as SimpleIdentifier;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitDeclaredIdentifier(DeclaredIdentifier node) {
+ if (identical(node.type, _oldNode)) {
+ node.type = _newNode as TypeName;
+ return true;
+ } else if (identical(node.identifier, _oldNode)) {
+ node.identifier = _newNode as SimpleIdentifier;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitDefaultFormalParameter(DefaultFormalParameter node) {
+ if (identical(node.parameter, _oldNode)) {
+ node.parameter = _newNode as NormalFormalParameter;
+ return true;
+ } else if (identical(node.defaultValue, _oldNode)) {
+ node.defaultValue = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitDoStatement(DoStatement node) {
+ if (identical(node.body, _oldNode)) {
+ node.body = _newNode as Statement;
+ return true;
+ } else if (identical(node.condition, _oldNode)) {
+ node.condition = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitDottedName(DottedName node) {
+ if (_replaceInList(node.components)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitDoubleLiteral(DoubleLiteral node) => visitNode(node);
+
+ @override
+ bool visitEmptyFunctionBody(EmptyFunctionBody node) => visitNode(node);
+
+ @override
+ bool visitEmptyStatement(EmptyStatement node) => visitNode(node);
+
+ @override
+ bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitEnumDeclaration(EnumDeclaration node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ } else if (_replaceInList(node.constants)) {
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitExportDirective(ExportDirective node) =>
+ visitNamespaceDirective(node);
+
+ @override
+ bool visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitExpressionStatement(ExpressionStatement node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitExtendsClause(ExtendsClause node) {
+ if (identical(node.superclass, _oldNode)) {
+ node.superclass = _newNode as TypeName;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitFieldDeclaration(FieldDeclaration node) {
+ if (identical(node.fields, _oldNode)) {
+ node.fields = _newNode as VariableDeclarationList;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitFieldFormalParameter(FieldFormalParameter node) {
+ if (identical(node.type, _oldNode)) {
+ node.type = _newNode as TypeName;
+ return true;
+ } else if (identical(node.parameters, _oldNode)) {
+ node.parameters = _newNode as FormalParameterList;
+ return true;
+ }
+ return visitNormalFormalParameter(node);
+ }
+
+ @override
+ bool visitForEachStatement(ForEachStatement node) {
+ if (identical(node.loopVariable, _oldNode)) {
+ node.loopVariable = _newNode as DeclaredIdentifier;
+ return true;
+ } else if (identical(node.identifier, _oldNode)) {
+ node.identifier = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.iterable, _oldNode)) {
+ node.iterable = _newNode as Expression;
+ return true;
+ } else if (identical(node.body, _oldNode)) {
+ node.body = _newNode as Statement;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitFormalParameterList(FormalParameterList node) {
+ if (_replaceInList(node.parameters)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitForStatement(ForStatement node) {
+ if (identical(node.variables, _oldNode)) {
+ node.variables = _newNode as VariableDeclarationList;
+ return true;
+ } else if (identical(node.initialization, _oldNode)) {
+ node.initialization = _newNode as Expression;
+ return true;
+ } else if (identical(node.condition, _oldNode)) {
+ node.condition = _newNode as Expression;
+ return true;
+ } else if (identical(node.body, _oldNode)) {
+ node.body = _newNode as Statement;
+ return true;
+ } else if (_replaceInList(node.updaters)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitFunctionDeclaration(FunctionDeclaration node) {
+ if (identical(node.returnType, _oldNode)) {
+ node.returnType = _newNode as TypeName;
+ return true;
+ } else if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.functionExpression, _oldNode)) {
+ node.functionExpression = _newNode as FunctionExpression;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+ if (identical(node.functionDeclaration, _oldNode)) {
+ node.functionDeclaration = _newNode as FunctionDeclaration;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitFunctionExpression(FunctionExpression node) {
+ if (identical(node.parameters, _oldNode)) {
+ node.parameters = _newNode as FormalParameterList;
+ return true;
+ } else if (identical(node.body, _oldNode)) {
+ node.body = _newNode as FunctionBody;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ if (identical(node.function, _oldNode)) {
+ node.function = _newNode as Expression;
+ return true;
+ } else if (identical(node.argumentList, _oldNode)) {
+ node.argumentList = _newNode as ArgumentList;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitFunctionTypeAlias(FunctionTypeAlias node) {
+ if (identical(node.returnType, _oldNode)) {
+ node.returnType = _newNode as TypeName;
+ return true;
+ } else if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.typeParameters, _oldNode)) {
+ node.typeParameters = _newNode as TypeParameterList;
+ return true;
+ } else if (identical(node.parameters, _oldNode)) {
+ node.parameters = _newNode as FormalParameterList;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+ if (identical(node.returnType, _oldNode)) {
+ node.returnType = _newNode as TypeName;
+ return true;
+ } else if (identical(node.parameters, _oldNode)) {
+ node.parameters = _newNode as FormalParameterList;
+ return true;
+ }
+ return visitNormalFormalParameter(node);
+ }
+
+ @override
+ bool visitHideCombinator(HideCombinator node) {
+ if (_replaceInList(node.hiddenNames)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitIfStatement(IfStatement node) {
+ if (identical(node.condition, _oldNode)) {
+ node.condition = _newNode as Expression;
+ return true;
+ } else if (identical(node.thenStatement, _oldNode)) {
+ node.thenStatement = _newNode as Statement;
+ return true;
+ } else if (identical(node.elseStatement, _oldNode)) {
+ node.elseStatement = _newNode as Statement;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitImplementsClause(ImplementsClause node) {
+ if (_replaceInList(node.interfaces)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitImportDirective(ImportDirective node) {
+ if (identical(node.prefix, _oldNode)) {
+ node.prefix = _newNode as SimpleIdentifier;
+ return true;
+ }
+ return visitNamespaceDirective(node);
+ }
+
+ @override
+ bool visitIndexExpression(IndexExpression node) {
+ if (identical(node.target, _oldNode)) {
+ node.target = _newNode as Expression;
+ return true;
+ } else if (identical(node.index, _oldNode)) {
+ node.index = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitInstanceCreationExpression(InstanceCreationExpression node) {
+ if (identical(node.constructorName, _oldNode)) {
+ node.constructorName = _newNode as ConstructorName;
+ return true;
+ } else if (identical(node.argumentList, _oldNode)) {
+ node.argumentList = _newNode as ArgumentList;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitIntegerLiteral(IntegerLiteral node) => visitNode(node);
+
+ @override
+ bool visitInterpolationExpression(InterpolationExpression node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitInterpolationString(InterpolationString node) => visitNode(node);
+
+ @override
+ bool visitIsExpression(IsExpression node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ } else if (identical(node.type, _oldNode)) {
+ node.type = _newNode as TypeName;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitLabel(Label node) {
+ if (identical(node.label, _oldNode)) {
+ node.label = _newNode as SimpleIdentifier;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitLabeledStatement(LabeledStatement node) {
+ if (identical(node.statement, _oldNode)) {
+ node.statement = _newNode as Statement;
+ return true;
+ } else if (_replaceInList(node.labels)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitLibraryDirective(LibraryDirective node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as LibraryIdentifier;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitLibraryIdentifier(LibraryIdentifier node) {
+ if (_replaceInList(node.components)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitListLiteral(ListLiteral node) {
+ if (_replaceInList(node.elements)) {
+ return true;
+ }
+ return visitTypedLiteral(node);
+ }
+
+ @override
+ bool visitMapLiteral(MapLiteral node) {
+ if (_replaceInList(node.entries)) {
+ return true;
+ }
+ return visitTypedLiteral(node);
+ }
+
+ @override
+ bool visitMapLiteralEntry(MapLiteralEntry node) {
+ if (identical(node.key, _oldNode)) {
+ node.key = _newNode as Expression;
+ return true;
+ } else if (identical(node.value, _oldNode)) {
+ node.value = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitMethodDeclaration(MethodDeclaration node) {
+ if (identical(node.returnType, _oldNode)) {
+ node.returnType = _newNode as TypeName;
+ return true;
+ } else if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.parameters, _oldNode)) {
+ node.parameters = _newNode as FormalParameterList;
+ return true;
+ } else if (identical(node.body, _oldNode)) {
+ node.body = _newNode as FunctionBody;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitMethodInvocation(MethodInvocation node) {
+ if (identical(node.target, _oldNode)) {
+ node.target = _newNode as Expression;
+ return true;
+ } else if (identical(node.methodName, _oldNode)) {
+ node.methodName = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.argumentList, _oldNode)) {
+ node.argumentList = _newNode as ArgumentList;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitNamedExpression(NamedExpression node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as Label;
+ return true;
+ } else if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ bool visitNamespaceDirective(NamespaceDirective node) {
+ if (_replaceInList(node.combinators)) {
+ return true;
+ }
+ return visitUriBasedDirective(node);
+ }
+
+ @override
+ bool visitNativeClause(NativeClause node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as StringLiteral;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitNativeFunctionBody(NativeFunctionBody node) {
+ if (identical(node.stringLiteral, _oldNode)) {
+ node.stringLiteral = _newNode as StringLiteral;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ bool visitNode(AstNode node) {
+ throw new IllegalArgumentException(
+ "The old node is not a child of it's parent");
+ }
+
+ bool visitNormalFormalParameter(NormalFormalParameter node) {
+ if (identical(node.documentationComment, _oldNode)) {
+ node.documentationComment = _newNode as Comment;
+ return true;
+ } else if (identical(node.identifier, _oldNode)) {
+ node.identifier = _newNode as SimpleIdentifier;
+ return true;
+ } else if (_replaceInList(node.metadata)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitNullLiteral(NullLiteral node) => visitNode(node);
+
+ @override
+ bool visitParenthesizedExpression(ParenthesizedExpression node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitPartDirective(PartDirective node) => visitUriBasedDirective(node);
+
+ @override
+ bool visitPartOfDirective(PartOfDirective node) {
+ if (identical(node.libraryName, _oldNode)) {
+ node.libraryName = _newNode as LibraryIdentifier;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitPostfixExpression(PostfixExpression node) {
+ if (identical(node.operand, _oldNode)) {
+ node.operand = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitPrefixedIdentifier(PrefixedIdentifier node) {
+ if (identical(node.prefix, _oldNode)) {
+ node.prefix = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.identifier, _oldNode)) {
+ node.identifier = _newNode as SimpleIdentifier;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitPrefixExpression(PrefixExpression node) {
+ if (identical(node.operand, _oldNode)) {
+ node.operand = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitPropertyAccess(PropertyAccess node) {
+ if (identical(node.target, _oldNode)) {
+ node.target = _newNode as Expression;
+ return true;
+ } else if (identical(node.propertyName, _oldNode)) {
+ node.propertyName = _newNode as SimpleIdentifier;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
+ if (identical(node.constructorName, _oldNode)) {
+ node.constructorName = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.argumentList, _oldNode)) {
+ node.argumentList = _newNode as ArgumentList;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitRethrowExpression(RethrowExpression node) => visitNode(node);
+
+ @override
+ bool visitReturnStatement(ReturnStatement node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
+
+ @override
+ bool visitShowCombinator(ShowCombinator node) {
+ if (_replaceInList(node.shownNames)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitSimpleFormalParameter(SimpleFormalParameter node) {
+ if (identical(node.type, _oldNode)) {
+ node.type = _newNode as TypeName;
+ return true;
+ }
+ return visitNormalFormalParameter(node);
+ }
+
+ @override
+ bool visitSimpleIdentifier(SimpleIdentifier node) => visitNode(node);
+
+ @override
+ bool visitSimpleStringLiteral(SimpleStringLiteral node) => visitNode(node);
+
+ @override
+ bool visitStringInterpolation(StringInterpolation node) {
+ if (_replaceInList(node.elements)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ if (identical(node.constructorName, _oldNode)) {
+ node.constructorName = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.argumentList, _oldNode)) {
+ node.argumentList = _newNode as ArgumentList;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitSuperExpression(SuperExpression node) => visitNode(node);
+
+ @override
+ bool visitSwitchCase(SwitchCase node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitSwitchMember(node);
+ }
+
+ @override
+ bool visitSwitchDefault(SwitchDefault node) => visitSwitchMember(node);
+
+ bool visitSwitchMember(SwitchMember node) {
+ if (_replaceInList(node.labels)) {
+ return true;
+ } else if (_replaceInList(node.statements)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitSwitchStatement(SwitchStatement node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ } else if (_replaceInList(node.members)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitSymbolLiteral(SymbolLiteral node) => visitNode(node);
+
+ @override
+ bool visitThisExpression(ThisExpression node) => visitNode(node);
+
+ @override
+ bool visitThrowExpression(ThrowExpression node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ if (identical(node.variables, _oldNode)) {
+ node.variables = _newNode as VariableDeclarationList;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitTryStatement(TryStatement node) {
+ if (identical(node.body, _oldNode)) {
+ node.body = _newNode as Block;
+ return true;
+ } else if (identical(node.finallyBlock, _oldNode)) {
+ node.finallyBlock = _newNode as Block;
+ return true;
+ } else if (_replaceInList(node.catchClauses)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitTypeArgumentList(TypeArgumentList node) {
+ if (_replaceInList(node.arguments)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ bool visitTypedLiteral(TypedLiteral node) {
+ if (identical(node.typeArguments, _oldNode)) {
+ node.typeArguments = _newNode as TypeArgumentList;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitTypeName(TypeName node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as Identifier;
+ return true;
+ } else if (identical(node.typeArguments, _oldNode)) {
+ node.typeArguments = _newNode as TypeArgumentList;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitTypeParameter(TypeParameter node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.bound, _oldNode)) {
+ node.bound = _newNode as TypeName;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitTypeParameterList(TypeParameterList node) {
+ if (_replaceInList(node.typeParameters)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ bool visitUriBasedDirective(UriBasedDirective node) {
+ if (identical(node.uri, _oldNode)) {
+ node.uri = _newNode as StringLiteral;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitVariableDeclaration(VariableDeclaration node) {
+ if (identical(node.name, _oldNode)) {
+ node.name = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.initializer, _oldNode)) {
+ node.initializer = _newNode as Expression;
+ return true;
+ }
+ return visitAnnotatedNode(node);
+ }
+
+ @override
+ bool visitVariableDeclarationList(VariableDeclarationList node) {
+ if (identical(node.type, _oldNode)) {
+ node.type = _newNode as TypeName;
+ return true;
+ } else if (_replaceInList(node.variables)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+ if (identical(node.variables, _oldNode)) {
+ node.variables = _newNode as VariableDeclarationList;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitWhileStatement(WhileStatement node) {
+ if (identical(node.condition, _oldNode)) {
+ node.condition = _newNode as Expression;
+ return true;
+ } else if (identical(node.body, _oldNode)) {
+ node.body = _newNode as Statement;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitWithClause(WithClause node) {
+ if (_replaceInList(node.mixinTypes)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
+ bool visitYieldStatement(YieldStatement node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as Expression;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ bool _replaceInList(NodeList list) {
+ int count = list.length;
+ for (int i = 0; i < count; i++) {
+ if (identical(_oldNode, list[i])) {
+ list[i] = _newNode;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Replace the [oldNode] with the [newNode] in the AST structure containing
+ * the old node. Return `true` if the replacement was successful.
+ *
+ * Throws an [IllegalArgumentException] if either node is `null`, if the old
+ * node does not have a parent node, or if the AST structure has been
+ * corrupted.
+ */
+ static bool replace(AstNode oldNode, AstNode newNode) {
+ if (oldNode == null || newNode == null) {
+ throw new IllegalArgumentException(
+ "The old and new nodes must be non-null");
+ } else if (identical(oldNode, newNode)) {
+ return true;
+ }
+ AstNode parent = oldNode.parent;
+ if (parent == null) {
+ throw new IllegalArgumentException(
+ "The old node is not a child of another node");
+ }
+ NodeReplacer replacer = new NodeReplacer(oldNode, newNode);
+ return parent.accept(replacer);
+ }
+}
+
+/**
+ * Traverse the AST from initial child node to successive parents, building a
+ * collection of local variable and parameter names visible to the initial child
+ * node. In case of name shadowing, the first name seen is the most specific one
+ * so names are not redefined.
+ *
+ * Completion test code coverage is 95%. The two basic blocks that are not
+ * executed cannot be executed. They are included for future reference.
+ */
+class ScopedNameFinder extends GeneralizingAstVisitor<Object> {
+ Declaration _declarationNode;
+
+ AstNode _immediateChild;
+
+ Map<String, SimpleIdentifier> _locals =
+ new HashMap<String, SimpleIdentifier>();
+
+ final int _position;
+
+ bool _referenceIsWithinLocalFunction = false;
+
+ ScopedNameFinder(this._position);
+
+ Declaration get declaration => _declarationNode;
+
+ Map<String, SimpleIdentifier> get locals => _locals;
+
+ @override
+ Object visitBlock(Block node) {
+ _checkStatements(node.statements);
+ return super.visitBlock(node);
+ }
+
+ @override
+ Object visitCatchClause(CatchClause node) {
+ _addToScope(node.exceptionParameter);
+ _addToScope(node.stackTraceParameter);
+ return super.visitCatchClause(node);
+ }
+
+ @override
+ Object visitConstructorDeclaration(ConstructorDeclaration node) {
+ if (!identical(_immediateChild, node.parameters)) {
+ _addParameters(node.parameters.parameters);
+ }
+ _declarationNode = node;
+ return null;
+ }
+
+ @override
+ Object visitFieldDeclaration(FieldDeclaration node) {
+ _declarationNode = node;
+ return null;
+ }
+
+ @override
+ Object visitForEachStatement(ForEachStatement node) {
+ DeclaredIdentifier loopVariable = node.loopVariable;
+ if (loopVariable != null) {
+ _addToScope(loopVariable.identifier);
+ }
+ return super.visitForEachStatement(node);
+ }
+
+ @override
+ Object visitForStatement(ForStatement node) {
+ if (!identical(_immediateChild, node.variables) && node.variables != null) {
+ _addVariables(node.variables.variables);
+ }
+ return super.visitForStatement(node);
+ }
+
+ @override
+ Object visitFunctionDeclaration(FunctionDeclaration node) {
+ if (node.parent is! FunctionDeclarationStatement) {
+ _declarationNode = node;
+ return null;
+ }
+ return super.visitFunctionDeclaration(node);
+ }
+
+ @override
+ Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+ _referenceIsWithinLocalFunction = true;
+ return super.visitFunctionDeclarationStatement(node);
+ }
+
+ @override
+ Object visitFunctionExpression(FunctionExpression node) {
+ if (node.parameters != null &&
+ !identical(_immediateChild, node.parameters)) {
+ _addParameters(node.parameters.parameters);
+ }
+ return super.visitFunctionExpression(node);
+ }
+
+ @override
+ Object visitMethodDeclaration(MethodDeclaration node) {
+ _declarationNode = node;
+ if (node.parameters == null) {
+ return null;
+ }
+ if (!identical(_immediateChild, node.parameters)) {
+ _addParameters(node.parameters.parameters);
+ }
+ return null;
+ }
+
+ @override
+ Object visitNode(AstNode node) {
+ _immediateChild = node;
+ AstNode parent = node.parent;
+ if (parent != null) {
+ parent.accept(this);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSwitchMember(SwitchMember node) {
+ _checkStatements(node.statements);
+ return super.visitSwitchMember(node);
+ }
+
+ @override
+ Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ _declarationNode = node;
+ return null;
+ }
+
+ @override
+ Object visitTypeAlias(TypeAlias node) {
+ _declarationNode = node;
+ return null;
+ }
+
+ void _addParameters(NodeList<FormalParameter> vars) {
+ for (FormalParameter var2 in vars) {
+ _addToScope(var2.identifier);
+ }
+ }
+
+ void _addToScope(SimpleIdentifier identifier) {
+ if (identifier != null && _isInRange(identifier)) {
+ String name = identifier.name;
+ if (!_locals.containsKey(name)) {
+ _locals[name] = identifier;
+ }
+ }
+ }
+
+ void _addVariables(NodeList<VariableDeclaration> variables) {
+ for (VariableDeclaration variable in variables) {
+ _addToScope(variable.name);
+ }
+ }
+
+ /**
+ * Check the given list of [statements] for any that come before the immediate
+ * child and that define a name that would be visible to the immediate child.
+ */
+ void _checkStatements(List<Statement> statements) {
+ for (Statement statement in statements) {
+ if (identical(statement, _immediateChild)) {
+ return;
+ }
+ if (statement is VariableDeclarationStatement) {
+ _addVariables(statement.variables.variables);
+ } else if (statement is FunctionDeclarationStatement &&
+ !_referenceIsWithinLocalFunction) {
+ _addToScope(statement.functionDeclaration.name);
+ }
+ }
+ }
+
+ bool _isInRange(AstNode node) {
+ if (_position < 0) {
+ // if source position is not set then all nodes are in range
+ return true;
+ // not reached
+ }
+ return node.end < _position;
+ }
+}
+
+/**
+ * A visitor used to write a source representation of a visited AST node (and
+ * all of it's children) to a writer.
+ */
+class ToSourceVisitor implements AstVisitor<Object> {
+ /**
+ * The writer to which the source is to be written.
+ */
+ final PrintWriter _writer;
+
+ /**
+ * Initialize a newly created visitor to write source code representing the
+ * visited nodes to the given [writer].
+ */
+ ToSourceVisitor(this._writer);
+
+ @override
+ Object visitAdjacentStrings(AdjacentStrings node) {
+ _visitNodeListWithSeparator(node.strings, " ");
+ return null;
+ }
+
+ @override
+ Object visitAnnotation(Annotation node) {
+ _writer.print('@');
+ _visitNode(node.name);
+ _visitNodeWithPrefix(".", node.constructorName);
+ _visitNode(node.arguments);
+ return null;
+ }
+
+ @override
+ Object visitArgumentList(ArgumentList node) {
+ _writer.print('(');
+ _visitNodeListWithSeparator(node.arguments, ", ");
+ _writer.print(')');
+ return null;
+ }
+
+ @override
+ Object visitAsExpression(AsExpression node) {
+ _visitNode(node.expression);
+ _writer.print(" as ");
+ _visitNode(node.type);
+ return null;
+ }
+
+ @override
+ Object visitAssertStatement(AssertStatement node) {
+ _writer.print("assert (");
+ _visitNode(node.condition);
+ if (node.message != null) {
+ _writer.print(', ');
+ _visitNode(node.message);
+ }
+ _writer.print(");");
+ return null;
+ }
+
+ @override
+ Object visitAssignmentExpression(AssignmentExpression node) {
+ _visitNode(node.leftHandSide);
+ _writer.print(' ');
+ _writer.print(node.operator.lexeme);
+ _writer.print(' ');
+ _visitNode(node.rightHandSide);
+ return null;
+ }
+
+ @override
+ Object visitAwaitExpression(AwaitExpression node) {
+ _writer.print("await ");
+ _visitNode(node.expression);
+ return null;
+ }
+
+ @override
+ Object visitBinaryExpression(BinaryExpression node) {
+ _visitNode(node.leftOperand);
+ _writer.print(' ');
+ _writer.print(node.operator.lexeme);
+ _writer.print(' ');
+ _visitNode(node.rightOperand);
+ return null;
+ }
+
+ @override
+ Object visitBlock(Block node) {
+ _writer.print('{');
+ _visitNodeListWithSeparator(node.statements, " ");
+ _writer.print('}');
+ return null;
+ }
+
+ @override
+ Object visitBlockFunctionBody(BlockFunctionBody node) {
+ Token keyword = node.keyword;
+ if (keyword != null) {
+ _writer.print(keyword.lexeme);
+ if (node.star != null) {
+ _writer.print('*');
+ }
+ _writer.print(' ');
+ }
+ _visitNode(node.block);
+ return null;
+ }
+
+ @override
+ Object visitBooleanLiteral(BooleanLiteral node) {
+ _writer.print(node.literal.lexeme);
+ return null;
+ }
+
+ @override
+ Object visitBreakStatement(BreakStatement node) {
+ _writer.print("break");
+ _visitNodeWithPrefix(" ", node.label);
+ _writer.print(";");
+ return null;
+ }
+
+ @override
+ Object visitCascadeExpression(CascadeExpression node) {
+ _visitNode(node.target);
+ _visitNodeList(node.cascadeSections);
+ return null;
+ }
+
+ @override
+ Object visitCatchClause(CatchClause node) {
+ _visitNodeWithPrefix("on ", node.exceptionType);
+ if (node.catchKeyword != null) {
+ if (node.exceptionType != null) {
+ _writer.print(' ');
+ }
+ _writer.print("catch (");
+ _visitNode(node.exceptionParameter);
+ _visitNodeWithPrefix(", ", node.stackTraceParameter);
+ _writer.print(") ");
+ } else {
+ _writer.print(" ");
+ }
+ _visitNode(node.body);
+ return null;
+ }
+
+ @override
+ Object visitClassDeclaration(ClassDeclaration node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _visitTokenWithSuffix(node.abstractKeyword, " ");
+ _writer.print("class ");
+ _visitNode(node.name);
+ _visitNode(node.typeParameters);
+ _visitNodeWithPrefix(" ", node.extendsClause);
+ _visitNodeWithPrefix(" ", node.withClause);
+ _visitNodeWithPrefix(" ", node.implementsClause);
+ _writer.print(" {");
+ _visitNodeListWithSeparator(node.members, " ");
+ _writer.print("}");
+ return null;
+ }
+
+ @override
+ Object visitClassTypeAlias(ClassTypeAlias node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ if (node.abstractKeyword != null) {
+ _writer.print("abstract ");
+ }
+ _writer.print("class ");
+ _visitNode(node.name);
+ _visitNode(node.typeParameters);
+ _writer.print(" = ");
+ _visitNode(node.superclass);
+ _visitNodeWithPrefix(" ", node.withClause);
+ _visitNodeWithPrefix(" ", node.implementsClause);
+ _writer.print(";");
+ return null;
+ }
+
+ @override
+ Object visitComment(Comment node) => null;
+
+ @override
+ Object visitCommentReference(CommentReference node) => null;
+
+ @override
+ Object visitCompilationUnit(CompilationUnit node) {
+ ScriptTag scriptTag = node.scriptTag;
+ NodeList<Directive> directives = node.directives;
+ _visitNode(scriptTag);
+ String prefix = scriptTag == null ? "" : " ";
+ _visitNodeListWithSeparatorAndPrefix(prefix, directives, " ");
+ prefix = scriptTag == null && directives.isEmpty ? "" : " ";
+ _visitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " ");
+ return null;
+ }
+
+ @override
+ Object visitConditionalExpression(ConditionalExpression node) {
+ _visitNode(node.condition);
+ _writer.print(" ? ");
+ _visitNode(node.thenExpression);
+ _writer.print(" : ");
+ _visitNode(node.elseExpression);
+ return null;
+ }
+
+ @override
+ Object visitConfiguration(Configuration node) {
+ _writer.print('if (');
+ _visitNode(node.name);
+ _visitNodeWithPrefix(" == ", node.value);
+ _writer.print(') ');
+ _visitNode(node.libraryUri);
+ return null;
+ }
+
+ @override
+ Object visitConstructorDeclaration(ConstructorDeclaration node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _visitTokenWithSuffix(node.externalKeyword, " ");
+ _visitTokenWithSuffix(node.constKeyword, " ");
+ _visitTokenWithSuffix(node.factoryKeyword, " ");
+ _visitNode(node.returnType);
+ _visitNodeWithPrefix(".", node.name);
+ _visitNode(node.parameters);
+ _visitNodeListWithSeparatorAndPrefix(" : ", node.initializers, ", ");
+ _visitNodeWithPrefix(" = ", node.redirectedConstructor);
+ _visitFunctionWithPrefix(" ", node.body);
+ return null;
+ }
+
+ @override
+ Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+ _visitTokenWithSuffix(node.thisKeyword, ".");
+ _visitNode(node.fieldName);
+ _writer.print(" = ");
+ _visitNode(node.expression);
+ return null;
+ }
+
+ @override
+ Object visitConstructorName(ConstructorName node) {
+ _visitNode(node.type);
+ _visitNodeWithPrefix(".", node.name);
+ return null;
+ }
+
+ @override
+ Object visitContinueStatement(ContinueStatement node) {
+ _writer.print("continue");
+ _visitNodeWithPrefix(" ", node.label);
+ _writer.print(";");
+ return null;
+ }
+
+ @override
+ Object visitDeclaredIdentifier(DeclaredIdentifier node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _visitTokenWithSuffix(node.keyword, " ");
+ _visitNodeWithSuffix(node.type, " ");
+ _visitNode(node.identifier);
+ return null;
+ }
+
+ @override
+ Object visitDefaultFormalParameter(DefaultFormalParameter node) {
+ _visitNode(node.parameter);
+ if (node.separator != null) {
+ _writer.print(" ");
+ _writer.print(node.separator.lexeme);
+ _visitNodeWithPrefix(" ", node.defaultValue);
+ }
+ return null;
+ }
+
+ @override
+ Object visitDoStatement(DoStatement node) {
+ _writer.print("do ");
+ _visitNode(node.body);
+ _writer.print(" while (");
+ _visitNode(node.condition);
+ _writer.print(");");
+ return null;
+ }
+
+ @override
+ Object visitDottedName(DottedName node) {
+ _visitNodeListWithSeparator(node.components, ".");
+ return null;
+ }
+
+ @override
+ Object visitDoubleLiteral(DoubleLiteral node) {
+ _writer.print(node.literal.lexeme);
+ return null;
+ }
+
+ @override
+ Object visitEmptyFunctionBody(EmptyFunctionBody node) {
+ _writer.print(';');
+ return null;
+ }
+
+ @override
+ Object visitEmptyStatement(EmptyStatement node) {
+ _writer.print(';');
+ return null;
+ }
+
+ @override
+ Object visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _visitNode(node.name);
+ return null;
+ }
+
+ @override
+ Object visitEnumDeclaration(EnumDeclaration node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _writer.print("enum ");
+ _visitNode(node.name);
+ _writer.print(" {");
+ _visitNodeListWithSeparator(node.constants, ", ");
+ _writer.print("}");
+ return null;
+ }
+
+ @override
+ Object visitExportDirective(ExportDirective node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _writer.print("export ");
+ _visitNode(node.uri);
+ _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
+ _writer.print(';');
+ return null;
+ }
+
+ @override
+ Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ Token keyword = node.keyword;
+ if (keyword != null) {
+ _writer.print(keyword.lexeme);
+ _writer.print(' ');
+ }
+ _writer.print("=> ");
+ _visitNode(node.expression);
+ if (node.semicolon != null) {
+ _writer.print(';');
+ }
+ return null;
+ }
+
+ @override
+ Object visitExpressionStatement(ExpressionStatement node) {
+ _visitNode(node.expression);
+ _writer.print(';');
+ return null;
+ }
+
+ @override
+ Object visitExtendsClause(ExtendsClause node) {
+ _writer.print("extends ");
+ _visitNode(node.superclass);
+ return null;
+ }
+
+ @override
+ Object visitFieldDeclaration(FieldDeclaration node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _visitTokenWithSuffix(node.staticKeyword, " ");
+ _visitNode(node.fields);
+ _writer.print(";");
+ return null;
+ }
+
+ @override
+ Object visitFieldFormalParameter(FieldFormalParameter node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+ _visitTokenWithSuffix(node.keyword, " ");
+ _visitNodeWithSuffix(node.type, " ");
+ _writer.print("this.");
+ _visitNode(node.identifier);
+ _visitNode(node.typeParameters);
+ _visitNode(node.parameters);
+ return null;
+ }
+
+ @override
+ Object visitForEachStatement(ForEachStatement node) {
+ DeclaredIdentifier loopVariable = node.loopVariable;
+ if (node.awaitKeyword != null) {
+ _writer.print("await ");
+ }
+ _writer.print("for (");
+ if (loopVariable == null) {
+ _visitNode(node.identifier);
+ } else {
+ _visitNode(loopVariable);
+ }
+ _writer.print(" in ");
+ _visitNode(node.iterable);
+ _writer.print(") ");
+ _visitNode(node.body);
+ return null;
+ }
+
+ @override
+ Object visitFormalParameterList(FormalParameterList node) {
+ String groupEnd = null;
+ _writer.print('(');
+ NodeList<FormalParameter> parameters = node.parameters;
+ int size = parameters.length;
+ for (int i = 0; i < size; i++) {
+ FormalParameter parameter = parameters[i];
+ if (i > 0) {
+ _writer.print(", ");
+ }
+ if (groupEnd == null && parameter is DefaultFormalParameter) {
+ if (parameter.kind == ParameterKind.NAMED) {
+ groupEnd = "}";
+ _writer.print('{');
+ } else {
+ groupEnd = "]";
+ _writer.print('[');
+ }
+ }
+ parameter.accept(this);
+ }
+ if (groupEnd != null) {
+ _writer.print(groupEnd);
+ }
+ _writer.print(')');
+ return null;
+ }
+
+ @override
+ Object visitForStatement(ForStatement node) {
+ Expression initialization = node.initialization;
+ _writer.print("for (");
+ if (initialization != null) {
+ _visitNode(initialization);
+ } else {
+ _visitNode(node.variables);
+ }
+ _writer.print(";");
+ _visitNodeWithPrefix(" ", node.condition);
+ _writer.print(";");
+ _visitNodeListWithSeparatorAndPrefix(" ", node.updaters, ", ");
+ _writer.print(") ");
+ _visitNode(node.body);
+ return null;
+ }
+
+ @override
+ Object visitFunctionDeclaration(FunctionDeclaration node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _visitTokenWithSuffix(node.externalKeyword, " ");
+ _visitNodeWithSuffix(node.returnType, " ");
+ _visitTokenWithSuffix(node.propertyKeyword, " ");
+ _visitNode(node.name);
+ _visitNode(node.functionExpression);
+ return null;
+ }
+
+ @override
+ Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+ _visitNode(node.functionDeclaration);
+ return null;
+ }
+
+ @override
+ Object visitFunctionExpression(FunctionExpression node) {
+ _visitNode(node.typeParameters);
+ _visitNode(node.parameters);
+ if (node.body is! EmptyFunctionBody) {
+ _writer.print(' ');
+ }
+ _visitNode(node.body);
+ return null;
+ }
+
+ @override
+ Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ _visitNode(node.function);
+ _visitNode(node.typeArguments);
+ _visitNode(node.argumentList);
+ return null;
+ }
+
+ @override
+ Object visitFunctionTypeAlias(FunctionTypeAlias node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _writer.print("typedef ");
+ _visitNodeWithSuffix(node.returnType, " ");
+ _visitNode(node.name);
+ _visitNode(node.typeParameters);
+ _visitNode(node.parameters);
+ _writer.print(";");
+ return null;
+ }
+
+ @override
+ Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+ _visitNodeWithSuffix(node.returnType, " ");
+ _visitNode(node.identifier);
+ _visitNode(node.typeParameters);
+ _visitNode(node.parameters);
+ return null;
+ }
+
+ @override
+ Object visitHideCombinator(HideCombinator node) {
+ _writer.print("hide ");
+ _visitNodeListWithSeparator(node.hiddenNames, ", ");
+ return null;
+ }
+
+ @override
+ Object visitIfStatement(IfStatement node) {
+ _writer.print("if (");
+ _visitNode(node.condition);
+ _writer.print(") ");
+ _visitNode(node.thenStatement);
+ _visitNodeWithPrefix(" else ", node.elseStatement);
+ return null;
+ }
+
+ @override
+ Object visitImplementsClause(ImplementsClause node) {
+ _writer.print("implements ");
+ _visitNodeListWithSeparator(node.interfaces, ", ");
+ return null;
+ }
+
+ @override
+ Object visitImportDirective(ImportDirective node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _writer.print("import ");
+ _visitNode(node.uri);
+ if (node.deferredKeyword != null) {
+ _writer.print(" deferred");
+ }
+ _visitNodeWithPrefix(" as ", node.prefix);
+ _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
+ _writer.print(';');
+ return null;
+ }
+
+ @override
+ Object visitIndexExpression(IndexExpression node) {
+ if (node.isCascaded) {
+ _writer.print("..");
+ } else {
+ _visitNode(node.target);
+ }
+ _writer.print('[');
+ _visitNode(node.index);
+ _writer.print(']');
+ return null;
+ }
+
+ @override
+ Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+ _visitTokenWithSuffix(node.keyword, " ");
+ _visitNode(node.constructorName);
+ _visitNode(node.argumentList);
+ return null;
+ }
+
+ @override
+ Object visitIntegerLiteral(IntegerLiteral node) {
+ _writer.print(node.literal.lexeme);
+ return null;
+ }
+
+ @override
+ Object visitInterpolationExpression(InterpolationExpression node) {
+ if (node.rightBracket != null) {
+ _writer.print("\${");
+ _visitNode(node.expression);
+ _writer.print("}");
+ } else {
+ _writer.print("\$");
+ _visitNode(node.expression);
+ }
+ return null;
+ }
+
+ @override
+ Object visitInterpolationString(InterpolationString node) {
+ _writer.print(node.contents.lexeme);
+ return null;
+ }
+
+ @override
+ Object visitIsExpression(IsExpression node) {
+ _visitNode(node.expression);
+ if (node.notOperator == null) {
+ _writer.print(" is ");
+ } else {
+ _writer.print(" is! ");
+ }
+ _visitNode(node.type);
+ return null;
+ }
+
+ @override
+ Object visitLabel(Label node) {
+ _visitNode(node.label);
+ _writer.print(":");
+ return null;
+ }
+
+ @override
+ Object visitLabeledStatement(LabeledStatement node) {
+ _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
+ _visitNode(node.statement);
+ return null;
+ }
+
+ @override
+ Object visitLibraryDirective(LibraryDirective node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _writer.print("library ");
+ _visitNode(node.name);
+ _writer.print(';');
+ return null;
+ }
+
+ @override
+ Object visitLibraryIdentifier(LibraryIdentifier node) {
+ _writer.print(node.name);
+ return null;
+ }
+
+ @override
+ Object visitListLiteral(ListLiteral node) {
+ if (node.constKeyword != null) {
+ _writer.print(node.constKeyword.lexeme);
+ _writer.print(' ');
+ }
+ _visitNodeWithSuffix(node.typeArguments, " ");
+ _writer.print("[");
+ _visitNodeListWithSeparator(node.elements, ", ");
+ _writer.print("]");
+ return null;
+ }
+
+ @override
+ Object visitMapLiteral(MapLiteral node) {
+ if (node.constKeyword != null) {
+ _writer.print(node.constKeyword.lexeme);
+ _writer.print(' ');
+ }
+ _visitNodeWithSuffix(node.typeArguments, " ");
+ _writer.print("{");
+ _visitNodeListWithSeparator(node.entries, ", ");
+ _writer.print("}");
+ return null;
+ }
+
+ @override
+ Object visitMapLiteralEntry(MapLiteralEntry node) {
+ _visitNode(node.key);
+ _writer.print(" : ");
+ _visitNode(node.value);
+ return null;
+ }
+
+ @override
+ Object visitMethodDeclaration(MethodDeclaration node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _visitTokenWithSuffix(node.externalKeyword, " ");
+ _visitTokenWithSuffix(node.modifierKeyword, " ");
+ _visitNodeWithSuffix(node.returnType, " ");
+ _visitTokenWithSuffix(node.propertyKeyword, " ");
+ _visitTokenWithSuffix(node.operatorKeyword, " ");
+ _visitNode(node.name);
+ if (!node.isGetter) {
+ _visitNode(node.typeParameters);
+ _visitNode(node.parameters);
+ }
+ _visitFunctionWithPrefix(" ", node.body);
+ return null;
+ }
+
+ @override
+ Object visitMethodInvocation(MethodInvocation node) {
+ if (node.isCascaded) {
+ _writer.print("..");
+ } else {
+ if (node.target != null) {
+ node.target.accept(this);
+ _writer.print(node.operator.lexeme);
+ }
+ }
+ _visitNode(node.methodName);
+ _visitNode(node.typeArguments);
+ _visitNode(node.argumentList);
+ return null;
+ }
+
+ @override
+ Object visitNamedExpression(NamedExpression node) {
+ _visitNode(node.name);
+ _visitNodeWithPrefix(" ", node.expression);
+ return null;
+ }
+
+ @override
+ Object visitNativeClause(NativeClause node) {
+ _writer.print("native ");
+ _visitNode(node.name);
+ return null;
+ }
+
+ @override
+ Object visitNativeFunctionBody(NativeFunctionBody node) {
+ _writer.print("native ");
+ _visitNode(node.stringLiteral);
+ _writer.print(';');
+ return null;
+ }
+
+ @override
+ Object visitNullLiteral(NullLiteral node) {
+ _writer.print("null");
+ return null;
+ }
+
+ @override
+ Object visitParenthesizedExpression(ParenthesizedExpression node) {
+ _writer.print('(');
+ _visitNode(node.expression);
+ _writer.print(')');
+ return null;
+ }
+
+ @override
+ Object visitPartDirective(PartDirective node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _writer.print("part ");
+ _visitNode(node.uri);
+ _writer.print(';');
+ return null;
+ }
+
+ @override
+ Object visitPartOfDirective(PartOfDirective node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _writer.print("part of ");
+ _visitNode(node.libraryName);
+ _writer.print(';');
+ return null;
+ }
+
+ @override
+ Object visitPostfixExpression(PostfixExpression node) {
+ _visitNode(node.operand);
+ _writer.print(node.operator.lexeme);
+ return null;
+ }
+
+ @override
+ Object visitPrefixedIdentifier(PrefixedIdentifier node) {
+ _visitNode(node.prefix);
+ _writer.print('.');
+ _visitNode(node.identifier);
+ return null;
+ }
+
+ @override
+ Object visitPrefixExpression(PrefixExpression node) {
+ _writer.print(node.operator.lexeme);
+ _visitNode(node.operand);
+ return null;
+ }
+
+ @override
+ Object visitPropertyAccess(PropertyAccess node) {
+ if (node.isCascaded) {
+ _writer.print("..");
+ } else {
+ _visitNode(node.target);
+ _writer.print(node.operator.lexeme);
+ }
+ _visitNode(node.propertyName);
+ return null;
+ }
+
+ @override
+ Object visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
+ _writer.print("this");
+ _visitNodeWithPrefix(".", node.constructorName);
+ _visitNode(node.argumentList);
+ return null;
+ }
+
+ @override
+ Object visitRethrowExpression(RethrowExpression node) {
+ _writer.print("rethrow");
+ return null;
+ }
+
+ @override
+ Object visitReturnStatement(ReturnStatement node) {
+ Expression expression = node.expression;
+ if (expression == null) {
+ _writer.print("return;");
+ } else {
+ _writer.print("return ");
+ expression.accept(this);
+ _writer.print(";");
+ }
+ return null;
+ }
+
+ @override
+ Object visitScriptTag(ScriptTag node) {
+ _writer.print(node.scriptTag.lexeme);
+ return null;
+ }
+
+ @override
+ Object visitShowCombinator(ShowCombinator node) {
+ _writer.print("show ");
+ _visitNodeListWithSeparator(node.shownNames, ", ");
+ return null;
+ }
+
+ @override
+ Object visitSimpleFormalParameter(SimpleFormalParameter node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+ _visitTokenWithSuffix(node.keyword, " ");
+ _visitNodeWithSuffix(node.type, " ");
+ _visitNode(node.identifier);
+ return null;
+ }
+
+ @override
+ Object visitSimpleIdentifier(SimpleIdentifier node) {
+ _writer.print(node.token.lexeme);
+ return null;
+ }
+
+ @override
+ Object visitSimpleStringLiteral(SimpleStringLiteral node) {
+ _writer.print(node.literal.lexeme);
+ return null;
+ }
+
+ @override
+ Object visitStringInterpolation(StringInterpolation node) {
+ _visitNodeList(node.elements);
+ return null;
+ }
+
+ @override
+ Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ _writer.print("super");
+ _visitNodeWithPrefix(".", node.constructorName);
+ _visitNode(node.argumentList);
+ return null;
+ }
+
+ @override
+ Object visitSuperExpression(SuperExpression node) {
+ _writer.print("super");
+ return null;
+ }
+
+ @override
+ Object visitSwitchCase(SwitchCase node) {
+ _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
+ _writer.print("case ");
+ _visitNode(node.expression);
+ _writer.print(": ");
+ _visitNodeListWithSeparator(node.statements, " ");
+ return null;
+ }
+
+ @override
+ Object visitSwitchDefault(SwitchDefault node) {
+ _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
+ _writer.print("default: ");
+ _visitNodeListWithSeparator(node.statements, " ");
+ return null;
+ }
+
+ @override
+ Object visitSwitchStatement(SwitchStatement node) {
+ _writer.print("switch (");
+ _visitNode(node.expression);
+ _writer.print(") {");
+ _visitNodeListWithSeparator(node.members, " ");
+ _writer.print("}");
+ return null;
+ }
+
+ @override
+ Object visitSymbolLiteral(SymbolLiteral node) {
+ _writer.print("#");
+ List<Token> components = node.components;
+ for (int i = 0; i < components.length; i++) {
+ if (i > 0) {
+ _writer.print(".");
+ }
+ _writer.print(components[i].lexeme);
+ }
+ return null;
+ }
+
+ @override
+ Object visitThisExpression(ThisExpression node) {
+ _writer.print("this");
+ return null;
+ }
+
+ @override
+ Object visitThrowExpression(ThrowExpression node) {
+ _writer.print("throw ");
+ _visitNode(node.expression);
+ return null;
+ }
+
+ @override
+ Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ _visitNodeWithSuffix(node.variables, ";");
+ return null;
+ }
+
+ @override
+ Object visitTryStatement(TryStatement node) {
+ _writer.print("try ");
+ _visitNode(node.body);
+ _visitNodeListWithSeparatorAndPrefix(" ", node.catchClauses, " ");
+ _visitNodeWithPrefix(" finally ", node.finallyBlock);
+ return null;
+ }
+
+ @override
+ Object visitTypeArgumentList(TypeArgumentList node) {
+ _writer.print('<');
+ _visitNodeListWithSeparator(node.arguments, ", ");
+ _writer.print('>');
+ return null;
+ }
+
+ @override
+ Object visitTypeName(TypeName node) {
+ _visitNode(node.name);
+ _visitNode(node.typeArguments);
+ return null;
+ }
+
+ @override
+ Object visitTypeParameter(TypeParameter node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _visitNode(node.name);
+ _visitNodeWithPrefix(" extends ", node.bound);
+ return null;
+ }
+
+ @override
+ Object visitTypeParameterList(TypeParameterList node) {
+ _writer.print('<');
+ _visitNodeListWithSeparator(node.typeParameters, ", ");
+ _writer.print('>');
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclaration(VariableDeclaration node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _visitNode(node.name);
+ _visitNodeWithPrefix(" = ", node.initializer);
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclarationList(VariableDeclarationList node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ _visitTokenWithSuffix(node.keyword, " ");
+ _visitNodeWithSuffix(node.type, " ");
+ _visitNodeListWithSeparator(node.variables, ", ");
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+ _visitNode(node.variables);
+ _writer.print(";");
+ return null;
+ }
+
+ @override
+ Object visitWhileStatement(WhileStatement node) {
+ _writer.print("while (");
+ _visitNode(node.condition);
+ _writer.print(") ");
+ _visitNode(node.body);
+ return null;
+ }
+
+ @override
+ Object visitWithClause(WithClause node) {
+ _writer.print("with ");
+ _visitNodeListWithSeparator(node.mixinTypes, ", ");
+ return null;
+ }
+
+ @override
+ Object visitYieldStatement(YieldStatement node) {
+ if (node.star != null) {
+ _writer.print("yield* ");
+ } else {
+ _writer.print("yield ");
+ }
+ _visitNode(node.expression);
+ _writer.print(";");
+ return null;
+ }
+
+ /**
+ * Visit the given function [body], printing the [prefix] before if the body
+ * is not empty.
+ */
+ void _visitFunctionWithPrefix(String prefix, FunctionBody body) {
+ if (body is! EmptyFunctionBody) {
+ _writer.print(prefix);
+ }
+ _visitNode(body);
+ }
+
+ /**
+ * Safely visit the given [node].
+ */
+ void _visitNode(AstNode node) {
+ if (node != null) {
+ node.accept(this);
+ }
+ }
+
+ /**
+ * Print a list of [nodes] without any separation.
+ */
+ void _visitNodeList(NodeList<AstNode> nodes) {
+ _visitNodeListWithSeparator(nodes, "");
+ }
+
+ /**
+ * Print a list of [nodes], separated by the given [separator].
+ */
+ void _visitNodeListWithSeparator(NodeList<AstNode> nodes, String separator) {
+ if (nodes != null) {
+ int size = nodes.length;
+ for (int i = 0; i < size; i++) {
+ if (i > 0) {
+ _writer.print(separator);
+ }
+ nodes[i].accept(this);
+ }
+ }
+ }
+
+ /**
+ * Print a list of [nodes], prefixed by the given [prefix] if the list is not
+ * empty, and separated by the given [separator].
+ */
+ void _visitNodeListWithSeparatorAndPrefix(
+ String prefix, NodeList<AstNode> nodes, String separator) {
+ if (nodes != null) {
+ int size = nodes.length;
+ if (size > 0) {
+ _writer.print(prefix);
+ for (int i = 0; i < size; i++) {
+ if (i > 0) {
+ _writer.print(separator);
+ }
+ nodes[i].accept(this);
+ }
+ }
+ }
+ }
+
+ /**
+ * Print a list of [nodes], separated by the given [separator], followed by
+ * the given [suffix] if the list is not empty.
+ */
+ void _visitNodeListWithSeparatorAndSuffix(
+ NodeList<AstNode> nodes, String separator, String suffix) {
+ if (nodes != null) {
+ int size = nodes.length;
+ if (size > 0) {
+ for (int i = 0; i < size; i++) {
+ if (i > 0) {
+ _writer.print(separator);
+ }
+ nodes[i].accept(this);
+ }
+ _writer.print(suffix);
+ }
+ }
+ }
+
+ /**
+ * Safely visit the given [node], printing the [prefix] before the node if it
+ * is non-`null`.
+ */
+ void _visitNodeWithPrefix(String prefix, AstNode node) {
+ if (node != null) {
+ _writer.print(prefix);
+ node.accept(this);
+ }
+ }
+
+ /**
+ * Safely visit the given [node], printing the [suffix] after the node if it
+ * is non-`null`.
+ */
+ void _visitNodeWithSuffix(AstNode node, String suffix) {
+ if (node != null) {
+ node.accept(this);
+ _writer.print(suffix);
+ }
+ }
+
+ /**
+ * Safely visit the given [token], printing the [suffix] after the token if it
+ * is non-`null`.
+ */
+ void _visitTokenWithSuffix(Token token, String suffix) {
+ if (token != null) {
+ _writer.print(token.lexeme);
+ _writer.print(suffix);
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index ff39868..00e4fe2 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1807,6 +1807,9 @@
@override
ElementLocation get location {
if (_cachedLocation == null) {
+ if (library == null) {
+ return new ElementLocationImpl.con1(this);
+ }
_cachedLocation = new ElementLocationImpl.con1(this);
}
return _cachedLocation;
@@ -1860,11 +1863,9 @@
if (identical(this, object)) {
return true;
}
- if (object == null || hashCode != object.hashCode) {
- return false;
- }
- return object.runtimeType == runtimeType &&
- (object as Element).location == location;
+ return object is Element &&
+ object.kind == kind &&
+ object.location == location;
}
/**
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index fea415f..9599775 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -439,6 +439,7 @@
@override
String get displayName => _baseElement.displayName;
+ @deprecated
@override
SourceRange get docRange => _baseElement.docRange;
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 4268f1c..03c361d 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -169,14 +169,17 @@
List<DartType> _typeArguments;
/**
- * The list of [typeParameters].
+ * The list of [typeParameters], if it has been computed already. Otherwise
+ * `null`.
*/
List<TypeParameterElement> _typeParameters;
/**
- * The list of [boundTypeParameters].
+ * True if this type is the result of instantiating type parameters (and thus
+ * any type parameters bound by the typedef should be considered part of
+ * [typeParameters] rather than [boundTypeParameters]).
*/
- List<TypeParameterElement> _boundTypeParameters;
+ final bool _isInstantiated;
/**
* The set of typedefs which should not be expanded when exploring this type,
@@ -191,15 +194,15 @@
*/
FunctionTypeImpl(ExecutableElement element,
[List<FunctionTypeAliasElement> prunedTypedefs])
- : this._(element, null, prunedTypedefs, null, null, null);
+ : this._(element, null, prunedTypedefs, null, false);
/**
* Initialize a newly created function type to be declared by the given
- * [element], with the given [name].
+ * [element], with the given [name] and [typeArguments].
*/
- FunctionTypeImpl.elementWithName(Element element, String name)
- : prunedTypedefs = null,
- super(element, name);
+ FunctionTypeImpl.elementWithNameAndArgs(
+ Element element, String name, List<DartType> typeArguments)
+ : this._(element, name, null, typeArguments, true);
/**
* Initialize a newly created function type to be declared by the given
@@ -207,38 +210,14 @@
*/
FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element,
[List<FunctionTypeAliasElement> prunedTypedefs])
- : this._(element, element?.name, prunedTypedefs, null, null, null);
+ : this._(element, element?.name, prunedTypedefs, null, false);
/**
* Private constructor.
*/
- FunctionTypeImpl._(
- TypeParameterizedElement element,
- String name,
- this.prunedTypedefs,
- List<DartType> typeArguments,
- List<TypeParameterElement> typeParameters,
- List<TypeParameterElement> boundTypeParameters)
+ FunctionTypeImpl._(TypeParameterizedElement element, String name,
+ this.prunedTypedefs, List<DartType> typeArguments, this._isInstantiated)
: super(element, name) {
- _boundTypeParameters = boundTypeParameters ??
- element?.typeParameters ??
- TypeParameterElement.EMPTY_LIST;
-
- if (typeParameters == null) {
- // Combine the generic type variables from all enclosing contexts, except
- // for this generic function's type variables. Those variables are
- // tracked in [boundTypeParameters].
- typeParameters = <TypeParameterElement>[];
- Element e = element?.enclosingElement;
- while (e != null) {
- if (e is TypeParameterizedElement) {
- typeParameters.addAll((e as TypeParameterizedElement).typeParameters);
- }
- e = e.enclosingElement;
- }
- }
- _typeParameters = typeParameters;
-
if (typeArguments == null) {
// TODO(jmesserly): reuse TypeParameterTypeImpl.getTypes once we can
// make it generic, which will allow it to return List<DartType> instead
@@ -265,7 +244,13 @@
DartType get baseReturnType => element.returnType;
@override
- List<TypeParameterElement> get boundTypeParameters => _boundTypeParameters;
+ List<TypeParameterElement> get boundTypeParameters {
+ if (_isInstantiated) {
+ return TypeParameterElement.EMPTY_LIST;
+ } else {
+ return element?.typeParameters ?? TypeParameterElement.EMPTY_LIST;
+ }
+ }
@override
String get displayName {
@@ -536,7 +521,31 @@
List<DartType> get typeArguments => _typeArguments;
@override
- List<TypeParameterElement> get typeParameters => _typeParameters;
+ List<TypeParameterElement> get typeParameters {
+ if (_typeParameters == null) {
+ // Combine the generic type variables from all enclosing contexts, except
+ // for this generic function's type variables. Those variables are
+ // tracked in [boundTypeParameters].
+ _typeParameters = <TypeParameterElement>[];
+ Element e = element?.enclosingElement;
+ while (e != null) {
+ if (e is TypeParameterizedElement) {
+ _typeParameters.addAll(e.typeParameters);
+ }
+ e = e.enclosingElement;
+ }
+ if (_isInstantiated) {
+ // Once the type has been instantiated, type parameters defined at the
+ // site of the declaration of the method are no longer considered part
+ // [boundTypeParameters]; they are part of [typeParameters].
+ List<TypeParameterElement> parametersToAdd = element?.typeParameters;
+ if (parametersToAdd != null) {
+ _typeParameters.addAll(parametersToAdd);
+ }
+ }
+ }
+ return _typeParameters;
+ }
@override
bool operator ==(Object object) {
@@ -715,13 +724,11 @@
//
// Now instantiate([V]), and the result should be:
// {U/T, V/S} T -> S.
- List<TypeParameterElement> newTypeParams = typeParameters.toList();
List<DartType> newTypeArgs = typeArguments.toList();
- newTypeParams.addAll(boundTypeParameters);
newTypeArgs.addAll(argumentTypes);
- return new FunctionTypeImpl._(element, name, prunedTypedefs, newTypeArgs,
- newTypeParams, TypeParameterElement.EMPTY_LIST);
+ return new FunctionTypeImpl._(
+ element, name, prunedTypedefs, newTypeArgs, true);
}
@override
@@ -973,8 +980,8 @@
List<DartType> typeArgs = typeArguments
.map((TypeImpl t) => t.pruned(prune))
.toList(growable: false);
- return new FunctionTypeImpl._(element, name, prune, typeArgs,
- _typeParameters, _boundTypeParameters);
+ return new FunctionTypeImpl._(
+ element, name, prune, typeArgs, _isInstantiated);
}
}
@@ -1001,7 +1008,7 @@
List<DartType> typeArgs =
TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
return new FunctionTypeImpl._(
- element, name, prune, typeArgs, _typeParameters, _boundTypeParameters);
+ element, name, prune, typeArgs, _isInstantiated);
}
@override
@@ -1107,11 +1114,14 @@
/**
* Initialize a newly created type to be declared by the given [element],
- * with the given [name].
+ * with the given [name] and [typeArguents].
*/
- InterfaceTypeImpl.elementWithName(ClassElement element, String name)
+ InterfaceTypeImpl.elementWithNameAndArgs(
+ ClassElement element, String name, List<DartType> typeArguments)
: prunedTypedefs = null,
- super(element, name);
+ super(element, name) {
+ this.typeArguments = typeArguments;
+ }
/**
* Initialize a newly created type to have the given [name]. This constructor
@@ -1295,16 +1305,16 @@
}
@override
- PropertyAccessorElement getGetter(String getterName) => PropertyAccessorMember
- .from((element as ClassElementImpl).getGetter(getterName), this);
+ PropertyAccessorElement getGetter(String getterName) =>
+ PropertyAccessorMember.from(element.getGetter(getterName), this);
@override
- MethodElement getMethod(String methodName) => MethodMember.from(
- (element as ClassElementImpl).getMethod(methodName), this);
+ MethodElement getMethod(String methodName) =>
+ MethodMember.from(element.getMethod(methodName), this);
@override
- PropertyAccessorElement getSetter(String setterName) => PropertyAccessorMember
- .from((element as ClassElementImpl).getSetter(setterName), this);
+ PropertyAccessorElement getSetter(String setterName) =>
+ PropertyAccessorMember.from(element.getSetter(setterName), this);
@override
bool isDirectSupertypeOf(InterfaceType type) {
diff --git a/pkg/analyzer/lib/src/generated/ast.dart b/pkg/analyzer/lib/src/generated/ast.dart
index 06ae37c..9d8ddcb 100644
--- a/pkg/analyzer/lib/src/generated/ast.dart
+++ b/pkg/analyzer/lib/src/generated/ast.dart
@@ -8,6 +8,7 @@
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/type.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
@@ -16,9 +17,11 @@
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
-import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap;
import 'package:analyzer/src/generated/utilities_dart.dart';
+export 'package:analyzer/dart/ast/visitor.dart';
+export 'package:analyzer/src/dart/ast/utilities.dart';
+
/**
* Two or more string literals that are implicitly concatenated because of being
* adjacent (separated only by whitespace).
@@ -906,1961 +909,6 @@
}
/**
- * An AST visitor that will clone any AST structure that it visits. The cloner
- * will only clone the structure, it will not preserve any resolution results or
- * properties associated with the nodes.
- */
-class AstCloner implements AstVisitor<AstNode> {
- /**
- * A flag indicating whether tokens should be cloned while cloning an AST
- * structure.
- */
- final bool cloneTokens;
-
- /**
- * Initialize a newly created AST cloner to optionally clone tokens while
- * cloning AST nodes if [cloneTokens] is `true`.
- */
- AstCloner(
- [this.cloneTokens =
- false]); // TODO(brianwilkerson) Change this to be a named parameter.
-
- /**
- * Return a clone of the given [node].
- */
- AstNode cloneNode(AstNode node) {
- if (node == null) {
- return null;
- }
- return node.accept(this) as AstNode;
- }
-
- /**
- * Return a list containing cloned versions of the nodes in the given list of
- * [nodes].
- */
- List<AstNode> cloneNodeList(NodeList nodes) {
- int count = nodes.length;
- List clonedNodes = new List();
- for (int i = 0; i < count; i++) {
- clonedNodes.add((nodes[i]).accept(this) as AstNode);
- }
- return clonedNodes;
- }
-
- /**
- * Clone the given [token] if tokens are supposed to be cloned.
- */
- Token cloneToken(Token token) {
- if (cloneTokens) {
- return (token == null ? null : token.copy());
- } else {
- return token;
- }
- }
-
- /**
- * Clone the given [tokens] if tokens are supposed to be cloned.
- */
- List<Token> cloneTokenList(List<Token> tokens) {
- if (cloneTokens) {
- return tokens.map((Token token) => token.copy()).toList();
- }
- return tokens;
- }
-
- @override
- AdjacentStrings visitAdjacentStrings(AdjacentStrings node) =>
- new AdjacentStrings(cloneNodeList(node.strings));
-
- @override
- Annotation visitAnnotation(Annotation node) => new Annotation(
- cloneToken(node.atSign),
- cloneNode(node.name),
- cloneToken(node.period),
- cloneNode(node.constructorName),
- cloneNode(node.arguments));
-
- @override
- ArgumentList visitArgumentList(ArgumentList node) => new ArgumentList(
- cloneToken(node.leftParenthesis),
- cloneNodeList(node.arguments),
- cloneToken(node.rightParenthesis));
-
- @override
- AsExpression visitAsExpression(AsExpression node) => new AsExpression(
- cloneNode(node.expression),
- cloneToken(node.asOperator),
- cloneNode(node.type));
-
- @override
- AstNode visitAssertStatement(AssertStatement node) => new AssertStatement(
- cloneToken(node.assertKeyword),
- cloneToken(node.leftParenthesis),
- cloneNode(node.condition),
- cloneToken(node.comma),
- cloneNode(node.message),
- cloneToken(node.rightParenthesis),
- cloneToken(node.semicolon));
-
- @override
- AssignmentExpression visitAssignmentExpression(AssignmentExpression node) =>
- new AssignmentExpression(cloneNode(node.leftHandSide),
- cloneToken(node.operator), cloneNode(node.rightHandSide));
-
- @override
- AwaitExpression visitAwaitExpression(AwaitExpression node) =>
- new AwaitExpression(
- cloneToken(node.awaitKeyword), cloneNode(node.expression));
-
- @override
- BinaryExpression visitBinaryExpression(BinaryExpression node) =>
- new BinaryExpression(cloneNode(node.leftOperand),
- cloneToken(node.operator), cloneNode(node.rightOperand));
-
- @override
- Block visitBlock(Block node) => new Block(cloneToken(node.leftBracket),
- cloneNodeList(node.statements), cloneToken(node.rightBracket));
-
- @override
- BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
- new BlockFunctionBody(cloneToken(node.keyword), cloneToken(node.star),
- cloneNode(node.block));
-
- @override
- BooleanLiteral visitBooleanLiteral(BooleanLiteral node) =>
- new BooleanLiteral(cloneToken(node.literal), node.value);
-
- @override
- BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement(
- cloneToken(node.breakKeyword),
- cloneNode(node.label),
- cloneToken(node.semicolon));
-
- @override
- CascadeExpression visitCascadeExpression(CascadeExpression node) =>
- new CascadeExpression(
- cloneNode(node.target), cloneNodeList(node.cascadeSections));
-
- @override
- CatchClause visitCatchClause(CatchClause node) => new CatchClause(
- cloneToken(node.onKeyword),
- cloneNode(node.exceptionType),
- cloneToken(node.catchKeyword),
- cloneToken(node.leftParenthesis),
- cloneNode(node.exceptionParameter),
- cloneToken(node.comma),
- cloneNode(node.stackTraceParameter),
- cloneToken(node.rightParenthesis),
- cloneNode(node.body));
-
- @override
- ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
- ClassDeclaration copy = new ClassDeclaration(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.abstractKeyword),
- cloneToken(node.classKeyword),
- cloneNode(node.name),
- cloneNode(node.typeParameters),
- cloneNode(node.extendsClause),
- cloneNode(node.withClause),
- cloneNode(node.implementsClause),
- cloneToken(node.leftBracket),
- cloneNodeList(node.members),
- cloneToken(node.rightBracket));
- copy.nativeClause = cloneNode(node.nativeClause);
- return copy;
- }
-
- @override
- ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.typedefKeyword),
- cloneNode(node.name),
- cloneNode(node.typeParameters),
- cloneToken(node.equals),
- cloneToken(node.abstractKeyword),
- cloneNode(node.superclass),
- cloneNode(node.withClause),
- cloneNode(node.implementsClause),
- cloneToken(node.semicolon));
-
- @override
- Comment visitComment(Comment node) {
- if (node.isDocumentation) {
- return Comment.createDocumentationCommentWithReferences(
- cloneTokenList(node.tokens), cloneNodeList(node.references));
- } else if (node.isBlock) {
- return Comment.createBlockComment(cloneTokenList(node.tokens));
- }
- return Comment.createEndOfLineComment(cloneTokenList(node.tokens));
- }
-
- @override
- CommentReference visitCommentReference(CommentReference node) =>
- new CommentReference(
- cloneToken(node.newKeyword), cloneNode(node.identifier));
-
- @override
- CompilationUnit visitCompilationUnit(CompilationUnit node) {
- CompilationUnit clone = new CompilationUnit(
- cloneToken(node.beginToken),
- cloneNode(node.scriptTag),
- cloneNodeList(node.directives),
- cloneNodeList(node.declarations),
- cloneToken(node.endToken));
- clone.lineInfo = node.lineInfo;
- return clone;
- }
-
- @override
- ConditionalExpression visitConditionalExpression(
- ConditionalExpression node) =>
- new ConditionalExpression(
- cloneNode(node.condition),
- cloneToken(node.question),
- cloneNode(node.thenExpression),
- cloneToken(node.colon),
- cloneNode(node.elseExpression));
-
- @override
- Configuration visitConfiguration(Configuration node) => new Configuration(
- cloneToken(node.ifKeyword),
- cloneToken(node.leftParenthesis),
- cloneNode(node.name),
- cloneToken(node.equalToken),
- cloneNode(node.value),
- cloneToken(node.rightParenthesis),
- cloneNode(node.libraryUri));
-
- @override
- ConstructorDeclaration visitConstructorDeclaration(
- ConstructorDeclaration node) =>
- new ConstructorDeclaration(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.externalKeyword),
- cloneToken(node.constKeyword),
- cloneToken(node.factoryKeyword),
- cloneNode(node.returnType),
- cloneToken(node.period),
- cloneNode(node.name),
- cloneNode(node.parameters),
- cloneToken(node.separator),
- cloneNodeList(node.initializers),
- cloneNode(node.redirectedConstructor),
- cloneNode(node.body));
-
- @override
- ConstructorFieldInitializer visitConstructorFieldInitializer(
- ConstructorFieldInitializer node) =>
- new ConstructorFieldInitializer(
- cloneToken(node.thisKeyword),
- cloneToken(node.period),
- cloneNode(node.fieldName),
- cloneToken(node.equals),
- cloneNode(node.expression));
-
- @override
- ConstructorName visitConstructorName(ConstructorName node) =>
- new ConstructorName(
- cloneNode(node.type), cloneToken(node.period), cloneNode(node.name));
-
- @override
- ContinueStatement visitContinueStatement(ContinueStatement node) =>
- new ContinueStatement(cloneToken(node.continueKeyword),
- cloneNode(node.label), cloneToken(node.semicolon));
-
- @override
- DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
- new DeclaredIdentifier(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.keyword),
- cloneNode(node.type),
- cloneNode(node.identifier));
-
- @override
- DefaultFormalParameter visitDefaultFormalParameter(
- DefaultFormalParameter node) =>
- new DefaultFormalParameter(cloneNode(node.parameter), node.kind,
- cloneToken(node.separator), cloneNode(node.defaultValue));
-
- @override
- DoStatement visitDoStatement(DoStatement node) => new DoStatement(
- cloneToken(node.doKeyword),
- cloneNode(node.body),
- cloneToken(node.whileKeyword),
- cloneToken(node.leftParenthesis),
- cloneNode(node.condition),
- cloneToken(node.rightParenthesis),
- cloneToken(node.semicolon));
-
- @override
- DottedName visitDottedName(DottedName node) =>
- new DottedName(cloneNodeList(node.components));
-
- @override
- DoubleLiteral visitDoubleLiteral(DoubleLiteral node) =>
- new DoubleLiteral(cloneToken(node.literal), node.value);
-
- @override
- EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) =>
- new EmptyFunctionBody(cloneToken(node.semicolon));
-
- @override
- EmptyStatement visitEmptyStatement(EmptyStatement node) =>
- new EmptyStatement(cloneToken(node.semicolon));
-
- @override
- AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
- new EnumConstantDeclaration(cloneNode(node.documentationComment),
- cloneNodeList(node.metadata), cloneNode(node.name));
-
- @override
- EnumDeclaration visitEnumDeclaration(EnumDeclaration node) =>
- new EnumDeclaration(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.enumKeyword),
- cloneNode(node.name),
- cloneToken(node.leftBracket),
- cloneNodeList(node.constants),
- cloneToken(node.rightBracket));
-
- @override
- ExportDirective visitExportDirective(ExportDirective node) {
- ExportDirective directive = new ExportDirective(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.keyword),
- cloneNode(node.uri),
- cloneNodeList(node.configurations),
- cloneNodeList(node.combinators),
- cloneToken(node.semicolon));
- directive.source = node.source;
- directive.uriContent = node.uriContent;
- return directive;
- }
-
- @override
- ExpressionFunctionBody visitExpressionFunctionBody(
- ExpressionFunctionBody node) =>
- new ExpressionFunctionBody(
- cloneToken(node.keyword),
- cloneToken(node.functionDefinition),
- cloneNode(node.expression),
- cloneToken(node.semicolon));
-
- @override
- ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
- new ExpressionStatement(
- cloneNode(node.expression), cloneToken(node.semicolon));
-
- @override
- ExtendsClause visitExtendsClause(ExtendsClause node) => new ExtendsClause(
- cloneToken(node.extendsKeyword), cloneNode(node.superclass));
-
- @override
- FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
- new FieldDeclaration(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.staticKeyword),
- cloneNode(node.fields),
- cloneToken(node.semicolon));
-
- @override
- FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
- new FieldFormalParameter(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.keyword),
- cloneNode(node.type),
- cloneToken(node.thisKeyword),
- cloneToken(node.period),
- cloneNode(node.identifier),
- cloneNode(node.typeParameters),
- cloneNode(node.parameters));
-
- @override
- ForEachStatement visitForEachStatement(ForEachStatement node) {
- DeclaredIdentifier loopVariable = node.loopVariable;
- if (loopVariable == null) {
- return new ForEachStatement.withReference(
- cloneToken(node.awaitKeyword),
- cloneToken(node.forKeyword),
- cloneToken(node.leftParenthesis),
- cloneNode(node.identifier),
- cloneToken(node.inKeyword),
- cloneNode(node.iterable),
- cloneToken(node.rightParenthesis),
- cloneNode(node.body));
- }
- return new ForEachStatement.withDeclaration(
- cloneToken(node.awaitKeyword),
- cloneToken(node.forKeyword),
- cloneToken(node.leftParenthesis),
- cloneNode(loopVariable),
- cloneToken(node.inKeyword),
- cloneNode(node.iterable),
- cloneToken(node.rightParenthesis),
- cloneNode(node.body));
- }
-
- @override
- FormalParameterList visitFormalParameterList(FormalParameterList node) =>
- new FormalParameterList(
- cloneToken(node.leftParenthesis),
- cloneNodeList(node.parameters),
- cloneToken(node.leftDelimiter),
- cloneToken(node.rightDelimiter),
- cloneToken(node.rightParenthesis));
-
- @override
- ForStatement visitForStatement(ForStatement node) => new ForStatement(
- cloneToken(node.forKeyword),
- cloneToken(node.leftParenthesis),
- cloneNode(node.variables),
- cloneNode(node.initialization),
- cloneToken(node.leftSeparator),
- cloneNode(node.condition),
- cloneToken(node.rightSeparator),
- cloneNodeList(node.updaters),
- cloneToken(node.rightParenthesis),
- cloneNode(node.body));
-
- @override
- FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
- new FunctionDeclaration(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.externalKeyword),
- cloneNode(node.returnType),
- cloneToken(node.propertyKeyword),
- cloneNode(node.name),
- cloneNode(node.functionExpression));
-
- @override
- FunctionDeclarationStatement visitFunctionDeclarationStatement(
- FunctionDeclarationStatement node) =>
- new FunctionDeclarationStatement(cloneNode(node.functionDeclaration));
-
- @override
- FunctionExpression visitFunctionExpression(FunctionExpression node) =>
- new FunctionExpression(cloneNode(node.typeParameters),
- cloneNode(node.parameters), cloneNode(node.body));
-
- @override
- FunctionExpressionInvocation visitFunctionExpressionInvocation(
- FunctionExpressionInvocation node) =>
- new FunctionExpressionInvocation(cloneNode(node.function),
- cloneNode(node.typeArguments), cloneNode(node.argumentList));
-
- @override
- FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
- new FunctionTypeAlias(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.typedefKeyword),
- cloneNode(node.returnType),
- cloneNode(node.name),
- cloneNode(node.typeParameters),
- cloneNode(node.parameters),
- cloneToken(node.semicolon));
-
- @override
- FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
- FunctionTypedFormalParameter node) =>
- new FunctionTypedFormalParameter(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneNode(node.returnType),
- cloneNode(node.identifier),
- cloneNode(node.typeParameters),
- cloneNode(node.parameters));
-
- @override
- HideCombinator visitHideCombinator(HideCombinator node) => new HideCombinator(
- cloneToken(node.keyword), cloneNodeList(node.hiddenNames));
-
- @override
- IfStatement visitIfStatement(IfStatement node) => new IfStatement(
- cloneToken(node.ifKeyword),
- cloneToken(node.leftParenthesis),
- cloneNode(node.condition),
- cloneToken(node.rightParenthesis),
- cloneNode(node.thenStatement),
- cloneToken(node.elseKeyword),
- cloneNode(node.elseStatement));
-
- @override
- ImplementsClause visitImplementsClause(ImplementsClause node) =>
- new ImplementsClause(
- cloneToken(node.implementsKeyword), cloneNodeList(node.interfaces));
-
- @override
- ImportDirective visitImportDirective(ImportDirective node) {
- ImportDirective directive = new ImportDirective(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.keyword),
- cloneNode(node.uri),
- cloneNodeList(node.configurations),
- cloneToken(node.deferredKeyword),
- cloneToken(node.asKeyword),
- cloneNode(node.prefix),
- cloneNodeList(node.combinators),
- cloneToken(node.semicolon));
- directive.source = node.source;
- directive.uriContent = node.uriContent;
- return directive;
- }
-
- @override
- IndexExpression visitIndexExpression(IndexExpression node) {
- Token period = node.period;
- if (period == null) {
- return new IndexExpression.forTarget(
- cloneNode(node.target),
- cloneToken(node.leftBracket),
- cloneNode(node.index),
- cloneToken(node.rightBracket));
- } else {
- return new IndexExpression.forCascade(
- cloneToken(period),
- cloneToken(node.leftBracket),
- cloneNode(node.index),
- cloneToken(node.rightBracket));
- }
- }
-
- @override
- InstanceCreationExpression visitInstanceCreationExpression(
- InstanceCreationExpression node) =>
- new InstanceCreationExpression(cloneToken(node.keyword),
- cloneNode(node.constructorName), cloneNode(node.argumentList));
-
- @override
- IntegerLiteral visitIntegerLiteral(IntegerLiteral node) =>
- new IntegerLiteral(cloneToken(node.literal), node.value);
-
- @override
- InterpolationExpression visitInterpolationExpression(
- InterpolationExpression node) =>
- new InterpolationExpression(cloneToken(node.leftBracket),
- cloneNode(node.expression), cloneToken(node.rightBracket));
-
- @override
- InterpolationString visitInterpolationString(InterpolationString node) =>
- new InterpolationString(cloneToken(node.contents), node.value);
-
- @override
- IsExpression visitIsExpression(IsExpression node) => new IsExpression(
- cloneNode(node.expression),
- cloneToken(node.isOperator),
- cloneToken(node.notOperator),
- cloneNode(node.type));
-
- @override
- Label visitLabel(Label node) =>
- new Label(cloneNode(node.label), cloneToken(node.colon));
-
- @override
- LabeledStatement visitLabeledStatement(LabeledStatement node) =>
- new LabeledStatement(
- cloneNodeList(node.labels), cloneNode(node.statement));
-
- @override
- LibraryDirective visitLibraryDirective(LibraryDirective node) =>
- new LibraryDirective(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.libraryKeyword),
- cloneNode(node.name),
- cloneToken(node.semicolon));
-
- @override
- LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) =>
- new LibraryIdentifier(cloneNodeList(node.components));
-
- @override
- ListLiteral visitListLiteral(ListLiteral node) => new ListLiteral(
- cloneToken(node.constKeyword),
- cloneNode(node.typeArguments),
- cloneToken(node.leftBracket),
- cloneNodeList(node.elements),
- cloneToken(node.rightBracket));
-
- @override
- MapLiteral visitMapLiteral(MapLiteral node) => new MapLiteral(
- cloneToken(node.constKeyword),
- cloneNode(node.typeArguments),
- cloneToken(node.leftBracket),
- cloneNodeList(node.entries),
- cloneToken(node.rightBracket));
-
- @override
- MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
- new MapLiteralEntry(cloneNode(node.key), cloneToken(node.separator),
- cloneNode(node.value));
-
- @override
- MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
- new MethodDeclaration(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.externalKeyword),
- cloneToken(node.modifierKeyword),
- cloneNode(node.returnType),
- cloneToken(node.propertyKeyword),
- cloneToken(node.operatorKeyword),
- cloneNode(node.name),
- cloneNode(node.typeParameters),
- cloneNode(node.parameters),
- cloneNode(node.body));
-
- @override
- MethodInvocation visitMethodInvocation(MethodInvocation node) =>
- new MethodInvocation(
- cloneNode(node.target),
- cloneToken(node.operator),
- cloneNode(node.methodName),
- cloneNode(node.typeArguments),
- cloneNode(node.argumentList));
-
- @override
- NamedExpression visitNamedExpression(NamedExpression node) =>
- new NamedExpression(cloneNode(node.name), cloneNode(node.expression));
-
- @override
- AstNode visitNativeClause(NativeClause node) =>
- new NativeClause(cloneToken(node.nativeKeyword), cloneNode(node.name));
-
- @override
- NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) =>
- new NativeFunctionBody(cloneToken(node.nativeKeyword),
- cloneNode(node.stringLiteral), cloneToken(node.semicolon));
-
- @override
- NullLiteral visitNullLiteral(NullLiteral node) =>
- new NullLiteral(cloneToken(node.literal));
-
- @override
- ParenthesizedExpression visitParenthesizedExpression(
- ParenthesizedExpression node) =>
- new ParenthesizedExpression(cloneToken(node.leftParenthesis),
- cloneNode(node.expression), cloneToken(node.rightParenthesis));
-
- @override
- PartDirective visitPartDirective(PartDirective node) {
- PartDirective directive = new PartDirective(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.partKeyword),
- cloneNode(node.uri),
- cloneToken(node.semicolon));
- directive.source = node.source;
- directive.uriContent = node.uriContent;
- return directive;
- }
-
- @override
- PartOfDirective visitPartOfDirective(PartOfDirective node) =>
- new PartOfDirective(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.partKeyword),
- cloneToken(node.ofKeyword),
- cloneNode(node.libraryName),
- cloneToken(node.semicolon));
-
- @override
- PostfixExpression visitPostfixExpression(PostfixExpression node) =>
- new PostfixExpression(cloneNode(node.operand), cloneToken(node.operator));
-
- @override
- PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) =>
- new PrefixedIdentifier(cloneNode(node.prefix), cloneToken(node.period),
- cloneNode(node.identifier));
-
- @override
- PrefixExpression visitPrefixExpression(PrefixExpression node) =>
- new PrefixExpression(cloneToken(node.operator), cloneNode(node.operand));
-
- @override
- PropertyAccess visitPropertyAccess(PropertyAccess node) => new PropertyAccess(
- cloneNode(node.target),
- cloneToken(node.operator),
- cloneNode(node.propertyName));
-
- @override
- RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) =>
- new RedirectingConstructorInvocation(
- cloneToken(node.thisKeyword),
- cloneToken(node.period),
- cloneNode(node.constructorName),
- cloneNode(node.argumentList));
-
- @override
- RethrowExpression visitRethrowExpression(RethrowExpression node) =>
- new RethrowExpression(cloneToken(node.rethrowKeyword));
-
- @override
- ReturnStatement visitReturnStatement(ReturnStatement node) =>
- new ReturnStatement(cloneToken(node.returnKeyword),
- cloneNode(node.expression), cloneToken(node.semicolon));
-
- @override
- ScriptTag visitScriptTag(ScriptTag node) =>
- new ScriptTag(cloneToken(node.scriptTag));
-
- @override
- ShowCombinator visitShowCombinator(ShowCombinator node) => new ShowCombinator(
- cloneToken(node.keyword), cloneNodeList(node.shownNames));
-
- @override
- SimpleFormalParameter visitSimpleFormalParameter(
- SimpleFormalParameter node) =>
- new SimpleFormalParameter(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.keyword),
- cloneNode(node.type),
- cloneNode(node.identifier));
-
- @override
- SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) =>
- new SimpleIdentifier(cloneToken(node.token));
-
- @override
- SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) =>
- new SimpleStringLiteral(cloneToken(node.literal), node.value);
-
- @override
- StringInterpolation visitStringInterpolation(StringInterpolation node) =>
- new StringInterpolation(cloneNodeList(node.elements));
-
- @override
- SuperConstructorInvocation visitSuperConstructorInvocation(
- SuperConstructorInvocation node) =>
- new SuperConstructorInvocation(
- cloneToken(node.superKeyword),
- cloneToken(node.period),
- cloneNode(node.constructorName),
- cloneNode(node.argumentList));
-
- @override
- SuperExpression visitSuperExpression(SuperExpression node) =>
- new SuperExpression(cloneToken(node.superKeyword));
-
- @override
- SwitchCase visitSwitchCase(SwitchCase node) => new SwitchCase(
- cloneNodeList(node.labels),
- cloneToken(node.keyword),
- cloneNode(node.expression),
- cloneToken(node.colon),
- cloneNodeList(node.statements));
-
- @override
- SwitchDefault visitSwitchDefault(SwitchDefault node) => new SwitchDefault(
- cloneNodeList(node.labels),
- cloneToken(node.keyword),
- cloneToken(node.colon),
- cloneNodeList(node.statements));
-
- @override
- SwitchStatement visitSwitchStatement(SwitchStatement node) =>
- new SwitchStatement(
- cloneToken(node.switchKeyword),
- cloneToken(node.leftParenthesis),
- cloneNode(node.expression),
- cloneToken(node.rightParenthesis),
- cloneToken(node.leftBracket),
- cloneNodeList(node.members),
- cloneToken(node.rightBracket));
-
- @override
- SymbolLiteral visitSymbolLiteral(SymbolLiteral node) => new SymbolLiteral(
- cloneToken(node.poundSign), cloneTokenList(node.components));
-
- @override
- ThisExpression visitThisExpression(ThisExpression node) =>
- new ThisExpression(cloneToken(node.thisKeyword));
-
- @override
- ThrowExpression visitThrowExpression(ThrowExpression node) =>
- new ThrowExpression(
- cloneToken(node.throwKeyword), cloneNode(node.expression));
-
- @override
- TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
- TopLevelVariableDeclaration node) =>
- new TopLevelVariableDeclaration(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneNode(node.variables),
- cloneToken(node.semicolon));
-
- @override
- TryStatement visitTryStatement(TryStatement node) => new TryStatement(
- cloneToken(node.tryKeyword),
- cloneNode(node.body),
- cloneNodeList(node.catchClauses),
- cloneToken(node.finallyKeyword),
- cloneNode(node.finallyBlock));
-
- @override
- TypeArgumentList visitTypeArgumentList(TypeArgumentList node) =>
- new TypeArgumentList(cloneToken(node.leftBracket),
- cloneNodeList(node.arguments), cloneToken(node.rightBracket));
-
- @override
- TypeName visitTypeName(TypeName node) =>
- new TypeName(cloneNode(node.name), cloneNode(node.typeArguments));
-
- @override
- TypeParameter visitTypeParameter(TypeParameter node) => new TypeParameter(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneNode(node.name),
- cloneToken(node.extendsKeyword),
- cloneNode(node.bound));
-
- @override
- TypeParameterList visitTypeParameterList(TypeParameterList node) =>
- new TypeParameterList(cloneToken(node.leftBracket),
- cloneNodeList(node.typeParameters), cloneToken(node.rightBracket));
-
- @override
- VariableDeclaration visitVariableDeclaration(VariableDeclaration node) =>
- new VariableDeclaration(cloneNode(node.name), cloneToken(node.equals),
- cloneNode(node.initializer));
-
- @override
- VariableDeclarationList visitVariableDeclarationList(
- VariableDeclarationList node) =>
- new VariableDeclarationList(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneToken(node.keyword),
- cloneNode(node.type),
- cloneNodeList(node.variables));
-
- @override
- VariableDeclarationStatement visitVariableDeclarationStatement(
- VariableDeclarationStatement node) =>
- new VariableDeclarationStatement(
- cloneNode(node.variables), cloneToken(node.semicolon));
-
- @override
- WhileStatement visitWhileStatement(WhileStatement node) => new WhileStatement(
- cloneToken(node.whileKeyword),
- cloneToken(node.leftParenthesis),
- cloneNode(node.condition),
- cloneToken(node.rightParenthesis),
- cloneNode(node.body));
-
- @override
- WithClause visitWithClause(WithClause node) => new WithClause(
- cloneToken(node.withKeyword), cloneNodeList(node.mixinTypes));
-
- @override
- YieldStatement visitYieldStatement(YieldStatement node) => new YieldStatement(
- cloneToken(node.yieldKeyword),
- cloneToken(node.star),
- cloneNode(node.expression),
- cloneToken(node.semicolon));
-
- /**
- * Return a clone of the given [node].
- */
- static AstNode clone(AstNode node) {
- return node.accept(new AstCloner());
- }
-}
-
-/**
- * An AstVisitor that compares the structure of two AstNodes to see whether they
- * are equal.
- */
-class AstComparator implements AstVisitor<bool> {
- /**
- * The AST node with which the node being visited is to be compared. This is
- * only valid at the beginning of each visit method (until [isEqualNodes] is
- * invoked).
- */
- AstNode _other;
-
- /**
- * Return `true` if the [first] node and the [second] node have the same
- * structure.
- *
- * *Note:* This method is only visible for testing purposes and should not be
- * used by clients.
- */
- bool isEqualNodes(AstNode first, AstNode second) {
- if (first == null) {
- return second == null;
- } else if (second == null) {
- return false;
- } else if (first.runtimeType != second.runtimeType) {
- return false;
- }
- _other = second;
- return first.accept(this);
- }
-
- /**
- * Return `true` if the [first] token and the [second] token have the same
- * structure.
- *
- * *Note:* This method is only visible for testing purposes and should not be
- * used by clients.
- */
- bool isEqualTokens(Token first, Token second) {
- if (first == null) {
- return second == null;
- } else if (second == null) {
- return false;
- } else if (identical(first, second)) {
- return true;
- }
- return first.offset == second.offset &&
- first.length == second.length &&
- first.lexeme == second.lexeme;
- }
-
- @override
- bool visitAdjacentStrings(AdjacentStrings node) {
- AdjacentStrings other = _other as AdjacentStrings;
- return _isEqualNodeLists(node.strings, other.strings);
- }
-
- @override
- bool visitAnnotation(Annotation node) {
- Annotation other = _other as Annotation;
- return isEqualTokens(node.atSign, other.atSign) &&
- isEqualNodes(node.name, other.name) &&
- isEqualTokens(node.period, other.period) &&
- isEqualNodes(node.constructorName, other.constructorName) &&
- isEqualNodes(node.arguments, other.arguments);
- }
-
- @override
- bool visitArgumentList(ArgumentList node) {
- ArgumentList other = _other as ArgumentList;
- return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- _isEqualNodeLists(node.arguments, other.arguments) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis);
- }
-
- @override
- bool visitAsExpression(AsExpression node) {
- AsExpression other = _other as AsExpression;
- return isEqualNodes(node.expression, other.expression) &&
- isEqualTokens(node.asOperator, other.asOperator) &&
- isEqualNodes(node.type, other.type);
- }
-
- @override
- bool visitAssertStatement(AssertStatement node) {
- AssertStatement other = _other as AssertStatement;
- return isEqualTokens(node.assertKeyword, other.assertKeyword) &&
- isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- isEqualNodes(node.condition, other.condition) &&
- isEqualTokens(node.comma, other.comma) &&
- isEqualNodes(node.message, other.message) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitAssignmentExpression(AssignmentExpression node) {
- AssignmentExpression other = _other as AssignmentExpression;
- return isEqualNodes(node.leftHandSide, other.leftHandSide) &&
- isEqualTokens(node.operator, other.operator) &&
- isEqualNodes(node.rightHandSide, other.rightHandSide);
- }
-
- @override
- bool visitAwaitExpression(AwaitExpression node) {
- AwaitExpression other = _other as AwaitExpression;
- return isEqualTokens(node.awaitKeyword, other.awaitKeyword) &&
- isEqualNodes(node.expression, other.expression);
- }
-
- @override
- bool visitBinaryExpression(BinaryExpression node) {
- BinaryExpression other = _other as BinaryExpression;
- return isEqualNodes(node.leftOperand, other.leftOperand) &&
- isEqualTokens(node.operator, other.operator) &&
- isEqualNodes(node.rightOperand, other.rightOperand);
- }
-
- @override
- bool visitBlock(Block node) {
- Block other = _other as Block;
- return isEqualTokens(node.leftBracket, other.leftBracket) &&
- _isEqualNodeLists(node.statements, other.statements) &&
- isEqualTokens(node.rightBracket, other.rightBracket);
- }
-
- @override
- bool visitBlockFunctionBody(BlockFunctionBody node) {
- BlockFunctionBody other = _other as BlockFunctionBody;
- return isEqualNodes(node.block, other.block);
- }
-
- @override
- bool visitBooleanLiteral(BooleanLiteral node) {
- BooleanLiteral other = _other as BooleanLiteral;
- return isEqualTokens(node.literal, other.literal) &&
- node.value == other.value;
- }
-
- @override
- bool visitBreakStatement(BreakStatement node) {
- BreakStatement other = _other as BreakStatement;
- return isEqualTokens(node.breakKeyword, other.breakKeyword) &&
- isEqualNodes(node.label, other.label) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitCascadeExpression(CascadeExpression node) {
- CascadeExpression other = _other as CascadeExpression;
- return isEqualNodes(node.target, other.target) &&
- _isEqualNodeLists(node.cascadeSections, other.cascadeSections);
- }
-
- @override
- bool visitCatchClause(CatchClause node) {
- CatchClause other = _other as CatchClause;
- return isEqualTokens(node.onKeyword, other.onKeyword) &&
- isEqualNodes(node.exceptionType, other.exceptionType) &&
- isEqualTokens(node.catchKeyword, other.catchKeyword) &&
- isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- isEqualNodes(node.exceptionParameter, other.exceptionParameter) &&
- isEqualTokens(node.comma, other.comma) &&
- isEqualNodes(node.stackTraceParameter, other.stackTraceParameter) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
- isEqualNodes(node.body, other.body);
- }
-
- @override
- bool visitClassDeclaration(ClassDeclaration node) {
- ClassDeclaration other = _other as ClassDeclaration;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.abstractKeyword, other.abstractKeyword) &&
- isEqualTokens(node.classKeyword, other.classKeyword) &&
- isEqualNodes(node.name, other.name) &&
- isEqualNodes(node.typeParameters, other.typeParameters) &&
- isEqualNodes(node.extendsClause, other.extendsClause) &&
- isEqualNodes(node.withClause, other.withClause) &&
- isEqualNodes(node.implementsClause, other.implementsClause) &&
- isEqualTokens(node.leftBracket, other.leftBracket) &&
- _isEqualNodeLists(node.members, other.members) &&
- isEqualTokens(node.rightBracket, other.rightBracket);
- }
-
- @override
- bool visitClassTypeAlias(ClassTypeAlias node) {
- ClassTypeAlias other = _other as ClassTypeAlias;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.typedefKeyword, other.typedefKeyword) &&
- isEqualNodes(node.name, other.name) &&
- isEqualNodes(node.typeParameters, other.typeParameters) &&
- isEqualTokens(node.equals, other.equals) &&
- isEqualTokens(node.abstractKeyword, other.abstractKeyword) &&
- isEqualNodes(node.superclass, other.superclass) &&
- isEqualNodes(node.withClause, other.withClause) &&
- isEqualNodes(node.implementsClause, other.implementsClause) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitComment(Comment node) {
- Comment other = _other as Comment;
- return _isEqualNodeLists(node.references, other.references);
- }
-
- @override
- bool visitCommentReference(CommentReference node) {
- CommentReference other = _other as CommentReference;
- return isEqualTokens(node.newKeyword, other.newKeyword) &&
- isEqualNodes(node.identifier, other.identifier);
- }
-
- @override
- bool visitCompilationUnit(CompilationUnit node) {
- CompilationUnit other = _other as CompilationUnit;
- return isEqualTokens(node.beginToken, other.beginToken) &&
- isEqualNodes(node.scriptTag, other.scriptTag) &&
- _isEqualNodeLists(node.directives, other.directives) &&
- _isEqualNodeLists(node.declarations, other.declarations) &&
- isEqualTokens(node.endToken, other.endToken);
- }
-
- @override
- bool visitConditionalExpression(ConditionalExpression node) {
- ConditionalExpression other = _other as ConditionalExpression;
- return isEqualNodes(node.condition, other.condition) &&
- isEqualTokens(node.question, other.question) &&
- isEqualNodes(node.thenExpression, other.thenExpression) &&
- isEqualTokens(node.colon, other.colon) &&
- isEqualNodes(node.elseExpression, other.elseExpression);
- }
-
- @override
- bool visitConfiguration(Configuration node) {
- Configuration other = _other as Configuration;
- return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
- isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- isEqualNodes(node.name, other.name) &&
- isEqualTokens(node.equalToken, other.equalToken) &&
- isEqualNodes(node.value, other.value) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
- isEqualNodes(node.libraryUri, other.libraryUri);
- }
-
- @override
- bool visitConstructorDeclaration(ConstructorDeclaration node) {
- ConstructorDeclaration other = _other as ConstructorDeclaration;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.externalKeyword, other.externalKeyword) &&
- isEqualTokens(node.constKeyword, other.constKeyword) &&
- isEqualTokens(node.factoryKeyword, other.factoryKeyword) &&
- isEqualNodes(node.returnType, other.returnType) &&
- isEqualTokens(node.period, other.period) &&
- isEqualNodes(node.name, other.name) &&
- isEqualNodes(node.parameters, other.parameters) &&
- isEqualTokens(node.separator, other.separator) &&
- _isEqualNodeLists(node.initializers, other.initializers) &&
- isEqualNodes(node.redirectedConstructor, other.redirectedConstructor) &&
- isEqualNodes(node.body, other.body);
- }
-
- @override
- bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
- ConstructorFieldInitializer other = _other as ConstructorFieldInitializer;
- return isEqualTokens(node.thisKeyword, other.thisKeyword) &&
- isEqualTokens(node.period, other.period) &&
- isEqualNodes(node.fieldName, other.fieldName) &&
- isEqualTokens(node.equals, other.equals) &&
- isEqualNodes(node.expression, other.expression);
- }
-
- @override
- bool visitConstructorName(ConstructorName node) {
- ConstructorName other = _other as ConstructorName;
- return isEqualNodes(node.type, other.type) &&
- isEqualTokens(node.period, other.period) &&
- isEqualNodes(node.name, other.name);
- }
-
- @override
- bool visitContinueStatement(ContinueStatement node) {
- ContinueStatement other = _other as ContinueStatement;
- return isEqualTokens(node.continueKeyword, other.continueKeyword) &&
- isEqualNodes(node.label, other.label) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitDeclaredIdentifier(DeclaredIdentifier node) {
- DeclaredIdentifier other = _other as DeclaredIdentifier;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.keyword, other.keyword) &&
- isEqualNodes(node.type, other.type) &&
- isEqualNodes(node.identifier, other.identifier);
- }
-
- @override
- bool visitDefaultFormalParameter(DefaultFormalParameter node) {
- DefaultFormalParameter other = _other as DefaultFormalParameter;
- return isEqualNodes(node.parameter, other.parameter) &&
- node.kind == other.kind &&
- isEqualTokens(node.separator, other.separator) &&
- isEqualNodes(node.defaultValue, other.defaultValue);
- }
-
- @override
- bool visitDoStatement(DoStatement node) {
- DoStatement other = _other as DoStatement;
- return isEqualTokens(node.doKeyword, other.doKeyword) &&
- isEqualNodes(node.body, other.body) &&
- isEqualTokens(node.whileKeyword, other.whileKeyword) &&
- isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- isEqualNodes(node.condition, other.condition) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitDottedName(DottedName node) {
- DottedName other = _other as DottedName;
- return _isEqualNodeLists(node.components, other.components);
- }
-
- @override
- bool visitDoubleLiteral(DoubleLiteral node) {
- DoubleLiteral other = _other as DoubleLiteral;
- return isEqualTokens(node.literal, other.literal) &&
- node.value == other.value;
- }
-
- @override
- bool visitEmptyFunctionBody(EmptyFunctionBody node) {
- EmptyFunctionBody other = _other as EmptyFunctionBody;
- return isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitEmptyStatement(EmptyStatement node) {
- EmptyStatement other = _other as EmptyStatement;
- return isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
- EnumConstantDeclaration other = _other as EnumConstantDeclaration;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualNodes(node.name, other.name);
- }
-
- @override
- bool visitEnumDeclaration(EnumDeclaration node) {
- EnumDeclaration other = _other as EnumDeclaration;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.enumKeyword, other.enumKeyword) &&
- isEqualNodes(node.name, other.name) &&
- isEqualTokens(node.leftBracket, other.leftBracket) &&
- _isEqualNodeLists(node.constants, other.constants) &&
- isEqualTokens(node.rightBracket, other.rightBracket);
- }
-
- @override
- bool visitExportDirective(ExportDirective node) {
- ExportDirective other = _other as ExportDirective;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.keyword, other.keyword) &&
- isEqualNodes(node.uri, other.uri) &&
- _isEqualNodeLists(node.combinators, other.combinators) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitExpressionFunctionBody(ExpressionFunctionBody node) {
- ExpressionFunctionBody other = _other as ExpressionFunctionBody;
- return isEqualTokens(node.functionDefinition, other.functionDefinition) &&
- isEqualNodes(node.expression, other.expression) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitExpressionStatement(ExpressionStatement node) {
- ExpressionStatement other = _other as ExpressionStatement;
- return isEqualNodes(node.expression, other.expression) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitExtendsClause(ExtendsClause node) {
- ExtendsClause other = _other as ExtendsClause;
- return isEqualTokens(node.extendsKeyword, other.extendsKeyword) &&
- isEqualNodes(node.superclass, other.superclass);
- }
-
- @override
- bool visitFieldDeclaration(FieldDeclaration node) {
- FieldDeclaration other = _other as FieldDeclaration;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.staticKeyword, other.staticKeyword) &&
- isEqualNodes(node.fields, other.fields) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitFieldFormalParameter(FieldFormalParameter node) {
- FieldFormalParameter other = _other as FieldFormalParameter;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.keyword, other.keyword) &&
- isEqualNodes(node.type, other.type) &&
- isEqualTokens(node.thisKeyword, other.thisKeyword) &&
- isEqualTokens(node.period, other.period) &&
- isEqualNodes(node.identifier, other.identifier);
- }
-
- @override
- bool visitForEachStatement(ForEachStatement node) {
- ForEachStatement other = _other as ForEachStatement;
- return isEqualTokens(node.forKeyword, other.forKeyword) &&
- isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- isEqualNodes(node.loopVariable, other.loopVariable) &&
- isEqualTokens(node.inKeyword, other.inKeyword) &&
- isEqualNodes(node.iterable, other.iterable) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
- isEqualNodes(node.body, other.body);
- }
-
- @override
- bool visitFormalParameterList(FormalParameterList node) {
- FormalParameterList other = _other as FormalParameterList;
- return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- _isEqualNodeLists(node.parameters, other.parameters) &&
- isEqualTokens(node.leftDelimiter, other.leftDelimiter) &&
- isEqualTokens(node.rightDelimiter, other.rightDelimiter) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis);
- }
-
- @override
- bool visitForStatement(ForStatement node) {
- ForStatement other = _other as ForStatement;
- return isEqualTokens(node.forKeyword, other.forKeyword) &&
- isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- isEqualNodes(node.variables, other.variables) &&
- isEqualNodes(node.initialization, other.initialization) &&
- isEqualTokens(node.leftSeparator, other.leftSeparator) &&
- isEqualNodes(node.condition, other.condition) &&
- isEqualTokens(node.rightSeparator, other.rightSeparator) &&
- _isEqualNodeLists(node.updaters, other.updaters) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
- isEqualNodes(node.body, other.body);
- }
-
- @override
- bool visitFunctionDeclaration(FunctionDeclaration node) {
- FunctionDeclaration other = _other as FunctionDeclaration;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.externalKeyword, other.externalKeyword) &&
- isEqualNodes(node.returnType, other.returnType) &&
- isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
- isEqualNodes(node.name, other.name) &&
- isEqualNodes(node.functionExpression, other.functionExpression);
- }
-
- @override
- bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
- FunctionDeclarationStatement other = _other as FunctionDeclarationStatement;
- return isEqualNodes(node.functionDeclaration, other.functionDeclaration);
- }
-
- @override
- bool visitFunctionExpression(FunctionExpression node) {
- FunctionExpression other = _other as FunctionExpression;
- return isEqualNodes(node.parameters, other.parameters) &&
- isEqualNodes(node.body, other.body);
- }
-
- @override
- bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
- FunctionExpressionInvocation other = _other as FunctionExpressionInvocation;
- return isEqualNodes(node.function, other.function) &&
- isEqualNodes(node.argumentList, other.argumentList);
- }
-
- @override
- bool visitFunctionTypeAlias(FunctionTypeAlias node) {
- FunctionTypeAlias other = _other as FunctionTypeAlias;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.typedefKeyword, other.typedefKeyword) &&
- isEqualNodes(node.returnType, other.returnType) &&
- isEqualNodes(node.name, other.name) &&
- isEqualNodes(node.typeParameters, other.typeParameters) &&
- isEqualNodes(node.parameters, other.parameters) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
- FunctionTypedFormalParameter other = _other as FunctionTypedFormalParameter;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualNodes(node.returnType, other.returnType) &&
- isEqualNodes(node.identifier, other.identifier) &&
- isEqualNodes(node.parameters, other.parameters);
- }
-
- @override
- bool visitHideCombinator(HideCombinator node) {
- HideCombinator other = _other as HideCombinator;
- return isEqualTokens(node.keyword, other.keyword) &&
- _isEqualNodeLists(node.hiddenNames, other.hiddenNames);
- }
-
- @override
- bool visitIfStatement(IfStatement node) {
- IfStatement other = _other as IfStatement;
- return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
- isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- isEqualNodes(node.condition, other.condition) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
- isEqualNodes(node.thenStatement, other.thenStatement) &&
- isEqualTokens(node.elseKeyword, other.elseKeyword) &&
- isEqualNodes(node.elseStatement, other.elseStatement);
- }
-
- @override
- bool visitImplementsClause(ImplementsClause node) {
- ImplementsClause other = _other as ImplementsClause;
- return isEqualTokens(node.implementsKeyword, other.implementsKeyword) &&
- _isEqualNodeLists(node.interfaces, other.interfaces);
- }
-
- @override
- bool visitImportDirective(ImportDirective node) {
- ImportDirective other = _other as ImportDirective;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.keyword, other.keyword) &&
- isEqualNodes(node.uri, other.uri) &&
- isEqualTokens(node.deferredKeyword, other.deferredKeyword) &&
- isEqualTokens(node.asKeyword, other.asKeyword) &&
- isEqualNodes(node.prefix, other.prefix) &&
- _isEqualNodeLists(node.combinators, other.combinators) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitIndexExpression(IndexExpression node) {
- IndexExpression other = _other as IndexExpression;
- return isEqualNodes(node.target, other.target) &&
- isEqualTokens(node.leftBracket, other.leftBracket) &&
- isEqualNodes(node.index, other.index) &&
- isEqualTokens(node.rightBracket, other.rightBracket);
- }
-
- @override
- bool visitInstanceCreationExpression(InstanceCreationExpression node) {
- InstanceCreationExpression other = _other as InstanceCreationExpression;
- return isEqualTokens(node.keyword, other.keyword) &&
- isEqualNodes(node.constructorName, other.constructorName) &&
- isEqualNodes(node.argumentList, other.argumentList);
- }
-
- @override
- bool visitIntegerLiteral(IntegerLiteral node) {
- IntegerLiteral other = _other as IntegerLiteral;
- return isEqualTokens(node.literal, other.literal) &&
- (node.value == other.value);
- }
-
- @override
- bool visitInterpolationExpression(InterpolationExpression node) {
- InterpolationExpression other = _other as InterpolationExpression;
- return isEqualTokens(node.leftBracket, other.leftBracket) &&
- isEqualNodes(node.expression, other.expression) &&
- isEqualTokens(node.rightBracket, other.rightBracket);
- }
-
- @override
- bool visitInterpolationString(InterpolationString node) {
- InterpolationString other = _other as InterpolationString;
- return isEqualTokens(node.contents, other.contents) &&
- node.value == other.value;
- }
-
- @override
- bool visitIsExpression(IsExpression node) {
- IsExpression other = _other as IsExpression;
- return isEqualNodes(node.expression, other.expression) &&
- isEqualTokens(node.isOperator, other.isOperator) &&
- isEqualTokens(node.notOperator, other.notOperator) &&
- isEqualNodes(node.type, other.type);
- }
-
- @override
- bool visitLabel(Label node) {
- Label other = _other as Label;
- return isEqualNodes(node.label, other.label) &&
- isEqualTokens(node.colon, other.colon);
- }
-
- @override
- bool visitLabeledStatement(LabeledStatement node) {
- LabeledStatement other = _other as LabeledStatement;
- return _isEqualNodeLists(node.labels, other.labels) &&
- isEqualNodes(node.statement, other.statement);
- }
-
- @override
- bool visitLibraryDirective(LibraryDirective node) {
- LibraryDirective other = _other as LibraryDirective;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.libraryKeyword, other.libraryKeyword) &&
- isEqualNodes(node.name, other.name) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitLibraryIdentifier(LibraryIdentifier node) {
- LibraryIdentifier other = _other as LibraryIdentifier;
- return _isEqualNodeLists(node.components, other.components);
- }
-
- @override
- bool visitListLiteral(ListLiteral node) {
- ListLiteral other = _other as ListLiteral;
- return isEqualTokens(node.constKeyword, other.constKeyword) &&
- isEqualNodes(node.typeArguments, other.typeArguments) &&
- isEqualTokens(node.leftBracket, other.leftBracket) &&
- _isEqualNodeLists(node.elements, other.elements) &&
- isEqualTokens(node.rightBracket, other.rightBracket);
- }
-
- @override
- bool visitMapLiteral(MapLiteral node) {
- MapLiteral other = _other as MapLiteral;
- return isEqualTokens(node.constKeyword, other.constKeyword) &&
- isEqualNodes(node.typeArguments, other.typeArguments) &&
- isEqualTokens(node.leftBracket, other.leftBracket) &&
- _isEqualNodeLists(node.entries, other.entries) &&
- isEqualTokens(node.rightBracket, other.rightBracket);
- }
-
- @override
- bool visitMapLiteralEntry(MapLiteralEntry node) {
- MapLiteralEntry other = _other as MapLiteralEntry;
- return isEqualNodes(node.key, other.key) &&
- isEqualTokens(node.separator, other.separator) &&
- isEqualNodes(node.value, other.value);
- }
-
- @override
- bool visitMethodDeclaration(MethodDeclaration node) {
- MethodDeclaration other = _other as MethodDeclaration;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.externalKeyword, other.externalKeyword) &&
- isEqualTokens(node.modifierKeyword, other.modifierKeyword) &&
- isEqualNodes(node.returnType, other.returnType) &&
- isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
- isEqualTokens(node.propertyKeyword, other.propertyKeyword) &&
- isEqualNodes(node.name, other.name) &&
- isEqualNodes(node.parameters, other.parameters) &&
- isEqualNodes(node.body, other.body);
- }
-
- @override
- bool visitMethodInvocation(MethodInvocation node) {
- MethodInvocation other = _other as MethodInvocation;
- return isEqualNodes(node.target, other.target) &&
- isEqualTokens(node.operator, other.operator) &&
- isEqualNodes(node.methodName, other.methodName) &&
- isEqualNodes(node.argumentList, other.argumentList);
- }
-
- @override
- bool visitNamedExpression(NamedExpression node) {
- NamedExpression other = _other as NamedExpression;
- return isEqualNodes(node.name, other.name) &&
- isEqualNodes(node.expression, other.expression);
- }
-
- @override
- bool visitNativeClause(NativeClause node) {
- NativeClause other = _other as NativeClause;
- return isEqualTokens(node.nativeKeyword, other.nativeKeyword) &&
- isEqualNodes(node.name, other.name);
- }
-
- @override
- bool visitNativeFunctionBody(NativeFunctionBody node) {
- NativeFunctionBody other = _other as NativeFunctionBody;
- return isEqualTokens(node.nativeKeyword, other.nativeKeyword) &&
- isEqualNodes(node.stringLiteral, other.stringLiteral) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitNullLiteral(NullLiteral node) {
- NullLiteral other = _other as NullLiteral;
- return isEqualTokens(node.literal, other.literal);
- }
-
- @override
- bool visitParenthesizedExpression(ParenthesizedExpression node) {
- ParenthesizedExpression other = _other as ParenthesizedExpression;
- return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- isEqualNodes(node.expression, other.expression) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis);
- }
-
- @override
- bool visitPartDirective(PartDirective node) {
- PartDirective other = _other as PartDirective;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.partKeyword, other.partKeyword) &&
- isEqualNodes(node.uri, other.uri) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitPartOfDirective(PartOfDirective node) {
- PartOfDirective other = _other as PartOfDirective;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.partKeyword, other.partKeyword) &&
- isEqualTokens(node.ofKeyword, other.ofKeyword) &&
- isEqualNodes(node.libraryName, other.libraryName) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitPostfixExpression(PostfixExpression node) {
- PostfixExpression other = _other as PostfixExpression;
- return isEqualNodes(node.operand, other.operand) &&
- isEqualTokens(node.operator, other.operator);
- }
-
- @override
- bool visitPrefixedIdentifier(PrefixedIdentifier node) {
- PrefixedIdentifier other = _other as PrefixedIdentifier;
- return isEqualNodes(node.prefix, other.prefix) &&
- isEqualTokens(node.period, other.period) &&
- isEqualNodes(node.identifier, other.identifier);
- }
-
- @override
- bool visitPrefixExpression(PrefixExpression node) {
- PrefixExpression other = _other as PrefixExpression;
- return isEqualTokens(node.operator, other.operator) &&
- isEqualNodes(node.operand, other.operand);
- }
-
- @override
- bool visitPropertyAccess(PropertyAccess node) {
- PropertyAccess other = _other as PropertyAccess;
- return isEqualNodes(node.target, other.target) &&
- isEqualTokens(node.operator, other.operator) &&
- isEqualNodes(node.propertyName, other.propertyName);
- }
-
- @override
- bool visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) {
- RedirectingConstructorInvocation other =
- _other as RedirectingConstructorInvocation;
- return isEqualTokens(node.thisKeyword, other.thisKeyword) &&
- isEqualTokens(node.period, other.period) &&
- isEqualNodes(node.constructorName, other.constructorName) &&
- isEqualNodes(node.argumentList, other.argumentList);
- }
-
- @override
- bool visitRethrowExpression(RethrowExpression node) {
- RethrowExpression other = _other as RethrowExpression;
- return isEqualTokens(node.rethrowKeyword, other.rethrowKeyword);
- }
-
- @override
- bool visitReturnStatement(ReturnStatement node) {
- ReturnStatement other = _other as ReturnStatement;
- return isEqualTokens(node.returnKeyword, other.returnKeyword) &&
- isEqualNodes(node.expression, other.expression) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitScriptTag(ScriptTag node) {
- ScriptTag other = _other as ScriptTag;
- return isEqualTokens(node.scriptTag, other.scriptTag);
- }
-
- @override
- bool visitShowCombinator(ShowCombinator node) {
- ShowCombinator other = _other as ShowCombinator;
- return isEqualTokens(node.keyword, other.keyword) &&
- _isEqualNodeLists(node.shownNames, other.shownNames);
- }
-
- @override
- bool visitSimpleFormalParameter(SimpleFormalParameter node) {
- SimpleFormalParameter other = _other as SimpleFormalParameter;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.keyword, other.keyword) &&
- isEqualNodes(node.type, other.type) &&
- isEqualNodes(node.identifier, other.identifier);
- }
-
- @override
- bool visitSimpleIdentifier(SimpleIdentifier node) {
- SimpleIdentifier other = _other as SimpleIdentifier;
- return isEqualTokens(node.token, other.token);
- }
-
- @override
- bool visitSimpleStringLiteral(SimpleStringLiteral node) {
- SimpleStringLiteral other = _other as SimpleStringLiteral;
- return isEqualTokens(node.literal, other.literal) &&
- (node.value == other.value);
- }
-
- @override
- bool visitStringInterpolation(StringInterpolation node) {
- StringInterpolation other = _other as StringInterpolation;
- return _isEqualNodeLists(node.elements, other.elements);
- }
-
- @override
- bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
- SuperConstructorInvocation other = _other as SuperConstructorInvocation;
- return isEqualTokens(node.superKeyword, other.superKeyword) &&
- isEqualTokens(node.period, other.period) &&
- isEqualNodes(node.constructorName, other.constructorName) &&
- isEqualNodes(node.argumentList, other.argumentList);
- }
-
- @override
- bool visitSuperExpression(SuperExpression node) {
- SuperExpression other = _other as SuperExpression;
- return isEqualTokens(node.superKeyword, other.superKeyword);
- }
-
- @override
- bool visitSwitchCase(SwitchCase node) {
- SwitchCase other = _other as SwitchCase;
- return _isEqualNodeLists(node.labels, other.labels) &&
- isEqualTokens(node.keyword, other.keyword) &&
- isEqualNodes(node.expression, other.expression) &&
- isEqualTokens(node.colon, other.colon) &&
- _isEqualNodeLists(node.statements, other.statements);
- }
-
- @override
- bool visitSwitchDefault(SwitchDefault node) {
- SwitchDefault other = _other as SwitchDefault;
- return _isEqualNodeLists(node.labels, other.labels) &&
- isEqualTokens(node.keyword, other.keyword) &&
- isEqualTokens(node.colon, other.colon) &&
- _isEqualNodeLists(node.statements, other.statements);
- }
-
- @override
- bool visitSwitchStatement(SwitchStatement node) {
- SwitchStatement other = _other as SwitchStatement;
- return isEqualTokens(node.switchKeyword, other.switchKeyword) &&
- isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- isEqualNodes(node.expression, other.expression) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
- isEqualTokens(node.leftBracket, other.leftBracket) &&
- _isEqualNodeLists(node.members, other.members) &&
- isEqualTokens(node.rightBracket, other.rightBracket);
- }
-
- @override
- bool visitSymbolLiteral(SymbolLiteral node) {
- SymbolLiteral other = _other as SymbolLiteral;
- return isEqualTokens(node.poundSign, other.poundSign) &&
- _isEqualTokenLists(node.components, other.components);
- }
-
- @override
- bool visitThisExpression(ThisExpression node) {
- ThisExpression other = _other as ThisExpression;
- return isEqualTokens(node.thisKeyword, other.thisKeyword);
- }
-
- @override
- bool visitThrowExpression(ThrowExpression node) {
- ThrowExpression other = _other as ThrowExpression;
- return isEqualTokens(node.throwKeyword, other.throwKeyword) &&
- isEqualNodes(node.expression, other.expression);
- }
-
- @override
- bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- TopLevelVariableDeclaration other = _other as TopLevelVariableDeclaration;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualNodes(node.variables, other.variables) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitTryStatement(TryStatement node) {
- TryStatement other = _other as TryStatement;
- return isEqualTokens(node.tryKeyword, other.tryKeyword) &&
- isEqualNodes(node.body, other.body) &&
- _isEqualNodeLists(node.catchClauses, other.catchClauses) &&
- isEqualTokens(node.finallyKeyword, other.finallyKeyword) &&
- isEqualNodes(node.finallyBlock, other.finallyBlock);
- }
-
- @override
- bool visitTypeArgumentList(TypeArgumentList node) {
- TypeArgumentList other = _other as TypeArgumentList;
- return isEqualTokens(node.leftBracket, other.leftBracket) &&
- _isEqualNodeLists(node.arguments, other.arguments) &&
- isEqualTokens(node.rightBracket, other.rightBracket);
- }
-
- @override
- bool visitTypeName(TypeName node) {
- TypeName other = _other as TypeName;
- return isEqualNodes(node.name, other.name) &&
- isEqualNodes(node.typeArguments, other.typeArguments);
- }
-
- @override
- bool visitTypeParameter(TypeParameter node) {
- TypeParameter other = _other as TypeParameter;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualNodes(node.name, other.name) &&
- isEqualTokens(node.extendsKeyword, other.extendsKeyword) &&
- isEqualNodes(node.bound, other.bound);
- }
-
- @override
- bool visitTypeParameterList(TypeParameterList node) {
- TypeParameterList other = _other as TypeParameterList;
- return isEqualTokens(node.leftBracket, other.leftBracket) &&
- _isEqualNodeLists(node.typeParameters, other.typeParameters) &&
- isEqualTokens(node.rightBracket, other.rightBracket);
- }
-
- @override
- bool visitVariableDeclaration(VariableDeclaration node) {
- VariableDeclaration other = _other as VariableDeclaration;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualNodes(node.name, other.name) &&
- isEqualTokens(node.equals, other.equals) &&
- isEqualNodes(node.initializer, other.initializer);
- }
-
- @override
- bool visitVariableDeclarationList(VariableDeclarationList node) {
- VariableDeclarationList other = _other as VariableDeclarationList;
- return isEqualNodes(
- node.documentationComment, other.documentationComment) &&
- _isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.keyword, other.keyword) &&
- isEqualNodes(node.type, other.type) &&
- _isEqualNodeLists(node.variables, other.variables);
- }
-
- @override
- bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
- VariableDeclarationStatement other = _other as VariableDeclarationStatement;
- return isEqualNodes(node.variables, other.variables) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- @override
- bool visitWhileStatement(WhileStatement node) {
- WhileStatement other = _other as WhileStatement;
- return isEqualTokens(node.whileKeyword, other.whileKeyword) &&
- isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
- isEqualNodes(node.condition, other.condition) &&
- isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
- isEqualNodes(node.body, other.body);
- }
-
- @override
- bool visitWithClause(WithClause node) {
- WithClause other = _other as WithClause;
- return isEqualTokens(node.withKeyword, other.withKeyword) &&
- _isEqualNodeLists(node.mixinTypes, other.mixinTypes);
- }
-
- @override
- bool visitYieldStatement(YieldStatement node) {
- YieldStatement other = _other as YieldStatement;
- return isEqualTokens(node.yieldKeyword, other.yieldKeyword) &&
- isEqualNodes(node.expression, other.expression) &&
- isEqualTokens(node.semicolon, other.semicolon);
- }
-
- /**
- * Return `true` if the [first] and [second] lists of AST nodes have the same
- * size and corresponding elements are equal.
- */
- bool _isEqualNodeLists(NodeList first, NodeList second) {
- if (first == null) {
- return second == null;
- } else if (second == null) {
- return false;
- }
- int size = first.length;
- if (second.length != size) {
- return false;
- }
- for (int i = 0; i < size; i++) {
- if (!isEqualNodes(first[i], second[i])) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Return `true` if the [first] and [second] lists of tokens have the same
- * length and corresponding elements are equal.
- */
- bool _isEqualTokenLists(List<Token> first, List<Token> second) {
- int length = first.length;
- if (second.length != length) {
- return false;
- }
- for (int i = 0; i < length; i++) {
- if (!isEqualTokens(first[i], second[i])) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Return `true` if the [first] and [second] nodes are equal.
- */
- static bool equalNodes(AstNode first, AstNode second) {
- AstComparator comparator = new AstComparator();
- return comparator.isEqualNodes(first, second);
- }
-}
-
-/**
* A node in the AST structure for a Dart program.
*/
abstract class AstNode {
@@ -3671,61 +1719,6 @@
}
/**
- * An AST visitor that will recursively visit all of the nodes in an AST
- * structure, similar to [GeneralizingAstVisitor]. This visitor uses a
- * breadth-first ordering rather than the depth-first ordering of
- * [GeneralizingAstVisitor].
- *
- * Subclasses that override a visit method must either invoke the overridden
- * visit method or explicitly invoke the more general visit method. Failure to
- * do so will cause the visit methods for superclasses of the node to not be
- * invoked and will cause the children of the visited node to not be visited.
- *
- * In addition, subclasses should <b>not</b> explicitly visit the children of a
- * node, but should ensure that the method [visitNode] is used to visit the
- * children (either directly or indirectly). Failure to do will break the order
- * in which nodes are visited.
- */
-class BreadthFirstVisitor<R> extends GeneralizingAstVisitor<R> {
- /**
- * A queue holding the nodes that have not yet been visited in the order in
- * which they ought to be visited.
- */
- Queue<AstNode> _queue = new Queue<AstNode>();
-
- /**
- * A visitor, used to visit the children of the current node, that will add
- * the nodes it visits to the [_queue].
- */
- GeneralizingAstVisitor<Object> _childVisitor;
-
- /**
- * Initialize a newly created visitor.
- */
- BreadthFirstVisitor() {
- _childVisitor = new GeneralizingAstVisitor_BreadthFirstVisitor(this);
- }
-
- /**
- * Visit all nodes in the tree starting at the given [root] node, in
- * breadth-first order.
- */
- void visitAllNodes(AstNode root) {
- _queue.add(root);
- while (!_queue.isEmpty) {
- AstNode next = _queue.removeFirst();
- next.accept(this);
- }
- }
-
- @override
- R visitNode(AstNode node) {
- node.visitChildren(_childVisitor);
- return null;
- }
-}
-
-/**
* A break statement.
*
* > breakStatement ::=
@@ -5129,373 +3122,6 @@
}
}
-/// Instances of the class [ConstantEvaluator] evaluate constant expressions to
-/// produce their compile-time value.
-///
-/// According to the Dart Language Specification:
-///
-/// > A constant expression is one of the following:
-/// >
-/// > * A literal number.
-/// > * A literal boolean.
-/// > * A literal string where any interpolated expression is a compile-time
-/// > constant that evaluates to a numeric, string or boolean value or to
-/// > **null**.
-/// > * A literal symbol.
-/// > * **null**.
-/// > * A qualified reference to a static constant variable.
-/// > * An identifier expression that denotes a constant variable, class or type
-/// > alias.
-/// > * A constant constructor invocation.
-/// > * A constant list literal.
-/// > * A constant map literal.
-/// > * A simple or qualified identifier denoting a top-level function or a
-/// > static method.
-/// > * A parenthesized expression _(e)_ where _e_ is a constant expression.
-/// > * <span>
-/// > An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
-/// > where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
-/// > expressions and <i>identical()</i> is statically bound to the predefined
-/// > dart function <i>identical()</i> discussed above.
-/// > </span>
-/// > * <span>
-/// > An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i>
-/// > or <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
-/// > <i>e<sub>2</sub></i> are constant expressions that evaluate to a
-/// > numeric, string or boolean value.
-/// > </span>
-/// > * <span>
-/// > An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &&
-/// > e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where
-/// > <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
-/// > expressions that evaluate to a boolean value.
-/// > </span>
-/// > * <span>
-/// > An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
-/// > e<sub>2</sub></i>, <i>e<sub>1</sub> & e<sub>2</sub></i>,
-/// > <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> >>
-/// > e<sub>2</sub></i> or <i>e<sub>1</sub> << e<sub>2</sub></i>, where
-/// > <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
-/// > expressions that evaluate to an integer value or to <b>null</b>.
-/// > </span>
-/// > * <span>
-/// > An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
-/// > e<sub>2</sub></i>, <i>e<sub>1</sub> -e<sub>2</sub></i>,
-/// > <i>e<sub>1</sub> * e<sub>2</sub></i>, <i>e<sub>1</sub> /
-/// > e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ e<sub>2</sub></i>,
-/// > <i>e<sub>1</sub> > e<sub>2</sub></i>, <i>e<sub>1</sub> <
-/// > e<sub>2</sub></i>, <i>e<sub>1</sub> >= e<sub>2</sub></i>,
-/// > <i>e<sub>1</sub> <= e<sub>2</sub></i> or <i>e<sub>1</sub> %
-/// > e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i> and
-/// > <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric
-/// > value or to <b>null</b>.
-/// > </span>
-/// > * <span>
-/// > An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
-/// > e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
-/// > <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
-/// > evaluates to a boolean value.
-/// > </span>
-///
-/// The values returned by instances of this class are therefore `null` and
-/// instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and
-/// `DartObject`.
-///
-/// In addition, this class defines several values that can be returned to
-/// indicate various conditions encountered during evaluation. These are
-/// documented with the static fields that define those values.
-class ConstantEvaluator extends GeneralizingAstVisitor<Object> {
- /**
- * The value returned for expressions (or non-expression nodes) that are not
- * compile-time constant expressions.
- */
- static Object NOT_A_CONSTANT = new Object();
-
- @override
- Object visitAdjacentStrings(AdjacentStrings node) {
- StringBuffer buffer = new StringBuffer();
- for (StringLiteral string in node.strings) {
- Object value = string.accept(this);
- if (identical(value, NOT_A_CONSTANT)) {
- return value;
- }
- buffer.write(value);
- }
- return buffer.toString();
- }
-
- @override
- Object visitBinaryExpression(BinaryExpression node) {
- Object leftOperand = node.leftOperand.accept(this);
- if (identical(leftOperand, NOT_A_CONSTANT)) {
- return leftOperand;
- }
- Object rightOperand = node.rightOperand.accept(this);
- if (identical(rightOperand, NOT_A_CONSTANT)) {
- return rightOperand;
- }
- while (true) {
- if (node.operator.type == TokenType.AMPERSAND) {
- // integer or {@code null}
- if (leftOperand is int && rightOperand is int) {
- return leftOperand & rightOperand;
- }
- } else if (node.operator.type == TokenType.AMPERSAND_AMPERSAND) {
- // boolean or {@code null}
- if (leftOperand is bool && rightOperand is bool) {
- return leftOperand && rightOperand;
- }
- } else if (node.operator.type == TokenType.BANG_EQ) {
- // numeric, string, boolean, or {@code null}
- if (leftOperand is bool && rightOperand is bool) {
- return leftOperand != rightOperand;
- } else if (leftOperand is num && rightOperand is num) {
- return leftOperand != rightOperand;
- } else if (leftOperand is String && rightOperand is String) {
- return leftOperand != rightOperand;
- }
- } else if (node.operator.type == TokenType.BAR) {
- // integer or {@code null}
- if (leftOperand is int && rightOperand is int) {
- return leftOperand | rightOperand;
- }
- } else if (node.operator.type == TokenType.BAR_BAR) {
- // boolean or {@code null}
- if (leftOperand is bool && rightOperand is bool) {
- return leftOperand || rightOperand;
- }
- } else if (node.operator.type == TokenType.CARET) {
- // integer or {@code null}
- if (leftOperand is int && rightOperand is int) {
- return leftOperand ^ rightOperand;
- }
- } else if (node.operator.type == TokenType.EQ_EQ) {
- // numeric, string, boolean, or {@code null}
- if (leftOperand is bool && rightOperand is bool) {
- return leftOperand == rightOperand;
- } else if (leftOperand is num && rightOperand is num) {
- return leftOperand == rightOperand;
- } else if (leftOperand is String && rightOperand is String) {
- return leftOperand == rightOperand;
- }
- } else if (node.operator.type == TokenType.GT) {
- // numeric or {@code null}
- if (leftOperand is num && rightOperand is num) {
- return leftOperand.compareTo(rightOperand) > 0;
- }
- } else if (node.operator.type == TokenType.GT_EQ) {
- // numeric or {@code null}
- if (leftOperand is num && rightOperand is num) {
- return leftOperand.compareTo(rightOperand) >= 0;
- }
- } else if (node.operator.type == TokenType.GT_GT) {
- // integer or {@code null}
- if (leftOperand is int && rightOperand is int) {
- return leftOperand >> rightOperand;
- }
- } else if (node.operator.type == TokenType.LT) {
- // numeric or {@code null}
- if (leftOperand is num && rightOperand is num) {
- return leftOperand.compareTo(rightOperand) < 0;
- }
- } else if (node.operator.type == TokenType.LT_EQ) {
- // numeric or {@code null}
- if (leftOperand is num && rightOperand is num) {
- return leftOperand.compareTo(rightOperand) <= 0;
- }
- } else if (node.operator.type == TokenType.LT_LT) {
- // integer or {@code null}
- if (leftOperand is int && rightOperand is int) {
- return leftOperand << rightOperand;
- }
- } else if (node.operator.type == TokenType.MINUS) {
- // numeric or {@code null}
- if (leftOperand is num && rightOperand is num) {
- return leftOperand - rightOperand;
- }
- } else if (node.operator.type == TokenType.PERCENT) {
- // numeric or {@code null}
- if (leftOperand is num && rightOperand is num) {
- return leftOperand.remainder(rightOperand);
- }
- } else if (node.operator.type == TokenType.PLUS) {
- // numeric or {@code null}
- if (leftOperand is num && rightOperand is num) {
- return leftOperand + rightOperand;
- }
- } else if (node.operator.type == TokenType.STAR) {
- // numeric or {@code null}
- if (leftOperand is num && rightOperand is num) {
- return leftOperand * rightOperand;
- }
- } else if (node.operator.type == TokenType.SLASH) {
- // numeric or {@code null}
- if (leftOperand is num && rightOperand is num) {
- return leftOperand / rightOperand;
- }
- } else if (node.operator.type == TokenType.TILDE_SLASH) {
- // numeric or {@code null}
- if (leftOperand is num && rightOperand is num) {
- return leftOperand ~/ rightOperand;
- }
- } else {}
- break;
- }
- // TODO(brianwilkerson) This doesn't handle numeric conversions.
- return visitExpression(node);
- }
-
- @override
- Object visitBooleanLiteral(BooleanLiteral node) => node.value ? true : false;
-
- @override
- Object visitDoubleLiteral(DoubleLiteral node) => node.value;
-
- @override
- Object visitIntegerLiteral(IntegerLiteral node) => node.value;
-
- @override
- Object visitInterpolationExpression(InterpolationExpression node) {
- Object value = node.expression.accept(this);
- if (value == null || value is bool || value is String || value is num) {
- return value;
- }
- return NOT_A_CONSTANT;
- }
-
- @override
- Object visitInterpolationString(InterpolationString node) => node.value;
-
- @override
- Object visitListLiteral(ListLiteral node) {
- List<Object> list = new List<Object>();
- for (Expression element in node.elements) {
- Object value = element.accept(this);
- if (identical(value, NOT_A_CONSTANT)) {
- return value;
- }
- list.add(value);
- }
- return list;
- }
-
- @override
- Object visitMapLiteral(MapLiteral node) {
- HashMap<String, Object> map = new HashMap<String, Object>();
- for (MapLiteralEntry entry in node.entries) {
- Object key = entry.key.accept(this);
- Object value = entry.value.accept(this);
- if (key is! String || identical(value, NOT_A_CONSTANT)) {
- return NOT_A_CONSTANT;
- }
- map[(key as String)] = value;
- }
- return map;
- }
-
- @override
- Object visitMethodInvocation(MethodInvocation node) => visitNode(node);
-
- @override
- Object visitNode(AstNode node) => NOT_A_CONSTANT;
-
- @override
- Object visitNullLiteral(NullLiteral node) => null;
-
- @override
- Object visitParenthesizedExpression(ParenthesizedExpression node) =>
- node.expression.accept(this);
-
- @override
- Object visitPrefixedIdentifier(PrefixedIdentifier node) =>
- _getConstantValue(null);
-
- @override
- Object visitPrefixExpression(PrefixExpression node) {
- Object operand = node.operand.accept(this);
- if (identical(operand, NOT_A_CONSTANT)) {
- return operand;
- }
- while (true) {
- if (node.operator.type == TokenType.BANG) {
- if (identical(operand, true)) {
- return false;
- } else if (identical(operand, false)) {
- return true;
- }
- } else if (node.operator.type == TokenType.TILDE) {
- if (operand is int) {
- return ~operand;
- }
- } else if (node.operator.type == TokenType.MINUS) {
- if (operand == null) {
- return null;
- } else if (operand is num) {
- return -operand;
- }
- } else {}
- break;
- }
- return NOT_A_CONSTANT;
- }
-
- @override
- Object visitPropertyAccess(PropertyAccess node) => _getConstantValue(null);
-
- @override
- Object visitSimpleIdentifier(SimpleIdentifier node) =>
- _getConstantValue(null);
-
- @override
- Object visitSimpleStringLiteral(SimpleStringLiteral node) => node.value;
-
- @override
- Object visitStringInterpolation(StringInterpolation node) {
- StringBuffer buffer = new StringBuffer();
- for (InterpolationElement element in node.elements) {
- Object value = element.accept(this);
- if (identical(value, NOT_A_CONSTANT)) {
- return value;
- }
- buffer.write(value);
- }
- return buffer.toString();
- }
-
- @override
- Object visitSymbolLiteral(SymbolLiteral node) {
- // TODO(brianwilkerson) This isn't optimal because a Symbol is not a String.
- StringBuffer buffer = new StringBuffer();
- for (Token component in node.components) {
- if (buffer.length > 0) {
- buffer.writeCharCode(0x2E);
- }
- buffer.write(component.lexeme);
- }
- return buffer.toString();
- }
-
- /**
- * Return the constant value of the static constant represented by the given
- * [element].
- */
- Object _getConstantValue(Element element) {
- // TODO(brianwilkerson) Implement this
- if (element is FieldElement) {
- FieldElement field = element;
- if (field.isStatic && field.isConst) {
- //field.getConstantValue();
- }
- // } else if (element instanceof VariableElement) {
- // VariableElement variable = (VariableElement) element;
- // if (variable.isStatic() && variable.isConst()) {
- // //variable.getConstantValue();
- // }
- }
- return NOT_A_CONSTANT;
- }
-}
-
/**
* A constructor declaration.
*
@@ -6265,37 +3891,6 @@
}
/**
- * A recursive AST visitor that is used to run over [Expression]s to determine
- * whether the expression is composed by at least one deferred
- * [PrefixedIdentifier].
- *
- * See [PrefixedIdentifier.isDeferred].
- */
-class DeferredLibraryReferenceDetector extends RecursiveAstVisitor<Object> {
- /**
- * A flag indicating whether an identifier from a deferred library has been
- * found.
- */
- bool _result = false;
-
- /**
- * Return `true` if the visitor found a [PrefixedIdentifier] that returned
- * `true` to the [PrefixedIdentifier.isDeferred] query.
- */
- bool get result => _result;
-
- @override
- Object visitPrefixedIdentifier(PrefixedIdentifier node) {
- if (!_result) {
- if (node.isDeferred) {
- _result = true;
- }
- }
- return null;
- }
-}
-
-/**
* A node that represents a directive.
*
* > directive ::=
@@ -6523,134 +4118,6 @@
}
/**
- * An object used to locate the [Element] associated with a given [AstNode].
- */
-class ElementLocator {
- /**
- * Return the element associated with the given [node], or `null` if there is
- * no element associated with the node.
- */
- static Element locate(AstNode node) {
- if (node == null) {
- return null;
- }
- ElementLocator_ElementMapper mapper = new ElementLocator_ElementMapper();
- return node.accept(mapper);
- }
-}
-
-/**
- * Visitor that maps nodes to elements.
- */
-class ElementLocator_ElementMapper extends GeneralizingAstVisitor<Element> {
- @override
- Element visitAnnotation(Annotation node) => node.element;
-
- @override
- Element visitAssignmentExpression(AssignmentExpression node) =>
- node.bestElement;
-
- @override
- Element visitBinaryExpression(BinaryExpression node) => node.bestElement;
-
- @override
- Element visitClassDeclaration(ClassDeclaration node) => node.element;
-
- @override
- Element visitCompilationUnit(CompilationUnit node) => node.element;
-
- @override
- Element visitConstructorDeclaration(ConstructorDeclaration node) =>
- node.element;
-
- @override
- Element visitFunctionDeclaration(FunctionDeclaration node) => node.element;
-
- @override
- Element visitIdentifier(Identifier node) {
- AstNode parent = node.parent;
- // Type name in Annotation
- if (parent is Annotation) {
- Annotation annotation = parent;
- if (identical(annotation.name, node) &&
- annotation.constructorName == null) {
- return annotation.element;
- }
- }
- // Extra work to map Constructor Declarations to their associated
- // Constructor Elements
- if (parent is ConstructorDeclaration) {
- ConstructorDeclaration decl = parent;
- Identifier returnType = decl.returnType;
- if (identical(returnType, node)) {
- SimpleIdentifier name = decl.name;
- if (name != null) {
- return name.bestElement;
- }
- Element element = node.bestElement;
- if (element is ClassElement) {
- return element.unnamedConstructor;
- }
- }
- }
- if (parent is LibraryIdentifier) {
- AstNode grandParent = parent.parent;
- if (grandParent is PartOfDirective) {
- Element element = grandParent.element;
- if (element is LibraryElement) {
- return element.definingCompilationUnit;
- }
- }
- }
- return node.bestElement;
- }
-
- @override
- Element visitImportDirective(ImportDirective node) => node.element;
-
- @override
- Element visitIndexExpression(IndexExpression node) => node.bestElement;
-
- @override
- Element visitInstanceCreationExpression(InstanceCreationExpression node) =>
- node.staticElement;
-
- @override
- Element visitLibraryDirective(LibraryDirective node) => node.element;
-
- @override
- Element visitMethodDeclaration(MethodDeclaration node) => node.element;
-
- @override
- Element visitMethodInvocation(MethodInvocation node) =>
- node.methodName.bestElement;
-
- @override
- Element visitPartOfDirective(PartOfDirective node) => node.element;
-
- @override
- Element visitPostfixExpression(PostfixExpression node) => node.bestElement;
-
- @override
- Element visitPrefixedIdentifier(PrefixedIdentifier node) => node.bestElement;
-
- @override
- Element visitPrefixExpression(PrefixExpression node) => node.bestElement;
-
- @override
- Element visitStringLiteral(StringLiteral node) {
- AstNode parent = node.parent;
- if (parent is UriBasedDirective) {
- return parent.uriElement;
- }
- return null;
- }
-
- @override
- Element visitVariableDeclaration(VariableDeclaration node) => node.element;
-}
-
-/**
* An empty function body, which can only appear in constructors or abstract
* methods.
*
@@ -8380,7 +5847,7 @@
* [MethodInvocation] nodes. Invocations of getters and setters are represented
* by either [PrefixedIdentifier] or [PropertyAccess] nodes.
*
- * > functionExpressionInvoction ::=
+ * > functionExpressionInvocation ::=
* > [Expression] [TypeArgumentList]? [ArgumentList]
*/
class FunctionExpressionInvocation extends Expression {
@@ -8736,447 +6203,6 @@
}
/**
- * An AST visitor that will recursively visit all of the nodes in an AST
- * structure (like instances of the class [RecursiveAstVisitor]). In addition,
- * when a node of a specific type is visited not only will the visit method for
- * that specific type of node be invoked, but additional methods for the
- * superclasses of that node will also be invoked. For example, using an
- * instance of this class to visit a [Block] will cause the method [visitBlock]
- * to be invoked but will also cause the methods [visitStatement] and
- * [visitNode] to be subsequently invoked. This allows visitors to be written
- * that visit all statements without needing to override the visit method for
- * each of the specific subclasses of [Statement].
- *
- * Subclasses that override a visit method must either invoke the overridden
- * visit method or explicitly invoke the more general visit method. Failure to
- * do so will cause the visit methods for superclasses of the node to not be
- * invoked and will cause the children of the visited node to not be visited.
- */
-class GeneralizingAstVisitor<R> implements AstVisitor<R> {
- @override
- R visitAdjacentStrings(AdjacentStrings node) => visitStringLiteral(node);
-
- R visitAnnotatedNode(AnnotatedNode node) => visitNode(node);
-
- @override
- R visitAnnotation(Annotation node) => visitNode(node);
-
- @override
- R visitArgumentList(ArgumentList node) => visitNode(node);
-
- @override
- R visitAsExpression(AsExpression node) => visitExpression(node);
-
- @override
- R visitAssertStatement(AssertStatement node) => visitStatement(node);
-
- @override
- R visitAssignmentExpression(AssignmentExpression node) =>
- visitExpression(node);
-
- @override
- R visitAwaitExpression(AwaitExpression node) => visitExpression(node);
-
- @override
- R visitBinaryExpression(BinaryExpression node) => visitExpression(node);
-
- @override
- R visitBlock(Block node) => visitStatement(node);
-
- @override
- R visitBlockFunctionBody(BlockFunctionBody node) => visitFunctionBody(node);
-
- @override
- R visitBooleanLiteral(BooleanLiteral node) => visitLiteral(node);
-
- @override
- R visitBreakStatement(BreakStatement node) => visitStatement(node);
-
- @override
- R visitCascadeExpression(CascadeExpression node) => visitExpression(node);
-
- @override
- R visitCatchClause(CatchClause node) => visitNode(node);
-
- @override
- R visitClassDeclaration(ClassDeclaration node) =>
- visitNamedCompilationUnitMember(node);
-
- R visitClassMember(ClassMember node) => visitDeclaration(node);
-
- @override
- R visitClassTypeAlias(ClassTypeAlias node) => visitTypeAlias(node);
-
- R visitCombinator(Combinator node) => visitNode(node);
-
- @override
- R visitComment(Comment node) => visitNode(node);
-
- @override
- R visitCommentReference(CommentReference node) => visitNode(node);
-
- @override
- R visitCompilationUnit(CompilationUnit node) => visitNode(node);
-
- R visitCompilationUnitMember(CompilationUnitMember node) =>
- visitDeclaration(node);
-
- @override
- R visitConditionalExpression(ConditionalExpression node) =>
- visitExpression(node);
-
- @override
- R visitConfiguration(Configuration node) => visitNode(node);
-
- @override
- R visitConstructorDeclaration(ConstructorDeclaration node) =>
- visitClassMember(node);
-
- @override
- R visitConstructorFieldInitializer(ConstructorFieldInitializer node) =>
- visitConstructorInitializer(node);
-
- R visitConstructorInitializer(ConstructorInitializer node) => visitNode(node);
-
- @override
- R visitConstructorName(ConstructorName node) => visitNode(node);
-
- @override
- R visitContinueStatement(ContinueStatement node) => visitStatement(node);
-
- R visitDeclaration(Declaration node) => visitAnnotatedNode(node);
-
- @override
- R visitDeclaredIdentifier(DeclaredIdentifier node) => visitDeclaration(node);
-
- @override
- R visitDefaultFormalParameter(DefaultFormalParameter node) =>
- visitFormalParameter(node);
-
- R visitDirective(Directive node) => visitAnnotatedNode(node);
-
- @override
- R visitDoStatement(DoStatement node) => visitStatement(node);
-
- @override
- R visitDottedName(DottedName node) => visitNode(node);
-
- @override
- R visitDoubleLiteral(DoubleLiteral node) => visitLiteral(node);
-
- @override
- R visitEmptyFunctionBody(EmptyFunctionBody node) => visitFunctionBody(node);
-
- @override
- R visitEmptyStatement(EmptyStatement node) => visitStatement(node);
-
- @override
- R visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
- visitDeclaration(node);
-
- @override
- R visitEnumDeclaration(EnumDeclaration node) =>
- visitNamedCompilationUnitMember(node);
-
- @override
- R visitExportDirective(ExportDirective node) => visitNamespaceDirective(node);
-
- R visitExpression(Expression node) => visitNode(node);
-
- @override
- R visitExpressionFunctionBody(ExpressionFunctionBody node) =>
- visitFunctionBody(node);
-
- @override
- R visitExpressionStatement(ExpressionStatement node) => visitStatement(node);
-
- @override
- R visitExtendsClause(ExtendsClause node) => visitNode(node);
-
- @override
- R visitFieldDeclaration(FieldDeclaration node) => visitClassMember(node);
-
- @override
- R visitFieldFormalParameter(FieldFormalParameter node) =>
- visitNormalFormalParameter(node);
-
- @override
- R visitForEachStatement(ForEachStatement node) => visitStatement(node);
-
- R visitFormalParameter(FormalParameter node) => visitNode(node);
-
- @override
- R visitFormalParameterList(FormalParameterList node) => visitNode(node);
-
- @override
- R visitForStatement(ForStatement node) => visitStatement(node);
-
- R visitFunctionBody(FunctionBody node) => visitNode(node);
-
- @override
- R visitFunctionDeclaration(FunctionDeclaration node) =>
- visitNamedCompilationUnitMember(node);
-
- @override
- R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
- visitStatement(node);
-
- @override
- R visitFunctionExpression(FunctionExpression node) => visitExpression(node);
-
- @override
- R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
- visitExpression(node);
-
- @override
- R visitFunctionTypeAlias(FunctionTypeAlias node) => visitTypeAlias(node);
-
- @override
- R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
- visitNormalFormalParameter(node);
-
- @override
- R visitHideCombinator(HideCombinator node) => visitCombinator(node);
-
- R visitIdentifier(Identifier node) => visitExpression(node);
-
- @override
- R visitIfStatement(IfStatement node) => visitStatement(node);
-
- @override
- R visitImplementsClause(ImplementsClause node) => visitNode(node);
-
- @override
- R visitImportDirective(ImportDirective node) => visitNamespaceDirective(node);
-
- @override
- R visitIndexExpression(IndexExpression node) => visitExpression(node);
-
- @override
- R visitInstanceCreationExpression(InstanceCreationExpression node) =>
- visitExpression(node);
-
- @override
- R visitIntegerLiteral(IntegerLiteral node) => visitLiteral(node);
-
- R visitInterpolationElement(InterpolationElement node) => visitNode(node);
-
- @override
- R visitInterpolationExpression(InterpolationExpression node) =>
- visitInterpolationElement(node);
-
- @override
- R visitInterpolationString(InterpolationString node) =>
- visitInterpolationElement(node);
-
- @override
- R visitIsExpression(IsExpression node) => visitExpression(node);
-
- @override
- R visitLabel(Label node) => visitNode(node);
-
- @override
- R visitLabeledStatement(LabeledStatement node) => visitStatement(node);
-
- @override
- R visitLibraryDirective(LibraryDirective node) => visitDirective(node);
-
- @override
- R visitLibraryIdentifier(LibraryIdentifier node) => visitIdentifier(node);
-
- @override
- R visitListLiteral(ListLiteral node) => visitTypedLiteral(node);
-
- R visitLiteral(Literal node) => visitExpression(node);
-
- @override
- R visitMapLiteral(MapLiteral node) => visitTypedLiteral(node);
-
- @override
- R visitMapLiteralEntry(MapLiteralEntry node) => visitNode(node);
-
- @override
- R visitMethodDeclaration(MethodDeclaration node) => visitClassMember(node);
-
- @override
- R visitMethodInvocation(MethodInvocation node) => visitExpression(node);
-
- R visitNamedCompilationUnitMember(NamedCompilationUnitMember node) =>
- visitCompilationUnitMember(node);
-
- @override
- R visitNamedExpression(NamedExpression node) => visitExpression(node);
-
- R visitNamespaceDirective(NamespaceDirective node) =>
- visitUriBasedDirective(node);
-
- @override
- R visitNativeClause(NativeClause node) => visitNode(node);
-
- @override
- R visitNativeFunctionBody(NativeFunctionBody node) => visitFunctionBody(node);
-
- R visitNode(AstNode node) {
- node.visitChildren(this);
- return null;
- }
-
- R visitNormalFormalParameter(NormalFormalParameter node) =>
- visitFormalParameter(node);
-
- @override
- R visitNullLiteral(NullLiteral node) => visitLiteral(node);
-
- @override
- R visitParenthesizedExpression(ParenthesizedExpression node) =>
- visitExpression(node);
-
- @override
- R visitPartDirective(PartDirective node) => visitUriBasedDirective(node);
-
- @override
- R visitPartOfDirective(PartOfDirective node) => visitDirective(node);
-
- @override
- R visitPostfixExpression(PostfixExpression node) => visitExpression(node);
-
- @override
- R visitPrefixedIdentifier(PrefixedIdentifier node) => visitIdentifier(node);
-
- @override
- R visitPrefixExpression(PrefixExpression node) => visitExpression(node);
-
- @override
- R visitPropertyAccess(PropertyAccess node) => visitExpression(node);
-
- @override
- R visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) =>
- visitConstructorInitializer(node);
-
- @override
- R visitRethrowExpression(RethrowExpression node) => visitExpression(node);
-
- @override
- R visitReturnStatement(ReturnStatement node) => visitStatement(node);
-
- @override
- R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
-
- @override
- R visitShowCombinator(ShowCombinator node) => visitCombinator(node);
-
- @override
- R visitSimpleFormalParameter(SimpleFormalParameter node) =>
- visitNormalFormalParameter(node);
-
- @override
- R visitSimpleIdentifier(SimpleIdentifier node) => visitIdentifier(node);
-
- @override
- R visitSimpleStringLiteral(SimpleStringLiteral node) =>
- visitSingleStringLiteral(node);
-
- R visitSingleStringLiteral(SingleStringLiteral node) =>
- visitStringLiteral(node);
-
- R visitStatement(Statement node) => visitNode(node);
-
- @override
- R visitStringInterpolation(StringInterpolation node) =>
- visitSingleStringLiteral(node);
-
- R visitStringLiteral(StringLiteral node) => visitLiteral(node);
-
- @override
- R visitSuperConstructorInvocation(SuperConstructorInvocation node) =>
- visitConstructorInitializer(node);
-
- @override
- R visitSuperExpression(SuperExpression node) => visitExpression(node);
-
- @override
- R visitSwitchCase(SwitchCase node) => visitSwitchMember(node);
-
- @override
- R visitSwitchDefault(SwitchDefault node) => visitSwitchMember(node);
-
- R visitSwitchMember(SwitchMember node) => visitNode(node);
-
- @override
- R visitSwitchStatement(SwitchStatement node) => visitStatement(node);
-
- @override
- R visitSymbolLiteral(SymbolLiteral node) => visitLiteral(node);
-
- @override
- R visitThisExpression(ThisExpression node) => visitExpression(node);
-
- @override
- R visitThrowExpression(ThrowExpression node) => visitExpression(node);
-
- @override
- R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) =>
- visitCompilationUnitMember(node);
-
- @override
- R visitTryStatement(TryStatement node) => visitStatement(node);
-
- R visitTypeAlias(TypeAlias node) => visitNamedCompilationUnitMember(node);
-
- @override
- R visitTypeArgumentList(TypeArgumentList node) => visitNode(node);
-
- R visitTypedLiteral(TypedLiteral node) => visitLiteral(node);
-
- @override
- R visitTypeName(TypeName node) => visitNode(node);
-
- @override
- R visitTypeParameter(TypeParameter node) => visitNode(node);
-
- @override
- R visitTypeParameterList(TypeParameterList node) => visitNode(node);
-
- R visitUriBasedDirective(UriBasedDirective node) => visitDirective(node);
-
- @override
- R visitVariableDeclaration(VariableDeclaration node) =>
- visitDeclaration(node);
-
- @override
- R visitVariableDeclarationList(VariableDeclarationList node) =>
- visitNode(node);
-
- @override
- R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
- visitStatement(node);
-
- @override
- R visitWhileStatement(WhileStatement node) => visitStatement(node);
-
- @override
- R visitWithClause(WithClause node) => visitNode(node);
-
- @override
- R visitYieldStatement(YieldStatement node) => visitStatement(node);
-}
-
-class GeneralizingAstVisitor_BreadthFirstVisitor
- extends GeneralizingAstVisitor<Object> {
- final BreadthFirstVisitor BreadthFirstVisitor_this;
-
- GeneralizingAstVisitor_BreadthFirstVisitor(this.BreadthFirstVisitor_this)
- : super();
-
- @override
- Object visitNode(AstNode node) {
- BreadthFirstVisitor_this._queue.add(node);
- return null;
- }
-}
-
-/**
* A combinator that restricts the names being imported to those that are not in
* a given list.
*
@@ -9643,1065 +6669,6 @@
}
/**
- * An object that will clone any AST structure that it visits. The cloner will
- * clone the structure, replacing the specified ASTNode with a new ASTNode,
- * mapping the old token stream to a new token stream, and preserving resolution
- * results.
- */
-class IncrementalAstCloner implements AstVisitor<AstNode> {
- /**
- * The node to be replaced during the cloning process.
- */
- final AstNode _oldNode;
-
- /**
- * The replacement node used during the cloning process.
- */
- final AstNode _newNode;
-
- /**
- * A mapping of old tokens to new tokens used during the cloning process.
- */
- final TokenMap _tokenMap;
-
- /**
- * Construct a new instance that will replace the [oldNode] with the [newNode]
- * in the process of cloning an existing AST structure. The [tokenMap] is a
- * mapping of old tokens to new tokens.
- */
- IncrementalAstCloner(this._oldNode, this._newNode, this._tokenMap);
-
- @override
- AdjacentStrings visitAdjacentStrings(AdjacentStrings node) =>
- new AdjacentStrings(_cloneNodeList(node.strings));
-
- @override
- Annotation visitAnnotation(Annotation node) {
- Annotation copy = new Annotation(
- _mapToken(node.atSign),
- _cloneNode(node.name),
- _mapToken(node.period),
- _cloneNode(node.constructorName),
- _cloneNode(node.arguments));
- copy.element = node.element;
- return copy;
- }
-
- @override
- ArgumentList visitArgumentList(ArgumentList node) => new ArgumentList(
- _mapToken(node.leftParenthesis),
- _cloneNodeList(node.arguments),
- _mapToken(node.rightParenthesis));
-
- @override
- AsExpression visitAsExpression(AsExpression node) {
- AsExpression copy = new AsExpression(_cloneNode(node.expression),
- _mapToken(node.asOperator), _cloneNode(node.type));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- AstNode visitAssertStatement(AssertStatement node) => new AssertStatement(
- _mapToken(node.assertKeyword),
- _mapToken(node.leftParenthesis),
- _cloneNode(node.condition),
- _mapToken(node.comma),
- _cloneNode(node.message),
- _mapToken(node.rightParenthesis),
- _mapToken(node.semicolon));
-
- @override
- AssignmentExpression visitAssignmentExpression(AssignmentExpression node) {
- AssignmentExpression copy = new AssignmentExpression(
- _cloneNode(node.leftHandSide),
- _mapToken(node.operator),
- _cloneNode(node.rightHandSide));
- copy.propagatedElement = node.propagatedElement;
- copy.propagatedType = node.propagatedType;
- copy.staticElement = node.staticElement;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- AwaitExpression visitAwaitExpression(AwaitExpression node) =>
- new AwaitExpression(
- _mapToken(node.awaitKeyword), _cloneNode(node.expression));
-
- @override
- BinaryExpression visitBinaryExpression(BinaryExpression node) {
- BinaryExpression copy = new BinaryExpression(_cloneNode(node.leftOperand),
- _mapToken(node.operator), _cloneNode(node.rightOperand));
- copy.propagatedElement = node.propagatedElement;
- copy.propagatedType = node.propagatedType;
- copy.staticElement = node.staticElement;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- Block visitBlock(Block node) => new Block(_mapToken(node.leftBracket),
- _cloneNodeList(node.statements), _mapToken(node.rightBracket));
-
- @override
- BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
- new BlockFunctionBody(_mapToken(node.keyword), _mapToken(node.star),
- _cloneNode(node.block));
-
- @override
- BooleanLiteral visitBooleanLiteral(BooleanLiteral node) {
- BooleanLiteral copy =
- new BooleanLiteral(_mapToken(node.literal), node.value);
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement(
- _mapToken(node.breakKeyword),
- _cloneNode(node.label),
- _mapToken(node.semicolon));
-
- @override
- CascadeExpression visitCascadeExpression(CascadeExpression node) {
- CascadeExpression copy = new CascadeExpression(
- _cloneNode(node.target), _cloneNodeList(node.cascadeSections));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- CatchClause visitCatchClause(CatchClause node) => new CatchClause(
- _mapToken(node.onKeyword),
- _cloneNode(node.exceptionType),
- _mapToken(node.catchKeyword),
- _mapToken(node.leftParenthesis),
- _cloneNode(node.exceptionParameter),
- _mapToken(node.comma),
- _cloneNode(node.stackTraceParameter),
- _mapToken(node.rightParenthesis),
- _cloneNode(node.body));
-
- @override
- ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
- ClassDeclaration copy = new ClassDeclaration(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.abstractKeyword),
- _mapToken(node.classKeyword),
- _cloneNode(node.name),
- _cloneNode(node.typeParameters),
- _cloneNode(node.extendsClause),
- _cloneNode(node.withClause),
- _cloneNode(node.implementsClause),
- _mapToken(node.leftBracket),
- _cloneNodeList(node.members),
- _mapToken(node.rightBracket));
- copy.nativeClause = _cloneNode(node.nativeClause);
- return copy;
- }
-
- @override
- ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.typedefKeyword),
- _cloneNode(node.name),
- _cloneNode(node.typeParameters),
- _mapToken(node.equals),
- _mapToken(node.abstractKeyword),
- _cloneNode(node.superclass),
- _cloneNode(node.withClause),
- _cloneNode(node.implementsClause),
- _mapToken(node.semicolon));
-
- @override
- Comment visitComment(Comment node) {
- if (node.isDocumentation) {
- return Comment.createDocumentationCommentWithReferences(
- _mapTokens(node.tokens), _cloneNodeList(node.references));
- } else if (node.isBlock) {
- return Comment.createBlockComment(_mapTokens(node.tokens));
- }
- return Comment.createEndOfLineComment(_mapTokens(node.tokens));
- }
-
- @override
- CommentReference visitCommentReference(CommentReference node) =>
- new CommentReference(
- _mapToken(node.newKeyword), _cloneNode(node.identifier));
-
- @override
- CompilationUnit visitCompilationUnit(CompilationUnit node) {
- CompilationUnit copy = new CompilationUnit(
- _mapToken(node.beginToken),
- _cloneNode(node.scriptTag),
- _cloneNodeList(node.directives),
- _cloneNodeList(node.declarations),
- _mapToken(node.endToken));
- copy.lineInfo = node.lineInfo;
- copy.element = node.element;
- return copy;
- }
-
- @override
- ConditionalExpression visitConditionalExpression(ConditionalExpression node) {
- ConditionalExpression copy = new ConditionalExpression(
- _cloneNode(node.condition),
- _mapToken(node.question),
- _cloneNode(node.thenExpression),
- _mapToken(node.colon),
- _cloneNode(node.elseExpression));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- Configuration visitConfiguration(Configuration node) => new Configuration(
- _mapToken(node.ifKeyword),
- _mapToken(node.leftParenthesis),
- _cloneNode(node.name),
- _mapToken(node.equalToken),
- _cloneNode(node.value),
- _mapToken(node.rightParenthesis),
- _cloneNode(node.libraryUri));
-
- @override
- ConstructorDeclaration visitConstructorDeclaration(
- ConstructorDeclaration node) {
- ConstructorDeclaration copy = new ConstructorDeclaration(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.externalKeyword),
- _mapToken(node.constKeyword),
- _mapToken(node.factoryKeyword),
- _cloneNode(node.returnType),
- _mapToken(node.period),
- _cloneNode(node.name),
- _cloneNode(node.parameters),
- _mapToken(node.separator),
- _cloneNodeList(node.initializers),
- _cloneNode(node.redirectedConstructor),
- _cloneNode(node.body));
- copy.element = node.element;
- return copy;
- }
-
- @override
- ConstructorFieldInitializer visitConstructorFieldInitializer(
- ConstructorFieldInitializer node) =>
- new ConstructorFieldInitializer(
- _mapToken(node.thisKeyword),
- _mapToken(node.period),
- _cloneNode(node.fieldName),
- _mapToken(node.equals),
- _cloneNode(node.expression));
-
- @override
- ConstructorName visitConstructorName(ConstructorName node) {
- ConstructorName copy = new ConstructorName(
- _cloneNode(node.type), _mapToken(node.period), _cloneNode(node.name));
- copy.staticElement = node.staticElement;
- return copy;
- }
-
- @override
- ContinueStatement visitContinueStatement(ContinueStatement node) =>
- new ContinueStatement(_mapToken(node.continueKeyword),
- _cloneNode(node.label), _mapToken(node.semicolon));
-
- @override
- DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
- new DeclaredIdentifier(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.keyword),
- _cloneNode(node.type),
- _cloneNode(node.identifier));
-
- @override
- DefaultFormalParameter visitDefaultFormalParameter(
- DefaultFormalParameter node) =>
- new DefaultFormalParameter(_cloneNode(node.parameter), node.kind,
- _mapToken(node.separator), _cloneNode(node.defaultValue));
-
- @override
- DoStatement visitDoStatement(DoStatement node) => new DoStatement(
- _mapToken(node.doKeyword),
- _cloneNode(node.body),
- _mapToken(node.whileKeyword),
- _mapToken(node.leftParenthesis),
- _cloneNode(node.condition),
- _mapToken(node.rightParenthesis),
- _mapToken(node.semicolon));
-
- @override
- DottedName visitDottedName(DottedName node) =>
- new DottedName(_cloneNodeList(node.components));
-
- @override
- DoubleLiteral visitDoubleLiteral(DoubleLiteral node) {
- DoubleLiteral copy = new DoubleLiteral(_mapToken(node.literal), node.value);
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) =>
- new EmptyFunctionBody(_mapToken(node.semicolon));
-
- @override
- EmptyStatement visitEmptyStatement(EmptyStatement node) =>
- new EmptyStatement(_mapToken(node.semicolon));
-
- @override
- AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
- new EnumConstantDeclaration(_cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata), _cloneNode(node.name));
-
- @override
- AstNode visitEnumDeclaration(EnumDeclaration node) => new EnumDeclaration(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.enumKeyword),
- _cloneNode(node.name),
- _mapToken(node.leftBracket),
- _cloneNodeList(node.constants),
- _mapToken(node.rightBracket));
-
- @override
- ExportDirective visitExportDirective(ExportDirective node) {
- ExportDirective copy = new ExportDirective(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.keyword),
- _cloneNode(node.uri),
- _cloneNodeList(node.configurations),
- _cloneNodeList(node.combinators),
- _mapToken(node.semicolon));
- copy.element = node.element;
- return copy;
- }
-
- @override
- ExpressionFunctionBody visitExpressionFunctionBody(
- ExpressionFunctionBody node) =>
- new ExpressionFunctionBody(
- _mapToken(node.keyword),
- _mapToken(node.functionDefinition),
- _cloneNode(node.expression),
- _mapToken(node.semicolon));
-
- @override
- ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
- new ExpressionStatement(
- _cloneNode(node.expression), _mapToken(node.semicolon));
-
- @override
- ExtendsClause visitExtendsClause(ExtendsClause node) => new ExtendsClause(
- _mapToken(node.extendsKeyword), _cloneNode(node.superclass));
-
- @override
- FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
- new FieldDeclaration(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.staticKeyword),
- _cloneNode(node.fields),
- _mapToken(node.semicolon));
-
- @override
- FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
- new FieldFormalParameter(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.keyword),
- _cloneNode(node.type),
- _mapToken(node.thisKeyword),
- _mapToken(node.period),
- _cloneNode(node.identifier),
- _cloneNode(node.typeParameters),
- _cloneNode(node.parameters));
-
- @override
- ForEachStatement visitForEachStatement(ForEachStatement node) {
- DeclaredIdentifier loopVariable = node.loopVariable;
- if (loopVariable == null) {
- return new ForEachStatement.withReference(
- _mapToken(node.awaitKeyword),
- _mapToken(node.forKeyword),
- _mapToken(node.leftParenthesis),
- _cloneNode(node.identifier),
- _mapToken(node.inKeyword),
- _cloneNode(node.iterable),
- _mapToken(node.rightParenthesis),
- _cloneNode(node.body));
- }
- return new ForEachStatement.withDeclaration(
- _mapToken(node.awaitKeyword),
- _mapToken(node.forKeyword),
- _mapToken(node.leftParenthesis),
- _cloneNode(loopVariable),
- _mapToken(node.inKeyword),
- _cloneNode(node.iterable),
- _mapToken(node.rightParenthesis),
- _cloneNode(node.body));
- }
-
- @override
- FormalParameterList visitFormalParameterList(FormalParameterList node) =>
- new FormalParameterList(
- _mapToken(node.leftParenthesis),
- _cloneNodeList(node.parameters),
- _mapToken(node.leftDelimiter),
- _mapToken(node.rightDelimiter),
- _mapToken(node.rightParenthesis));
-
- @override
- ForStatement visitForStatement(ForStatement node) => new ForStatement(
- _mapToken(node.forKeyword),
- _mapToken(node.leftParenthesis),
- _cloneNode(node.variables),
- _cloneNode(node.initialization),
- _mapToken(node.leftSeparator),
- _cloneNode(node.condition),
- _mapToken(node.rightSeparator),
- _cloneNodeList(node.updaters),
- _mapToken(node.rightParenthesis),
- _cloneNode(node.body));
-
- @override
- FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
- new FunctionDeclaration(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.externalKeyword),
- _cloneNode(node.returnType),
- _mapToken(node.propertyKeyword),
- _cloneNode(node.name),
- _cloneNode(node.functionExpression));
-
- @override
- FunctionDeclarationStatement visitFunctionDeclarationStatement(
- FunctionDeclarationStatement node) =>
- new FunctionDeclarationStatement(_cloneNode(node.functionDeclaration));
-
- @override
- FunctionExpression visitFunctionExpression(FunctionExpression node) {
- FunctionExpression copy = new FunctionExpression(
- _cloneNode(node.typeParameters),
- _cloneNode(node.parameters),
- _cloneNode(node.body));
- copy.element = node.element;
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- FunctionExpressionInvocation visitFunctionExpressionInvocation(
- FunctionExpressionInvocation node) {
- FunctionExpressionInvocation copy = new FunctionExpressionInvocation(
- _cloneNode(node.function),
- _cloneNode(node.typeArguments),
- _cloneNode(node.argumentList));
- copy.propagatedElement = node.propagatedElement;
- copy.propagatedType = node.propagatedType;
- copy.staticElement = node.staticElement;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
- new FunctionTypeAlias(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.typedefKeyword),
- _cloneNode(node.returnType),
- _cloneNode(node.name),
- _cloneNode(node.typeParameters),
- _cloneNode(node.parameters),
- _mapToken(node.semicolon));
-
- @override
- FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
- FunctionTypedFormalParameter node) =>
- new FunctionTypedFormalParameter(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _cloneNode(node.returnType),
- _cloneNode(node.identifier),
- _cloneNode(node.typeParameters),
- _cloneNode(node.parameters));
-
- @override
- HideCombinator visitHideCombinator(HideCombinator node) => new HideCombinator(
- _mapToken(node.keyword), _cloneNodeList(node.hiddenNames));
-
- @override
- IfStatement visitIfStatement(IfStatement node) => new IfStatement(
- _mapToken(node.ifKeyword),
- _mapToken(node.leftParenthesis),
- _cloneNode(node.condition),
- _mapToken(node.rightParenthesis),
- _cloneNode(node.thenStatement),
- _mapToken(node.elseKeyword),
- _cloneNode(node.elseStatement));
-
- @override
- ImplementsClause visitImplementsClause(ImplementsClause node) =>
- new ImplementsClause(
- _mapToken(node.implementsKeyword), _cloneNodeList(node.interfaces));
-
- @override
- ImportDirective visitImportDirective(ImportDirective node) =>
- new ImportDirective(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.keyword),
- _cloneNode(node.uri),
- _cloneNodeList(node.configurations),
- _mapToken(node.deferredKeyword),
- _mapToken(node.asKeyword),
- _cloneNode(node.prefix),
- _cloneNodeList(node.combinators),
- _mapToken(node.semicolon));
-
- @override
- IndexExpression visitIndexExpression(IndexExpression node) {
- Token period = _mapToken(node.period);
- IndexExpression copy;
- if (period == null) {
- copy = new IndexExpression.forTarget(
- _cloneNode(node.target),
- _mapToken(node.leftBracket),
- _cloneNode(node.index),
- _mapToken(node.rightBracket));
- } else {
- copy = new IndexExpression.forCascade(period, _mapToken(node.leftBracket),
- _cloneNode(node.index), _mapToken(node.rightBracket));
- }
- copy.auxiliaryElements = node.auxiliaryElements;
- copy.propagatedElement = node.propagatedElement;
- copy.propagatedType = node.propagatedType;
- copy.staticElement = node.staticElement;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- InstanceCreationExpression visitInstanceCreationExpression(
- InstanceCreationExpression node) {
- InstanceCreationExpression copy = new InstanceCreationExpression(
- _mapToken(node.keyword),
- _cloneNode(node.constructorName),
- _cloneNode(node.argumentList));
- copy.propagatedType = node.propagatedType;
- copy.staticElement = node.staticElement;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- IntegerLiteral visitIntegerLiteral(IntegerLiteral node) {
- IntegerLiteral copy =
- new IntegerLiteral(_mapToken(node.literal), node.value);
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- InterpolationExpression visitInterpolationExpression(
- InterpolationExpression node) =>
- new InterpolationExpression(_mapToken(node.leftBracket),
- _cloneNode(node.expression), _mapToken(node.rightBracket));
-
- @override
- InterpolationString visitInterpolationString(InterpolationString node) =>
- new InterpolationString(_mapToken(node.contents), node.value);
-
- @override
- IsExpression visitIsExpression(IsExpression node) {
- IsExpression copy = new IsExpression(
- _cloneNode(node.expression),
- _mapToken(node.isOperator),
- _mapToken(node.notOperator),
- _cloneNode(node.type));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- Label visitLabel(Label node) =>
- new Label(_cloneNode(node.label), _mapToken(node.colon));
-
- @override
- LabeledStatement visitLabeledStatement(LabeledStatement node) =>
- new LabeledStatement(
- _cloneNodeList(node.labels), _cloneNode(node.statement));
-
- @override
- LibraryDirective visitLibraryDirective(LibraryDirective node) =>
- new LibraryDirective(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.libraryKeyword),
- _cloneNode(node.name),
- _mapToken(node.semicolon));
-
- @override
- LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) {
- LibraryIdentifier copy =
- new LibraryIdentifier(_cloneNodeList(node.components));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- ListLiteral visitListLiteral(ListLiteral node) {
- ListLiteral copy = new ListLiteral(
- _mapToken(node.constKeyword),
- _cloneNode(node.typeArguments),
- _mapToken(node.leftBracket),
- _cloneNodeList(node.elements),
- _mapToken(node.rightBracket));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- MapLiteral visitMapLiteral(MapLiteral node) {
- MapLiteral copy = new MapLiteral(
- _mapToken(node.constKeyword),
- _cloneNode(node.typeArguments),
- _mapToken(node.leftBracket),
- _cloneNodeList(node.entries),
- _mapToken(node.rightBracket));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
- new MapLiteralEntry(_cloneNode(node.key), _mapToken(node.separator),
- _cloneNode(node.value));
-
- @override
- MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
- new MethodDeclaration(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.externalKeyword),
- _mapToken(node.modifierKeyword),
- _cloneNode(node.returnType),
- _mapToken(node.propertyKeyword),
- _mapToken(node.operatorKeyword),
- _cloneNode(node.name),
- _cloneNode(node._typeParameters),
- _cloneNode(node.parameters),
- _cloneNode(node.body));
-
- @override
- MethodInvocation visitMethodInvocation(MethodInvocation node) {
- MethodInvocation copy = new MethodInvocation(
- _cloneNode(node.target),
- _mapToken(node.operator),
- _cloneNode(node.methodName),
- _cloneNode(node.typeArguments),
- _cloneNode(node.argumentList));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- NamedExpression visitNamedExpression(NamedExpression node) {
- NamedExpression copy =
- new NamedExpression(_cloneNode(node.name), _cloneNode(node.expression));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- AstNode visitNativeClause(NativeClause node) =>
- new NativeClause(_mapToken(node.nativeKeyword), _cloneNode(node.name));
-
- @override
- NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) =>
- new NativeFunctionBody(_mapToken(node.nativeKeyword),
- _cloneNode(node.stringLiteral), _mapToken(node.semicolon));
-
- @override
- NullLiteral visitNullLiteral(NullLiteral node) {
- NullLiteral copy = new NullLiteral(_mapToken(node.literal));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- ParenthesizedExpression visitParenthesizedExpression(
- ParenthesizedExpression node) {
- ParenthesizedExpression copy = new ParenthesizedExpression(
- _mapToken(node.leftParenthesis),
- _cloneNode(node.expression),
- _mapToken(node.rightParenthesis));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- PartDirective visitPartDirective(PartDirective node) {
- PartDirective copy = new PartDirective(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.partKeyword),
- _cloneNode(node.uri),
- _mapToken(node.semicolon));
- copy.element = node.element;
- return copy;
- }
-
- @override
- PartOfDirective visitPartOfDirective(PartOfDirective node) {
- PartOfDirective copy = new PartOfDirective(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.partKeyword),
- _mapToken(node.ofKeyword),
- _cloneNode(node.libraryName),
- _mapToken(node.semicolon));
- copy.element = node.element;
- return copy;
- }
-
- @override
- PostfixExpression visitPostfixExpression(PostfixExpression node) {
- PostfixExpression copy = new PostfixExpression(
- _cloneNode(node.operand), _mapToken(node.operator));
- copy.propagatedElement = node.propagatedElement;
- copy.propagatedType = node.propagatedType;
- copy.staticElement = node.staticElement;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) {
- PrefixedIdentifier copy = new PrefixedIdentifier(_cloneNode(node.prefix),
- _mapToken(node.period), _cloneNode(node.identifier));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- PrefixExpression visitPrefixExpression(PrefixExpression node) {
- PrefixExpression copy = new PrefixExpression(
- _mapToken(node.operator), _cloneNode(node.operand));
- copy.propagatedElement = node.propagatedElement;
- copy.propagatedType = node.propagatedType;
- copy.staticElement = node.staticElement;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- PropertyAccess visitPropertyAccess(PropertyAccess node) {
- PropertyAccess copy = new PropertyAccess(_cloneNode(node.target),
- _mapToken(node.operator), _cloneNode(node.propertyName));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) {
- RedirectingConstructorInvocation copy =
- new RedirectingConstructorInvocation(
- _mapToken(node.thisKeyword),
- _mapToken(node.period),
- _cloneNode(node.constructorName),
- _cloneNode(node.argumentList));
- copy.staticElement = node.staticElement;
- return copy;
- }
-
- @override
- RethrowExpression visitRethrowExpression(RethrowExpression node) {
- RethrowExpression copy =
- new RethrowExpression(_mapToken(node.rethrowKeyword));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- ReturnStatement visitReturnStatement(ReturnStatement node) =>
- new ReturnStatement(_mapToken(node.returnKeyword),
- _cloneNode(node.expression), _mapToken(node.semicolon));
-
- @override
- ScriptTag visitScriptTag(ScriptTag node) =>
- new ScriptTag(_mapToken(node.scriptTag));
-
- @override
- ShowCombinator visitShowCombinator(ShowCombinator node) => new ShowCombinator(
- _mapToken(node.keyword), _cloneNodeList(node.shownNames));
-
- @override
- SimpleFormalParameter visitSimpleFormalParameter(
- SimpleFormalParameter node) =>
- new SimpleFormalParameter(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.keyword),
- _cloneNode(node.type),
- _cloneNode(node.identifier));
-
- @override
- SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
- Token mappedToken = _mapToken(node.token);
- if (mappedToken == null) {
- // This only happens for SimpleIdentifiers created by the parser as part
- // of scanning documentation comments (the tokens for those identifiers
- // are not in the original token stream and hence do not get copied).
- // This extra check can be removed if the scanner is changed to scan
- // documentation comments for the parser.
- mappedToken = node.token;
- }
- SimpleIdentifier copy = new SimpleIdentifier(mappedToken);
- copy.auxiliaryElements = node.auxiliaryElements;
- copy.propagatedElement = node.propagatedElement;
- copy.propagatedType = node.propagatedType;
- copy.staticElement = node.staticElement;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) {
- SimpleStringLiteral copy =
- new SimpleStringLiteral(_mapToken(node.literal), node.value);
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- StringInterpolation visitStringInterpolation(StringInterpolation node) {
- StringInterpolation copy =
- new StringInterpolation(_cloneNodeList(node.elements));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- SuperConstructorInvocation visitSuperConstructorInvocation(
- SuperConstructorInvocation node) {
- SuperConstructorInvocation copy = new SuperConstructorInvocation(
- _mapToken(node.superKeyword),
- _mapToken(node.period),
- _cloneNode(node.constructorName),
- _cloneNode(node.argumentList));
- copy.staticElement = node.staticElement;
- return copy;
- }
-
- @override
- SuperExpression visitSuperExpression(SuperExpression node) {
- SuperExpression copy = new SuperExpression(_mapToken(node.superKeyword));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- SwitchCase visitSwitchCase(SwitchCase node) => new SwitchCase(
- _cloneNodeList(node.labels),
- _mapToken(node.keyword),
- _cloneNode(node.expression),
- _mapToken(node.colon),
- _cloneNodeList(node.statements));
-
- @override
- SwitchDefault visitSwitchDefault(SwitchDefault node) => new SwitchDefault(
- _cloneNodeList(node.labels),
- _mapToken(node.keyword),
- _mapToken(node.colon),
- _cloneNodeList(node.statements));
-
- @override
- SwitchStatement visitSwitchStatement(SwitchStatement node) =>
- new SwitchStatement(
- _mapToken(node.switchKeyword),
- _mapToken(node.leftParenthesis),
- _cloneNode(node.expression),
- _mapToken(node.rightParenthesis),
- _mapToken(node.leftBracket),
- _cloneNodeList(node.members),
- _mapToken(node.rightBracket));
-
- @override
- AstNode visitSymbolLiteral(SymbolLiteral node) {
- SymbolLiteral copy = new SymbolLiteral(
- _mapToken(node.poundSign), _mapTokens(node.components));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- ThisExpression visitThisExpression(ThisExpression node) {
- ThisExpression copy = new ThisExpression(_mapToken(node.thisKeyword));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- ThrowExpression visitThrowExpression(ThrowExpression node) {
- ThrowExpression copy = new ThrowExpression(
- _mapToken(node.throwKeyword), _cloneNode(node.expression));
- copy.propagatedType = node.propagatedType;
- copy.staticType = node.staticType;
- return copy;
- }
-
- @override
- TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
- TopLevelVariableDeclaration node) =>
- new TopLevelVariableDeclaration(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _cloneNode(node.variables),
- _mapToken(node.semicolon));
-
- @override
- TryStatement visitTryStatement(TryStatement node) => new TryStatement(
- _mapToken(node.tryKeyword),
- _cloneNode(node.body),
- _cloneNodeList(node.catchClauses),
- _mapToken(node.finallyKeyword),
- _cloneNode(node.finallyBlock));
-
- @override
- TypeArgumentList visitTypeArgumentList(TypeArgumentList node) =>
- new TypeArgumentList(_mapToken(node.leftBracket),
- _cloneNodeList(node.arguments), _mapToken(node.rightBracket));
-
- @override
- TypeName visitTypeName(TypeName node) {
- TypeName copy =
- new TypeName(_cloneNode(node.name), _cloneNode(node.typeArguments));
- copy.type = node.type;
- return copy;
- }
-
- @override
- TypeParameter visitTypeParameter(TypeParameter node) => new TypeParameter(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _cloneNode(node.name),
- _mapToken(node.extendsKeyword),
- _cloneNode(node.bound));
-
- @override
- TypeParameterList visitTypeParameterList(TypeParameterList node) =>
- new TypeParameterList(_mapToken(node.leftBracket),
- _cloneNodeList(node.typeParameters), _mapToken(node.rightBracket));
-
- @override
- VariableDeclaration visitVariableDeclaration(VariableDeclaration node) =>
- new VariableDeclaration(_cloneNode(node.name), _mapToken(node.equals),
- _cloneNode(node.initializer));
-
- @override
- VariableDeclarationList visitVariableDeclarationList(
- VariableDeclarationList node) =>
- new VariableDeclarationList(
- null,
- _cloneNodeList(node.metadata),
- _mapToken(node.keyword),
- _cloneNode(node.type),
- _cloneNodeList(node.variables));
-
- @override
- VariableDeclarationStatement visitVariableDeclarationStatement(
- VariableDeclarationStatement node) =>
- new VariableDeclarationStatement(
- _cloneNode(node.variables), _mapToken(node.semicolon));
-
- @override
- WhileStatement visitWhileStatement(WhileStatement node) => new WhileStatement(
- _mapToken(node.whileKeyword),
- _mapToken(node.leftParenthesis),
- _cloneNode(node.condition),
- _mapToken(node.rightParenthesis),
- _cloneNode(node.body));
-
- @override
- WithClause visitWithClause(WithClause node) => new WithClause(
- _mapToken(node.withKeyword), _cloneNodeList(node.mixinTypes));
-
- @override
- YieldStatement visitYieldStatement(YieldStatement node) => new YieldStatement(
- _mapToken(node.yieldKeyword),
- _mapToken(node.star),
- _cloneNode(node.expression),
- _mapToken(node.semicolon));
-
- AstNode _cloneNode(AstNode node) {
- if (node == null) {
- return null;
- }
- if (identical(node, _oldNode)) {
- return _newNode;
- }
- return node.accept(this) as AstNode;
- }
-
- List _cloneNodeList(NodeList nodes) {
- List clonedNodes = new List();
- for (AstNode node in nodes) {
- clonedNodes.add(_cloneNode(node));
- }
- return clonedNodes;
- }
-
- Token _mapToken(Token oldToken) {
- if (oldToken == null) {
- return null;
- }
- return _tokenMap.get(oldToken);
- }
-
- List<Token> _mapTokens(List<Token> oldTokens) {
- List<Token> newTokens = new List<Token>(oldTokens.length);
- for (int index = 0; index < newTokens.length; index++) {
- newTokens[index] = _mapToken(oldTokens[index]);
- }
- return newTokens;
- }
-}
-
-/**
* An index expression.
*
* > indexExpression ::=
@@ -11059,14 +7026,14 @@
*
* > integerLiteral ::=
* > decimalIntegerLiteral
- * > | hexidecimalIntegerLiteral
+ * > | hexadecimalIntegerLiteral
* >
* > decimalIntegerLiteral ::=
* > decimalDigit+
* >
- * > hexidecimalIntegerLiteral ::=
- * > '0x' hexidecimalDigit+
- * > | '0X' hexidecimalDigit+
+ * > hexadecimalIntegerLiteral ::=
+ * > '0x' hexadecimalDigit+
+ * > | '0X' hexadecimalDigit+
*/
class IntegerLiteral extends Literal {
/**
@@ -12086,7 +8053,7 @@
* [FunctionExpressionInvocation] nodes. Invocations of getters and setters are
* represented by either [PrefixedIdentifier] or [PropertyAccess] nodes.
*
- * > methodInvoction ::=
+ * > methodInvocation ::=
* > ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
*/
class MethodInvocation extends Expression {
@@ -12694,1392 +8661,6 @@
}
/**
- * An object used to locate the [AstNode] associated with a source range, given
- * the AST structure built from the source. More specifically, they will return
- * the [AstNode] with the shortest length whose source range completely
- * encompasses the specified range.
- */
-class NodeLocator extends UnifyingAstVisitor<Object> {
- /**
- * The start offset of the range used to identify the node.
- */
- int _startOffset = 0;
-
- /**
- * The end offset of the range used to identify the node.
- */
- int _endOffset = 0;
-
- /**
- * The element that was found that corresponds to the given source range, or
- * `null` if there is no such element.
- */
- AstNode _foundNode;
-
- /**
- * Initialize a newly created locator to locate an [AstNode] by locating the
- * node within an AST structure that corresponds to the given range of
- * characters (between the [startOffset] and [endOffset] in the source.
- */
- NodeLocator(int startOffset, [int endOffset])
- : this._startOffset = startOffset,
- this._endOffset = endOffset == null ? startOffset : endOffset;
-
- /**
- * Return the node that was found that corresponds to the given source range
- * or `null` if there is no such node.
- */
- AstNode get foundNode => _foundNode;
-
- /**
- * Search within the given AST [node] for an identifier representing an
- * element in the specified source range. Return the element that was found,
- * or `null` if no element was found.
- */
- AstNode searchWithin(AstNode node) {
- if (node == null) {
- return null;
- }
- try {
- node.accept(this);
- } on NodeLocator_NodeFoundException {
- // A node with the right source position was found.
- } catch (exception, stackTrace) {
- AnalysisEngine.instance.logger.logInformation(
- "Unable to locate element at offset ($_startOffset - $_endOffset)",
- new CaughtException(exception, stackTrace));
- return null;
- }
- return _foundNode;
- }
-
- @override
- Object visitNode(AstNode node) {
- Token beginToken = node.beginToken;
- Token endToken = node.endToken;
- // Don't include synthetic tokens.
- while (endToken != beginToken) {
- if (endToken.type == TokenType.EOF || !endToken.isSynthetic) {
- break;
- }
- endToken = endToken.previous;
- }
- int end = endToken.end;
- int start = node.offset;
- if (end < _startOffset) {
- return null;
- }
- if (start > _endOffset) {
- return null;
- }
- try {
- node.visitChildren(this);
- } on NodeLocator_NodeFoundException {
- rethrow;
- } catch (exception, stackTrace) {
- // Ignore the exception and proceed in order to visit the rest of the
- // structure.
- AnalysisEngine.instance.logger.logInformation(
- "Exception caught while traversing an AST structure.",
- new CaughtException(exception, stackTrace));
- }
- if (start <= _startOffset && _endOffset <= end) {
- _foundNode = node;
- throw new NodeLocator_NodeFoundException();
- }
- return null;
- }
-}
-
-/**
- * An object used to locate the [AstNode] associated with a source range.
- * More specifically, they will return the deepest [AstNode] which completely
- * encompasses the specified range.
- */
-class NodeLocator2 extends UnifyingAstVisitor<Object> {
- /**
- * The inclusive start offset of the range used to identify the node.
- */
- int _startOffset = 0;
-
- /**
- * The inclusive end offset of the range used to identify the node.
- */
- int _endOffset = 0;
-
- /**
- * The found node or `null` if there is no such node.
- */
- AstNode _foundNode;
-
- /**
- * Initialize a newly created locator to locate the deepest [AstNode] for
- * which `node.offset <= [startOffset]` and `[endOffset] < node.end`.
- *
- * If [endOffset] is not provided, then it is considered the same as the
- * given [startOffset].
- */
- NodeLocator2(int startOffset, [int endOffset])
- : this._startOffset = startOffset,
- this._endOffset = endOffset == null ? startOffset : endOffset;
-
- /**
- * Search within the given AST [node] and return the node that was found,
- * or `null` if no node was found.
- */
- AstNode searchWithin(AstNode node) {
- if (node == null) {
- return null;
- }
- try {
- node.accept(this);
- } on NodeLocator_NodeFoundException {} catch (exception, stackTrace) {
- AnalysisEngine.instance.logger.logInformation(
- "Unable to locate element at offset ($_startOffset - $_endOffset)",
- new CaughtException(exception, stackTrace));
- return null;
- }
- return _foundNode;
- }
-
- @override
- Object visitNode(AstNode node) {
- Token beginToken = node.beginToken;
- Token endToken = node.endToken;
- // Don't include synthetic tokens.
- while (endToken != beginToken) {
- if (endToken.type == TokenType.EOF || !endToken.isSynthetic) {
- break;
- }
- endToken = endToken.previous;
- }
- int end = endToken.end;
- int start = node.offset;
- if (end <= _startOffset) {
- return null;
- }
- if (start > _endOffset) {
- return null;
- }
- try {
- node.visitChildren(this);
- } on NodeLocator_NodeFoundException {
- rethrow;
- } catch (exception, stackTrace) {
- // Ignore the exception and proceed in order to visit the rest of the
- // structure.
- AnalysisEngine.instance.logger.logInformation(
- "Exception caught while traversing an AST structure.",
- new CaughtException(exception, stackTrace));
- }
- if (start <= _startOffset && _endOffset < end) {
- _foundNode = node;
- throw new NodeLocator_NodeFoundException();
- }
- return null;
- }
-}
-
-/**
- * An exception used by [NodeLocator] to cancel visiting after a node has been
- * found.
- */
-class NodeLocator_NodeFoundException extends RuntimeException {}
-
-/**
- * An object that will replace one child node in an AST node with another node.
- */
-class NodeReplacer implements AstVisitor<bool> {
- /**
- * The node being replaced.
- */
- final AstNode _oldNode;
-
- /**
- * The node that is replacing the old node.
- */
- final AstNode _newNode;
-
- /**
- * Initialize a newly created node locator to replace the [_oldNode] with the
- * [_newNode].
- */
- NodeReplacer(this._oldNode, this._newNode);
-
- @override
- bool visitAdjacentStrings(AdjacentStrings node) {
- if (_replaceInList(node.strings)) {
- return true;
- }
- return visitNode(node);
- }
-
- bool visitAnnotatedNode(AnnotatedNode node) {
- if (identical(node.documentationComment, _oldNode)) {
- node.documentationComment = _newNode as Comment;
- return true;
- } else if (_replaceInList(node.metadata)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitAnnotation(Annotation node) {
- if (identical(node.arguments, _oldNode)) {
- node.arguments = _newNode as ArgumentList;
- return true;
- } else if (identical(node.constructorName, _oldNode)) {
- node.constructorName = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.name, _oldNode)) {
- node.name = _newNode as Identifier;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitArgumentList(ArgumentList node) {
- if (_replaceInList(node.arguments)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitAsExpression(AsExpression node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- } else if (identical(node.type, _oldNode)) {
- node.type = _newNode as TypeName;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitAssertStatement(AssertStatement node) {
- if (identical(node.condition, _oldNode)) {
- node.condition = _newNode as Expression;
- return true;
- }
- if (identical(node._message, _oldNode)) {
- node.message = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitAssignmentExpression(AssignmentExpression node) {
- if (identical(node.leftHandSide, _oldNode)) {
- node.leftHandSide = _newNode as Expression;
- return true;
- } else if (identical(node.rightHandSide, _oldNode)) {
- node.rightHandSide = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitAwaitExpression(AwaitExpression node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitBinaryExpression(BinaryExpression node) {
- if (identical(node.leftOperand, _oldNode)) {
- node.leftOperand = _newNode as Expression;
- return true;
- } else if (identical(node.rightOperand, _oldNode)) {
- node.rightOperand = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitBlock(Block node) {
- if (_replaceInList(node.statements)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitBlockFunctionBody(BlockFunctionBody node) {
- if (identical(node.block, _oldNode)) {
- node.block = _newNode as Block;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitBooleanLiteral(BooleanLiteral node) => visitNode(node);
-
- @override
- bool visitBreakStatement(BreakStatement node) {
- if (identical(node.label, _oldNode)) {
- node.label = _newNode as SimpleIdentifier;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitCascadeExpression(CascadeExpression node) {
- if (identical(node.target, _oldNode)) {
- node.target = _newNode as Expression;
- return true;
- } else if (_replaceInList(node.cascadeSections)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitCatchClause(CatchClause node) {
- if (identical(node.exceptionType, _oldNode)) {
- node.exceptionType = _newNode as TypeName;
- return true;
- } else if (identical(node.exceptionParameter, _oldNode)) {
- node.exceptionParameter = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.stackTraceParameter, _oldNode)) {
- node.stackTraceParameter = _newNode as SimpleIdentifier;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitClassDeclaration(ClassDeclaration node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.typeParameters, _oldNode)) {
- node.typeParameters = _newNode as TypeParameterList;
- return true;
- } else if (identical(node.extendsClause, _oldNode)) {
- node.extendsClause = _newNode as ExtendsClause;
- return true;
- } else if (identical(node.withClause, _oldNode)) {
- node.withClause = _newNode as WithClause;
- return true;
- } else if (identical(node.implementsClause, _oldNode)) {
- node.implementsClause = _newNode as ImplementsClause;
- return true;
- } else if (identical(node.nativeClause, _oldNode)) {
- node.nativeClause = _newNode as NativeClause;
- return true;
- } else if (_replaceInList(node.members)) {
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitClassTypeAlias(ClassTypeAlias node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.typeParameters, _oldNode)) {
- node.typeParameters = _newNode as TypeParameterList;
- return true;
- } else if (identical(node.superclass, _oldNode)) {
- node.superclass = _newNode as TypeName;
- return true;
- } else if (identical(node.withClause, _oldNode)) {
- node.withClause = _newNode as WithClause;
- return true;
- } else if (identical(node.implementsClause, _oldNode)) {
- node.implementsClause = _newNode as ImplementsClause;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitComment(Comment node) {
- if (_replaceInList(node.references)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitCommentReference(CommentReference node) {
- if (identical(node.identifier, _oldNode)) {
- node.identifier = _newNode as Identifier;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitCompilationUnit(CompilationUnit node) {
- if (identical(node.scriptTag, _oldNode)) {
- node.scriptTag = _newNode as ScriptTag;
- return true;
- } else if (_replaceInList(node.directives)) {
- return true;
- } else if (_replaceInList(node.declarations)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitConditionalExpression(ConditionalExpression node) {
- if (identical(node.condition, _oldNode)) {
- node.condition = _newNode as Expression;
- return true;
- } else if (identical(node.thenExpression, _oldNode)) {
- node.thenExpression = _newNode as Expression;
- return true;
- } else if (identical(node.elseExpression, _oldNode)) {
- node.elseExpression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitConfiguration(Configuration node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as DottedName;
- return true;
- } else if (identical(node.value, _oldNode)) {
- node.value = _newNode as StringLiteral;
- return true;
- } else if (identical(node.libraryUri, _oldNode)) {
- node.libraryUri = _newNode as StringLiteral;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitConstructorDeclaration(ConstructorDeclaration node) {
- if (identical(node.returnType, _oldNode)) {
- node.returnType = _newNode as Identifier;
- return true;
- } else if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.parameters, _oldNode)) {
- node.parameters = _newNode as FormalParameterList;
- return true;
- } else if (identical(node.redirectedConstructor, _oldNode)) {
- node.redirectedConstructor = _newNode as ConstructorName;
- return true;
- } else if (identical(node.body, _oldNode)) {
- node.body = _newNode as FunctionBody;
- return true;
- } else if (_replaceInList(node.initializers)) {
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
- if (identical(node.fieldName, _oldNode)) {
- node.fieldName = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitConstructorName(ConstructorName node) {
- if (identical(node.type, _oldNode)) {
- node.type = _newNode as TypeName;
- return true;
- } else if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitContinueStatement(ContinueStatement node) {
- if (identical(node.label, _oldNode)) {
- node.label = _newNode as SimpleIdentifier;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitDeclaredIdentifier(DeclaredIdentifier node) {
- if (identical(node.type, _oldNode)) {
- node.type = _newNode as TypeName;
- return true;
- } else if (identical(node.identifier, _oldNode)) {
- node.identifier = _newNode as SimpleIdentifier;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitDefaultFormalParameter(DefaultFormalParameter node) {
- if (identical(node.parameter, _oldNode)) {
- node.parameter = _newNode as NormalFormalParameter;
- return true;
- } else if (identical(node.defaultValue, _oldNode)) {
- node.defaultValue = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitDoStatement(DoStatement node) {
- if (identical(node.body, _oldNode)) {
- node.body = _newNode as Statement;
- return true;
- } else if (identical(node.condition, _oldNode)) {
- node.condition = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitDottedName(DottedName node) {
- if (_replaceInList(node.components)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitDoubleLiteral(DoubleLiteral node) => visitNode(node);
-
- @override
- bool visitEmptyFunctionBody(EmptyFunctionBody node) => visitNode(node);
-
- @override
- bool visitEmptyStatement(EmptyStatement node) => visitNode(node);
-
- @override
- bool visitEnumConstantDeclaration(EnumConstantDeclaration node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitEnumDeclaration(EnumDeclaration node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- } else if (_replaceInList(node.constants)) {
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitExportDirective(ExportDirective node) =>
- visitNamespaceDirective(node);
-
- @override
- bool visitExpressionFunctionBody(ExpressionFunctionBody node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitExpressionStatement(ExpressionStatement node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitExtendsClause(ExtendsClause node) {
- if (identical(node.superclass, _oldNode)) {
- node.superclass = _newNode as TypeName;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitFieldDeclaration(FieldDeclaration node) {
- if (identical(node.fields, _oldNode)) {
- node.fields = _newNode as VariableDeclarationList;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitFieldFormalParameter(FieldFormalParameter node) {
- if (identical(node.type, _oldNode)) {
- node.type = _newNode as TypeName;
- return true;
- } else if (identical(node.parameters, _oldNode)) {
- node.parameters = _newNode as FormalParameterList;
- return true;
- }
- return visitNormalFormalParameter(node);
- }
-
- @override
- bool visitForEachStatement(ForEachStatement node) {
- if (identical(node.loopVariable, _oldNode)) {
- node.loopVariable = _newNode as DeclaredIdentifier;
- return true;
- } else if (identical(node.identifier, _oldNode)) {
- node.identifier = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.iterable, _oldNode)) {
- node.iterable = _newNode as Expression;
- return true;
- } else if (identical(node.body, _oldNode)) {
- node.body = _newNode as Statement;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitFormalParameterList(FormalParameterList node) {
- if (_replaceInList(node.parameters)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitForStatement(ForStatement node) {
- if (identical(node.variables, _oldNode)) {
- node.variables = _newNode as VariableDeclarationList;
- return true;
- } else if (identical(node.initialization, _oldNode)) {
- node.initialization = _newNode as Expression;
- return true;
- } else if (identical(node.condition, _oldNode)) {
- node.condition = _newNode as Expression;
- return true;
- } else if (identical(node.body, _oldNode)) {
- node.body = _newNode as Statement;
- return true;
- } else if (_replaceInList(node.updaters)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitFunctionDeclaration(FunctionDeclaration node) {
- if (identical(node.returnType, _oldNode)) {
- node.returnType = _newNode as TypeName;
- return true;
- } else if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.functionExpression, _oldNode)) {
- node.functionExpression = _newNode as FunctionExpression;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
- if (identical(node.functionDeclaration, _oldNode)) {
- node.functionDeclaration = _newNode as FunctionDeclaration;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitFunctionExpression(FunctionExpression node) {
- if (identical(node.parameters, _oldNode)) {
- node.parameters = _newNode as FormalParameterList;
- return true;
- } else if (identical(node.body, _oldNode)) {
- node.body = _newNode as FunctionBody;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
- if (identical(node.function, _oldNode)) {
- node.function = _newNode as Expression;
- return true;
- } else if (identical(node.argumentList, _oldNode)) {
- node.argumentList = _newNode as ArgumentList;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitFunctionTypeAlias(FunctionTypeAlias node) {
- if (identical(node.returnType, _oldNode)) {
- node.returnType = _newNode as TypeName;
- return true;
- } else if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.typeParameters, _oldNode)) {
- node.typeParameters = _newNode as TypeParameterList;
- return true;
- } else if (identical(node.parameters, _oldNode)) {
- node.parameters = _newNode as FormalParameterList;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
- if (identical(node.returnType, _oldNode)) {
- node.returnType = _newNode as TypeName;
- return true;
- } else if (identical(node.parameters, _oldNode)) {
- node.parameters = _newNode as FormalParameterList;
- return true;
- }
- return visitNormalFormalParameter(node);
- }
-
- @override
- bool visitHideCombinator(HideCombinator node) {
- if (_replaceInList(node.hiddenNames)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitIfStatement(IfStatement node) {
- if (identical(node.condition, _oldNode)) {
- node.condition = _newNode as Expression;
- return true;
- } else if (identical(node.thenStatement, _oldNode)) {
- node.thenStatement = _newNode as Statement;
- return true;
- } else if (identical(node.elseStatement, _oldNode)) {
- node.elseStatement = _newNode as Statement;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitImplementsClause(ImplementsClause node) {
- if (_replaceInList(node.interfaces)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitImportDirective(ImportDirective node) {
- if (identical(node.prefix, _oldNode)) {
- node.prefix = _newNode as SimpleIdentifier;
- return true;
- }
- return visitNamespaceDirective(node);
- }
-
- @override
- bool visitIndexExpression(IndexExpression node) {
- if (identical(node.target, _oldNode)) {
- node.target = _newNode as Expression;
- return true;
- } else if (identical(node.index, _oldNode)) {
- node.index = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitInstanceCreationExpression(InstanceCreationExpression node) {
- if (identical(node.constructorName, _oldNode)) {
- node.constructorName = _newNode as ConstructorName;
- return true;
- } else if (identical(node.argumentList, _oldNode)) {
- node.argumentList = _newNode as ArgumentList;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitIntegerLiteral(IntegerLiteral node) => visitNode(node);
-
- @override
- bool visitInterpolationExpression(InterpolationExpression node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitInterpolationString(InterpolationString node) => visitNode(node);
-
- @override
- bool visitIsExpression(IsExpression node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- } else if (identical(node.type, _oldNode)) {
- node.type = _newNode as TypeName;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitLabel(Label node) {
- if (identical(node.label, _oldNode)) {
- node.label = _newNode as SimpleIdentifier;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitLabeledStatement(LabeledStatement node) {
- if (identical(node.statement, _oldNode)) {
- node.statement = _newNode as Statement;
- return true;
- } else if (_replaceInList(node.labels)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitLibraryDirective(LibraryDirective node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as LibraryIdentifier;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitLibraryIdentifier(LibraryIdentifier node) {
- if (_replaceInList(node.components)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitListLiteral(ListLiteral node) {
- if (_replaceInList(node.elements)) {
- return true;
- }
- return visitTypedLiteral(node);
- }
-
- @override
- bool visitMapLiteral(MapLiteral node) {
- if (_replaceInList(node.entries)) {
- return true;
- }
- return visitTypedLiteral(node);
- }
-
- @override
- bool visitMapLiteralEntry(MapLiteralEntry node) {
- if (identical(node.key, _oldNode)) {
- node.key = _newNode as Expression;
- return true;
- } else if (identical(node.value, _oldNode)) {
- node.value = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitMethodDeclaration(MethodDeclaration node) {
- if (identical(node.returnType, _oldNode)) {
- node.returnType = _newNode as TypeName;
- return true;
- } else if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.parameters, _oldNode)) {
- node.parameters = _newNode as FormalParameterList;
- return true;
- } else if (identical(node.body, _oldNode)) {
- node.body = _newNode as FunctionBody;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitMethodInvocation(MethodInvocation node) {
- if (identical(node.target, _oldNode)) {
- node.target = _newNode as Expression;
- return true;
- } else if (identical(node.methodName, _oldNode)) {
- node.methodName = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.argumentList, _oldNode)) {
- node.argumentList = _newNode as ArgumentList;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitNamedExpression(NamedExpression node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as Label;
- return true;
- } else if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- bool visitNamespaceDirective(NamespaceDirective node) {
- if (_replaceInList(node.combinators)) {
- return true;
- }
- return visitUriBasedDirective(node);
- }
-
- @override
- bool visitNativeClause(NativeClause node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as StringLiteral;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitNativeFunctionBody(NativeFunctionBody node) {
- if (identical(node.stringLiteral, _oldNode)) {
- node.stringLiteral = _newNode as StringLiteral;
- return true;
- }
- return visitNode(node);
- }
-
- bool visitNode(AstNode node) {
- throw new IllegalArgumentException(
- "The old node is not a child of it's parent");
- }
-
- bool visitNormalFormalParameter(NormalFormalParameter node) {
- if (identical(node.documentationComment, _oldNode)) {
- node.documentationComment = _newNode as Comment;
- return true;
- } else if (identical(node.identifier, _oldNode)) {
- node.identifier = _newNode as SimpleIdentifier;
- return true;
- } else if (_replaceInList(node.metadata)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitNullLiteral(NullLiteral node) => visitNode(node);
-
- @override
- bool visitParenthesizedExpression(ParenthesizedExpression node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitPartDirective(PartDirective node) => visitUriBasedDirective(node);
-
- @override
- bool visitPartOfDirective(PartOfDirective node) {
- if (identical(node.libraryName, _oldNode)) {
- node.libraryName = _newNode as LibraryIdentifier;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitPostfixExpression(PostfixExpression node) {
- if (identical(node.operand, _oldNode)) {
- node.operand = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitPrefixedIdentifier(PrefixedIdentifier node) {
- if (identical(node.prefix, _oldNode)) {
- node.prefix = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.identifier, _oldNode)) {
- node.identifier = _newNode as SimpleIdentifier;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitPrefixExpression(PrefixExpression node) {
- if (identical(node.operand, _oldNode)) {
- node.operand = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitPropertyAccess(PropertyAccess node) {
- if (identical(node.target, _oldNode)) {
- node.target = _newNode as Expression;
- return true;
- } else if (identical(node.propertyName, _oldNode)) {
- node.propertyName = _newNode as SimpleIdentifier;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) {
- if (identical(node.constructorName, _oldNode)) {
- node.constructorName = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.argumentList, _oldNode)) {
- node.argumentList = _newNode as ArgumentList;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitRethrowExpression(RethrowExpression node) => visitNode(node);
-
- @override
- bool visitReturnStatement(ReturnStatement node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
-
- @override
- bool visitShowCombinator(ShowCombinator node) {
- if (_replaceInList(node.shownNames)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitSimpleFormalParameter(SimpleFormalParameter node) {
- if (identical(node.type, _oldNode)) {
- node.type = _newNode as TypeName;
- return true;
- }
- return visitNormalFormalParameter(node);
- }
-
- @override
- bool visitSimpleIdentifier(SimpleIdentifier node) => visitNode(node);
-
- @override
- bool visitSimpleStringLiteral(SimpleStringLiteral node) => visitNode(node);
-
- @override
- bool visitStringInterpolation(StringInterpolation node) {
- if (_replaceInList(node.elements)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitSuperConstructorInvocation(SuperConstructorInvocation node) {
- if (identical(node.constructorName, _oldNode)) {
- node.constructorName = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.argumentList, _oldNode)) {
- node.argumentList = _newNode as ArgumentList;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitSuperExpression(SuperExpression node) => visitNode(node);
-
- @override
- bool visitSwitchCase(SwitchCase node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitSwitchMember(node);
- }
-
- @override
- bool visitSwitchDefault(SwitchDefault node) => visitSwitchMember(node);
-
- bool visitSwitchMember(SwitchMember node) {
- if (_replaceInList(node.labels)) {
- return true;
- } else if (_replaceInList(node.statements)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitSwitchStatement(SwitchStatement node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- } else if (_replaceInList(node.members)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitSymbolLiteral(SymbolLiteral node) => visitNode(node);
-
- @override
- bool visitThisExpression(ThisExpression node) => visitNode(node);
-
- @override
- bool visitThrowExpression(ThrowExpression node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- if (identical(node.variables, _oldNode)) {
- node.variables = _newNode as VariableDeclarationList;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitTryStatement(TryStatement node) {
- if (identical(node.body, _oldNode)) {
- node.body = _newNode as Block;
- return true;
- } else if (identical(node.finallyBlock, _oldNode)) {
- node.finallyBlock = _newNode as Block;
- return true;
- } else if (_replaceInList(node.catchClauses)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitTypeArgumentList(TypeArgumentList node) {
- if (_replaceInList(node.arguments)) {
- return true;
- }
- return visitNode(node);
- }
-
- bool visitTypedLiteral(TypedLiteral node) {
- if (identical(node.typeArguments, _oldNode)) {
- node.typeArguments = _newNode as TypeArgumentList;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitTypeName(TypeName node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as Identifier;
- return true;
- } else if (identical(node.typeArguments, _oldNode)) {
- node.typeArguments = _newNode as TypeArgumentList;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitTypeParameter(TypeParameter node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.bound, _oldNode)) {
- node.bound = _newNode as TypeName;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitTypeParameterList(TypeParameterList node) {
- if (_replaceInList(node.typeParameters)) {
- return true;
- }
- return visitNode(node);
- }
-
- bool visitUriBasedDirective(UriBasedDirective node) {
- if (identical(node.uri, _oldNode)) {
- node.uri = _newNode as StringLiteral;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitVariableDeclaration(VariableDeclaration node) {
- if (identical(node.name, _oldNode)) {
- node.name = _newNode as SimpleIdentifier;
- return true;
- } else if (identical(node.initializer, _oldNode)) {
- node.initializer = _newNode as Expression;
- return true;
- }
- return visitAnnotatedNode(node);
- }
-
- @override
- bool visitVariableDeclarationList(VariableDeclarationList node) {
- if (identical(node.type, _oldNode)) {
- node.type = _newNode as TypeName;
- return true;
- } else if (_replaceInList(node.variables)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
- if (identical(node.variables, _oldNode)) {
- node.variables = _newNode as VariableDeclarationList;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitWhileStatement(WhileStatement node) {
- if (identical(node.condition, _oldNode)) {
- node.condition = _newNode as Expression;
- return true;
- } else if (identical(node.body, _oldNode)) {
- node.body = _newNode as Statement;
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitWithClause(WithClause node) {
- if (_replaceInList(node.mixinTypes)) {
- return true;
- }
- return visitNode(node);
- }
-
- @override
- bool visitYieldStatement(YieldStatement node) {
- if (identical(node.expression, _oldNode)) {
- node.expression = _newNode as Expression;
- return true;
- }
- return visitNode(node);
- }
-
- bool _replaceInList(NodeList list) {
- int count = list.length;
- for (int i = 0; i < count; i++) {
- if (identical(_oldNode, list[i])) {
- list[i] = _newNode;
- return true;
- }
- }
- return false;
- }
-
- /**
- * Replace the [oldNode] with the [newNode] in the AST structure containing
- * the old node. Return `true` if the replacement was successful.
- *
- * Throws an [IllegalArgumentException] if either node is `null`, if the old
- * node does not have a parent node, or if the AST structure has been
- * corrupted.
- */
- static bool replace(AstNode oldNode, AstNode newNode) {
- if (oldNode == null || newNode == null) {
- throw new IllegalArgumentException(
- "The old and new nodes must be non-null");
- } else if (identical(oldNode, newNode)) {
- return true;
- }
- AstNode parent = oldNode.parent;
- if (parent == null) {
- throw new IllegalArgumentException(
- "The old node is not a child of another node");
- }
- NodeReplacer replacer = new NodeReplacer(oldNode, newNode);
- return parent.accept(replacer);
- }
-}
-
-/**
* A formal parameter that is required (is not optional).
*
* > normalFormalParameter ::=
@@ -14934,667 +9515,6 @@
}
/**
- * An AST visitor that will recursively visit all of the nodes in an AST
- * structure. For example, using an instance of this class to visit a [Block]
- * will also cause all of the statements in the block to be visited.
- *
- * Subclasses that override a visit method must either invoke the overridden
- * visit method or must explicitly ask the visited node to visit its children.
- * Failure to do so will cause the children of the visited node to not be
- * visited.
- */
-class RecursiveAstVisitor<R> implements AstVisitor<R> {
- @override
- R visitAdjacentStrings(AdjacentStrings node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitAnnotation(Annotation node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitArgumentList(ArgumentList node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitAsExpression(AsExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitAssertStatement(AssertStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitAssignmentExpression(AssignmentExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitAwaitExpression(AwaitExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitBinaryExpression(BinaryExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitBlock(Block node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitBlockFunctionBody(BlockFunctionBody node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitBooleanLiteral(BooleanLiteral node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitBreakStatement(BreakStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitCascadeExpression(CascadeExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitCatchClause(CatchClause node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitClassDeclaration(ClassDeclaration node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitClassTypeAlias(ClassTypeAlias node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitComment(Comment node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitCommentReference(CommentReference node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitCompilationUnit(CompilationUnit node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitConditionalExpression(ConditionalExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitConfiguration(Configuration node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitConstructorDeclaration(ConstructorDeclaration node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitConstructorName(ConstructorName node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitContinueStatement(ContinueStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitDeclaredIdentifier(DeclaredIdentifier node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitDefaultFormalParameter(DefaultFormalParameter node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitDoStatement(DoStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitDottedName(DottedName node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitDoubleLiteral(DoubleLiteral node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitEmptyFunctionBody(EmptyFunctionBody node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitEmptyStatement(EmptyStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitEnumConstantDeclaration(EnumConstantDeclaration node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitEnumDeclaration(EnumDeclaration node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitExportDirective(ExportDirective node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitExpressionFunctionBody(ExpressionFunctionBody node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitExpressionStatement(ExpressionStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitExtendsClause(ExtendsClause node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitFieldDeclaration(FieldDeclaration node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitFieldFormalParameter(FieldFormalParameter node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitForEachStatement(ForEachStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitFormalParameterList(FormalParameterList node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitForStatement(ForStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitFunctionDeclaration(FunctionDeclaration node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitFunctionExpression(FunctionExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitFunctionTypeAlias(FunctionTypeAlias node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitHideCombinator(HideCombinator node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitIfStatement(IfStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitImplementsClause(ImplementsClause node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitImportDirective(ImportDirective node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitIndexExpression(IndexExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitInstanceCreationExpression(InstanceCreationExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitIntegerLiteral(IntegerLiteral node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitInterpolationExpression(InterpolationExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitInterpolationString(InterpolationString node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitIsExpression(IsExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitLabel(Label node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitLabeledStatement(LabeledStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitLibraryDirective(LibraryDirective node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitLibraryIdentifier(LibraryIdentifier node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitListLiteral(ListLiteral node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitMapLiteral(MapLiteral node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitMapLiteralEntry(MapLiteralEntry node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitMethodDeclaration(MethodDeclaration node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitMethodInvocation(MethodInvocation node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitNamedExpression(NamedExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitNativeClause(NativeClause node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitNativeFunctionBody(NativeFunctionBody node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitNullLiteral(NullLiteral node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitParenthesizedExpression(ParenthesizedExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitPartDirective(PartDirective node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitPartOfDirective(PartOfDirective node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitPostfixExpression(PostfixExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitPrefixedIdentifier(PrefixedIdentifier node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitPrefixExpression(PrefixExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitPropertyAccess(PropertyAccess node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitRethrowExpression(RethrowExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitReturnStatement(ReturnStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitScriptTag(ScriptTag node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitShowCombinator(ShowCombinator node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitSimpleFormalParameter(SimpleFormalParameter node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitSimpleIdentifier(SimpleIdentifier node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitSimpleStringLiteral(SimpleStringLiteral node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitStringInterpolation(StringInterpolation node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitSuperConstructorInvocation(SuperConstructorInvocation node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitSuperExpression(SuperExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitSwitchCase(SwitchCase node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitSwitchDefault(SwitchDefault node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitSwitchStatement(SwitchStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitSymbolLiteral(SymbolLiteral node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitThisExpression(ThisExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitThrowExpression(ThrowExpression node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitTryStatement(TryStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitTypeArgumentList(TypeArgumentList node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitTypeName(TypeName node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitTypeParameter(TypeParameter node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitTypeParameterList(TypeParameterList node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitVariableDeclaration(VariableDeclaration node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitVariableDeclarationList(VariableDeclarationList node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitVariableDeclarationStatement(VariableDeclarationStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitWhileStatement(WhileStatement node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitWithClause(WithClause node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitYieldStatement(YieldStatement node) {
- node.visitChildren(this);
- return null;
- }
-}
-
-/**
* The invocation of a constructor in the same class from within a constructor's
* initialization list.
*
@@ -15795,191 +9715,6 @@
}
/**
- * Traverse the AST from initial child node to successive parents, building a
- * collection of local variable and parameter names visible to the initial child
- * node. In case of name shadowing, the first name seen is the most specific one
- * so names are not redefined.
- *
- * Completion test code coverage is 95%. The two basic blocks that are not
- * executed cannot be executed. They are included for future reference.
- */
-class ScopedNameFinder extends GeneralizingAstVisitor<Object> {
- Declaration _declarationNode;
-
- AstNode _immediateChild;
-
- Map<String, SimpleIdentifier> _locals =
- new HashMap<String, SimpleIdentifier>();
-
- final int _position;
-
- bool _referenceIsWithinLocalFunction = false;
-
- ScopedNameFinder(this._position);
-
- Declaration get declaration => _declarationNode;
-
- Map<String, SimpleIdentifier> get locals => _locals;
-
- @override
- Object visitBlock(Block node) {
- _checkStatements(node.statements);
- return super.visitBlock(node);
- }
-
- @override
- Object visitCatchClause(CatchClause node) {
- _addToScope(node.exceptionParameter);
- _addToScope(node.stackTraceParameter);
- return super.visitCatchClause(node);
- }
-
- @override
- Object visitConstructorDeclaration(ConstructorDeclaration node) {
- if (!identical(_immediateChild, node.parameters)) {
- _addParameters(node.parameters.parameters);
- }
- _declarationNode = node;
- return null;
- }
-
- @override
- Object visitFieldDeclaration(FieldDeclaration node) {
- _declarationNode = node;
- return null;
- }
-
- @override
- Object visitForEachStatement(ForEachStatement node) {
- DeclaredIdentifier loopVariable = node.loopVariable;
- if (loopVariable != null) {
- _addToScope(loopVariable.identifier);
- }
- return super.visitForEachStatement(node);
- }
-
- @override
- Object visitForStatement(ForStatement node) {
- if (!identical(_immediateChild, node.variables) && node.variables != null) {
- _addVariables(node.variables.variables);
- }
- return super.visitForStatement(node);
- }
-
- @override
- Object visitFunctionDeclaration(FunctionDeclaration node) {
- if (node.parent is! FunctionDeclarationStatement) {
- _declarationNode = node;
- return null;
- }
- return super.visitFunctionDeclaration(node);
- }
-
- @override
- Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
- _referenceIsWithinLocalFunction = true;
- return super.visitFunctionDeclarationStatement(node);
- }
-
- @override
- Object visitFunctionExpression(FunctionExpression node) {
- if (node.parameters != null &&
- !identical(_immediateChild, node.parameters)) {
- _addParameters(node.parameters.parameters);
- }
- return super.visitFunctionExpression(node);
- }
-
- @override
- Object visitMethodDeclaration(MethodDeclaration node) {
- _declarationNode = node;
- if (node.parameters == null) {
- return null;
- }
- if (!identical(_immediateChild, node.parameters)) {
- _addParameters(node.parameters.parameters);
- }
- return null;
- }
-
- @override
- Object visitNode(AstNode node) {
- _immediateChild = node;
- AstNode parent = node.parent;
- if (parent != null) {
- parent.accept(this);
- }
- return null;
- }
-
- @override
- Object visitSwitchMember(SwitchMember node) {
- _checkStatements(node.statements);
- return super.visitSwitchMember(node);
- }
-
- @override
- Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- _declarationNode = node;
- return null;
- }
-
- @override
- Object visitTypeAlias(TypeAlias node) {
- _declarationNode = node;
- return null;
- }
-
- void _addParameters(NodeList<FormalParameter> vars) {
- for (FormalParameter var2 in vars) {
- _addToScope(var2.identifier);
- }
- }
-
- void _addToScope(SimpleIdentifier identifier) {
- if (identifier != null && _isInRange(identifier)) {
- String name = identifier.name;
- if (!_locals.containsKey(name)) {
- _locals[name] = identifier;
- }
- }
- }
-
- void _addVariables(NodeList<VariableDeclaration> variables) {
- for (VariableDeclaration variable in variables) {
- _addToScope(variable.name);
- }
- }
-
- /**
- * Check the given list of [statements] for any that come before the immediate
- * child and that define a name that would be visible to the immediate child.
- */
- void _checkStatements(List<Statement> statements) {
- for (Statement statement in statements) {
- if (identical(statement, _immediateChild)) {
- return;
- }
- if (statement is VariableDeclarationStatement) {
- _addVariables(statement.variables.variables);
- } else if (statement is FunctionDeclarationStatement &&
- !_referenceIsWithinLocalFunction) {
- _addToScope(statement.functionDeclaration.name);
- }
- }
- }
-
- bool _isInRange(AstNode node) {
- if (_position < 0) {
- // if source position is not set then all nodes are in range
- return true;
- // not reached
- }
- return node.end < _position;
- }
-}
-
-/**
* A script tag that can optionally occur at the beginning of a compilation unit.
*
* > scriptTag ::=
@@ -16059,344 +9794,6 @@
}
/**
- * An AST visitor that will do nothing when visiting an AST node. It is intended
- * to be a superclass for classes that use the visitor pattern primarily as a
- * dispatch mechanism (and hence don't need to recursively visit a whole
- * structure) and that only need to visit a small number of node types.
- */
-class SimpleAstVisitor<R> implements AstVisitor<R> {
- @override
- R visitAdjacentStrings(AdjacentStrings node) => null;
-
- @override
- R visitAnnotation(Annotation node) => null;
-
- @override
- R visitArgumentList(ArgumentList node) => null;
-
- @override
- R visitAsExpression(AsExpression node) => null;
-
- @override
- R visitAssertStatement(AssertStatement node) => null;
-
- @override
- R visitAssignmentExpression(AssignmentExpression node) => null;
-
- @override
- R visitAwaitExpression(AwaitExpression node) => null;
-
- @override
- R visitBinaryExpression(BinaryExpression node) => null;
-
- @override
- R visitBlock(Block node) => null;
-
- @override
- R visitBlockFunctionBody(BlockFunctionBody node) => null;
-
- @override
- R visitBooleanLiteral(BooleanLiteral node) => null;
-
- @override
- R visitBreakStatement(BreakStatement node) => null;
-
- @override
- R visitCascadeExpression(CascadeExpression node) => null;
-
- @override
- R visitCatchClause(CatchClause node) => null;
-
- @override
- R visitClassDeclaration(ClassDeclaration node) => null;
-
- @override
- R visitClassTypeAlias(ClassTypeAlias node) => null;
-
- @override
- R visitComment(Comment node) => null;
-
- @override
- R visitCommentReference(CommentReference node) => null;
-
- @override
- R visitCompilationUnit(CompilationUnit node) => null;
-
- @override
- R visitConditionalExpression(ConditionalExpression node) => null;
-
- @override
- R visitConfiguration(Configuration node) => null;
-
- @override
- R visitConstructorDeclaration(ConstructorDeclaration node) => null;
-
- @override
- R visitConstructorFieldInitializer(ConstructorFieldInitializer node) => null;
-
- @override
- R visitConstructorName(ConstructorName node) => null;
-
- @override
- R visitContinueStatement(ContinueStatement node) => null;
-
- @override
- R visitDeclaredIdentifier(DeclaredIdentifier node) => null;
-
- @override
- R visitDefaultFormalParameter(DefaultFormalParameter node) => null;
-
- @override
- R visitDoStatement(DoStatement node) => null;
-
- @override
- R visitDottedName(DottedName node) => null;
-
- @override
- R visitDoubleLiteral(DoubleLiteral node) => null;
-
- @override
- R visitEmptyFunctionBody(EmptyFunctionBody node) => null;
-
- @override
- R visitEmptyStatement(EmptyStatement node) => null;
-
- @override
- R visitEnumConstantDeclaration(EnumConstantDeclaration node) => null;
-
- @override
- R visitEnumDeclaration(EnumDeclaration node) => null;
-
- @override
- R visitExportDirective(ExportDirective node) => null;
-
- @override
- R visitExpressionFunctionBody(ExpressionFunctionBody node) => null;
-
- @override
- R visitExpressionStatement(ExpressionStatement node) => null;
-
- @override
- R visitExtendsClause(ExtendsClause node) => null;
-
- @override
- R visitFieldDeclaration(FieldDeclaration node) => null;
-
- @override
- R visitFieldFormalParameter(FieldFormalParameter node) => null;
-
- @override
- R visitForEachStatement(ForEachStatement node) => null;
-
- @override
- R visitFormalParameterList(FormalParameterList node) => null;
-
- @override
- R visitForStatement(ForStatement node) => null;
-
- @override
- R visitFunctionDeclaration(FunctionDeclaration node) => null;
-
- @override
- R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
- null;
-
- @override
- R visitFunctionExpression(FunctionExpression node) => null;
-
- @override
- R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
- null;
-
- @override
- R visitFunctionTypeAlias(FunctionTypeAlias node) => null;
-
- @override
- R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
- null;
-
- @override
- R visitHideCombinator(HideCombinator node) => null;
-
- @override
- R visitIfStatement(IfStatement node) => null;
-
- @override
- R visitImplementsClause(ImplementsClause node) => null;
-
- @override
- R visitImportDirective(ImportDirective node) => null;
-
- @override
- R visitIndexExpression(IndexExpression node) => null;
-
- @override
- R visitInstanceCreationExpression(InstanceCreationExpression node) => null;
-
- @override
- R visitIntegerLiteral(IntegerLiteral node) => null;
-
- @override
- R visitInterpolationExpression(InterpolationExpression node) => null;
-
- @override
- R visitInterpolationString(InterpolationString node) => null;
-
- @override
- R visitIsExpression(IsExpression node) => null;
-
- @override
- R visitLabel(Label node) => null;
-
- @override
- R visitLabeledStatement(LabeledStatement node) => null;
-
- @override
- R visitLibraryDirective(LibraryDirective node) => null;
-
- @override
- R visitLibraryIdentifier(LibraryIdentifier node) => null;
-
- @override
- R visitListLiteral(ListLiteral node) => null;
-
- @override
- R visitMapLiteral(MapLiteral node) => null;
-
- @override
- R visitMapLiteralEntry(MapLiteralEntry node) => null;
-
- @override
- R visitMethodDeclaration(MethodDeclaration node) => null;
-
- @override
- R visitMethodInvocation(MethodInvocation node) => null;
-
- @override
- R visitNamedExpression(NamedExpression node) => null;
-
- @override
- R visitNativeClause(NativeClause node) => null;
-
- @override
- R visitNativeFunctionBody(NativeFunctionBody node) => null;
-
- @override
- R visitNullLiteral(NullLiteral node) => null;
-
- @override
- R visitParenthesizedExpression(ParenthesizedExpression node) => null;
-
- @override
- R visitPartDirective(PartDirective node) => null;
-
- @override
- R visitPartOfDirective(PartOfDirective node) => null;
-
- @override
- R visitPostfixExpression(PostfixExpression node) => null;
-
- @override
- R visitPrefixedIdentifier(PrefixedIdentifier node) => null;
-
- @override
- R visitPrefixExpression(PrefixExpression node) => null;
-
- @override
- R visitPropertyAccess(PropertyAccess node) => null;
-
- @override
- R visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) =>
- null;
-
- @override
- R visitRethrowExpression(RethrowExpression node) => null;
-
- @override
- R visitReturnStatement(ReturnStatement node) => null;
-
- @override
- R visitScriptTag(ScriptTag node) => null;
-
- @override
- R visitShowCombinator(ShowCombinator node) => null;
-
- @override
- R visitSimpleFormalParameter(SimpleFormalParameter node) => null;
-
- @override
- R visitSimpleIdentifier(SimpleIdentifier node) => null;
-
- @override
- R visitSimpleStringLiteral(SimpleStringLiteral node) => null;
-
- @override
- R visitStringInterpolation(StringInterpolation node) => null;
-
- @override
- R visitSuperConstructorInvocation(SuperConstructorInvocation node) => null;
-
- @override
- R visitSuperExpression(SuperExpression node) => null;
-
- @override
- R visitSwitchCase(SwitchCase node) => null;
-
- @override
- R visitSwitchDefault(SwitchDefault node) => null;
-
- @override
- R visitSwitchStatement(SwitchStatement node) => null;
-
- @override
- R visitSymbolLiteral(SymbolLiteral node) => null;
-
- @override
- R visitThisExpression(ThisExpression node) => null;
-
- @override
- R visitThrowExpression(ThrowExpression node) => null;
-
- @override
- R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) => null;
-
- @override
- R visitTryStatement(TryStatement node) => null;
-
- @override
- R visitTypeArgumentList(TypeArgumentList node) => null;
-
- @override
- R visitTypeName(TypeName node) => null;
-
- @override
- R visitTypeParameter(TypeParameter node) => null;
-
- @override
- R visitTypeParameterList(TypeParameterList node) => null;
-
- @override
- R visitVariableDeclaration(VariableDeclaration node) => null;
-
- @override
- R visitVariableDeclarationList(VariableDeclarationList node) => null;
-
- @override
- R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
- null;
-
- @override
- R visitWhileStatement(WhileStatement node) => null;
-
- @override
- R visitWithClause(WithClause node) => null;
-
- @override
- R visitYieldStatement(YieldStatement node) => null;
-}
-
-/**
* A simple formal parameter.
*
* > simpleFormalParameter ::=
@@ -16920,8 +10317,8 @@
bool get isRaw;
/**
- * Return `true` if this string literal uses single qoutes (' or ''').
- * Return `false` if this string literal uses double qoutes (" or """).
+ * Return `true` if this string literal uses single quotes (' or ''').
+ * Return `false` if this string literal uses double quotes (" or """).
*/
bool get isSingleQuoted;
}
@@ -17757,1149 +11154,6 @@
}
/**
- * A visitor used to write a source representation of a visited AST node (and
- * all of it's children) to a writer.
- */
-class ToSourceVisitor implements AstVisitor<Object> {
- /**
- * The writer to which the source is to be written.
- */
- final PrintWriter _writer;
-
- /**
- * Initialize a newly created visitor to write source code representing the
- * visited nodes to the given [writer].
- */
- ToSourceVisitor(this._writer);
-
- @override
- Object visitAdjacentStrings(AdjacentStrings node) {
- _visitNodeListWithSeparator(node.strings, " ");
- return null;
- }
-
- @override
- Object visitAnnotation(Annotation node) {
- _writer.print('@');
- _visitNode(node.name);
- _visitNodeWithPrefix(".", node.constructorName);
- _visitNode(node.arguments);
- return null;
- }
-
- @override
- Object visitArgumentList(ArgumentList node) {
- _writer.print('(');
- _visitNodeListWithSeparator(node.arguments, ", ");
- _writer.print(')');
- return null;
- }
-
- @override
- Object visitAsExpression(AsExpression node) {
- _visitNode(node.expression);
- _writer.print(" as ");
- _visitNode(node.type);
- return null;
- }
-
- @override
- Object visitAssertStatement(AssertStatement node) {
- _writer.print("assert (");
- _visitNode(node.condition);
- if (node.message != null) {
- _writer.print(', ');
- _visitNode(node.message);
- }
- _writer.print(");");
- return null;
- }
-
- @override
- Object visitAssignmentExpression(AssignmentExpression node) {
- _visitNode(node.leftHandSide);
- _writer.print(' ');
- _writer.print(node.operator.lexeme);
- _writer.print(' ');
- _visitNode(node.rightHandSide);
- return null;
- }
-
- @override
- Object visitAwaitExpression(AwaitExpression node) {
- _writer.print("await ");
- _visitNode(node.expression);
- return null;
- }
-
- @override
- Object visitBinaryExpression(BinaryExpression node) {
- _visitNode(node.leftOperand);
- _writer.print(' ');
- _writer.print(node.operator.lexeme);
- _writer.print(' ');
- _visitNode(node.rightOperand);
- return null;
- }
-
- @override
- Object visitBlock(Block node) {
- _writer.print('{');
- _visitNodeListWithSeparator(node.statements, " ");
- _writer.print('}');
- return null;
- }
-
- @override
- Object visitBlockFunctionBody(BlockFunctionBody node) {
- Token keyword = node.keyword;
- if (keyword != null) {
- _writer.print(keyword.lexeme);
- if (node.star != null) {
- _writer.print('*');
- }
- _writer.print(' ');
- }
- _visitNode(node.block);
- return null;
- }
-
- @override
- Object visitBooleanLiteral(BooleanLiteral node) {
- _writer.print(node.literal.lexeme);
- return null;
- }
-
- @override
- Object visitBreakStatement(BreakStatement node) {
- _writer.print("break");
- _visitNodeWithPrefix(" ", node.label);
- _writer.print(";");
- return null;
- }
-
- @override
- Object visitCascadeExpression(CascadeExpression node) {
- _visitNode(node.target);
- _visitNodeList(node.cascadeSections);
- return null;
- }
-
- @override
- Object visitCatchClause(CatchClause node) {
- _visitNodeWithPrefix("on ", node.exceptionType);
- if (node.catchKeyword != null) {
- if (node.exceptionType != null) {
- _writer.print(' ');
- }
- _writer.print("catch (");
- _visitNode(node.exceptionParameter);
- _visitNodeWithPrefix(", ", node.stackTraceParameter);
- _writer.print(") ");
- } else {
- _writer.print(" ");
- }
- _visitNode(node.body);
- return null;
- }
-
- @override
- Object visitClassDeclaration(ClassDeclaration node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _visitTokenWithSuffix(node.abstractKeyword, " ");
- _writer.print("class ");
- _visitNode(node.name);
- _visitNode(node.typeParameters);
- _visitNodeWithPrefix(" ", node.extendsClause);
- _visitNodeWithPrefix(" ", node.withClause);
- _visitNodeWithPrefix(" ", node.implementsClause);
- _writer.print(" {");
- _visitNodeListWithSeparator(node.members, " ");
- _writer.print("}");
- return null;
- }
-
- @override
- Object visitClassTypeAlias(ClassTypeAlias node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- if (node.abstractKeyword != null) {
- _writer.print("abstract ");
- }
- _writer.print("class ");
- _visitNode(node.name);
- _visitNode(node.typeParameters);
- _writer.print(" = ");
- _visitNode(node.superclass);
- _visitNodeWithPrefix(" ", node.withClause);
- _visitNodeWithPrefix(" ", node.implementsClause);
- _writer.print(";");
- return null;
- }
-
- @override
- Object visitComment(Comment node) => null;
-
- @override
- Object visitCommentReference(CommentReference node) => null;
-
- @override
- Object visitCompilationUnit(CompilationUnit node) {
- ScriptTag scriptTag = node.scriptTag;
- NodeList<Directive> directives = node.directives;
- _visitNode(scriptTag);
- String prefix = scriptTag == null ? "" : " ";
- _visitNodeListWithSeparatorAndPrefix(prefix, directives, " ");
- prefix = scriptTag == null && directives.isEmpty ? "" : " ";
- _visitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " ");
- return null;
- }
-
- @override
- Object visitConditionalExpression(ConditionalExpression node) {
- _visitNode(node.condition);
- _writer.print(" ? ");
- _visitNode(node.thenExpression);
- _writer.print(" : ");
- _visitNode(node.elseExpression);
- return null;
- }
-
- @override
- Object visitConfiguration(Configuration node) {
- _writer.print('if (');
- _visitNode(node.name);
- _visitNodeWithPrefix(" == ", node.value);
- _writer.print(') ');
- _visitNode(node.libraryUri);
- return null;
- }
-
- @override
- Object visitConstructorDeclaration(ConstructorDeclaration node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _visitTokenWithSuffix(node.externalKeyword, " ");
- _visitTokenWithSuffix(node.constKeyword, " ");
- _visitTokenWithSuffix(node.factoryKeyword, " ");
- _visitNode(node.returnType);
- _visitNodeWithPrefix(".", node.name);
- _visitNode(node.parameters);
- _visitNodeListWithSeparatorAndPrefix(" : ", node.initializers, ", ");
- _visitNodeWithPrefix(" = ", node.redirectedConstructor);
- _visitFunctionWithPrefix(" ", node.body);
- return null;
- }
-
- @override
- Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
- _visitTokenWithSuffix(node.thisKeyword, ".");
- _visitNode(node.fieldName);
- _writer.print(" = ");
- _visitNode(node.expression);
- return null;
- }
-
- @override
- Object visitConstructorName(ConstructorName node) {
- _visitNode(node.type);
- _visitNodeWithPrefix(".", node.name);
- return null;
- }
-
- @override
- Object visitContinueStatement(ContinueStatement node) {
- _writer.print("continue");
- _visitNodeWithPrefix(" ", node.label);
- _writer.print(";");
- return null;
- }
-
- @override
- Object visitDeclaredIdentifier(DeclaredIdentifier node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _visitTokenWithSuffix(node.keyword, " ");
- _visitNodeWithSuffix(node.type, " ");
- _visitNode(node.identifier);
- return null;
- }
-
- @override
- Object visitDefaultFormalParameter(DefaultFormalParameter node) {
- _visitNode(node.parameter);
- if (node.separator != null) {
- _writer.print(" ");
- _writer.print(node.separator.lexeme);
- _visitNodeWithPrefix(" ", node.defaultValue);
- }
- return null;
- }
-
- @override
- Object visitDoStatement(DoStatement node) {
- _writer.print("do ");
- _visitNode(node.body);
- _writer.print(" while (");
- _visitNode(node.condition);
- _writer.print(");");
- return null;
- }
-
- @override
- Object visitDottedName(DottedName node) {
- _visitNodeListWithSeparator(node.components, ".");
- return null;
- }
-
- @override
- Object visitDoubleLiteral(DoubleLiteral node) {
- _writer.print(node.literal.lexeme);
- return null;
- }
-
- @override
- Object visitEmptyFunctionBody(EmptyFunctionBody node) {
- _writer.print(';');
- return null;
- }
-
- @override
- Object visitEmptyStatement(EmptyStatement node) {
- _writer.print(';');
- return null;
- }
-
- @override
- Object visitEnumConstantDeclaration(EnumConstantDeclaration node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _visitNode(node.name);
- return null;
- }
-
- @override
- Object visitEnumDeclaration(EnumDeclaration node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _writer.print("enum ");
- _visitNode(node.name);
- _writer.print(" {");
- _visitNodeListWithSeparator(node.constants, ", ");
- _writer.print("}");
- return null;
- }
-
- @override
- Object visitExportDirective(ExportDirective node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _writer.print("export ");
- _visitNode(node.uri);
- _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
- _writer.print(';');
- return null;
- }
-
- @override
- Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
- Token keyword = node.keyword;
- if (keyword != null) {
- _writer.print(keyword.lexeme);
- _writer.print(' ');
- }
- _writer.print("=> ");
- _visitNode(node.expression);
- if (node.semicolon != null) {
- _writer.print(';');
- }
- return null;
- }
-
- @override
- Object visitExpressionStatement(ExpressionStatement node) {
- _visitNode(node.expression);
- _writer.print(';');
- return null;
- }
-
- @override
- Object visitExtendsClause(ExtendsClause node) {
- _writer.print("extends ");
- _visitNode(node.superclass);
- return null;
- }
-
- @override
- Object visitFieldDeclaration(FieldDeclaration node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _visitTokenWithSuffix(node.staticKeyword, " ");
- _visitNode(node.fields);
- _writer.print(";");
- return null;
- }
-
- @override
- Object visitFieldFormalParameter(FieldFormalParameter node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
- _visitTokenWithSuffix(node.keyword, " ");
- _visitNodeWithSuffix(node.type, " ");
- _writer.print("this.");
- _visitNode(node.identifier);
- _visitNode(node.typeParameters);
- _visitNode(node.parameters);
- return null;
- }
-
- @override
- Object visitForEachStatement(ForEachStatement node) {
- DeclaredIdentifier loopVariable = node.loopVariable;
- if (node.awaitKeyword != null) {
- _writer.print("await ");
- }
- _writer.print("for (");
- if (loopVariable == null) {
- _visitNode(node.identifier);
- } else {
- _visitNode(loopVariable);
- }
- _writer.print(" in ");
- _visitNode(node.iterable);
- _writer.print(") ");
- _visitNode(node.body);
- return null;
- }
-
- @override
- Object visitFormalParameterList(FormalParameterList node) {
- String groupEnd = null;
- _writer.print('(');
- NodeList<FormalParameter> parameters = node.parameters;
- int size = parameters.length;
- for (int i = 0; i < size; i++) {
- FormalParameter parameter = parameters[i];
- if (i > 0) {
- _writer.print(", ");
- }
- if (groupEnd == null && parameter is DefaultFormalParameter) {
- if (parameter.kind == ParameterKind.NAMED) {
- groupEnd = "}";
- _writer.print('{');
- } else {
- groupEnd = "]";
- _writer.print('[');
- }
- }
- parameter.accept(this);
- }
- if (groupEnd != null) {
- _writer.print(groupEnd);
- }
- _writer.print(')');
- return null;
- }
-
- @override
- Object visitForStatement(ForStatement node) {
- Expression initialization = node.initialization;
- _writer.print("for (");
- if (initialization != null) {
- _visitNode(initialization);
- } else {
- _visitNode(node.variables);
- }
- _writer.print(";");
- _visitNodeWithPrefix(" ", node.condition);
- _writer.print(";");
- _visitNodeListWithSeparatorAndPrefix(" ", node.updaters, ", ");
- _writer.print(") ");
- _visitNode(node.body);
- return null;
- }
-
- @override
- Object visitFunctionDeclaration(FunctionDeclaration node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _visitTokenWithSuffix(node.externalKeyword, " ");
- _visitNodeWithSuffix(node.returnType, " ");
- _visitTokenWithSuffix(node.propertyKeyword, " ");
- _visitNode(node.name);
- _visitNode(node.functionExpression);
- return null;
- }
-
- @override
- Object visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
- _visitNode(node.functionDeclaration);
- return null;
- }
-
- @override
- Object visitFunctionExpression(FunctionExpression node) {
- _visitNode(node.typeParameters);
- _visitNode(node.parameters);
- if (node.body is! EmptyFunctionBody) {
- _writer.print(' ');
- }
- _visitNode(node.body);
- return null;
- }
-
- @override
- Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
- _visitNode(node.function);
- _visitNode(node.typeArguments);
- _visitNode(node.argumentList);
- return null;
- }
-
- @override
- Object visitFunctionTypeAlias(FunctionTypeAlias node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _writer.print("typedef ");
- _visitNodeWithSuffix(node.returnType, " ");
- _visitNode(node.name);
- _visitNode(node.typeParameters);
- _visitNode(node.parameters);
- _writer.print(";");
- return null;
- }
-
- @override
- Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
- _visitNodeWithSuffix(node.returnType, " ");
- _visitNode(node.identifier);
- _visitNode(node.typeParameters);
- _visitNode(node.parameters);
- return null;
- }
-
- @override
- Object visitHideCombinator(HideCombinator node) {
- _writer.print("hide ");
- _visitNodeListWithSeparator(node.hiddenNames, ", ");
- return null;
- }
-
- @override
- Object visitIfStatement(IfStatement node) {
- _writer.print("if (");
- _visitNode(node.condition);
- _writer.print(") ");
- _visitNode(node.thenStatement);
- _visitNodeWithPrefix(" else ", node.elseStatement);
- return null;
- }
-
- @override
- Object visitImplementsClause(ImplementsClause node) {
- _writer.print("implements ");
- _visitNodeListWithSeparator(node.interfaces, ", ");
- return null;
- }
-
- @override
- Object visitImportDirective(ImportDirective node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _writer.print("import ");
- _visitNode(node.uri);
- if (node.deferredKeyword != null) {
- _writer.print(" deferred");
- }
- _visitNodeWithPrefix(" as ", node.prefix);
- _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
- _writer.print(';');
- return null;
- }
-
- @override
- Object visitIndexExpression(IndexExpression node) {
- if (node.isCascaded) {
- _writer.print("..");
- } else {
- _visitNode(node.target);
- }
- _writer.print('[');
- _visitNode(node.index);
- _writer.print(']');
- return null;
- }
-
- @override
- Object visitInstanceCreationExpression(InstanceCreationExpression node) {
- _visitTokenWithSuffix(node.keyword, " ");
- _visitNode(node.constructorName);
- _visitNode(node.argumentList);
- return null;
- }
-
- @override
- Object visitIntegerLiteral(IntegerLiteral node) {
- _writer.print(node.literal.lexeme);
- return null;
- }
-
- @override
- Object visitInterpolationExpression(InterpolationExpression node) {
- if (node.rightBracket != null) {
- _writer.print("\${");
- _visitNode(node.expression);
- _writer.print("}");
- } else {
- _writer.print("\$");
- _visitNode(node.expression);
- }
- return null;
- }
-
- @override
- Object visitInterpolationString(InterpolationString node) {
- _writer.print(node.contents.lexeme);
- return null;
- }
-
- @override
- Object visitIsExpression(IsExpression node) {
- _visitNode(node.expression);
- if (node.notOperator == null) {
- _writer.print(" is ");
- } else {
- _writer.print(" is! ");
- }
- _visitNode(node.type);
- return null;
- }
-
- @override
- Object visitLabel(Label node) {
- _visitNode(node.label);
- _writer.print(":");
- return null;
- }
-
- @override
- Object visitLabeledStatement(LabeledStatement node) {
- _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
- _visitNode(node.statement);
- return null;
- }
-
- @override
- Object visitLibraryDirective(LibraryDirective node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _writer.print("library ");
- _visitNode(node.name);
- _writer.print(';');
- return null;
- }
-
- @override
- Object visitLibraryIdentifier(LibraryIdentifier node) {
- _writer.print(node.name);
- return null;
- }
-
- @override
- Object visitListLiteral(ListLiteral node) {
- if (node.constKeyword != null) {
- _writer.print(node.constKeyword.lexeme);
- _writer.print(' ');
- }
- _visitNodeWithSuffix(node.typeArguments, " ");
- _writer.print("[");
- _visitNodeListWithSeparator(node.elements, ", ");
- _writer.print("]");
- return null;
- }
-
- @override
- Object visitMapLiteral(MapLiteral node) {
- if (node.constKeyword != null) {
- _writer.print(node.constKeyword.lexeme);
- _writer.print(' ');
- }
- _visitNodeWithSuffix(node.typeArguments, " ");
- _writer.print("{");
- _visitNodeListWithSeparator(node.entries, ", ");
- _writer.print("}");
- return null;
- }
-
- @override
- Object visitMapLiteralEntry(MapLiteralEntry node) {
- _visitNode(node.key);
- _writer.print(" : ");
- _visitNode(node.value);
- return null;
- }
-
- @override
- Object visitMethodDeclaration(MethodDeclaration node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _visitTokenWithSuffix(node.externalKeyword, " ");
- _visitTokenWithSuffix(node.modifierKeyword, " ");
- _visitNodeWithSuffix(node.returnType, " ");
- _visitTokenWithSuffix(node.propertyKeyword, " ");
- _visitTokenWithSuffix(node.operatorKeyword, " ");
- _visitNode(node.name);
- if (!node.isGetter) {
- _visitNode(node.typeParameters);
- _visitNode(node.parameters);
- }
- _visitFunctionWithPrefix(" ", node.body);
- return null;
- }
-
- @override
- Object visitMethodInvocation(MethodInvocation node) {
- if (node.isCascaded) {
- _writer.print("..");
- } else {
- if (node.target != null) {
- node.target.accept(this);
- _writer.print(node.operator.lexeme);
- }
- }
- _visitNode(node.methodName);
- _visitNode(node.typeArguments);
- _visitNode(node.argumentList);
- return null;
- }
-
- @override
- Object visitNamedExpression(NamedExpression node) {
- _visitNode(node.name);
- _visitNodeWithPrefix(" ", node.expression);
- return null;
- }
-
- @override
- Object visitNativeClause(NativeClause node) {
- _writer.print("native ");
- _visitNode(node.name);
- return null;
- }
-
- @override
- Object visitNativeFunctionBody(NativeFunctionBody node) {
- _writer.print("native ");
- _visitNode(node.stringLiteral);
- _writer.print(';');
- return null;
- }
-
- @override
- Object visitNullLiteral(NullLiteral node) {
- _writer.print("null");
- return null;
- }
-
- @override
- Object visitParenthesizedExpression(ParenthesizedExpression node) {
- _writer.print('(');
- _visitNode(node.expression);
- _writer.print(')');
- return null;
- }
-
- @override
- Object visitPartDirective(PartDirective node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _writer.print("part ");
- _visitNode(node.uri);
- _writer.print(';');
- return null;
- }
-
- @override
- Object visitPartOfDirective(PartOfDirective node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _writer.print("part of ");
- _visitNode(node.libraryName);
- _writer.print(';');
- return null;
- }
-
- @override
- Object visitPostfixExpression(PostfixExpression node) {
- _visitNode(node.operand);
- _writer.print(node.operator.lexeme);
- return null;
- }
-
- @override
- Object visitPrefixedIdentifier(PrefixedIdentifier node) {
- _visitNode(node.prefix);
- _writer.print('.');
- _visitNode(node.identifier);
- return null;
- }
-
- @override
- Object visitPrefixExpression(PrefixExpression node) {
- _writer.print(node.operator.lexeme);
- _visitNode(node.operand);
- return null;
- }
-
- @override
- Object visitPropertyAccess(PropertyAccess node) {
- if (node.isCascaded) {
- _writer.print("..");
- } else {
- _visitNode(node.target);
- _writer.print(node.operator.lexeme);
- }
- _visitNode(node.propertyName);
- return null;
- }
-
- @override
- Object visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) {
- _writer.print("this");
- _visitNodeWithPrefix(".", node.constructorName);
- _visitNode(node.argumentList);
- return null;
- }
-
- @override
- Object visitRethrowExpression(RethrowExpression node) {
- _writer.print("rethrow");
- return null;
- }
-
- @override
- Object visitReturnStatement(ReturnStatement node) {
- Expression expression = node.expression;
- if (expression == null) {
- _writer.print("return;");
- } else {
- _writer.print("return ");
- expression.accept(this);
- _writer.print(";");
- }
- return null;
- }
-
- @override
- Object visitScriptTag(ScriptTag node) {
- _writer.print(node.scriptTag.lexeme);
- return null;
- }
-
- @override
- Object visitShowCombinator(ShowCombinator node) {
- _writer.print("show ");
- _visitNodeListWithSeparator(node.shownNames, ", ");
- return null;
- }
-
- @override
- Object visitSimpleFormalParameter(SimpleFormalParameter node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
- _visitTokenWithSuffix(node.keyword, " ");
- _visitNodeWithSuffix(node.type, " ");
- _visitNode(node.identifier);
- return null;
- }
-
- @override
- Object visitSimpleIdentifier(SimpleIdentifier node) {
- _writer.print(node.token.lexeme);
- return null;
- }
-
- @override
- Object visitSimpleStringLiteral(SimpleStringLiteral node) {
- _writer.print(node.literal.lexeme);
- return null;
- }
-
- @override
- Object visitStringInterpolation(StringInterpolation node) {
- _visitNodeList(node.elements);
- return null;
- }
-
- @override
- Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
- _writer.print("super");
- _visitNodeWithPrefix(".", node.constructorName);
- _visitNode(node.argumentList);
- return null;
- }
-
- @override
- Object visitSuperExpression(SuperExpression node) {
- _writer.print("super");
- return null;
- }
-
- @override
- Object visitSwitchCase(SwitchCase node) {
- _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
- _writer.print("case ");
- _visitNode(node.expression);
- _writer.print(": ");
- _visitNodeListWithSeparator(node.statements, " ");
- return null;
- }
-
- @override
- Object visitSwitchDefault(SwitchDefault node) {
- _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
- _writer.print("default: ");
- _visitNodeListWithSeparator(node.statements, " ");
- return null;
- }
-
- @override
- Object visitSwitchStatement(SwitchStatement node) {
- _writer.print("switch (");
- _visitNode(node.expression);
- _writer.print(") {");
- _visitNodeListWithSeparator(node.members, " ");
- _writer.print("}");
- return null;
- }
-
- @override
- Object visitSymbolLiteral(SymbolLiteral node) {
- _writer.print("#");
- List<Token> components = node.components;
- for (int i = 0; i < components.length; i++) {
- if (i > 0) {
- _writer.print(".");
- }
- _writer.print(components[i].lexeme);
- }
- return null;
- }
-
- @override
- Object visitThisExpression(ThisExpression node) {
- _writer.print("this");
- return null;
- }
-
- @override
- Object visitThrowExpression(ThrowExpression node) {
- _writer.print("throw ");
- _visitNode(node.expression);
- return null;
- }
-
- @override
- Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- _visitNodeWithSuffix(node.variables, ";");
- return null;
- }
-
- @override
- Object visitTryStatement(TryStatement node) {
- _writer.print("try ");
- _visitNode(node.body);
- _visitNodeListWithSeparatorAndPrefix(" ", node.catchClauses, " ");
- _visitNodeWithPrefix(" finally ", node.finallyBlock);
- return null;
- }
-
- @override
- Object visitTypeArgumentList(TypeArgumentList node) {
- _writer.print('<');
- _visitNodeListWithSeparator(node.arguments, ", ");
- _writer.print('>');
- return null;
- }
-
- @override
- Object visitTypeName(TypeName node) {
- _visitNode(node.name);
- _visitNode(node.typeArguments);
- return null;
- }
-
- @override
- Object visitTypeParameter(TypeParameter node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _visitNode(node.name);
- _visitNodeWithPrefix(" extends ", node.bound);
- return null;
- }
-
- @override
- Object visitTypeParameterList(TypeParameterList node) {
- _writer.print('<');
- _visitNodeListWithSeparator(node.typeParameters, ", ");
- _writer.print('>');
- return null;
- }
-
- @override
- Object visitVariableDeclaration(VariableDeclaration node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _visitNode(node.name);
- _visitNodeWithPrefix(" = ", node.initializer);
- return null;
- }
-
- @override
- Object visitVariableDeclarationList(VariableDeclarationList node) {
- _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
- _visitTokenWithSuffix(node.keyword, " ");
- _visitNodeWithSuffix(node.type, " ");
- _visitNodeListWithSeparator(node.variables, ", ");
- return null;
- }
-
- @override
- Object visitVariableDeclarationStatement(VariableDeclarationStatement node) {
- _visitNode(node.variables);
- _writer.print(";");
- return null;
- }
-
- @override
- Object visitWhileStatement(WhileStatement node) {
- _writer.print("while (");
- _visitNode(node.condition);
- _writer.print(") ");
- _visitNode(node.body);
- return null;
- }
-
- @override
- Object visitWithClause(WithClause node) {
- _writer.print("with ");
- _visitNodeListWithSeparator(node.mixinTypes, ", ");
- return null;
- }
-
- @override
- Object visitYieldStatement(YieldStatement node) {
- if (node.star != null) {
- _writer.print("yield* ");
- } else {
- _writer.print("yield ");
- }
- _visitNode(node.expression);
- _writer.print(";");
- return null;
- }
-
- /**
- * Visit the given function [body], printing the [prefix] before if the body
- * is not empty.
- */
- void _visitFunctionWithPrefix(String prefix, FunctionBody body) {
- if (body is! EmptyFunctionBody) {
- _writer.print(prefix);
- }
- _visitNode(body);
- }
-
- /**
- * Safely visit the given [node].
- */
- void _visitNode(AstNode node) {
- if (node != null) {
- node.accept(this);
- }
- }
-
- /**
- * Print a list of [nodes] without any separation.
- */
- void _visitNodeList(NodeList<AstNode> nodes) {
- _visitNodeListWithSeparator(nodes, "");
- }
-
- /**
- * Print a list of [nodes], separated by the given [separator].
- */
- void _visitNodeListWithSeparator(NodeList<AstNode> nodes, String separator) {
- if (nodes != null) {
- int size = nodes.length;
- for (int i = 0; i < size; i++) {
- if (i > 0) {
- _writer.print(separator);
- }
- nodes[i].accept(this);
- }
- }
- }
-
- /**
- * Print a list of [nodes], prefixed by the given [prefix] if the list is not
- * empty, and separated by the given [separator].
- */
- void _visitNodeListWithSeparatorAndPrefix(
- String prefix, NodeList<AstNode> nodes, String separator) {
- if (nodes != null) {
- int size = nodes.length;
- if (size > 0) {
- _writer.print(prefix);
- for (int i = 0; i < size; i++) {
- if (i > 0) {
- _writer.print(separator);
- }
- nodes[i].accept(this);
- }
- }
- }
- }
-
- /**
- * Print a list of [nodes], separated by the given [separator], followed by
- * the given [suffix] if the list is not empty.
- */
- void _visitNodeListWithSeparatorAndSuffix(
- NodeList<AstNode> nodes, String separator, String suffix) {
- if (nodes != null) {
- int size = nodes.length;
- if (size > 0) {
- for (int i = 0; i < size; i++) {
- if (i > 0) {
- _writer.print(separator);
- }
- nodes[i].accept(this);
- }
- _writer.print(suffix);
- }
- }
- }
-
- /**
- * Safely visit the given [node], printing the [prefix] before the node if it
- * is non-`null`.
- */
- void _visitNodeWithPrefix(String prefix, AstNode node) {
- if (node != null) {
- _writer.print(prefix);
- node.accept(this);
- }
- }
-
- /**
- * Safely visit the given [node], printing the [suffix] after the node if it
- * is non-`null`.
- */
- void _visitNodeWithSuffix(AstNode node, String suffix) {
- if (node != null) {
- node.accept(this);
- _writer.print(suffix);
- }
- }
-
- /**
- * Safely visit the given [token], printing the [suffix] after the token if it
- * is non-`null`.
- */
- void _visitTokenWithSuffix(Token token, String suffix) {
- if (token != null) {
- _writer.print(token.lexeme);
- _writer.print(suffix);
- }
- }
-}
-
-/**
* A try statement.
*
* > tryStatement ::=
@@ -19408,361 +11662,6 @@
}
/**
- * An AST visitor that will recursively visit all of the nodes in an AST
- * structure (like instances of the class [RecursiveAstVisitor]). In addition,
- * every node will also be visited by using a single unified [visitNode] method.
- *
- * Subclasses that override a visit method must either invoke the overridden
- * visit method or explicitly invoke the more general [visitNode] method.
- * Failure to do so will cause the children of the visited node to not be
- * visited.
- */
-class UnifyingAstVisitor<R> implements AstVisitor<R> {
- @override
- R visitAdjacentStrings(AdjacentStrings node) => visitNode(node);
-
- @override
- R visitAnnotation(Annotation node) => visitNode(node);
-
- @override
- R visitArgumentList(ArgumentList node) => visitNode(node);
-
- @override
- R visitAsExpression(AsExpression node) => visitNode(node);
-
- @override
- R visitAssertStatement(AssertStatement node) => visitNode(node);
-
- @override
- R visitAssignmentExpression(AssignmentExpression node) => visitNode(node);
-
- @override
- R visitAwaitExpression(AwaitExpression node) => visitNode(node);
-
- @override
- R visitBinaryExpression(BinaryExpression node) => visitNode(node);
-
- @override
- R visitBlock(Block node) => visitNode(node);
-
- @override
- R visitBlockFunctionBody(BlockFunctionBody node) => visitNode(node);
-
- @override
- R visitBooleanLiteral(BooleanLiteral node) => visitNode(node);
-
- @override
- R visitBreakStatement(BreakStatement node) => visitNode(node);
-
- @override
- R visitCascadeExpression(CascadeExpression node) => visitNode(node);
-
- @override
- R visitCatchClause(CatchClause node) => visitNode(node);
-
- @override
- R visitClassDeclaration(ClassDeclaration node) => visitNode(node);
-
- @override
- R visitClassTypeAlias(ClassTypeAlias node) => visitNode(node);
-
- @override
- R visitComment(Comment node) => visitNode(node);
-
- @override
- R visitCommentReference(CommentReference node) => visitNode(node);
-
- @override
- R visitCompilationUnit(CompilationUnit node) => visitNode(node);
-
- @override
- R visitConditionalExpression(ConditionalExpression node) => visitNode(node);
-
- @override
- R visitConfiguration(Configuration node) => visitNode(node);
-
- @override
- R visitConstructorDeclaration(ConstructorDeclaration node) => visitNode(node);
-
- @override
- R visitConstructorFieldInitializer(ConstructorFieldInitializer node) =>
- visitNode(node);
-
- @override
- R visitConstructorName(ConstructorName node) => visitNode(node);
-
- @override
- R visitContinueStatement(ContinueStatement node) => visitNode(node);
-
- @override
- R visitDeclaredIdentifier(DeclaredIdentifier node) => visitNode(node);
-
- @override
- R visitDefaultFormalParameter(DefaultFormalParameter node) => visitNode(node);
-
- @override
- R visitDoStatement(DoStatement node) => visitNode(node);
-
- @override
- R visitDottedName(DottedName node) => visitNode(node);
-
- @override
- R visitDoubleLiteral(DoubleLiteral node) => visitNode(node);
-
- @override
- R visitEmptyFunctionBody(EmptyFunctionBody node) => visitNode(node);
-
- @override
- R visitEmptyStatement(EmptyStatement node) => visitNode(node);
-
- @override
- R visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
- visitNode(node);
-
- @override
- R visitEnumDeclaration(EnumDeclaration node) => visitNode(node);
-
- @override
- R visitExportDirective(ExportDirective node) => visitNode(node);
-
- @override
- R visitExpressionFunctionBody(ExpressionFunctionBody node) => visitNode(node);
-
- @override
- R visitExpressionStatement(ExpressionStatement node) => visitNode(node);
-
- @override
- R visitExtendsClause(ExtendsClause node) => visitNode(node);
-
- @override
- R visitFieldDeclaration(FieldDeclaration node) => visitNode(node);
-
- @override
- R visitFieldFormalParameter(FieldFormalParameter node) => visitNode(node);
-
- @override
- R visitForEachStatement(ForEachStatement node) => visitNode(node);
-
- @override
- R visitFormalParameterList(FormalParameterList node) => visitNode(node);
-
- @override
- R visitForStatement(ForStatement node) => visitNode(node);
-
- @override
- R visitFunctionDeclaration(FunctionDeclaration node) => visitNode(node);
-
- @override
- R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
- visitNode(node);
-
- @override
- R visitFunctionExpression(FunctionExpression node) => visitNode(node);
-
- @override
- R visitFunctionExpressionInvocation(FunctionExpressionInvocation node) =>
- visitNode(node);
-
- @override
- R visitFunctionTypeAlias(FunctionTypeAlias node) => visitNode(node);
-
- @override
- R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) =>
- visitNode(node);
-
- @override
- R visitHideCombinator(HideCombinator node) => visitNode(node);
-
- @override
- R visitIfStatement(IfStatement node) => visitNode(node);
-
- @override
- R visitImplementsClause(ImplementsClause node) => visitNode(node);
-
- @override
- R visitImportDirective(ImportDirective node) => visitNode(node);
-
- @override
- R visitIndexExpression(IndexExpression node) => visitNode(node);
-
- @override
- R visitInstanceCreationExpression(InstanceCreationExpression node) =>
- visitNode(node);
-
- @override
- R visitIntegerLiteral(IntegerLiteral node) => visitNode(node);
-
- @override
- R visitInterpolationExpression(InterpolationExpression node) =>
- visitNode(node);
-
- @override
- R visitInterpolationString(InterpolationString node) => visitNode(node);
-
- @override
- R visitIsExpression(IsExpression node) => visitNode(node);
-
- @override
- R visitLabel(Label node) => visitNode(node);
-
- @override
- R visitLabeledStatement(LabeledStatement node) => visitNode(node);
-
- @override
- R visitLibraryDirective(LibraryDirective node) => visitNode(node);
-
- @override
- R visitLibraryIdentifier(LibraryIdentifier node) => visitNode(node);
-
- @override
- R visitListLiteral(ListLiteral node) => visitNode(node);
-
- @override
- R visitMapLiteral(MapLiteral node) => visitNode(node);
-
- @override
- R visitMapLiteralEntry(MapLiteralEntry node) => visitNode(node);
-
- @override
- R visitMethodDeclaration(MethodDeclaration node) => visitNode(node);
-
- @override
- R visitMethodInvocation(MethodInvocation node) => visitNode(node);
-
- @override
- R visitNamedExpression(NamedExpression node) => visitNode(node);
-
- @override
- R visitNativeClause(NativeClause node) => visitNode(node);
-
- @override
- R visitNativeFunctionBody(NativeFunctionBody node) => visitNode(node);
-
- R visitNode(AstNode node) {
- node.visitChildren(this);
- return null;
- }
-
- @override
- R visitNullLiteral(NullLiteral node) => visitNode(node);
-
- @override
- R visitParenthesizedExpression(ParenthesizedExpression node) =>
- visitNode(node);
-
- @override
- R visitPartDirective(PartDirective node) => visitNode(node);
-
- @override
- R visitPartOfDirective(PartOfDirective node) => visitNode(node);
-
- @override
- R visitPostfixExpression(PostfixExpression node) => visitNode(node);
-
- @override
- R visitPrefixedIdentifier(PrefixedIdentifier node) => visitNode(node);
-
- @override
- R visitPrefixExpression(PrefixExpression node) => visitNode(node);
-
- @override
- R visitPropertyAccess(PropertyAccess node) => visitNode(node);
-
- @override
- R visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) =>
- visitNode(node);
-
- @override
- R visitRethrowExpression(RethrowExpression node) => visitNode(node);
-
- @override
- R visitReturnStatement(ReturnStatement node) => visitNode(node);
-
- @override
- R visitScriptTag(ScriptTag scriptTag) => visitNode(scriptTag);
-
- @override
- R visitShowCombinator(ShowCombinator node) => visitNode(node);
-
- @override
- R visitSimpleFormalParameter(SimpleFormalParameter node) => visitNode(node);
-
- @override
- R visitSimpleIdentifier(SimpleIdentifier node) => visitNode(node);
-
- @override
- R visitSimpleStringLiteral(SimpleStringLiteral node) => visitNode(node);
-
- @override
- R visitStringInterpolation(StringInterpolation node) => visitNode(node);
-
- @override
- R visitSuperConstructorInvocation(SuperConstructorInvocation node) =>
- visitNode(node);
-
- @override
- R visitSuperExpression(SuperExpression node) => visitNode(node);
-
- @override
- R visitSwitchCase(SwitchCase node) => visitNode(node);
-
- @override
- R visitSwitchDefault(SwitchDefault node) => visitNode(node);
-
- @override
- R visitSwitchStatement(SwitchStatement node) => visitNode(node);
-
- @override
- R visitSymbolLiteral(SymbolLiteral node) => visitNode(node);
-
- @override
- R visitThisExpression(ThisExpression node) => visitNode(node);
-
- @override
- R visitThrowExpression(ThrowExpression node) => visitNode(node);
-
- @override
- R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) =>
- visitNode(node);
-
- @override
- R visitTryStatement(TryStatement node) => visitNode(node);
-
- @override
- R visitTypeArgumentList(TypeArgumentList node) => visitNode(node);
-
- @override
- R visitTypeName(TypeName node) => visitNode(node);
-
- @override
- R visitTypeParameter(TypeParameter node) => visitNode(node);
-
- @override
- R visitTypeParameterList(TypeParameterList node) => visitNode(node);
-
- @override
- R visitVariableDeclaration(VariableDeclaration node) => visitNode(node);
-
- @override
- R visitVariableDeclarationList(VariableDeclarationList node) =>
- visitNode(node);
-
- @override
- R visitVariableDeclarationStatement(VariableDeclarationStatement node) =>
- visitNode(node);
-
- @override
- R visitWhileStatement(WhileStatement node) => visitNode(node);
-
- @override
- R visitWithClause(WithClause node) => visitNode(node);
-
- @override
- R visitYieldStatement(YieldStatement node) => visitNode(node);
-}
-
-/**
* A directive that references a URI.
*
* > uriBasedDirective ::=
@@ -19928,7 +11827,7 @@
/**
* This overridden implementation of getDocumentationComment() looks in the
- * grandparent node for dartdoc comments if no documentation is specifically
+ * grandparent node for Dartdoc comments if no documentation is specifically
* available on the node.
*/
@override
diff --git a/pkg/analyzer/lib/src/generated/element_handle.dart b/pkg/analyzer/lib/src/generated/element_handle.dart
index f36d436..0a29cfb 100644
--- a/pkg/analyzer/lib/src/generated/element_handle.dart
+++ b/pkg/analyzer/lib/src/generated/element_handle.dart
@@ -335,6 +335,7 @@
@override
String get displayName => actualElement.displayName;
+ @deprecated
@override
SourceRange get docRange => actualElement.docRange;
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 06d0c56..9f0cda0 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -2129,7 +2129,7 @@
* given [propertyName], return the element that represents the property.
*/
Element _resolveElement(
- ClassElementImpl classElement, SimpleIdentifier propertyName) {
+ ClassElement classElement, SimpleIdentifier propertyName) {
String name = propertyName.name;
Element element = null;
if (propertyName.inSetterContext()) {
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 1861ffe..0e762ee 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1887,6 +1887,18 @@
List<WorkManager> get workManagers;
/**
+ * This method is invoked when the state of the [result] of the [entry] is
+ * [CacheState.INVALID], so it is about to be computed.
+ *
+ * If the context knows how to provide the value, it sets the value into
+ * the [entry] with all required dependencies, and returns `true`.
+ *
+ * Otherwise, it returns `false` to indicate that the result should be
+ * computed as usually.
+ */
+ bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result);
+
+ /**
* Return a list containing the sources of the libraries that are exported by
* the library with the given [source]. The list will be empty if the given
* source is invalid, if the given source does not represent a library, or if
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index f8cba0c..b67b905 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -48,7 +48,7 @@
*/
class DeclarationMatcher extends RecursiveAstVisitor {
/**
- * The libary containing the AST nodes being visited.
+ * The library containing the AST nodes being visited.
*/
LibraryElement _enclosingLibrary;
@@ -165,6 +165,8 @@
_assertEquals(constructor.parameters.length, 0);
}
}
+ // matches, set the element
+ node.name.staticElement = element;
}
@override
@@ -355,11 +357,12 @@
if (newElement != null) {
_addedElements.add(newElement);
if (newElement is MethodElement) {
- List<MethodElement> methods = _enclosingClass.methods;
+ List<MethodElement> methods = _enclosingClass.methods.toList();
methods.add(newElement);
_enclosingClass.methods = methods;
} else {
- List<PropertyAccessorElement> accessors = _enclosingClass.accessors;
+ List<PropertyAccessorElement> accessors =
+ _enclosingClass.accessors.toList();
accessors.add(newElement);
_enclosingClass.accessors = accessors;
}
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index bd13357..33510ed 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -4219,6 +4219,14 @@
return _tokenMatches(token, TokenType.OPEN_PAREN);
}
+ bool _isPeekGenericTypeParametersAndOpenParen() {
+ if (!parseGenericMethods) {
+ return false;
+ }
+ Token token = _skipTypeArgumentList(_peek());
+ return token != null && _tokenMatches(token, TokenType.OPEN_PAREN);
+ }
+
/**
* Return `true` if the current token appears to be the beginning of a switch
* member.
@@ -5216,6 +5224,9 @@
}
_reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
return null;
+ } else if (_isPeekGenericTypeParametersAndOpenParen()) {
+ return _parseFunctionDeclaration(
+ commentAndMetadata, modifiers.externalKeyword, null);
} else if (_tokenMatches(_peek(), TokenType.OPEN_PAREN)) {
TypeName returnType = _parseOptionalTypeNameComment();
_validateModifiersForTopLevelFunction(modifiers);
@@ -5275,7 +5286,8 @@
if (_peek().matchesAny([
TokenType.OPEN_PAREN,
TokenType.FUNCTION,
- TokenType.OPEN_CURLY_BRACKET
+ TokenType.OPEN_CURLY_BRACKET,
+ TokenType.LT
])) {
_validateModifiersForTopLevelFunction(modifiers);
return _parseFunctionDeclaration(
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index a52736d..35616c6 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2377,10 +2377,18 @@
@override
Object visitTypeParameter(TypeParameter node) {
SimpleIdentifier parameterName = node.name;
- if (_enclosingClass != null) {
- _findIdentifier(_enclosingClass.typeParameters, parameterName);
- } else if (_enclosingAlias != null) {
- _findIdentifier(_enclosingAlias.typeParameters, parameterName);
+
+ Element element;
+ if (_enclosingExecutable != null) {
+ element =
+ _findIdentifier(_enclosingExecutable.typeParameters, parameterName);
+ }
+ if (element == null) {
+ if (_enclosingClass != null) {
+ _findIdentifier(_enclosingClass.typeParameters, parameterName);
+ } else if (_enclosingAlias != null) {
+ _findIdentifier(_enclosingAlias.typeParameters, parameterName);
+ }
}
return super.visitTypeParameter(node);
}
@@ -5415,6 +5423,8 @@
* A stack of return types for all of the enclosing
* functions and methods.
*/
+ // TODO(leafp) Handle the implicit union type for Futures
+ // https://github.com/dart-lang/sdk/issues/25322
List<DartType> _returnStack = <DartType>[];
InferenceContext._(this._errorListener, TypeProvider typeProvider,
@@ -5423,9 +5433,15 @@
/**
* Get the return type of the current enclosing function, if any.
+ *
+ * The type returned for a function is the type that is expected
+ * to be used in a return or yield context. For ordinary functions
+ * this is the same as the return type of the function. For async
+ * functions returning Future<T> and for generator functions
+ * returning Stream<T> or Iterable<T>, this is T.
*/
DartType get returnContext =>
- (_returnStack.isNotEmpty) ? _returnStack.last : null;
+ _returnStack.isNotEmpty ? _returnStack.last : null;
/**
* Match type [t1] against type [t2] as follows.
@@ -8359,8 +8375,10 @@
@override
Object visitAwaitExpression(AwaitExpression node) {
- //TODO(leafp): Handle the implicit union type here
- DartType contextType = InferenceContext.getType(node);
+ // TODO(leafp): Handle the implicit union type here
+ // https://github.com/dart-lang/sdk/issues/25322
+ DartType contextType = StaticTypeAnalyzer.flattenFutures(
+ typeProvider, InferenceContext.getType(node));
if (contextType != null) {
InterfaceType futureT =
typeProvider.futureType.substitute4([contextType]);
@@ -8894,7 +8912,11 @@
DartType functionType = InferenceContext.getType(node);
if (functionType is FunctionType) {
_inferFormalParameterList(node.parameters, functionType);
- InferenceContext.setType(node.body, functionType.returnType);
+ DartType returnType = _computeReturnOrYieldType(
+ functionType.returnType,
+ _enclosingFunction.isGenerator,
+ _enclosingFunction.isAsynchronous);
+ InferenceContext.setType(node.body, returnType);
}
super.visitFunctionExpression(node);
} finally {
@@ -9099,7 +9121,11 @@
ExecutableElement outerFunction = _enclosingFunction;
try {
_enclosingFunction = node.element;
- InferenceContext.setType(node.body, node.element.type?.returnType);
+ DartType returnType = _computeReturnOrYieldType(
+ _enclosingFunction.type?.returnType,
+ _enclosingFunction.isGenerator,
+ _enclosingFunction.isAsynchronous);
+ InferenceContext.setType(node.body, returnType);
super.visitMethodDeclaration(node);
} finally {
_enclosingFunction = outerFunction;
@@ -9328,18 +9354,15 @@
// If we're not in a generator ([a]sync*, then we shouldn't have a yield.
// so don't infer
if (_enclosingFunction.isGenerator) {
- // If this is a yield*, then we just propagate the return type downwards
+ // If this just a yield, then we just pass on the element type
DartType type = returnType;
- // If this just a yield, then we need to get the element type
- if (node.star == null) {
+ if (node.star != null) {
+ // If this is a yield*, then we wrap the element return type
// If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
- InterfaceType wrapperD = _enclosingFunction.isSynchronous
- ? typeProvider.iterableDynamicType
- : typeProvider.streamDynamicType;
- // Match the types to instantiate the type arguments if possible
- List<DartType> targs =
- inferenceContext.matchTypes(wrapperD, returnType);
- type = (targs?.length == 1) ? targs[0] : null;
+ InterfaceType wrapperType = _enclosingFunction.isSynchronous
+ ? typeProvider.iterableType
+ : typeProvider.streamType;
+ type = wrapperType.substitute4(<DartType>[type]);
}
InferenceContext.setType(node.expression, type);
}
@@ -9380,6 +9403,34 @@
}
/**
+ * Given the declared return type of a function, compute the type of the
+ * values which should be returned or yielded as appropriate. If a type
+ * cannot be computed from the declared return type, return null.
+ */
+ DartType _computeReturnOrYieldType(
+ DartType declaredType, bool isGenerator, bool isAsynchronous) {
+ // Ordinary functions just return their declared types.
+ if (!isGenerator && !isAsynchronous) {
+ return declaredType;
+ }
+ if (isGenerator) {
+ if (declaredType is! InterfaceType) {
+ return null;
+ }
+ // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
+ InterfaceType rawType = isAsynchronous
+ ? typeProvider.streamDynamicType
+ : typeProvider.iterableDynamicType;
+ // Match the types to instantiate the type arguments if possible
+ List<DartType> typeArgs =
+ inferenceContext.matchTypes(rawType, declaredType);
+ return (typeArgs?.length == 1) ? typeArgs[0] : null;
+ }
+ // Must be asynchronous to reach here, so strip off any layers of Future
+ return StaticTypeAnalyzer.flattenFutures(typeProvider, declaredType);
+ }
+
+ /**
* The given expression is the expression used to compute the iterator for a
* for-each statement. Attempt to compute the type of objects that will be
* assigned to the loop variable and return that type. Return `null` if the
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index 1f98ba3..1fc4b33 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -18,6 +18,9 @@
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/summary/format.dart' show SdkBundle;
+import 'package:analyzer/src/summary/summary_sdk.dart';
+import 'package:path/path.dart' as pathos;
/**
* A Dart SDK installed in a specified directory. Typical Dart SDK layout is
@@ -241,7 +244,12 @@
@override
AnalysisContext get context {
if (_analysisContext == null) {
- _analysisContext = new SdkAnalysisContext();
+ SdkBundle sdkBundle = _getSummarySdkBundle();
+ if (sdkBundle != null) {
+ _analysisContext = new SummarySdkAnalysisContext(sdkBundle);
+ } else {
+ _analysisContext = new SdkAnalysisContext();
+ }
SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
_analysisContext.sourceFactory = factory;
List<String> uris = this.uris;
@@ -533,6 +541,26 @@
}
/**
+ * Return the [SdkBundle] for this SDK, if it exists, or `null` otherwise.
+ */
+ SdkBundle _getSummarySdkBundle() {
+ String rootPath = directory.getAbsolutePath();
+ String path = pathos.join(rootPath, 'lib', '_internal', 'analysis_summary');
+ try {
+ File file = new File(path);
+ if (file.existsSync()) {
+ List<int> bytes = file.readAsBytesSync();
+ return new SdkBundle.fromBuffer(bytes);
+ }
+ } catch (exception, stackTrace) {
+ AnalysisEngine.instance.logger.logError(
+ 'Failed to load SDK analysis summary from $path',
+ new CaughtException(exception, stackTrace));
+ }
+ return null;
+ }
+
+ /**
* Return the given [file] if it exists and is executable, or `null` if it
* does not exist or is not executable.
*/
diff --git a/pkg/analyzer/lib/src/summary/builder.dart b/pkg/analyzer/lib/src/summary/base.dart
similarity index 61%
rename from pkg/analyzer/lib/src/summary/builder.dart
rename to pkg/analyzer/lib/src/summary/base.dart
index c1bedfb..0002dc9 100644
--- a/pkg/analyzer/lib/src/summary/builder.dart
+++ b/pkg/analyzer/lib/src/summary/base.dart
@@ -3,9 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
/**
- * Format-agnostic infrastructure for building summary objects.
+ * Base functionality which code generated summary classes are built upon.
*/
-library analyzer.src.summary.builder;
+library analyzer.src.summary.base;
/**
* Instances of this class encapsulate the necessary state to keep track of a
@@ -20,3 +20,16 @@
// we switch to a serialization format that requires state tracking, the
// state will be stored here.
}
+
+/**
+ * Instances of this class represent data that has been read from a summary.
+ */
+abstract class SummaryClass {
+ /**
+ * Translate the data in this class into a map whose keys are the names of
+ * fields and whose values are the data stored in those fields.
+ *
+ * Intended for testing and debugging only.
+ */
+ Map<String, Object> toMap();
+}
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index d050d81..c4fb417 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -8,8 +8,12 @@
library analyzer.src.summary.format;
import 'dart:convert';
-import 'builder.dart' as builder;
+import 'base.dart' as base;
+/**
+ * Enum used to indicate the kind of entity referred to by a
+ * [PrelinkedReference].
+ */
enum PrelinkedReferenceKind {
classOrEnum,
typedef,
@@ -18,6 +22,9 @@
unresolved,
}
+/**
+ * Enum used to indicate the kind of an executable.
+ */
enum UnlinkedExecutableKind {
functionOrMethod,
getter,
@@ -25,18 +32,33 @@
constructor,
}
+/**
+ * Enum used to indicate the kind of a parameter.
+ */
enum UnlinkedParamKind {
required,
positional,
named,
}
-class PrelinkedDependency {
+/**
+ * Information about a dependency that exists between one library and another
+ * due to an "import" declaration.
+ */
+class PrelinkedDependency extends base.SummaryClass {
String _uri;
PrelinkedDependency.fromJson(Map json)
: _uri = json["uri"];
+ @override
+ Map<String, Object> toMap() => {
+ "uri": uri,
+ };
+
+ /**
+ * The relative URI used to import one library from the other.
+ */
String get uri => _uri ?? '';
}
@@ -45,8 +67,11 @@
bool _finished = false;
- PrelinkedDependencyBuilder(builder.BuilderContext context);
+ PrelinkedDependencyBuilder(base.BuilderContext context);
+ /**
+ * The relative URI used to import one library from the other.
+ */
void set uri(String _value) {
assert(!_finished);
assert(!_json.containsKey("uri"));
@@ -62,13 +87,16 @@
}
}
-PrelinkedDependencyBuilder encodePrelinkedDependency(builder.BuilderContext builderContext, {String uri}) {
+PrelinkedDependencyBuilder encodePrelinkedDependency(base.BuilderContext builderContext, {String uri}) {
PrelinkedDependencyBuilder builder = new PrelinkedDependencyBuilder(builderContext);
builder.uri = uri;
return builder;
}
-class PrelinkedLibrary {
+/**
+ * Pre-linked summary of a library.
+ */
+class PrelinkedLibrary extends base.SummaryClass {
List<PrelinkedUnit> _units;
List<PrelinkedDependency> _dependencies;
List<int> _importDependencies;
@@ -78,10 +106,41 @@
_dependencies = json["dependencies"]?.map((x) => new PrelinkedDependency.fromJson(x))?.toList(),
_importDependencies = json["importDependencies"];
+ @override
+ Map<String, Object> toMap() => {
+ "units": units,
+ "dependencies": dependencies,
+ "importDependencies": importDependencies,
+ };
+
PrelinkedLibrary.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UTF8.decode(buffer)));
+ /**
+ * The pre-linked summary of all the compilation units constituting the
+ * library. The summary of the defining compilation unit is listed first,
+ * followed by the summary of each part, in the order of the `part`
+ * declarations in the defining compilation unit.
+ */
List<PrelinkedUnit> get units => _units ?? const <PrelinkedUnit>[];
+
+ /**
+ * The libraries that this library depends on (either via an explicit import
+ * statement or via the implicit dependencies on `dart:core` and
+ * `dart:async`). The first element of this array is a pseudo-dependency
+ * representing the library itself (it is also used for "dynamic").
+ *
+ * TODO(paulberry): consider removing this entirely and just using
+ * [UnlinkedLibrary.imports].
+ */
List<PrelinkedDependency> get dependencies => _dependencies ?? const <PrelinkedDependency>[];
+
+ /**
+ * For each import in [UnlinkedUnit.imports], an index into [dependencies]
+ * of the library being imported.
+ *
+ * TODO(paulberry): if [dependencies] is removed, this can be removed as
+ * well, since there will effectively be a one-to-one mapping.
+ */
List<int> get importDependencies => _importDependencies ?? const <int>[];
}
@@ -90,28 +149,50 @@
bool _finished = false;
- PrelinkedLibraryBuilder(builder.BuilderContext context);
+ PrelinkedLibraryBuilder(base.BuilderContext context);
+ /**
+ * The pre-linked summary of all the compilation units constituting the
+ * library. The summary of the defining compilation unit is listed first,
+ * followed by the summary of each part, in the order of the `part`
+ * declarations in the defining compilation unit.
+ */
void set units(List<PrelinkedUnitBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("units"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["units"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * The libraries that this library depends on (either via an explicit import
+ * statement or via the implicit dependencies on `dart:core` and
+ * `dart:async`). The first element of this array is a pseudo-dependency
+ * representing the library itself (it is also used for "dynamic").
+ *
+ * TODO(paulberry): consider removing this entirely and just using
+ * [UnlinkedLibrary.imports].
+ */
void set dependencies(List<PrelinkedDependencyBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("dependencies"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["dependencies"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * For each import in [UnlinkedUnit.imports], an index into [dependencies]
+ * of the library being imported.
+ *
+ * TODO(paulberry): if [dependencies] is removed, this can be removed as
+ * well, since there will effectively be a one-to-one mapping.
+ */
void set importDependencies(List<int> _value) {
assert(!_finished);
assert(!_json.containsKey("importDependencies"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["importDependencies"] = _value.toList();
}
}
@@ -125,7 +206,7 @@
}
}
-PrelinkedLibraryBuilder encodePrelinkedLibrary(builder.BuilderContext builderContext, {List<PrelinkedUnitBuilder> units, List<PrelinkedDependencyBuilder> dependencies, List<int> importDependencies}) {
+PrelinkedLibraryBuilder encodePrelinkedLibrary(base.BuilderContext builderContext, {List<PrelinkedUnitBuilder> units, List<PrelinkedDependencyBuilder> dependencies, List<int> importDependencies}) {
PrelinkedLibraryBuilder builder = new PrelinkedLibraryBuilder(builderContext);
builder.units = units;
builder.dependencies = dependencies;
@@ -133,19 +214,54 @@
return builder;
}
-class PrelinkedReference {
+/**
+ * Information about the resolution of an [UnlinkedReference].
+ */
+class PrelinkedReference extends base.SummaryClass {
int _dependency;
PrelinkedReferenceKind _kind;
int _unit;
+ int _numTypeParameters;
PrelinkedReference.fromJson(Map json)
: _dependency = json["dependency"],
_kind = json["kind"] == null ? null : PrelinkedReferenceKind.values[json["kind"]],
- _unit = json["unit"];
+ _unit = json["unit"],
+ _numTypeParameters = json["numTypeParameters"];
+ @override
+ Map<String, Object> toMap() => {
+ "dependency": dependency,
+ "kind": kind,
+ "unit": unit,
+ "numTypeParameters": numTypeParameters,
+ };
+
+ /**
+ * Index into [PrelinkedLibrary.dependencies] indicating which imported library
+ * declares the entity being referred to.
+ */
int get dependency => _dependency ?? 0;
+
+ /**
+ * The kind of the entity being referred to. For the pseudo-type `dynamic`,
+ * the kind is [PrelinkedReferenceKind.classOrEnum].
+ */
PrelinkedReferenceKind get kind => _kind ?? PrelinkedReferenceKind.classOrEnum;
+
+ /**
+ * Integer index indicating which unit in the imported library contains the
+ * definition of the entity. As with indices into [PrelinkedLibrary.units],
+ * zero represents the defining compilation unit, and nonzero values
+ * represent parts in the order of the corresponding `part` declarations.
+ */
int get unit => _unit ?? 0;
+
+ /**
+ * If the entity being referred to is generic, the number of type parameters
+ * it accepts. Otherwise zero.
+ */
+ int get numTypeParameters => _numTypeParameters ?? 0;
}
class PrelinkedReferenceBuilder {
@@ -153,8 +269,12 @@
bool _finished = false;
- PrelinkedReferenceBuilder(builder.BuilderContext context);
+ PrelinkedReferenceBuilder(base.BuilderContext context);
+ /**
+ * Index into [PrelinkedLibrary.dependencies] indicating which imported library
+ * declares the entity being referred to.
+ */
void set dependency(int _value) {
assert(!_finished);
assert(!_json.containsKey("dependency"));
@@ -163,14 +283,24 @@
}
}
+ /**
+ * The kind of the entity being referred to. For the pseudo-type `dynamic`,
+ * the kind is [PrelinkedReferenceKind.classOrEnum].
+ */
void set kind(PrelinkedReferenceKind _value) {
assert(!_finished);
assert(!_json.containsKey("kind"));
- if (_value != null || _value == PrelinkedReferenceKind.classOrEnum) {
+ if (!(_value == null || _value == PrelinkedReferenceKind.classOrEnum)) {
_json["kind"] = _value.index;
}
}
+ /**
+ * Integer index indicating which unit in the imported library contains the
+ * definition of the entity. As with indices into [PrelinkedLibrary.units],
+ * zero represents the defining compilation unit, and nonzero values
+ * represent parts in the order of the corresponding `part` declarations.
+ */
void set unit(int _value) {
assert(!_finished);
assert(!_json.containsKey("unit"));
@@ -179,6 +309,18 @@
}
}
+ /**
+ * If the entity being referred to is generic, the number of type parameters
+ * it accepts. Otherwise zero.
+ */
+ void set numTypeParameters(int _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("numTypeParameters"));
+ if (_value != null) {
+ _json["numTypeParameters"] = _value;
+ }
+ }
+
Map finish() {
assert(!_finished);
_finished = true;
@@ -186,20 +328,33 @@
}
}
-PrelinkedReferenceBuilder encodePrelinkedReference(builder.BuilderContext builderContext, {int dependency, PrelinkedReferenceKind kind, int unit}) {
+PrelinkedReferenceBuilder encodePrelinkedReference(base.BuilderContext builderContext, {int dependency, PrelinkedReferenceKind kind, int unit, int numTypeParameters}) {
PrelinkedReferenceBuilder builder = new PrelinkedReferenceBuilder(builderContext);
builder.dependency = dependency;
builder.kind = kind;
builder.unit = unit;
+ builder.numTypeParameters = numTypeParameters;
return builder;
}
-class PrelinkedUnit {
+/**
+ * Pre-linked summary of a compilation unit.
+ */
+class PrelinkedUnit extends base.SummaryClass {
List<PrelinkedReference> _references;
PrelinkedUnit.fromJson(Map json)
: _references = json["references"]?.map((x) => new PrelinkedReference.fromJson(x))?.toList();
+ @override
+ Map<String, Object> toMap() => {
+ "references": references,
+ };
+
+ /**
+ * For each reference in [UnlinkedUnit.references], information about how
+ * that reference is resolved.
+ */
List<PrelinkedReference> get references => _references ?? const <PrelinkedReference>[];
}
@@ -208,12 +363,16 @@
bool _finished = false;
- PrelinkedUnitBuilder(builder.BuilderContext context);
+ PrelinkedUnitBuilder(base.BuilderContext context);
+ /**
+ * For each reference in [UnlinkedUnit.references], information about how
+ * that reference is resolved.
+ */
void set references(List<PrelinkedReferenceBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("references"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["references"] = _value.map((b) => b.finish()).toList();
}
}
@@ -225,13 +384,131 @@
}
}
-PrelinkedUnitBuilder encodePrelinkedUnit(builder.BuilderContext builderContext, {List<PrelinkedReferenceBuilder> references}) {
+PrelinkedUnitBuilder encodePrelinkedUnit(base.BuilderContext builderContext, {List<PrelinkedReferenceBuilder> references}) {
PrelinkedUnitBuilder builder = new PrelinkedUnitBuilder(builderContext);
builder.references = references;
return builder;
}
-class UnlinkedClass {
+/**
+ * Information about SDK.
+ */
+class SdkBundle extends base.SummaryClass {
+ List<String> _prelinkedLibraryUris;
+ List<PrelinkedLibrary> _prelinkedLibraries;
+ List<String> _unlinkedUnitUris;
+ List<UnlinkedUnit> _unlinkedUnits;
+
+ SdkBundle.fromJson(Map json)
+ : _prelinkedLibraryUris = json["prelinkedLibraryUris"],
+ _prelinkedLibraries = json["prelinkedLibraries"]?.map((x) => new PrelinkedLibrary.fromJson(x))?.toList(),
+ _unlinkedUnitUris = json["unlinkedUnitUris"],
+ _unlinkedUnits = json["unlinkedUnits"]?.map((x) => new UnlinkedUnit.fromJson(x))?.toList();
+
+ @override
+ Map<String, Object> toMap() => {
+ "prelinkedLibraryUris": prelinkedLibraryUris,
+ "prelinkedLibraries": prelinkedLibraries,
+ "unlinkedUnitUris": unlinkedUnitUris,
+ "unlinkedUnits": unlinkedUnits,
+ };
+
+ SdkBundle.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UTF8.decode(buffer)));
+
+ /**
+ * The list of URIs of items in [prelinkedLibraries], e.g. `dart:core`.
+ */
+ List<String> get prelinkedLibraryUris => _prelinkedLibraryUris ?? const <String>[];
+
+ /**
+ * Pre-linked libraries.
+ */
+ List<PrelinkedLibrary> get prelinkedLibraries => _prelinkedLibraries ?? const <PrelinkedLibrary>[];
+
+ /**
+ * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
+ */
+ List<String> get unlinkedUnitUris => _unlinkedUnitUris ?? const <String>[];
+
+ /**
+ * Unlinked information for the compilation units constituting the SDK.
+ */
+ List<UnlinkedUnit> get unlinkedUnits => _unlinkedUnits ?? const <UnlinkedUnit>[];
+}
+
+class SdkBundleBuilder {
+ final Map _json = {};
+
+ bool _finished = false;
+
+ SdkBundleBuilder(base.BuilderContext context);
+
+ /**
+ * The list of URIs of items in [prelinkedLibraries], e.g. `dart:core`.
+ */
+ void set prelinkedLibraryUris(List<String> _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("prelinkedLibraryUris"));
+ if (!(_value == null || _value.isEmpty)) {
+ _json["prelinkedLibraryUris"] = _value.toList();
+ }
+ }
+
+ /**
+ * Pre-linked libraries.
+ */
+ void set prelinkedLibraries(List<PrelinkedLibraryBuilder> _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("prelinkedLibraries"));
+ if (!(_value == null || _value.isEmpty)) {
+ _json["prelinkedLibraries"] = _value.map((b) => b.finish()).toList();
+ }
+ }
+
+ /**
+ * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
+ */
+ void set unlinkedUnitUris(List<String> _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("unlinkedUnitUris"));
+ if (!(_value == null || _value.isEmpty)) {
+ _json["unlinkedUnitUris"] = _value.toList();
+ }
+ }
+
+ /**
+ * Unlinked information for the compilation units constituting the SDK.
+ */
+ void set unlinkedUnits(List<UnlinkedUnitBuilder> _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("unlinkedUnits"));
+ if (!(_value == null || _value.isEmpty)) {
+ _json["unlinkedUnits"] = _value.map((b) => b.finish()).toList();
+ }
+ }
+
+ List<int> toBuffer() => UTF8.encode(JSON.encode(finish()));
+
+ Map finish() {
+ assert(!_finished);
+ _finished = true;
+ return _json;
+ }
+}
+
+SdkBundleBuilder encodeSdkBundle(base.BuilderContext builderContext, {List<String> prelinkedLibraryUris, List<PrelinkedLibraryBuilder> prelinkedLibraries, List<String> unlinkedUnitUris, List<UnlinkedUnitBuilder> unlinkedUnits}) {
+ SdkBundleBuilder builder = new SdkBundleBuilder(builderContext);
+ builder.prelinkedLibraryUris = prelinkedLibraryUris;
+ builder.prelinkedLibraries = prelinkedLibraries;
+ builder.unlinkedUnitUris = unlinkedUnitUris;
+ builder.unlinkedUnits = unlinkedUnits;
+ return builder;
+}
+
+/**
+ * Unlinked summary information about a class declaration.
+ */
+class UnlinkedClass extends base.SummaryClass {
String _name;
List<UnlinkedTypeParam> _typeParameters;
UnlinkedTypeRef _supertype;
@@ -255,15 +532,71 @@
_isMixinApplication = json["isMixinApplication"],
_hasNoSupertype = json["hasNoSupertype"];
+ @override
+ Map<String, Object> toMap() => {
+ "name": name,
+ "typeParameters": typeParameters,
+ "supertype": supertype,
+ "mixins": mixins,
+ "interfaces": interfaces,
+ "fields": fields,
+ "executables": executables,
+ "isAbstract": isAbstract,
+ "isMixinApplication": isMixinApplication,
+ "hasNoSupertype": hasNoSupertype,
+ };
+
+ /**
+ * Name of the class.
+ */
String get name => _name ?? '';
+
+ /**
+ * Type parameters of the class, if any.
+ */
List<UnlinkedTypeParam> get typeParameters => _typeParameters ?? const <UnlinkedTypeParam>[];
+
+ /**
+ * Supertype of the class, or `null` if either (a) the class doesn't
+ * explicitly declare a supertype (and hence has supertype `Object`), or (b)
+ * the class *is* `Object` (and hence has no supertype).
+ */
UnlinkedTypeRef get supertype => _supertype;
+
+ /**
+ * Mixins appearing in a `with` clause, if any.
+ */
List<UnlinkedTypeRef> get mixins => _mixins ?? const <UnlinkedTypeRef>[];
+
+ /**
+ * Interfaces appearing in an `implements` clause, if any.
+ */
List<UnlinkedTypeRef> get interfaces => _interfaces ?? const <UnlinkedTypeRef>[];
+
+ /**
+ * Field declarations contained in the class.
+ */
List<UnlinkedVariable> get fields => _fields ?? const <UnlinkedVariable>[];
+
+ /**
+ * Executable objects (methods, getters, and setters) contained in the class.
+ */
List<UnlinkedExecutable> get executables => _executables ?? const <UnlinkedExecutable>[];
+
+ /**
+ * Indicates whether the class is declared with the `abstract` keyword.
+ */
bool get isAbstract => _isAbstract ?? false;
+
+ /**
+ * Indicates whether the class is declared using mixin application syntax.
+ */
bool get isMixinApplication => _isMixinApplication ?? false;
+
+ /**
+ * Indicates whether this class is the core "Object" class (and hence has no
+ * supertype)
+ */
bool get hasNoSupertype => _hasNoSupertype ?? false;
}
@@ -272,8 +605,11 @@
bool _finished = false;
- UnlinkedClassBuilder(builder.BuilderContext context);
+ UnlinkedClassBuilder(base.BuilderContext context);
+ /**
+ * Name of the class.
+ */
void set name(String _value) {
assert(!_finished);
assert(!_json.containsKey("name"));
@@ -282,14 +618,22 @@
}
}
+ /**
+ * Type parameters of the class, if any.
+ */
void set typeParameters(List<UnlinkedTypeParamBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("typeParameters"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["typeParameters"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Supertype of the class, or `null` if either (a) the class doesn't
+ * explicitly declare a supertype (and hence has supertype `Object`), or (b)
+ * the class *is* `Object` (and hence has no supertype).
+ */
void set supertype(UnlinkedTypeRefBuilder _value) {
assert(!_finished);
assert(!_json.containsKey("supertype"));
@@ -298,38 +642,53 @@
}
}
+ /**
+ * Mixins appearing in a `with` clause, if any.
+ */
void set mixins(List<UnlinkedTypeRefBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("mixins"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["mixins"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Interfaces appearing in an `implements` clause, if any.
+ */
void set interfaces(List<UnlinkedTypeRefBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("interfaces"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["interfaces"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Field declarations contained in the class.
+ */
void set fields(List<UnlinkedVariableBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("fields"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["fields"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Executable objects (methods, getters, and setters) contained in the class.
+ */
void set executables(List<UnlinkedExecutableBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("executables"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["executables"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Indicates whether the class is declared with the `abstract` keyword.
+ */
void set isAbstract(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isAbstract"));
@@ -338,6 +697,9 @@
}
}
+ /**
+ * Indicates whether the class is declared using mixin application syntax.
+ */
void set isMixinApplication(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isMixinApplication"));
@@ -346,6 +708,10 @@
}
}
+ /**
+ * Indicates whether this class is the core "Object" class (and hence has no
+ * supertype)
+ */
void set hasNoSupertype(bool _value) {
assert(!_finished);
assert(!_json.containsKey("hasNoSupertype"));
@@ -361,7 +727,7 @@
}
}
-UnlinkedClassBuilder encodeUnlinkedClass(builder.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder supertype, List<UnlinkedTypeRefBuilder> mixins, List<UnlinkedTypeRefBuilder> interfaces, List<UnlinkedVariableBuilder> fields, List<UnlinkedExecutableBuilder> executables, bool isAbstract, bool isMixinApplication, bool hasNoSupertype}) {
+UnlinkedClassBuilder encodeUnlinkedClass(base.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder supertype, List<UnlinkedTypeRefBuilder> mixins, List<UnlinkedTypeRefBuilder> interfaces, List<UnlinkedVariableBuilder> fields, List<UnlinkedExecutableBuilder> executables, bool isAbstract, bool isMixinApplication, bool hasNoSupertype}) {
UnlinkedClassBuilder builder = new UnlinkedClassBuilder(builderContext);
builder.name = name;
builder.typeParameters = typeParameters;
@@ -376,16 +742,33 @@
return builder;
}
-class UnlinkedCombinator {
- List<UnlinkedCombinatorName> _shows;
- List<UnlinkedCombinatorName> _hides;
+/**
+ * Unlinked summary information about a `show` or `hide` combinator in an
+ * import or export declaration.
+ */
+class UnlinkedCombinator extends base.SummaryClass {
+ List<String> _shows;
+ List<String> _hides;
UnlinkedCombinator.fromJson(Map json)
- : _shows = json["shows"]?.map((x) => new UnlinkedCombinatorName.fromJson(x))?.toList(),
- _hides = json["hides"]?.map((x) => new UnlinkedCombinatorName.fromJson(x))?.toList();
+ : _shows = json["shows"],
+ _hides = json["hides"];
- List<UnlinkedCombinatorName> get shows => _shows ?? const <UnlinkedCombinatorName>[];
- List<UnlinkedCombinatorName> get hides => _hides ?? const <UnlinkedCombinatorName>[];
+ @override
+ Map<String, Object> toMap() => {
+ "shows": shows,
+ "hides": hides,
+ };
+
+ /**
+ * List of names which are shown. Empty if this is a `hide` combinator.
+ */
+ List<String> get shows => _shows ?? const <String>[];
+
+ /**
+ * List of names which are hidden. Empty if this is a `show` combinator.
+ */
+ List<String> get hides => _hides ?? const <String>[];
}
class UnlinkedCombinatorBuilder {
@@ -393,21 +776,27 @@
bool _finished = false;
- UnlinkedCombinatorBuilder(builder.BuilderContext context);
+ UnlinkedCombinatorBuilder(base.BuilderContext context);
- void set shows(List<UnlinkedCombinatorNameBuilder> _value) {
+ /**
+ * List of names which are shown. Empty if this is a `hide` combinator.
+ */
+ void set shows(List<String> _value) {
assert(!_finished);
assert(!_json.containsKey("shows"));
- if (_value != null || _value.isEmpty) {
- _json["shows"] = _value.map((b) => b.finish()).toList();
+ if (!(_value == null || _value.isEmpty)) {
+ _json["shows"] = _value.toList();
}
}
- void set hides(List<UnlinkedCombinatorNameBuilder> _value) {
+ /**
+ * List of names which are hidden. Empty if this is a `show` combinator.
+ */
+ void set hides(List<String> _value) {
assert(!_finished);
assert(!_json.containsKey("hides"));
- if (_value != null || _value.isEmpty) {
- _json["hides"] = _value.map((b) => b.finish()).toList();
+ if (!(_value == null || _value.isEmpty)) {
+ _json["hides"] = _value.toList();
}
}
@@ -418,51 +807,17 @@
}
}
-UnlinkedCombinatorBuilder encodeUnlinkedCombinator(builder.BuilderContext builderContext, {List<UnlinkedCombinatorNameBuilder> shows, List<UnlinkedCombinatorNameBuilder> hides}) {
+UnlinkedCombinatorBuilder encodeUnlinkedCombinator(base.BuilderContext builderContext, {List<String> shows, List<String> hides}) {
UnlinkedCombinatorBuilder builder = new UnlinkedCombinatorBuilder(builderContext);
builder.shows = shows;
builder.hides = hides;
return builder;
}
-class UnlinkedCombinatorName {
- String _name;
-
- UnlinkedCombinatorName.fromJson(Map json)
- : _name = json["name"];
-
- String get name => _name ?? '';
-}
-
-class UnlinkedCombinatorNameBuilder {
- final Map _json = {};
-
- bool _finished = false;
-
- UnlinkedCombinatorNameBuilder(builder.BuilderContext context);
-
- void set name(String _value) {
- assert(!_finished);
- assert(!_json.containsKey("name"));
- if (_value != null) {
- _json["name"] = _value;
- }
- }
-
- Map finish() {
- assert(!_finished);
- _finished = true;
- return _json;
- }
-}
-
-UnlinkedCombinatorNameBuilder encodeUnlinkedCombinatorName(builder.BuilderContext builderContext, {String name}) {
- UnlinkedCombinatorNameBuilder builder = new UnlinkedCombinatorNameBuilder(builderContext);
- builder.name = name;
- return builder;
-}
-
-class UnlinkedEnum {
+/**
+ * Unlinked summary information about an enum declaration.
+ */
+class UnlinkedEnum extends base.SummaryClass {
String _name;
List<UnlinkedEnumValue> _values;
@@ -470,7 +825,20 @@
: _name = json["name"],
_values = json["values"]?.map((x) => new UnlinkedEnumValue.fromJson(x))?.toList();
+ @override
+ Map<String, Object> toMap() => {
+ "name": name,
+ "values": values,
+ };
+
+ /**
+ * Name of the enum type.
+ */
String get name => _name ?? '';
+
+ /**
+ * Values listed in the enum declaration, in declaration order.
+ */
List<UnlinkedEnumValue> get values => _values ?? const <UnlinkedEnumValue>[];
}
@@ -479,8 +847,11 @@
bool _finished = false;
- UnlinkedEnumBuilder(builder.BuilderContext context);
+ UnlinkedEnumBuilder(base.BuilderContext context);
+ /**
+ * Name of the enum type.
+ */
void set name(String _value) {
assert(!_finished);
assert(!_json.containsKey("name"));
@@ -489,10 +860,13 @@
}
}
+ /**
+ * Values listed in the enum declaration, in declaration order.
+ */
void set values(List<UnlinkedEnumValueBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("values"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["values"] = _value.map((b) => b.finish()).toList();
}
}
@@ -504,19 +878,31 @@
}
}
-UnlinkedEnumBuilder encodeUnlinkedEnum(builder.BuilderContext builderContext, {String name, List<UnlinkedEnumValueBuilder> values}) {
+UnlinkedEnumBuilder encodeUnlinkedEnum(base.BuilderContext builderContext, {String name, List<UnlinkedEnumValueBuilder> values}) {
UnlinkedEnumBuilder builder = new UnlinkedEnumBuilder(builderContext);
builder.name = name;
builder.values = values;
return builder;
}
-class UnlinkedEnumValue {
+/**
+ * Unlinked summary information about a single enumerated value in an enum
+ * declaration.
+ */
+class UnlinkedEnumValue extends base.SummaryClass {
String _name;
UnlinkedEnumValue.fromJson(Map json)
: _name = json["name"];
+ @override
+ Map<String, Object> toMap() => {
+ "name": name,
+ };
+
+ /**
+ * Name of the enumerated value.
+ */
String get name => _name ?? '';
}
@@ -525,8 +911,11 @@
bool _finished = false;
- UnlinkedEnumValueBuilder(builder.BuilderContext context);
+ UnlinkedEnumValueBuilder(base.BuilderContext context);
+ /**
+ * Name of the enumerated value.
+ */
void set name(String _value) {
assert(!_finished);
assert(!_json.containsKey("name"));
@@ -542,13 +931,17 @@
}
}
-UnlinkedEnumValueBuilder encodeUnlinkedEnumValue(builder.BuilderContext builderContext, {String name}) {
+UnlinkedEnumValueBuilder encodeUnlinkedEnumValue(base.BuilderContext builderContext, {String name}) {
UnlinkedEnumValueBuilder builder = new UnlinkedEnumValueBuilder(builderContext);
builder.name = name;
return builder;
}
-class UnlinkedExecutable {
+/**
+ * Unlinked summary information about a function, method, getter, or setter
+ * declaration.
+ */
+class UnlinkedExecutable extends base.SummaryClass {
String _name;
List<UnlinkedTypeParam> _typeParameters;
UnlinkedTypeRef _returnType;
@@ -574,16 +967,87 @@
_hasImplicitReturnType = json["hasImplicitReturnType"],
_isExternal = json["isExternal"];
+ @override
+ Map<String, Object> toMap() => {
+ "name": name,
+ "typeParameters": typeParameters,
+ "returnType": returnType,
+ "parameters": parameters,
+ "kind": kind,
+ "isAbstract": isAbstract,
+ "isStatic": isStatic,
+ "isConst": isConst,
+ "isFactory": isFactory,
+ "hasImplicitReturnType": hasImplicitReturnType,
+ "isExternal": isExternal,
+ };
+
+ /**
+ * Name of the executable. For setters, this includes the trailing "=". For
+ * named constructors, this excludes the class name and excludes the ".".
+ * For unnamed constructors, this is the empty string.
+ */
String get name => _name ?? '';
+
+ /**
+ * Type parameters of the executable, if any. Empty if support for generic
+ * method syntax is disabled.
+ */
List<UnlinkedTypeParam> get typeParameters => _typeParameters ?? const <UnlinkedTypeParam>[];
+
+ /**
+ * Declared return type of the executable. Absent if the return type is
+ * `void`. Note that when strong mode is enabled, the actual return type may
+ * be different due to type inference.
+ */
UnlinkedTypeRef get returnType => _returnType;
+
+ /**
+ * Parameters of the executable, if any. Note that getters have no
+ * parameters (hence this will be the empty list), and setters have a single
+ * parameter.
+ */
List<UnlinkedParam> get parameters => _parameters ?? const <UnlinkedParam>[];
+
+ /**
+ * The kind of the executable (function/method, getter, setter, or
+ * constructor).
+ */
UnlinkedExecutableKind get kind => _kind ?? UnlinkedExecutableKind.functionOrMethod;
+
+ /**
+ * Indicates whether the executable is declared using the `abstract` keyword.
+ */
bool get isAbstract => _isAbstract ?? false;
+
+ /**
+ * Indicates whether the executable is declared using the `static` keyword.
+ *
+ * Note that for top level executables, this flag is false, since they are
+ * not declared using the `static` keyword (even though they are considered
+ * static for semantic purposes).
+ */
bool get isStatic => _isStatic ?? false;
+
+ /**
+ * Indicates whether the executable is declared using the `const` keyword.
+ */
bool get isConst => _isConst ?? false;
+
+ /**
+ * Indicates whether the executable is declared using the `factory` keyword.
+ */
bool get isFactory => _isFactory ?? false;
+
+ /**
+ * Indicates whether the executable lacks an explicit return type
+ * declaration. False for constructors and setters.
+ */
bool get hasImplicitReturnType => _hasImplicitReturnType ?? false;
+
+ /**
+ * Indicates whether the executable is declared using the `external` keyword.
+ */
bool get isExternal => _isExternal ?? false;
}
@@ -592,8 +1056,13 @@
bool _finished = false;
- UnlinkedExecutableBuilder(builder.BuilderContext context);
+ UnlinkedExecutableBuilder(base.BuilderContext context);
+ /**
+ * Name of the executable. For setters, this includes the trailing "=". For
+ * named constructors, this excludes the class name and excludes the ".".
+ * For unnamed constructors, this is the empty string.
+ */
void set name(String _value) {
assert(!_finished);
assert(!_json.containsKey("name"));
@@ -602,14 +1071,23 @@
}
}
+ /**
+ * Type parameters of the executable, if any. Empty if support for generic
+ * method syntax is disabled.
+ */
void set typeParameters(List<UnlinkedTypeParamBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("typeParameters"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["typeParameters"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Declared return type of the executable. Absent if the return type is
+ * `void`. Note that when strong mode is enabled, the actual return type may
+ * be different due to type inference.
+ */
void set returnType(UnlinkedTypeRefBuilder _value) {
assert(!_finished);
assert(!_json.containsKey("returnType"));
@@ -618,22 +1096,34 @@
}
}
+ /**
+ * Parameters of the executable, if any. Note that getters have no
+ * parameters (hence this will be the empty list), and setters have a single
+ * parameter.
+ */
void set parameters(List<UnlinkedParamBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("parameters"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["parameters"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * The kind of the executable (function/method, getter, setter, or
+ * constructor).
+ */
void set kind(UnlinkedExecutableKind _value) {
assert(!_finished);
assert(!_json.containsKey("kind"));
- if (_value != null || _value == UnlinkedExecutableKind.functionOrMethod) {
+ if (!(_value == null || _value == UnlinkedExecutableKind.functionOrMethod)) {
_json["kind"] = _value.index;
}
}
+ /**
+ * Indicates whether the executable is declared using the `abstract` keyword.
+ */
void set isAbstract(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isAbstract"));
@@ -642,6 +1132,13 @@
}
}
+ /**
+ * Indicates whether the executable is declared using the `static` keyword.
+ *
+ * Note that for top level executables, this flag is false, since they are
+ * not declared using the `static` keyword (even though they are considered
+ * static for semantic purposes).
+ */
void set isStatic(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isStatic"));
@@ -650,6 +1147,9 @@
}
}
+ /**
+ * Indicates whether the executable is declared using the `const` keyword.
+ */
void set isConst(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isConst"));
@@ -658,6 +1158,9 @@
}
}
+ /**
+ * Indicates whether the executable is declared using the `factory` keyword.
+ */
void set isFactory(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isFactory"));
@@ -666,6 +1169,10 @@
}
}
+ /**
+ * Indicates whether the executable lacks an explicit return type
+ * declaration. False for constructors and setters.
+ */
void set hasImplicitReturnType(bool _value) {
assert(!_finished);
assert(!_json.containsKey("hasImplicitReturnType"));
@@ -674,6 +1181,9 @@
}
}
+ /**
+ * Indicates whether the executable is declared using the `external` keyword.
+ */
void set isExternal(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isExternal"));
@@ -689,7 +1199,7 @@
}
}
-UnlinkedExecutableBuilder encodeUnlinkedExecutable(builder.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder returnType, List<UnlinkedParamBuilder> parameters, UnlinkedExecutableKind kind, bool isAbstract, bool isStatic, bool isConst, bool isFactory, bool hasImplicitReturnType, bool isExternal}) {
+UnlinkedExecutableBuilder encodeUnlinkedExecutable(base.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder returnType, List<UnlinkedParamBuilder> parameters, UnlinkedExecutableKind kind, bool isAbstract, bool isStatic, bool isConst, bool isFactory, bool hasImplicitReturnType, bool isExternal}) {
UnlinkedExecutableBuilder builder = new UnlinkedExecutableBuilder(builderContext);
builder.name = name;
builder.typeParameters = typeParameters;
@@ -705,7 +1215,10 @@
return builder;
}
-class UnlinkedExport {
+/**
+ * Unlinked summary information about an export declaration.
+ */
+class UnlinkedExport extends base.SummaryClass {
String _uri;
List<UnlinkedCombinator> _combinators;
@@ -713,7 +1226,20 @@
: _uri = json["uri"],
_combinators = json["combinators"]?.map((x) => new UnlinkedCombinator.fromJson(x))?.toList();
+ @override
+ Map<String, Object> toMap() => {
+ "uri": uri,
+ "combinators": combinators,
+ };
+
+ /**
+ * URI used in the source code to reference the exported library.
+ */
String get uri => _uri ?? '';
+
+ /**
+ * Combinators contained in this import declaration.
+ */
List<UnlinkedCombinator> get combinators => _combinators ?? const <UnlinkedCombinator>[];
}
@@ -722,8 +1248,11 @@
bool _finished = false;
- UnlinkedExportBuilder(builder.BuilderContext context);
+ UnlinkedExportBuilder(base.BuilderContext context);
+ /**
+ * URI used in the source code to reference the exported library.
+ */
void set uri(String _value) {
assert(!_finished);
assert(!_json.containsKey("uri"));
@@ -732,10 +1261,13 @@
}
}
+ /**
+ * Combinators contained in this import declaration.
+ */
void set combinators(List<UnlinkedCombinatorBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("combinators"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["combinators"] = _value.map((b) => b.finish()).toList();
}
}
@@ -747,14 +1279,17 @@
}
}
-UnlinkedExportBuilder encodeUnlinkedExport(builder.BuilderContext builderContext, {String uri, List<UnlinkedCombinatorBuilder> combinators}) {
+UnlinkedExportBuilder encodeUnlinkedExport(base.BuilderContext builderContext, {String uri, List<UnlinkedCombinatorBuilder> combinators}) {
UnlinkedExportBuilder builder = new UnlinkedExportBuilder(builderContext);
builder.uri = uri;
builder.combinators = combinators;
return builder;
}
-class UnlinkedImport {
+/**
+ * Unlinked summary information about an import declaration.
+ */
+class UnlinkedImport extends base.SummaryClass {
String _uri;
int _offset;
int _prefixReference;
@@ -770,11 +1305,48 @@
_isDeferred = json["isDeferred"],
_isImplicit = json["isImplicit"];
+ @override
+ Map<String, Object> toMap() => {
+ "uri": uri,
+ "offset": offset,
+ "prefixReference": prefixReference,
+ "combinators": combinators,
+ "isDeferred": isDeferred,
+ "isImplicit": isImplicit,
+ };
+
+ /**
+ * URI used in the source code to reference the imported library.
+ */
String get uri => _uri ?? '';
+
+ /**
+ * If [isImplicit] is false, offset of the "import" keyword. If [isImplicit]
+ * is true, zero.
+ */
int get offset => _offset ?? 0;
+
+ /**
+ * Index into [UnlinkedUnit.references] of the prefix declared by this
+ * import declaration, or zero if this import declaration declares no prefix.
+ *
+ * Note that multiple imports can declare the same prefix.
+ */
int get prefixReference => _prefixReference ?? 0;
+
+ /**
+ * Combinators contained in this import declaration.
+ */
List<UnlinkedCombinator> get combinators => _combinators ?? const <UnlinkedCombinator>[];
+
+ /**
+ * Indicates whether the import declaration uses the `deferred` keyword.
+ */
bool get isDeferred => _isDeferred ?? false;
+
+ /**
+ * Indicates whether the import declaration is implicit.
+ */
bool get isImplicit => _isImplicit ?? false;
}
@@ -783,8 +1355,11 @@
bool _finished = false;
- UnlinkedImportBuilder(builder.BuilderContext context);
+ UnlinkedImportBuilder(base.BuilderContext context);
+ /**
+ * URI used in the source code to reference the imported library.
+ */
void set uri(String _value) {
assert(!_finished);
assert(!_json.containsKey("uri"));
@@ -793,6 +1368,10 @@
}
}
+ /**
+ * If [isImplicit] is false, offset of the "import" keyword. If [isImplicit]
+ * is true, zero.
+ */
void set offset(int _value) {
assert(!_finished);
assert(!_json.containsKey("offset"));
@@ -801,6 +1380,12 @@
}
}
+ /**
+ * Index into [UnlinkedUnit.references] of the prefix declared by this
+ * import declaration, or zero if this import declaration declares no prefix.
+ *
+ * Note that multiple imports can declare the same prefix.
+ */
void set prefixReference(int _value) {
assert(!_finished);
assert(!_json.containsKey("prefixReference"));
@@ -809,14 +1394,20 @@
}
}
+ /**
+ * Combinators contained in this import declaration.
+ */
void set combinators(List<UnlinkedCombinatorBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("combinators"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["combinators"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Indicates whether the import declaration uses the `deferred` keyword.
+ */
void set isDeferred(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isDeferred"));
@@ -825,6 +1416,9 @@
}
}
+ /**
+ * Indicates whether the import declaration is implicit.
+ */
void set isImplicit(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isImplicit"));
@@ -840,7 +1434,7 @@
}
}
-UnlinkedImportBuilder encodeUnlinkedImport(builder.BuilderContext builderContext, {String uri, int offset, int prefixReference, List<UnlinkedCombinatorBuilder> combinators, bool isDeferred, bool isImplicit}) {
+UnlinkedImportBuilder encodeUnlinkedImport(base.BuilderContext builderContext, {String uri, int offset, int prefixReference, List<UnlinkedCombinatorBuilder> combinators, bool isDeferred, bool isImplicit}) {
UnlinkedImportBuilder builder = new UnlinkedImportBuilder(builderContext);
builder.uri = uri;
builder.offset = offset;
@@ -851,7 +1445,10 @@
return builder;
}
-class UnlinkedParam {
+/**
+ * Unlinked summary information about a function parameter.
+ */
+class UnlinkedParam extends base.SummaryClass {
String _name;
UnlinkedTypeRef _type;
List<UnlinkedParam> _parameters;
@@ -869,12 +1466,56 @@
_isInitializingFormal = json["isInitializingFormal"],
_hasImplicitType = json["hasImplicitType"];
+ @override
+ Map<String, Object> toMap() => {
+ "name": name,
+ "type": type,
+ "parameters": parameters,
+ "kind": kind,
+ "isFunctionTyped": isFunctionTyped,
+ "isInitializingFormal": isInitializingFormal,
+ "hasImplicitType": hasImplicitType,
+ };
+
+ /**
+ * Name of the parameter.
+ */
String get name => _name ?? '';
+
+ /**
+ * If [isFunctionTyped] is `true`, the declared return type. If
+ * [isFunctionTyped] is `false`, the declared type. Absent if
+ * [isFunctionTyped] is `true` and the declared return type is `void`. Note
+ * that when strong mode is enabled, the actual type may be different due to
+ * type inference.
+ */
UnlinkedTypeRef get type => _type;
+
+ /**
+ * If [isFunctionTyped] is `true`, the parameters of the function type.
+ */
List<UnlinkedParam> get parameters => _parameters ?? const <UnlinkedParam>[];
+
+ /**
+ * Kind of the parameter.
+ */
UnlinkedParamKind get kind => _kind ?? UnlinkedParamKind.required;
+
+ /**
+ * Indicates whether this is a function-typed parameter.
+ */
bool get isFunctionTyped => _isFunctionTyped ?? false;
+
+ /**
+ * Indicates whether this is an initializing formal parameter (i.e. it is
+ * declared using `this.` syntax).
+ */
bool get isInitializingFormal => _isInitializingFormal ?? false;
+
+ /**
+ * Indicates whether this parameter lacks an explicit type declaration.
+ * Always false for a function-typed parameter.
+ */
bool get hasImplicitType => _hasImplicitType ?? false;
}
@@ -883,8 +1524,11 @@
bool _finished = false;
- UnlinkedParamBuilder(builder.BuilderContext context);
+ UnlinkedParamBuilder(base.BuilderContext context);
+ /**
+ * Name of the parameter.
+ */
void set name(String _value) {
assert(!_finished);
assert(!_json.containsKey("name"));
@@ -893,6 +1537,13 @@
}
}
+ /**
+ * If [isFunctionTyped] is `true`, the declared return type. If
+ * [isFunctionTyped] is `false`, the declared type. Absent if
+ * [isFunctionTyped] is `true` and the declared return type is `void`. Note
+ * that when strong mode is enabled, the actual type may be different due to
+ * type inference.
+ */
void set type(UnlinkedTypeRefBuilder _value) {
assert(!_finished);
assert(!_json.containsKey("type"));
@@ -901,22 +1552,31 @@
}
}
+ /**
+ * If [isFunctionTyped] is `true`, the parameters of the function type.
+ */
void set parameters(List<UnlinkedParamBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("parameters"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["parameters"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Kind of the parameter.
+ */
void set kind(UnlinkedParamKind _value) {
assert(!_finished);
assert(!_json.containsKey("kind"));
- if (_value != null || _value == UnlinkedParamKind.required) {
+ if (!(_value == null || _value == UnlinkedParamKind.required)) {
_json["kind"] = _value.index;
}
}
+ /**
+ * Indicates whether this is a function-typed parameter.
+ */
void set isFunctionTyped(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isFunctionTyped"));
@@ -925,6 +1585,10 @@
}
}
+ /**
+ * Indicates whether this is an initializing formal parameter (i.e. it is
+ * declared using `this.` syntax).
+ */
void set isInitializingFormal(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isInitializingFormal"));
@@ -933,6 +1597,10 @@
}
}
+ /**
+ * Indicates whether this parameter lacks an explicit type declaration.
+ * Always false for a function-typed parameter.
+ */
void set hasImplicitType(bool _value) {
assert(!_finished);
assert(!_json.containsKey("hasImplicitType"));
@@ -948,7 +1616,7 @@
}
}
-UnlinkedParamBuilder encodeUnlinkedParam(builder.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder type, List<UnlinkedParamBuilder> parameters, UnlinkedParamKind kind, bool isFunctionTyped, bool isInitializingFormal, bool hasImplicitType}) {
+UnlinkedParamBuilder encodeUnlinkedParam(base.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder type, List<UnlinkedParamBuilder> parameters, UnlinkedParamKind kind, bool isFunctionTyped, bool isInitializingFormal, bool hasImplicitType}) {
UnlinkedParamBuilder builder = new UnlinkedParamBuilder(builderContext);
builder.name = name;
builder.type = type;
@@ -960,12 +1628,23 @@
return builder;
}
-class UnlinkedPart {
+/**
+ * Unlinked summary information about a part declaration.
+ */
+class UnlinkedPart extends base.SummaryClass {
String _uri;
UnlinkedPart.fromJson(Map json)
: _uri = json["uri"];
+ @override
+ Map<String, Object> toMap() => {
+ "uri": uri,
+ };
+
+ /**
+ * String used in the compilation unit to refer to the part file.
+ */
String get uri => _uri ?? '';
}
@@ -974,8 +1653,11 @@
bool _finished = false;
- UnlinkedPartBuilder(builder.BuilderContext context);
+ UnlinkedPartBuilder(base.BuilderContext context);
+ /**
+ * String used in the compilation unit to refer to the part file.
+ */
void set uri(String _value) {
assert(!_finished);
assert(!_json.containsKey("uri"));
@@ -991,31 +1673,61 @@
}
}
-UnlinkedPartBuilder encodeUnlinkedPart(builder.BuilderContext builderContext, {String uri}) {
+UnlinkedPartBuilder encodeUnlinkedPart(base.BuilderContext builderContext, {String uri}) {
UnlinkedPartBuilder builder = new UnlinkedPartBuilder(builderContext);
builder.uri = uri;
return builder;
}
-class UnlinkedReference {
+/**
+ * Unlinked summary information about a specific name contributed by a
+ * compilation unit to a library's public namespace.
+ *
+ * TODO(paulberry): add a count of generic parameters, so that resynthesis
+ * doesn't have to peek into the library to obtain this info.
+ *
+ * TODO(paulberry): for classes, add info about static members and
+ * constructors, since this will be needed to prelink info about constants.
+ *
+ * TODO(paulberry): some of this information is redundant with information
+ * elsewhere in the summary. Consider reducing the redundancy to reduce
+ * summary size.
+ */
+class UnlinkedPublicName extends base.SummaryClass {
String _name;
- int _prefixReference;
+ PrelinkedReferenceKind _kind;
- UnlinkedReference.fromJson(Map json)
+ UnlinkedPublicName.fromJson(Map json)
: _name = json["name"],
- _prefixReference = json["prefixReference"];
+ _kind = json["kind"] == null ? null : PrelinkedReferenceKind.values[json["kind"]];
+ @override
+ Map<String, Object> toMap() => {
+ "name": name,
+ "kind": kind,
+ };
+
+ /**
+ * The name itself.
+ */
String get name => _name ?? '';
- int get prefixReference => _prefixReference ?? 0;
+
+ /**
+ * The kind of object referred to by the name.
+ */
+ PrelinkedReferenceKind get kind => _kind ?? PrelinkedReferenceKind.classOrEnum;
}
-class UnlinkedReferenceBuilder {
+class UnlinkedPublicNameBuilder {
final Map _json = {};
bool _finished = false;
- UnlinkedReferenceBuilder(builder.BuilderContext context);
+ UnlinkedPublicNameBuilder(base.BuilderContext context);
+ /**
+ * The name itself.
+ */
void set name(String _value) {
assert(!_finished);
assert(!_json.containsKey("name"));
@@ -1024,6 +1736,188 @@
}
}
+ /**
+ * The kind of object referred to by the name.
+ */
+ void set kind(PrelinkedReferenceKind _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("kind"));
+ if (!(_value == null || _value == PrelinkedReferenceKind.classOrEnum)) {
+ _json["kind"] = _value.index;
+ }
+ }
+
+ Map finish() {
+ assert(!_finished);
+ _finished = true;
+ return _json;
+ }
+}
+
+UnlinkedPublicNameBuilder encodeUnlinkedPublicName(base.BuilderContext builderContext, {String name, PrelinkedReferenceKind kind}) {
+ UnlinkedPublicNameBuilder builder = new UnlinkedPublicNameBuilder(builderContext);
+ builder.name = name;
+ builder.kind = kind;
+ return builder;
+}
+
+/**
+ * Unlinked summary information about what a compilation unit contributes to a
+ * library's public namespace. This is the subset of [UnlinkedUnit] that is
+ * required from dependent libraries in order to perform prelinking.
+ */
+class UnlinkedPublicNamespace extends base.SummaryClass {
+ List<UnlinkedPublicName> _names;
+ List<UnlinkedExport> _exports;
+ List<UnlinkedPart> _parts;
+
+ UnlinkedPublicNamespace.fromJson(Map json)
+ : _names = json["names"]?.map((x) => new UnlinkedPublicName.fromJson(x))?.toList(),
+ _exports = json["exports"]?.map((x) => new UnlinkedExport.fromJson(x))?.toList(),
+ _parts = json["parts"]?.map((x) => new UnlinkedPart.fromJson(x))?.toList();
+
+ @override
+ Map<String, Object> toMap() => {
+ "names": names,
+ "exports": exports,
+ "parts": parts,
+ };
+
+ UnlinkedPublicNamespace.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UTF8.decode(buffer)));
+
+ /**
+ * Public names defined in the compilation unit.
+ *
+ * TODO(paulberry): consider sorting these names to reduce unnecessary
+ * relinking.
+ */
+ List<UnlinkedPublicName> get names => _names ?? const <UnlinkedPublicName>[];
+
+ /**
+ * Export declarations in the compilation unit.
+ */
+ List<UnlinkedExport> get exports => _exports ?? const <UnlinkedExport>[];
+
+ /**
+ * Part declarations in the compilation unit.
+ */
+ List<UnlinkedPart> get parts => _parts ?? const <UnlinkedPart>[];
+}
+
+class UnlinkedPublicNamespaceBuilder {
+ final Map _json = {};
+
+ bool _finished = false;
+
+ UnlinkedPublicNamespaceBuilder(base.BuilderContext context);
+
+ /**
+ * Public names defined in the compilation unit.
+ *
+ * TODO(paulberry): consider sorting these names to reduce unnecessary
+ * relinking.
+ */
+ void set names(List<UnlinkedPublicNameBuilder> _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("names"));
+ if (!(_value == null || _value.isEmpty)) {
+ _json["names"] = _value.map((b) => b.finish()).toList();
+ }
+ }
+
+ /**
+ * Export declarations in the compilation unit.
+ */
+ void set exports(List<UnlinkedExportBuilder> _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("exports"));
+ if (!(_value == null || _value.isEmpty)) {
+ _json["exports"] = _value.map((b) => b.finish()).toList();
+ }
+ }
+
+ /**
+ * Part declarations in the compilation unit.
+ */
+ void set parts(List<UnlinkedPartBuilder> _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("parts"));
+ if (!(_value == null || _value.isEmpty)) {
+ _json["parts"] = _value.map((b) => b.finish()).toList();
+ }
+ }
+
+ List<int> toBuffer() => UTF8.encode(JSON.encode(finish()));
+
+ Map finish() {
+ assert(!_finished);
+ _finished = true;
+ return _json;
+ }
+}
+
+UnlinkedPublicNamespaceBuilder encodeUnlinkedPublicNamespace(base.BuilderContext builderContext, {List<UnlinkedPublicNameBuilder> names, List<UnlinkedExportBuilder> exports, List<UnlinkedPartBuilder> parts}) {
+ UnlinkedPublicNamespaceBuilder builder = new UnlinkedPublicNamespaceBuilder(builderContext);
+ builder.names = names;
+ builder.exports = exports;
+ builder.parts = parts;
+ return builder;
+}
+
+/**
+ * Unlinked summary information about a name referred to in one library that
+ * might be defined in another.
+ */
+class UnlinkedReference extends base.SummaryClass {
+ String _name;
+ int _prefixReference;
+
+ UnlinkedReference.fromJson(Map json)
+ : _name = json["name"],
+ _prefixReference = json["prefixReference"];
+
+ @override
+ Map<String, Object> toMap() => {
+ "name": name,
+ "prefixReference": prefixReference,
+ };
+
+ /**
+ * Name of the entity being referred to. The empty string refers to the
+ * pseudo-type `dynamic`.
+ */
+ String get name => _name ?? '';
+
+ /**
+ * Prefix used to refer to the entity, or zero if no prefix is used. This is
+ * an index into [UnlinkedUnit.references].
+ */
+ int get prefixReference => _prefixReference ?? 0;
+}
+
+class UnlinkedReferenceBuilder {
+ final Map _json = {};
+
+ bool _finished = false;
+
+ UnlinkedReferenceBuilder(base.BuilderContext context);
+
+ /**
+ * Name of the entity being referred to. The empty string refers to the
+ * pseudo-type `dynamic`.
+ */
+ void set name(String _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("name"));
+ if (_value != null) {
+ _json["name"] = _value;
+ }
+ }
+
+ /**
+ * Prefix used to refer to the entity, or zero if no prefix is used. This is
+ * an index into [UnlinkedUnit.references].
+ */
void set prefixReference(int _value) {
assert(!_finished);
assert(!_json.containsKey("prefixReference"));
@@ -1039,14 +1933,17 @@
}
}
-UnlinkedReferenceBuilder encodeUnlinkedReference(builder.BuilderContext builderContext, {String name, int prefixReference}) {
+UnlinkedReferenceBuilder encodeUnlinkedReference(base.BuilderContext builderContext, {String name, int prefixReference}) {
UnlinkedReferenceBuilder builder = new UnlinkedReferenceBuilder(builderContext);
builder.name = name;
builder.prefixReference = prefixReference;
return builder;
}
-class UnlinkedTypedef {
+/**
+ * Unlinked summary information about a typedef declaration.
+ */
+class UnlinkedTypedef extends base.SummaryClass {
String _name;
List<UnlinkedTypeParam> _typeParameters;
UnlinkedTypeRef _returnType;
@@ -1058,9 +1955,32 @@
_returnType = json["returnType"] == null ? null : new UnlinkedTypeRef.fromJson(json["returnType"]),
_parameters = json["parameters"]?.map((x) => new UnlinkedParam.fromJson(x))?.toList();
+ @override
+ Map<String, Object> toMap() => {
+ "name": name,
+ "typeParameters": typeParameters,
+ "returnType": returnType,
+ "parameters": parameters,
+ };
+
+ /**
+ * Name of the typedef.
+ */
String get name => _name ?? '';
+
+ /**
+ * Type parameters of the typedef, if any.
+ */
List<UnlinkedTypeParam> get typeParameters => _typeParameters ?? const <UnlinkedTypeParam>[];
+
+ /**
+ * Return type of the typedef. Absent if the return type is `void`.
+ */
UnlinkedTypeRef get returnType => _returnType;
+
+ /**
+ * Parameters of the executable, if any.
+ */
List<UnlinkedParam> get parameters => _parameters ?? const <UnlinkedParam>[];
}
@@ -1069,8 +1989,11 @@
bool _finished = false;
- UnlinkedTypedefBuilder(builder.BuilderContext context);
+ UnlinkedTypedefBuilder(base.BuilderContext context);
+ /**
+ * Name of the typedef.
+ */
void set name(String _value) {
assert(!_finished);
assert(!_json.containsKey("name"));
@@ -1079,14 +2002,20 @@
}
}
+ /**
+ * Type parameters of the typedef, if any.
+ */
void set typeParameters(List<UnlinkedTypeParamBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("typeParameters"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["typeParameters"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Return type of the typedef. Absent if the return type is `void`.
+ */
void set returnType(UnlinkedTypeRefBuilder _value) {
assert(!_finished);
assert(!_json.containsKey("returnType"));
@@ -1095,10 +2024,13 @@
}
}
+ /**
+ * Parameters of the executable, if any.
+ */
void set parameters(List<UnlinkedParamBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("parameters"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["parameters"] = _value.map((b) => b.finish()).toList();
}
}
@@ -1110,7 +2042,7 @@
}
}
-UnlinkedTypedefBuilder encodeUnlinkedTypedef(builder.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder returnType, List<UnlinkedParamBuilder> parameters}) {
+UnlinkedTypedefBuilder encodeUnlinkedTypedef(base.BuilderContext builderContext, {String name, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder returnType, List<UnlinkedParamBuilder> parameters}) {
UnlinkedTypedefBuilder builder = new UnlinkedTypedefBuilder(builderContext);
builder.name = name;
builder.typeParameters = typeParameters;
@@ -1119,7 +2051,10 @@
return builder;
}
-class UnlinkedTypeParam {
+/**
+ * Unlinked summary information about a type parameter declaration.
+ */
+class UnlinkedTypeParam extends base.SummaryClass {
String _name;
UnlinkedTypeRef _bound;
@@ -1127,7 +2062,21 @@
: _name = json["name"],
_bound = json["bound"] == null ? null : new UnlinkedTypeRef.fromJson(json["bound"]);
+ @override
+ Map<String, Object> toMap() => {
+ "name": name,
+ "bound": bound,
+ };
+
+ /**
+ * Name of the type parameter.
+ */
String get name => _name ?? '';
+
+ /**
+ * Bound of the type parameter, if a bound is explicitly declared. Otherwise
+ * null.
+ */
UnlinkedTypeRef get bound => _bound;
}
@@ -1136,8 +2085,11 @@
bool _finished = false;
- UnlinkedTypeParamBuilder(builder.BuilderContext context);
+ UnlinkedTypeParamBuilder(base.BuilderContext context);
+ /**
+ * Name of the type parameter.
+ */
void set name(String _value) {
assert(!_finished);
assert(!_json.containsKey("name"));
@@ -1146,6 +2098,10 @@
}
}
+ /**
+ * Bound of the type parameter, if a bound is explicitly declared. Otherwise
+ * null.
+ */
void set bound(UnlinkedTypeRefBuilder _value) {
assert(!_finished);
assert(!_json.containsKey("bound"));
@@ -1161,14 +2117,17 @@
}
}
-UnlinkedTypeParamBuilder encodeUnlinkedTypeParam(builder.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder bound}) {
+UnlinkedTypeParamBuilder encodeUnlinkedTypeParam(base.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder bound}) {
UnlinkedTypeParamBuilder builder = new UnlinkedTypeParamBuilder(builderContext);
builder.name = name;
builder.bound = bound;
return builder;
}
-class UnlinkedTypeRef {
+/**
+ * Unlinked summary information about a reference to a type.
+ */
+class UnlinkedTypeRef extends base.SummaryClass {
int _reference;
int _paramReference;
List<UnlinkedTypeRef> _typeArguments;
@@ -1178,8 +2137,50 @@
_paramReference = json["paramReference"],
_typeArguments = json["typeArguments"]?.map((x) => new UnlinkedTypeRef.fromJson(x))?.toList();
+ @override
+ Map<String, Object> toMap() => {
+ "reference": reference,
+ "paramReference": paramReference,
+ "typeArguments": typeArguments,
+ };
+
+ /**
+ * Index into [UnlinkedUnit.references] for the type being referred to, or
+ * zero if this is a reference to a type parameter.
+ *
+ * Note that since zero is also a valid index into
+ * [UnlinkedUnit.references], we cannot distinguish between references to
+ * type parameters and references to types by checking [reference] against
+ * zero. To distinguish between references to type parameters and references
+ * to types, check whether [paramReference] is zero.
+ */
int get reference => _reference ?? 0;
+
+ /**
+ * If this is a reference to a type parameter, one-based index into the list
+ * of [UnlinkedTypeParam]s currently in effect. Indexing is done using De
+ * Bruijn index conventions; that is, innermost parameters come first, and
+ * if a class or method has multiple parameters, they are indexed from right
+ * to left. So for instance, if the enclosing declaration is
+ *
+ * class C<T,U> {
+ * m<V,W> {
+ * ...
+ * }
+ * }
+ *
+ * Then [paramReference] values of 1, 2, 3, and 4 represent W, V, U, and T,
+ * respectively.
+ *
+ * If the type being referred to is not a type parameter, [paramReference] is
+ * zero.
+ */
int get paramReference => _paramReference ?? 0;
+
+ /**
+ * If this is an instantiation of a generic type, the type arguments used to
+ * instantiate it. Trailing type arguments of type `dynamic` are omitted.
+ */
List<UnlinkedTypeRef> get typeArguments => _typeArguments ?? const <UnlinkedTypeRef>[];
}
@@ -1188,8 +2189,18 @@
bool _finished = false;
- UnlinkedTypeRefBuilder(builder.BuilderContext context);
+ UnlinkedTypeRefBuilder(base.BuilderContext context);
+ /**
+ * Index into [UnlinkedUnit.references] for the type being referred to, or
+ * zero if this is a reference to a type parameter.
+ *
+ * Note that since zero is also a valid index into
+ * [UnlinkedUnit.references], we cannot distinguish between references to
+ * type parameters and references to types by checking [reference] against
+ * zero. To distinguish between references to type parameters and references
+ * to types, check whether [paramReference] is zero.
+ */
void set reference(int _value) {
assert(!_finished);
assert(!_json.containsKey("reference"));
@@ -1198,6 +2209,25 @@
}
}
+ /**
+ * If this is a reference to a type parameter, one-based index into the list
+ * of [UnlinkedTypeParam]s currently in effect. Indexing is done using De
+ * Bruijn index conventions; that is, innermost parameters come first, and
+ * if a class or method has multiple parameters, they are indexed from right
+ * to left. So for instance, if the enclosing declaration is
+ *
+ * class C<T,U> {
+ * m<V,W> {
+ * ...
+ * }
+ * }
+ *
+ * Then [paramReference] values of 1, 2, 3, and 4 represent W, V, U, and T,
+ * respectively.
+ *
+ * If the type being referred to is not a type parameter, [paramReference] is
+ * zero.
+ */
void set paramReference(int _value) {
assert(!_finished);
assert(!_json.containsKey("paramReference"));
@@ -1206,10 +2236,14 @@
}
}
+ /**
+ * If this is an instantiation of a generic type, the type arguments used to
+ * instantiate it. Trailing type arguments of type `dynamic` are omitted.
+ */
void set typeArguments(List<UnlinkedTypeRefBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("typeArguments"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["typeArguments"] = _value.map((b) => b.finish()).toList();
}
}
@@ -1221,7 +2255,7 @@
}
}
-UnlinkedTypeRefBuilder encodeUnlinkedTypeRef(builder.BuilderContext builderContext, {int reference, int paramReference, List<UnlinkedTypeRefBuilder> typeArguments}) {
+UnlinkedTypeRefBuilder encodeUnlinkedTypeRef(base.BuilderContext builderContext, {int reference, int paramReference, List<UnlinkedTypeRefBuilder> typeArguments}) {
UnlinkedTypeRefBuilder builder = new UnlinkedTypeRefBuilder(builderContext);
builder.reference = reference;
builder.paramReference = paramReference;
@@ -1229,41 +2263,92 @@
return builder;
}
-class UnlinkedUnit {
+/**
+ * Unlinked summary information about a compilation unit ("part file").
+ */
+class UnlinkedUnit extends base.SummaryClass {
String _libraryName;
+ UnlinkedPublicNamespace _publicNamespace;
List<UnlinkedReference> _references;
List<UnlinkedClass> _classes;
List<UnlinkedEnum> _enums;
List<UnlinkedExecutable> _executables;
- List<UnlinkedExport> _exports;
List<UnlinkedImport> _imports;
- List<UnlinkedPart> _parts;
List<UnlinkedTypedef> _typedefs;
List<UnlinkedVariable> _variables;
UnlinkedUnit.fromJson(Map json)
: _libraryName = json["libraryName"],
+ _publicNamespace = json["publicNamespace"] == null ? null : new UnlinkedPublicNamespace.fromJson(json["publicNamespace"]),
_references = json["references"]?.map((x) => new UnlinkedReference.fromJson(x))?.toList(),
_classes = json["classes"]?.map((x) => new UnlinkedClass.fromJson(x))?.toList(),
_enums = json["enums"]?.map((x) => new UnlinkedEnum.fromJson(x))?.toList(),
_executables = json["executables"]?.map((x) => new UnlinkedExecutable.fromJson(x))?.toList(),
- _exports = json["exports"]?.map((x) => new UnlinkedExport.fromJson(x))?.toList(),
_imports = json["imports"]?.map((x) => new UnlinkedImport.fromJson(x))?.toList(),
- _parts = json["parts"]?.map((x) => new UnlinkedPart.fromJson(x))?.toList(),
_typedefs = json["typedefs"]?.map((x) => new UnlinkedTypedef.fromJson(x))?.toList(),
_variables = json["variables"]?.map((x) => new UnlinkedVariable.fromJson(x))?.toList();
+ @override
+ Map<String, Object> toMap() => {
+ "libraryName": libraryName,
+ "publicNamespace": publicNamespace,
+ "references": references,
+ "classes": classes,
+ "enums": enums,
+ "executables": executables,
+ "imports": imports,
+ "typedefs": typedefs,
+ "variables": variables,
+ };
+
UnlinkedUnit.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UTF8.decode(buffer)));
+ /**
+ * Name of the library (from a "library" declaration, if present).
+ */
String get libraryName => _libraryName ?? '';
+
+ /**
+ * Unlinked public namespace of this compilation unit.
+ */
+ UnlinkedPublicNamespace get publicNamespace => _publicNamespace;
+
+ /**
+ * Top level and prefixed names referred to by this compilation unit. The
+ * zeroth element of this array is always populated and always represents a
+ * reference to the pseudo-type "dynamic".
+ */
List<UnlinkedReference> get references => _references ?? const <UnlinkedReference>[];
+
+ /**
+ * Classes declared in the compilation unit.
+ */
List<UnlinkedClass> get classes => _classes ?? const <UnlinkedClass>[];
+
+ /**
+ * Enums declared in the compilation unit.
+ */
List<UnlinkedEnum> get enums => _enums ?? const <UnlinkedEnum>[];
+
+ /**
+ * Top level executable objects (functions, getters, and setters) declared in
+ * the compilation unit.
+ */
List<UnlinkedExecutable> get executables => _executables ?? const <UnlinkedExecutable>[];
- List<UnlinkedExport> get exports => _exports ?? const <UnlinkedExport>[];
+
+ /**
+ * Import declarations in the compilation unit.
+ */
List<UnlinkedImport> get imports => _imports ?? const <UnlinkedImport>[];
- List<UnlinkedPart> get parts => _parts ?? const <UnlinkedPart>[];
+
+ /**
+ * Typedefs declared in the compilation unit.
+ */
List<UnlinkedTypedef> get typedefs => _typedefs ?? const <UnlinkedTypedef>[];
+
+ /**
+ * Top level variables declared in the compilation unit.
+ */
List<UnlinkedVariable> get variables => _variables ?? const <UnlinkedVariable>[];
}
@@ -1272,8 +2357,11 @@
bool _finished = false;
- UnlinkedUnitBuilder(builder.BuilderContext context);
+ UnlinkedUnitBuilder(base.BuilderContext context);
+ /**
+ * Name of the library (from a "library" declaration, if present).
+ */
void set libraryName(String _value) {
assert(!_finished);
assert(!_json.containsKey("libraryName"));
@@ -1282,74 +2370,93 @@
}
}
+ /**
+ * Unlinked public namespace of this compilation unit.
+ */
+ void set publicNamespace(UnlinkedPublicNamespaceBuilder _value) {
+ assert(!_finished);
+ assert(!_json.containsKey("publicNamespace"));
+ if (_value != null) {
+ _json["publicNamespace"] = _value.finish();
+ }
+ }
+
+ /**
+ * Top level and prefixed names referred to by this compilation unit. The
+ * zeroth element of this array is always populated and always represents a
+ * reference to the pseudo-type "dynamic".
+ */
void set references(List<UnlinkedReferenceBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("references"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["references"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Classes declared in the compilation unit.
+ */
void set classes(List<UnlinkedClassBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("classes"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["classes"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Enums declared in the compilation unit.
+ */
void set enums(List<UnlinkedEnumBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("enums"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["enums"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Top level executable objects (functions, getters, and setters) declared in
+ * the compilation unit.
+ */
void set executables(List<UnlinkedExecutableBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("executables"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["executables"] = _value.map((b) => b.finish()).toList();
}
}
- void set exports(List<UnlinkedExportBuilder> _value) {
- assert(!_finished);
- assert(!_json.containsKey("exports"));
- if (_value != null || _value.isEmpty) {
- _json["exports"] = _value.map((b) => b.finish()).toList();
- }
- }
-
+ /**
+ * Import declarations in the compilation unit.
+ */
void set imports(List<UnlinkedImportBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("imports"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["imports"] = _value.map((b) => b.finish()).toList();
}
}
- void set parts(List<UnlinkedPartBuilder> _value) {
- assert(!_finished);
- assert(!_json.containsKey("parts"));
- if (_value != null || _value.isEmpty) {
- _json["parts"] = _value.map((b) => b.finish()).toList();
- }
- }
-
+ /**
+ * Typedefs declared in the compilation unit.
+ */
void set typedefs(List<UnlinkedTypedefBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("typedefs"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["typedefs"] = _value.map((b) => b.finish()).toList();
}
}
+ /**
+ * Top level variables declared in the compilation unit.
+ */
void set variables(List<UnlinkedVariableBuilder> _value) {
assert(!_finished);
assert(!_json.containsKey("variables"));
- if (_value != null || _value.isEmpty) {
+ if (!(_value == null || _value.isEmpty)) {
_json["variables"] = _value.map((b) => b.finish()).toList();
}
}
@@ -1363,22 +2470,25 @@
}
}
-UnlinkedUnitBuilder encodeUnlinkedUnit(builder.BuilderContext builderContext, {String libraryName, List<UnlinkedReferenceBuilder> references, List<UnlinkedClassBuilder> classes, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedExportBuilder> exports, List<UnlinkedImportBuilder> imports, List<UnlinkedPartBuilder> parts, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables}) {
+UnlinkedUnitBuilder encodeUnlinkedUnit(base.BuilderContext builderContext, {String libraryName, UnlinkedPublicNamespaceBuilder publicNamespace, List<UnlinkedReferenceBuilder> references, List<UnlinkedClassBuilder> classes, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedImportBuilder> imports, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables}) {
UnlinkedUnitBuilder builder = new UnlinkedUnitBuilder(builderContext);
builder.libraryName = libraryName;
+ builder.publicNamespace = publicNamespace;
builder.references = references;
builder.classes = classes;
builder.enums = enums;
builder.executables = executables;
- builder.exports = exports;
builder.imports = imports;
- builder.parts = parts;
builder.typedefs = typedefs;
builder.variables = variables;
return builder;
}
-class UnlinkedVariable {
+/**
+ * Unlinked summary information about a top level variable, local variable, or
+ * a field.
+ */
+class UnlinkedVariable extends base.SummaryClass {
String _name;
UnlinkedTypeRef _type;
bool _isStatic;
@@ -1394,11 +2504,49 @@
_isConst = json["isConst"],
_hasImplicitType = json["hasImplicitType"];
+ @override
+ Map<String, Object> toMap() => {
+ "name": name,
+ "type": type,
+ "isStatic": isStatic,
+ "isFinal": isFinal,
+ "isConst": isConst,
+ "hasImplicitType": hasImplicitType,
+ };
+
+ /**
+ * Name of the variable.
+ */
String get name => _name ?? '';
+
+ /**
+ * Declared type of the variable. Note that when strong mode is enabled, the
+ * actual type of the variable may be different due to type inference.
+ */
UnlinkedTypeRef get type => _type;
+
+ /**
+ * Indicates whether the variable is declared using the `static` keyword.
+ *
+ * Note that for top level variables, this flag is false, since they are not
+ * declared using the `static` keyword (even though they are considered
+ * static for semantic purposes).
+ */
bool get isStatic => _isStatic ?? false;
+
+ /**
+ * Indicates whether the variable is declared using the `final` keyword.
+ */
bool get isFinal => _isFinal ?? false;
+
+ /**
+ * Indicates whether the variable is declared using the `const` keyword.
+ */
bool get isConst => _isConst ?? false;
+
+ /**
+ * Indicates whether this variable lacks an explicit type declaration.
+ */
bool get hasImplicitType => _hasImplicitType ?? false;
}
@@ -1407,8 +2555,11 @@
bool _finished = false;
- UnlinkedVariableBuilder(builder.BuilderContext context);
+ UnlinkedVariableBuilder(base.BuilderContext context);
+ /**
+ * Name of the variable.
+ */
void set name(String _value) {
assert(!_finished);
assert(!_json.containsKey("name"));
@@ -1417,6 +2568,10 @@
}
}
+ /**
+ * Declared type of the variable. Note that when strong mode is enabled, the
+ * actual type of the variable may be different due to type inference.
+ */
void set type(UnlinkedTypeRefBuilder _value) {
assert(!_finished);
assert(!_json.containsKey("type"));
@@ -1425,6 +2580,13 @@
}
}
+ /**
+ * Indicates whether the variable is declared using the `static` keyword.
+ *
+ * Note that for top level variables, this flag is false, since they are not
+ * declared using the `static` keyword (even though they are considered
+ * static for semantic purposes).
+ */
void set isStatic(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isStatic"));
@@ -1433,6 +2595,9 @@
}
}
+ /**
+ * Indicates whether the variable is declared using the `final` keyword.
+ */
void set isFinal(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isFinal"));
@@ -1441,6 +2606,9 @@
}
}
+ /**
+ * Indicates whether the variable is declared using the `const` keyword.
+ */
void set isConst(bool _value) {
assert(!_finished);
assert(!_json.containsKey("isConst"));
@@ -1449,6 +2617,9 @@
}
}
+ /**
+ * Indicates whether this variable lacks an explicit type declaration.
+ */
void set hasImplicitType(bool _value) {
assert(!_finished);
assert(!_json.containsKey("hasImplicitType"));
@@ -1464,7 +2635,7 @@
}
}
-UnlinkedVariableBuilder encodeUnlinkedVariable(builder.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder type, bool isStatic, bool isFinal, bool isConst, bool hasImplicitType}) {
+UnlinkedVariableBuilder encodeUnlinkedVariable(base.BuilderContext builderContext, {String name, UnlinkedTypeRefBuilder type, bool isStatic, bool isFinal, bool isConst, bool hasImplicitType}) {
UnlinkedVariableBuilder builder = new UnlinkedVariableBuilder(builderContext);
builder.name = name;
builder.type = type;
diff --git a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
new file mode 100644
index 0000000..bd9e3a2
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.src.summary.public_namespace_visitor;
+
+import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/src/summary/base.dart';
+import 'package:analyzer/src/summary/format.dart';
+
+/**
+ * Compute the public namespace portion of the summary for the given [unit],
+ * which is presumed to be an unresolved AST.
+ */
+UnlinkedPublicNamespaceBuilder computePublicNamespace(
+ BuilderContext ctx, CompilationUnit unit) {
+ _PublicNamespaceVisitor visitor = new _PublicNamespaceVisitor(ctx);
+ unit.accept(visitor);
+ return encodeUnlinkedPublicNamespace(ctx,
+ names: visitor.names, exports: visitor.exports, parts: visitor.parts);
+}
+
+class _CombinatorEncoder extends SimpleAstVisitor<UnlinkedCombinatorBuilder> {
+ final BuilderContext ctx;
+
+ _CombinatorEncoder(this.ctx);
+
+ List<String> encodeNames(NodeList<SimpleIdentifier> names) =>
+ names.map((SimpleIdentifier id) => id.name).toList();
+
+ @override
+ UnlinkedCombinatorBuilder visitHideCombinator(HideCombinator node) {
+ return encodeUnlinkedCombinator(ctx, hides: encodeNames(node.hiddenNames));
+ }
+
+ @override
+ UnlinkedCombinatorBuilder visitShowCombinator(ShowCombinator node) {
+ return encodeUnlinkedCombinator(ctx, shows: encodeNames(node.shownNames));
+ }
+}
+
+class _PublicNamespaceVisitor extends RecursiveAstVisitor {
+ final BuilderContext ctx;
+ final List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[];
+ final List<UnlinkedExportBuilder> exports = <UnlinkedExportBuilder>[];
+ final List<UnlinkedPartBuilder> parts = <UnlinkedPartBuilder>[];
+
+ _PublicNamespaceVisitor(this.ctx);
+
+ void addNameIfPublic(String name, PrelinkedReferenceKind kind) {
+ if (isPublic(name)) {
+ names.add(encodeUnlinkedPublicName(ctx, name: name, kind: kind));
+ }
+ }
+
+ bool isPublic(String name) => !name.startsWith('_');
+
+ @override
+ visitClassDeclaration(ClassDeclaration node) {
+ addNameIfPublic(node.name.name, PrelinkedReferenceKind.classOrEnum);
+ }
+
+ @override
+ visitClassTypeAlias(ClassTypeAlias node) {
+ addNameIfPublic(node.name.name, PrelinkedReferenceKind.classOrEnum);
+ }
+
+ @override
+ visitEnumDeclaration(EnumDeclaration node) {
+ addNameIfPublic(node.name.name, PrelinkedReferenceKind.classOrEnum);
+ }
+
+ @override
+ visitExportDirective(ExportDirective node) {
+ exports.add(encodeUnlinkedExport(ctx,
+ uri: node.uri.stringValue,
+ combinators: node.combinators
+ .map((Combinator c) => c.accept(new _CombinatorEncoder(ctx)))
+ .toList()));
+ }
+
+ @override
+ visitFunctionDeclaration(FunctionDeclaration node) {
+ String name = node.name.name;
+ if (node.isSetter) {
+ name += '=';
+ }
+ addNameIfPublic(name, PrelinkedReferenceKind.other);
+ }
+
+ @override
+ visitFunctionTypeAlias(FunctionTypeAlias node) {
+ addNameIfPublic(node.name.name, PrelinkedReferenceKind.typedef);
+ }
+
+ @override
+ visitPartDirective(PartDirective node) {
+ parts.add(encodeUnlinkedPart(ctx, uri: node.uri.stringValue));
+ }
+
+ @override
+ visitVariableDeclaration(VariableDeclaration node) {
+ String name = node.name.name;
+ addNameIfPublic(name, PrelinkedReferenceKind.other);
+ if (!node.isFinal && !node.isConst) {
+ addNameIfPublic('$name=', PrelinkedReferenceKind.other);
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 719c2f8..e83b661 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -25,66 +25,6 @@
typedef UnlinkedUnit GetUnlinkedSummaryCallback(String uri);
/**
- * Specialization of [FunctionTypeImpl] used for function types resynthesized
- * from summaries.
- */
-class ResynthesizedFunctionTypeImpl extends FunctionTypeImpl
- with ResynthesizedType {
- final SummaryResynthesizer summaryResynthesizer;
-
- ResynthesizedFunctionTypeImpl(
- FunctionTypeAliasElement element, String name, this.summaryResynthesizer)
- : super.elementWithName(element, name);
-
- int get _numTypeParameters {
- FunctionTypeAliasElement element = this.element;
- return element.typeParameters.length;
- }
-}
-
-/**
- * Specialization of [InterfaceTypeImpl] used for interface types resynthesized
- * from summaries.
- */
-class ResynthesizedInterfaceTypeImpl extends InterfaceTypeImpl
- with ResynthesizedType {
- final SummaryResynthesizer summaryResynthesizer;
-
- ResynthesizedInterfaceTypeImpl(
- ClassElement element, String name, this.summaryResynthesizer)
- : super.elementWithName(element, name);
-
- int get _numTypeParameters => element.typeParameters.length;
-}
-
-/**
- * Common code for types resynthesized from summaries. This code takes care of
- * filling in the appropriate number of copies of `dynamic` when it is queried
- * for type parameters on a bare type reference (i.e. it converts `List` to
- * `List<dynamic>`).
- */
-abstract class ResynthesizedType implements DartType {
- /**
- * The type arguments, if known. Otherwise `null`.
- */
- List<DartType> _typeArguments;
-
- SummaryResynthesizer get summaryResynthesizer;
-
- List<DartType> get typeArguments {
- if (_typeArguments == null) {
- // Default to replicating "dynamic" as many times as the class element
- // requires.
- _typeArguments = new List<DartType>.filled(
- _numTypeParameters, summaryResynthesizer.typeProvider.dynamicType);
- }
- return _typeArguments;
- }
-
- int get _numTypeParameters;
-}
-
-/**
* Implementation of [ElementResynthesizer] used when resynthesizing an element
* model from summaries.
*/
@@ -112,9 +52,6 @@
/**
* The [TypeProvider] used to obtain core types (such as Object, int, List,
* and dynamic) during resynthesis.
- *
- * TODO(paulberry): will this create a chicken-and-egg problem when trying to
- * resynthesize the core library from summaries?
*/
final TypeProvider typeProvider;
@@ -133,10 +70,9 @@
final Map<String, LibraryElement> _resynthesizedLibraries =
<String, LibraryElement>{};
- SummaryResynthesizer(AnalysisContext context, this.getPrelinkedSummary,
- this.getUnlinkedSummary, this.sourceFactory)
- : super(context),
- typeProvider = context.typeProvider;
+ SummaryResynthesizer(AnalysisContext context, this.typeProvider,
+ this.getPrelinkedSummary, this.getUnlinkedSummary, this.sourceFactory)
+ : super(context);
/**
* Number of libraries that have been resynthesized so far.
@@ -181,7 +117,7 @@
getUnlinkedSummary(uri)
];
Source librarySource = _getSource(uri);
- for (UnlinkedPart part in serializedUnits[0].parts) {
+ for (UnlinkedPart part in serializedUnits[0].publicNamespace.parts) {
String partAbsUri =
sourceFactory.resolveUri(librarySource, part.uri).uri.toString();
serializedUnits.add(getUnlinkedSummary(partAbsUri));
@@ -228,6 +164,17 @@
final Source librarySource;
/**
+ * Indicates whether [librarySource] is the `dart:core` library.
+ */
+ bool isCoreLibrary;
+
+ /**
+ * Classes which should have their supertype set to "object" once
+ * resynthesis is complete. Only used if [isCoreLibrary] is `true`.
+ */
+ List<ClassElementImpl> delayedObjectSubclasses = <ClassElementImpl>[];
+
+ /**
* [ElementHolder] into which resynthesized elements should be placed. This
* object is recreated afresh for each unit in the library, and is used to
* populate the [CompilationUnitElement].
@@ -260,7 +207,9 @@
List<TypeParameterElement> currentTypeParameters;
_LibraryResynthesizer(this.summaryResynthesizer, this.prelinkedLibrary,
- this.unlinkedUnits, this.librarySource);
+ this.unlinkedUnits, this.librarySource) {
+ isCoreLibrary = librarySource.uri.toString() == 'dart:core';
+ }
/**
* Resynthesize a [ClassElement] and place it in [unitHolder].
@@ -280,7 +229,11 @@
if (serializedClass.supertype != null) {
classElement.supertype = buildType(serializedClass.supertype);
} else if (!serializedClass.hasNoSupertype) {
- classElement.supertype = summaryResynthesizer.typeProvider.objectType;
+ if (isCoreLibrary) {
+ delayedObjectSubclasses.add(classElement);
+ } else {
+ classElement.supertype = summaryResynthesizer.typeProvider.objectType;
+ }
}
classElement.interfaces =
serializedClass.interfaces.map(buildType).toList();
@@ -312,7 +265,12 @@
new ConstructorElementImpl('', -1);
constructor.synthetic = true;
constructor.returnType = correspondingType;
- constructor.type = new FunctionTypeImpl(constructor);
+ constructor.type = new FunctionTypeImpl.elementWithNameAndArgs(
+ constructor,
+ null,
+ currentTypeParameters
+ .map((TypeParameterElement e) => e.type)
+ .toList());
memberHolder.addConstructor(constructor);
}
classElement.constructors = memberHolder.constructors;
@@ -335,15 +293,15 @@
NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) {
if (serializedCombinator.shows.isNotEmpty) {
ShowElementCombinatorImpl combinator = new ShowElementCombinatorImpl();
- combinator.shownNames = serializedCombinator.shows
- .map((UnlinkedCombinatorName n) => n.name)
- .toList();
+ // Note: we call toList() so that we don't retain a reference to the
+ // deserialized data structure.
+ combinator.shownNames = serializedCombinator.shows.toList();
return combinator;
} else {
HideElementCombinatorImpl combinator = new HideElementCombinatorImpl();
- combinator.hiddenNames = serializedCombinator.hides
- .map((UnlinkedCombinatorName n) => n.name)
- .toList();
+ // Note: we call toList() so that we don't retain a reference to the
+ // deserialized data structure.
+ combinator.hiddenNames = serializedCombinator.hides.toList();
return combinator;
}
}
@@ -367,6 +325,7 @@
* associated fields and implicit accessors.
*/
void buildEnum(UnlinkedEnum serializedEnum) {
+ assert(!isCoreLibrary);
// TODO(paulberry): add offset support (for this element type and others)
ClassElementImpl classElement =
new ClassElementImpl(serializedEnum.name, -1);
@@ -493,7 +452,12 @@
} else {
executableElement.returnType = VoidTypeImpl.instance;
}
- executableElement.type = new FunctionTypeImpl(executableElement);
+ executableElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
+ executableElement,
+ null,
+ currentTypeParameters
+ ?.map((TypeParameterElement e) => e.type)
+ ?.toList());
executableElement.hasImplicitReturnType =
serializedExecutable.hasImplicitReturnType;
executableElement.external = serializedExecutable.isExternal;
@@ -572,18 +536,18 @@
*/
FieldElementImpl buildImplicitField(String name, DartType type,
UnlinkedExecutableKind kind, ElementHolder holder) {
- if (holder.getField(name) == null) {
- FieldElementImpl field = new FieldElementImpl(name, -1);
+ FieldElementImpl field = holder.getField(name);
+ if (field == null) {
+ field = new FieldElementImpl(name, -1);
field.synthetic = true;
field.final2 = kind == UnlinkedExecutableKind.getter;
field.type = type;
holder.addField(field);
return field;
} else {
- // TODO(paulberry): if adding a setter where there was previously
- // only a getter, remove "final" modifier.
// TODO(paulberry): what if the getter and setter have a type mismatch?
- throw new UnimplementedError();
+ field.final2 = false;
+ return field;
}
}
@@ -654,11 +618,12 @@
definingCompilationUnit.librarySource = librarySource;
List<CompilationUnitElement> parts = <CompilationUnitElement>[];
UnlinkedUnit unlinkedDefiningUnit = unlinkedUnits[0];
- assert(
- unlinkedDefiningUnit.parts.length + 1 == prelinkedLibrary.units.length);
+ assert(unlinkedDefiningUnit.publicNamespace.parts.length + 1 ==
+ prelinkedLibrary.units.length);
for (int i = 1; i < prelinkedLibrary.units.length; i++) {
- CompilationUnitElementImpl part =
- buildPart(unlinkedDefiningUnit.parts[i - 1].uri, unlinkedUnits[i]);
+ CompilationUnitElementImpl part = buildPart(
+ unlinkedDefiningUnit.publicNamespace.parts[i - 1].uri,
+ unlinkedUnits[i]);
parts.add(part);
}
libraryElement.parts = parts;
@@ -669,11 +634,18 @@
}
libraryElement.imports = imports;
libraryElement.exports =
- unlinkedDefiningUnit.exports.map(buildExport).toList();
+ unlinkedDefiningUnit.publicNamespace.exports.map(buildExport).toList();
populateUnit(definingCompilationUnit, 0);
for (int i = 0; i < parts.length; i++) {
populateUnit(parts[i], i + 1);
}
+ if (isCoreLibrary) {
+ ClassElement objectElement = libraryElement.getType('Object');
+ assert(objectElement != null);
+ for (ClassElementImpl classElement in delayedObjectSubclasses) {
+ classElement.supertype = objectElement.type;
+ }
+ }
return libraryElement;
}
@@ -765,7 +737,8 @@
if (referenceResolution.unit != 0) {
UnlinkedUnit referencedLibraryDefiningUnit =
summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri);
- String uri = referencedLibraryDefiningUnit.parts[0].uri;
+ String uri = referencedLibraryDefiningUnit.publicNamespace.parts[
+ referenceResolution.unit - 1].uri;
Source partSource = summaryResynthesizer.sourceFactory
.resolveUri(referencedLibrarySource, uri);
partUri = partSource.uri.toString();
@@ -780,7 +753,8 @@
} else {
referencedLibraryUri = librarySource.uri.toString();
if (referenceResolution.unit != 0) {
- String uri = unlinkedUnits[0].parts[referenceResolution.unit - 1].uri;
+ String uri = unlinkedUnits[0].publicNamespace.parts[
+ referenceResolution.unit - 1].uri;
Source partSource =
summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
partUri = partSource.uri.toString();
@@ -788,33 +762,36 @@
partUri = referencedLibraryUri;
}
}
- ResynthesizedType resynthesizedType;
ElementLocationImpl location = new ElementLocationImpl.con3(
<String>[referencedLibraryUri, partUri, reference.name]);
+ List<DartType> typeArguments = const <DartType>[];
+ if (referenceResolution.numTypeParameters != 0) {
+ typeArguments = <DartType>[];
+ for (int i = 0; i < referenceResolution.numTypeParameters; i++) {
+ if (i < type.typeArguments.length) {
+ typeArguments.add(buildType(type.typeArguments[i]));
+ } else {
+ typeArguments.add(summaryResynthesizer.typeProvider.dynamicType);
+ }
+ }
+ }
switch (referenceResolution.kind) {
case PrelinkedReferenceKind.classOrEnum:
- resynthesizedType = new ResynthesizedInterfaceTypeImpl(
+ return new InterfaceTypeImpl.elementWithNameAndArgs(
new ClassElementHandle(summaryResynthesizer, location),
reference.name,
- summaryResynthesizer);
- break;
+ typeArguments);
case PrelinkedReferenceKind.typedef:
- resynthesizedType = new ResynthesizedFunctionTypeImpl(
+ return new FunctionTypeImpl.elementWithNameAndArgs(
new FunctionTypeAliasElementHandle(
summaryResynthesizer, location),
reference.name,
- summaryResynthesizer);
- break;
+ typeArguments);
default:
// TODO(paulberry): figure out how to handle this case (which should
// only occur in the event of erroneous code).
throw new UnimplementedError();
}
- if (type.typeArguments.isNotEmpty) {
- resynthesizedType._typeArguments =
- type.typeArguments.map(buildType).toList();
- }
- return resynthesizedType;
}
}
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index 9a13020..eddb78c 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -9,7 +9,7 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/summary/builder.dart';
+import 'package:analyzer/src/summary/base.dart';
import 'package:analyzer/src/summary/format.dart';
/**
@@ -156,28 +156,64 @@
*/
void addCompilationUnitElements(CompilationUnitElement element, int unitNum) {
UnlinkedUnitBuilder b = new UnlinkedUnitBuilder(ctx);
+ referenceMap.clear();
unlinkedReferences = <UnlinkedReferenceBuilder>[
encodeUnlinkedReference(ctx)
];
prelinkedReferences = <PrelinkedReferenceBuilder>[
encodePrelinkedReference(ctx, kind: PrelinkedReferenceKind.classOrEnum)
];
+ List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[];
+ for (PropertyAccessorElement accessor in element.accessors) {
+ if (accessor.isPublic) {
+ names.add(encodeUnlinkedPublicName(ctx,
+ kind: PrelinkedReferenceKind.other, name: accessor.name));
+ }
+ }
+ for (ClassElement cls in element.types) {
+ if (cls.isPublic) {
+ names.add(encodeUnlinkedPublicName(ctx,
+ kind: PrelinkedReferenceKind.classOrEnum, name: cls.name));
+ }
+ }
+ for (ClassElement enm in element.enums) {
+ if (enm.isPublic) {
+ names.add(encodeUnlinkedPublicName(ctx,
+ kind: PrelinkedReferenceKind.classOrEnum, name: enm.name));
+ }
+ }
+ for (FunctionElement function in element.functions) {
+ if (function.isPublic) {
+ names.add(encodeUnlinkedPublicName(ctx,
+ kind: PrelinkedReferenceKind.other, name: function.name));
+ }
+ }
+ for (FunctionTypeAliasElement typedef in element.functionTypeAliases) {
+ if (typedef.isPublic) {
+ names.add(encodeUnlinkedPublicName(ctx,
+ kind: PrelinkedReferenceKind.typedef, name: typedef.name));
+ }
+ }
if (unitNum == 0) {
+ if (libraryElement.name.isNotEmpty) {
+ b.libraryName = libraryElement.name;
+ }
+ b.publicNamespace = encodeUnlinkedPublicNamespace(ctx,
+ exports: libraryElement.exports.map(serializeExport).toList(),
+ parts: libraryElement.parts
+ .map((CompilationUnitElement e) =>
+ encodeUnlinkedPart(ctx, uri: e.uri))
+ .toList(),
+ names: names);
+ b.imports = libraryElement.imports.map(serializeImport).toList();
+ } else {
// TODO(paulberry): we need to figure out a way to record library, part,
// import, and export declarations that appear in non-defining
// compilation units (even though such declarations are prohibited by the
// language), so that if the user makes code changes that cause a
// non-defining compilation unit to become a defining compilation unit,
// we can create a correct summary by simply re-linking.
- if (libraryElement.name.isNotEmpty) {
- b.libraryName = libraryElement.name;
- }
- b.exports = libraryElement.exports.map(serializeExport).toList();
- b.imports = libraryElement.imports.map(serializeImport).toList();
- b.parts = libraryElement.parts
- .map(
- (CompilationUnitElement e) => encodeUnlinkedPart(ctx, uri: e.uri))
- .toList();
+ b.publicNamespace = encodeUnlinkedPublicNamespace(ctx, names: names);
}
b.classes = element.types.map(serializeClass).toList();
b.enums = element.enums.map(serializeEnum).toList();
@@ -306,21 +342,14 @@
NamespaceCombinator combinator) {
UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder(ctx);
if (combinator is ShowElementCombinator) {
- b.shows = combinator.shownNames.map(serializeCombinatorName).toList();
+ b.shows = combinator.shownNames;
} else if (combinator is HideElementCombinator) {
- b.hides = combinator.hiddenNames.map(serializeCombinatorName).toList();
+ b.hides = combinator.hiddenNames;
}
return b;
}
/**
- * Serialize the given [name] into an [UnlinkedCombinatorName].
- */
- UnlinkedCombinatorNameBuilder serializeCombinatorName(String name) {
- return encodeUnlinkedCombinatorName(ctx, name: name);
- }
-
- /**
* Return the index of the entry in the dependency table
* ([PrelinkedLibrary.dependencies]) for the given [dependentLibrary]. A new
* entry is added to the table if necessary to satisfy the request.
@@ -447,7 +476,9 @@
/**
* Serialize the given [parameter] into an [UnlinkedParam].
*/
- UnlinkedParamBuilder serializeParam(ParameterElement parameter) {
+ UnlinkedParamBuilder serializeParam(ParameterElement parameter,
+ [Element context]) {
+ context ??= parameter;
UnlinkedParamBuilder b = new UnlinkedParamBuilder(ctx);
b.name = parameter.name;
switch (parameter.parameterKind) {
@@ -468,9 +499,11 @@
if (!type.returnType.isVoid) {
b.type = serializeTypeRef(type.returnType, parameter);
}
- b.parameters = type.parameters.map(serializeParam).toList();
+ b.parameters = type.parameters
+ .map((parameter) => serializeParam(parameter, context))
+ .toList();
} else {
- b.type = serializeTypeRef(type, parameter);
+ b.type = serializeTypeRef(type, context);
b.hasImplicitType = parameter.hasImplicitType;
}
return b;
@@ -544,6 +577,10 @@
element.getAncestor((Element e) => e is CompilationUnitElement);
int unit = dependentLibrary.units.indexOf(unitElement);
assert(unit != -1);
+ int numTypeParameters = 0;
+ if (element is TypeParameterizedElement) {
+ numTypeParameters = element.typeParameters.length;
+ }
int index = unlinkedReferences.length;
// TODO(paulberry): set UnlinkedReference.prefix.
unlinkedReferences
@@ -553,7 +590,8 @@
kind: element is FunctionTypeAliasElement
? PrelinkedReferenceKind.typedef
: PrelinkedReferenceKind.classOrEnum,
- unit: unit));
+ unit: unit,
+ numTypeParameters: numTypeParameters));
return index;
});
}
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
new file mode 100644
index 0000000..70b7bdd
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -0,0 +1,355 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.src.summary.summary_sdk;
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/context/cache.dart' show CacheEntry;
+import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart' show Source, SourceKind;
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/resynthesize.dart';
+import 'package:analyzer/src/task/dart.dart'
+ show
+ LIBRARY_ELEMENT1,
+ LIBRARY_ELEMENT2,
+ LIBRARY_ELEMENT3,
+ LIBRARY_ELEMENT4,
+ LIBRARY_ELEMENT5,
+ LIBRARY_ELEMENT6,
+ LIBRARY_ELEMENT7,
+ LIBRARY_ELEMENT8,
+ READY_LIBRARY_ELEMENT2,
+ READY_LIBRARY_ELEMENT5,
+ READY_LIBRARY_ELEMENT6,
+ TYPE_PROVIDER;
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/model.dart'
+ show AnalysisTarget, ResultDescriptor, TargetedResult;
+
+/**
+ * An [SdkAnalysisContext] for Dart SDK with a summary [SdkBundle].
+ */
+class SummarySdkAnalysisContext extends SdkAnalysisContext {
+ final SdkBundle bundle;
+ final SummaryTypeProvider typeProvider = new SummaryTypeProvider();
+
+ SummaryResynthesizer resynthesizer;
+
+ SummarySdkAnalysisContext(this.bundle);
+
+ @override
+ bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
+ if (resynthesizer == null) {
+ resynthesizer = new SummaryResynthesizer(this, typeProvider,
+ _getPrelinkedSummary, _getUnlinkedSummary, sourceFactory);
+ _buildCoreLibrary();
+ _buildAsyncLibrary();
+ }
+ if (result == TYPE_PROVIDER) {
+ entry.setValue(result, typeProvider, TargetedResult.EMPTY_LIST);
+ return true;
+ }
+ AnalysisTarget target = entry.target;
+// print('SummarySdkAnalysisContext: $result of $target');
+ if (target is Source && target.isInSystemLibrary) {
+ if (result == LIBRARY_ELEMENT1 ||
+ result == LIBRARY_ELEMENT2 ||
+ result == LIBRARY_ELEMENT3 ||
+ result == LIBRARY_ELEMENT4 ||
+ result == LIBRARY_ELEMENT5 ||
+ result == LIBRARY_ELEMENT6 ||
+ result == LIBRARY_ELEMENT7 ||
+ result == LIBRARY_ELEMENT8 ||
+ result == LIBRARY_ELEMENT) {
+ // TODO(scheglov) try to find a way to avoid listing every result
+ // e.g. "result.whenComplete == LIBRARY_ELEMENT"
+ String uri = target.uri.toString();
+ LibraryElement libraryElement = resynthesizer.getLibraryElement(uri);
+ entry.setValue(result, libraryElement, TargetedResult.EMPTY_LIST);
+ return true;
+ } else if (result == READY_LIBRARY_ELEMENT2 ||
+ result == READY_LIBRARY_ELEMENT5 ||
+ result == READY_LIBRARY_ELEMENT6) {
+ entry.setValue(result, true, TargetedResult.EMPTY_LIST);
+ return true;
+ } else if (result == SOURCE_KIND) {
+ // TODO(scheglov) not every source is a library
+ entry.setValue(result, SourceKind.LIBRARY, TargetedResult.EMPTY_LIST);
+ return true;
+ } else {
+// throw new UnimplementedError('$result of $target');
+ }
+ }
+ return false;
+ }
+
+ void _buildAsyncLibrary() {
+ LibraryElement library = resynthesizer.getLibraryElement('dart:async');
+ typeProvider.initializeAsync(library);
+ }
+
+ void _buildCoreLibrary() {
+ LibraryElement library = resynthesizer.getLibraryElement('dart:core');
+ typeProvider.initializeCore(library);
+ }
+
+ PrelinkedLibrary _getPrelinkedSummary(String uri) {
+ for (int i = 0; i < bundle.prelinkedLibraryUris.length; i++) {
+ if (bundle.prelinkedLibraryUris[i] == uri) {
+ return bundle.prelinkedLibraries[i];
+ }
+ }
+ throw new StateError('Unable to find prelinked summary for $uri');
+ }
+
+ UnlinkedUnit _getUnlinkedSummary(String uri) {
+ for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
+ if (bundle.unlinkedUnitUris[i] == uri) {
+ return bundle.unlinkedUnits[i];
+ }
+ }
+ throw new StateError('Unable to find unlinked summary for $uri');
+ }
+}
+
+/**
+ * Implementation of [TypeProvider] which can be initialized separately with
+ * `dart:core` and `dart:async` libraries.
+ */
+class SummaryTypeProvider implements TypeProvider {
+ bool _isCoreInitialized = false;
+ bool _isAsyncInitialized = false;
+
+ InterfaceType _boolType;
+ InterfaceType _deprecatedType;
+ InterfaceType _doubleType;
+ InterfaceType _functionType;
+ InterfaceType _futureDynamicType;
+ InterfaceType _futureNullType;
+ InterfaceType _futureType;
+ InterfaceType _intType;
+ InterfaceType _iterableDynamicType;
+ InterfaceType _iterableType;
+ InterfaceType _listType;
+ InterfaceType _mapType;
+ DartObjectImpl _nullObject;
+ InterfaceType _nullType;
+ InterfaceType _numType;
+ InterfaceType _objectType;
+ InterfaceType _stackTraceType;
+ InterfaceType _streamDynamicType;
+ InterfaceType _streamType;
+ InterfaceType _stringType;
+ InterfaceType _symbolType;
+ InterfaceType _typeType;
+
+ @override
+ InterfaceType get boolType {
+ assert(_isCoreInitialized);
+ return _boolType;
+ }
+
+ @override
+ DartType get bottomType => BottomTypeImpl.instance;
+
+ @override
+ InterfaceType get deprecatedType {
+ assert(_isCoreInitialized);
+ return _deprecatedType;
+ }
+
+ @override
+ InterfaceType get doubleType {
+ assert(_isCoreInitialized);
+ return _doubleType;
+ }
+
+ @override
+ DartType get dynamicType => DynamicTypeImpl.instance;
+
+ @override
+ InterfaceType get functionType {
+ assert(_isCoreInitialized);
+ return _functionType;
+ }
+
+ @override
+ InterfaceType get futureDynamicType {
+ assert(_isAsyncInitialized);
+ return _futureDynamicType;
+ }
+
+ @override
+ InterfaceType get futureNullType {
+ assert(_isAsyncInitialized);
+ return _futureNullType;
+ }
+
+ @override
+ InterfaceType get futureType {
+ assert(_isAsyncInitialized);
+ return _futureType;
+ }
+
+ @override
+ InterfaceType get intType {
+ assert(_isCoreInitialized);
+ return _intType;
+ }
+
+ @override
+ InterfaceType get iterableDynamicType {
+ assert(_isCoreInitialized);
+ return _iterableDynamicType;
+ }
+
+ @override
+ InterfaceType get iterableType {
+ assert(_isCoreInitialized);
+ return _iterableType;
+ }
+
+ @override
+ InterfaceType get listType {
+ assert(_isCoreInitialized);
+ return _listType;
+ }
+
+ @override
+ InterfaceType get mapType {
+ assert(_isCoreInitialized);
+ return _mapType;
+ }
+
+ @override
+ List<InterfaceType> get nonSubtypableTypes => <InterfaceType>[
+ nullType,
+ numType,
+ intType,
+ doubleType,
+ boolType,
+ stringType
+ ];
+
+ @override
+ DartObjectImpl get nullObject {
+ if (_nullObject == null) {
+ _nullObject = new DartObjectImpl(nullType, NullState.NULL_STATE);
+ }
+ return _nullObject;
+ }
+
+ @override
+ InterfaceType get nullType {
+ assert(_isCoreInitialized);
+ return _nullType;
+ }
+
+ @override
+ InterfaceType get numType {
+ assert(_isCoreInitialized);
+ return _numType;
+ }
+
+ @override
+ InterfaceType get objectType {
+ assert(_isCoreInitialized);
+ return _objectType;
+ }
+
+ @override
+ InterfaceType get stackTraceType {
+ assert(_isCoreInitialized);
+ return _stackTraceType;
+ }
+
+ @override
+ InterfaceType get streamDynamicType {
+ assert(_isAsyncInitialized);
+ return _streamDynamicType;
+ }
+
+ @override
+ InterfaceType get streamType {
+ assert(_isAsyncInitialized);
+ return _streamType;
+ }
+
+ @override
+ InterfaceType get stringType {
+ assert(_isCoreInitialized);
+ return _stringType;
+ }
+
+ @override
+ InterfaceType get symbolType {
+ assert(_isCoreInitialized);
+ return _symbolType;
+ }
+
+ @override
+ InterfaceType get typeType {
+ assert(_isCoreInitialized);
+ return _typeType;
+ }
+
+ @override
+ DartType get undefinedType => UndefinedTypeImpl.instance;
+
+ /**
+ * Initialize the `dart:async` types provided by this type provider.
+ */
+ void initializeAsync(LibraryElement library) {
+ assert(_isCoreInitialized);
+ assert(!_isAsyncInitialized);
+ _isAsyncInitialized = true;
+ _futureType = _getType(library, "Future");
+ _streamType = _getType(library, "Stream");
+ _futureDynamicType = _futureType.substitute4(<DartType>[dynamicType]);
+ _futureNullType = _futureType.substitute4(<DartType>[_nullType]);
+ _streamDynamicType = _streamType.substitute4(<DartType>[dynamicType]);
+ }
+
+ /**
+ * Initialize the `dart:core` types provided by this type provider.
+ */
+ void initializeCore(LibraryElement library) {
+ assert(!_isCoreInitialized);
+ assert(!_isAsyncInitialized);
+ _isCoreInitialized = true;
+ _boolType = _getType(library, "bool");
+ _deprecatedType = _getType(library, "Deprecated");
+ _doubleType = _getType(library, "double");
+ _functionType = _getType(library, "Function");
+ _intType = _getType(library, "int");
+ _iterableType = _getType(library, "Iterable");
+ _listType = _getType(library, "List");
+ _mapType = _getType(library, "Map");
+ _nullType = _getType(library, "Null");
+ _numType = _getType(library, "num");
+ _objectType = _getType(library, "Object");
+ _stackTraceType = _getType(library, "StackTrace");
+ _stringType = _getType(library, "String");
+ _symbolType = _getType(library, "Symbol");
+ _typeType = _getType(library, "Type");
+ _iterableDynamicType = _iterableType.substitute4(<DartType>[dynamicType]);
+ }
+
+ /**
+ * Return the type with the given [name] from the given [library], or
+ * throw a [StateError] if there is no class with the given name.
+ */
+ InterfaceType _getType(LibraryElement library, String name) {
+ Element element = library.getType(name);
+ if (element == null) {
+ throw new StateError("No definition of type $name");
+ }
+ return (element as ClassElement).type;
+ }
+}
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 5a64d4c..56dc665 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -145,6 +145,114 @@
new ListResultDescriptor<Source>('CONTAINING_LIBRARIES', Source.EMPTY_LIST);
/**
+ * The flag specifying that [RESOLVED_UNIT] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT1] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT1 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT1', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT10] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT10 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT10', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT11] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT11 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT11', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT2] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT2 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT2', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT3] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT3 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT3', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT4] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT4 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT4', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT5] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT5 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT5', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT6] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT6 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT6', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT7] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT7 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT7', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT8] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT8 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT8', false);
+
+/**
+ * The flag specifying that [RESOLVED_UNIT9] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT9 =
+ new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT9', false);
+
+/**
* The sources representing the export closure of a library.
* The [Source]s include only library sources, not their units.
*
@@ -738,6 +846,7 @@
buildInputs, <ResultDescriptor>[
COMPILATION_UNIT_CONSTANTS,
COMPILATION_UNIT_ELEMENT,
+ CREATED_RESOLVED_UNIT1,
RESOLVED_UNIT1
]);
@@ -790,6 +899,7 @@
outputs[COMPILATION_UNIT_CONSTANTS] = constants;
outputs[COMPILATION_UNIT_ELEMENT] = element;
outputs[RESOLVED_UNIT1] = unit;
+ outputs[CREATED_RESOLVED_UNIT1] = true;
}
/**
@@ -1099,7 +1209,7 @@
'BuildEnumMemberElementsTask',
createTask,
buildInputs,
- <ResultDescriptor>[RESOLVED_UNIT2]);
+ <ResultDescriptor>[CREATED_RESOLVED_UNIT2, RESOLVED_UNIT2]);
BuildEnumMemberElementsTask(
InternalAnalysisContext context, AnalysisTarget target)
@@ -1120,6 +1230,7 @@
//
EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
unit.accept(builder);
+ outputs[CREATED_RESOLVED_UNIT2] = true;
outputs[RESOLVED_UNIT2] = unit;
}
@@ -2398,7 +2509,7 @@
'EvaluateUnitConstantsTask',
createTask,
buildInputs,
- <ResultDescriptor>[RESOLVED_UNIT11]);
+ <ResultDescriptor>[CREATED_RESOLVED_UNIT11, RESOLVED_UNIT11]);
EvaluateUnitConstantsTask(AnalysisContext context, LibrarySpecificUnit target)
: super(context, target);
@@ -2412,6 +2523,7 @@
// all constants are evaluated before this method is called.
CompilationUnit unit = getRequiredInput(UNIT_INPUT);
outputs[RESOLVED_UNIT11] = unit;
+ outputs[CREATED_RESOLVED_UNIT11] = true;
}
/**
@@ -2891,7 +3003,7 @@
'InferInstanceMembersInUnitTask',
createTask,
buildInputs,
- <ResultDescriptor>[RESOLVED_UNIT9]);
+ <ResultDescriptor>[CREATED_RESOLVED_UNIT9, RESOLVED_UNIT9]);
/**
* Initialize a newly created task to build a library element for the given
@@ -2923,6 +3035,7 @@
// Record outputs.
//
outputs[RESOLVED_UNIT9] = unit;
+ outputs[CREATED_RESOLVED_UNIT9] = true;
}
/**
@@ -2941,12 +3054,12 @@
// Require that field re-resolution be complete for all units in the
// current library cycle.
'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
- (CompilationUnitElementImpl unit) => RESOLVED_UNIT8
+ (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT8
.of(new LibrarySpecificUnit(unit.librarySource, unit.source))),
// Require that full inference be complete for all dependencies of the
// current library cycle.
'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
- (CompilationUnitElementImpl unit) => RESOLVED_UNIT9
+ (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT9
.of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
};
}
@@ -3012,7 +3125,7 @@
'InferStaticVariableTypesInUnitTask',
createTask,
buildInputs,
- <ResultDescriptor>[RESOLVED_UNIT7]);
+ <ResultDescriptor>[CREATED_RESOLVED_UNIT7, RESOLVED_UNIT7]);
/**
* Initialize a newly created task to build a library element for the given
@@ -3037,6 +3150,7 @@
// preparing all of the inputs.
//
outputs[RESOLVED_UNIT7] = unit;
+ outputs[CREATED_RESOLVED_UNIT7] = true;
}
/**
@@ -3186,7 +3300,7 @@
// Require that full inference be complete for all dependencies of the
// current library cycle.
'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
- (CompilationUnitElementImpl unit) => RESOLVED_UNIT9
+ (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT9
.of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
};
}
@@ -3599,6 +3713,7 @@
buildInputs, <ResultDescriptor>[
INFERABLE_STATIC_VARIABLES_IN_UNIT,
PROPAGABLE_VARIABLES_IN_UNIT,
+ CREATED_RESOLVED_UNIT5,
RESOLVED_UNIT5
]);
@@ -3634,6 +3749,7 @@
}
outputs[PROPAGABLE_VARIABLES_IN_UNIT] = visitor.propagableVariables;
outputs[RESOLVED_UNIT5] = unit;
+ outputs[CREATED_RESOLVED_UNIT5] = true;
}
/**
@@ -3654,7 +3770,7 @@
// Require that full inference be complete for all dependencies of the
// current library cycle.
'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
- (CompilationUnitElementImpl unit) => RESOLVED_UNIT9
+ (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT9
.of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
};
}
@@ -3799,7 +3915,7 @@
'PropagateVariableTypesInUnitTask',
createTask,
buildInputs,
- <ResultDescriptor>[RESOLVED_UNIT6]);
+ <ResultDescriptor>[CREATED_RESOLVED_UNIT6, RESOLVED_UNIT6]);
PropagateVariableTypesInUnitTask(
InternalAnalysisContext context, LibrarySpecificUnit unit)
@@ -3820,6 +3936,7 @@
// preparing all of the inputs.
//
outputs[RESOLVED_UNIT6] = unit;
+ outputs[CREATED_RESOLVED_UNIT6] = true;
}
/**
@@ -4369,7 +4486,7 @@
'ResolveInstanceFieldsInUnitTask',
createTask,
buildInputs,
- <ResultDescriptor>[RESOLVED_UNIT8]);
+ <ResultDescriptor>[CREATED_RESOLVED_UNIT8, RESOLVED_UNIT8]);
/**
* Initialize a newly created task to build a library element for the given
@@ -4415,6 +4532,7 @@
// Record outputs.
//
outputs[RESOLVED_UNIT8] = unit;
+ outputs[CREATED_RESOLVED_UNIT8] = true;
}
/**
@@ -4434,12 +4552,12 @@
// Require that static variable inference be complete for all units in
// the current library cycle.
'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
- (CompilationUnitElementImpl unit) => RESOLVED_UNIT7
+ (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT7
.of(new LibrarySpecificUnit(unit.librarySource, unit.source))),
// Require that full inference be complete for all dependencies of the
// current library cycle.
'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
- (CompilationUnitElementImpl unit) => RESOLVED_UNIT9
+ (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT9
.of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
};
}
@@ -4689,6 +4807,7 @@
'ResolveUnitTask', createTask, buildInputs, <ResultDescriptor>[
CONSTANT_EXPRESSIONS_DEPENDENCIES,
RESOLVE_UNIT_ERRORS,
+ CREATED_RESOLVED_UNIT10,
RESOLVED_UNIT10
]);
@@ -4736,6 +4855,7 @@
outputs[CONSTANT_EXPRESSIONS_DEPENDENCIES] = constExprDependencies;
outputs[RESOLVE_UNIT_ERRORS] = getTargetSourceErrors(errorListener, target);
outputs[RESOLVED_UNIT10] = unit;
+ outputs[CREATED_RESOLVED_UNIT10] = true;
}
/**
@@ -4755,7 +4875,7 @@
// Require that inference be complete for all units in the
// current library cycle.
'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
- (CompilationUnitElementImpl unit) => RESOLVED_UNIT9
+ (CompilationUnitElementImpl unit) => CREATED_RESOLVED_UNIT9
.of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
};
}
@@ -4793,10 +4913,11 @@
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveUnitTypeNamesTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[RESOLVE_TYPE_NAMES_ERRORS, RESOLVED_UNIT3]);
+ 'ResolveUnitTypeNamesTask', createTask, buildInputs, <ResultDescriptor>[
+ RESOLVE_TYPE_NAMES_ERRORS,
+ CREATED_RESOLVED_UNIT3,
+ RESOLVED_UNIT3
+ ]);
ResolveUnitTypeNamesTask(
InternalAnalysisContext context, AnalysisTarget target)
@@ -4827,6 +4948,7 @@
outputs[RESOLVE_TYPE_NAMES_ERRORS] =
getTargetSourceErrors(errorListener, target);
outputs[RESOLVED_UNIT3] = unit;
+ outputs[CREATED_RESOLVED_UNIT3] = true;
}
/**
@@ -4883,8 +5005,11 @@
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'ResolveVariableReferencesTask',
createTask,
- buildInputs,
- <ResultDescriptor>[RESOLVED_UNIT4, VARIABLE_REFERENCE_ERRORS]);
+ buildInputs, <ResultDescriptor>[
+ CREATED_RESOLVED_UNIT4,
+ RESOLVED_UNIT4,
+ VARIABLE_REFERENCE_ERRORS
+ ]);
ResolveVariableReferencesTask(
InternalAnalysisContext context, AnalysisTarget target)
@@ -4915,6 +5040,7 @@
// Record outputs.
//
outputs[RESOLVED_UNIT4] = unit;
+ outputs[CREATED_RESOLVED_UNIT4] = true;
outputs[VARIABLE_REFERENCE_ERRORS] =
getTargetSourceErrors(errorListener, target);
}
@@ -5077,10 +5203,11 @@
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'StrongModeVerifyUnitTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[STRONG_MODE_ERRORS, RESOLVED_UNIT]);
+ 'StrongModeVerifyUnitTask', createTask, buildInputs, <ResultDescriptor>[
+ STRONG_MODE_ERRORS,
+ CREATED_RESOLVED_UNIT,
+ RESOLVED_UNIT
+ ]);
StrongModeVerifyUnitTask(
InternalAnalysisContext context, AnalysisTarget target)
@@ -5101,11 +5228,11 @@
unit.accept(new CodeChecker(
typeProvider, new StrongTypeSystemImpl(), errorListener));
}
-
//
// Record outputs.
//
outputs[STRONG_MODE_ERRORS] = getUniqueErrors(errorListener.errors);
+ outputs[CREATED_RESOLVED_UNIT] = true;
outputs[RESOLVED_UNIT] = unit;
}
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index 7cdbe1c..db9cd1d 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -504,7 +504,7 @@
}
/**
- * Object used by CycleAwareDependencyWalker to report a single strongly
+ * Object used by [CycleAwareDependencyWalker] to report a single strongly
* connected component of nodes.
*/
class StronglyConnectedComponent<Node> {
@@ -702,14 +702,19 @@
//
throw new UnimplementedError();
} else if (inputState != CacheState.VALID) {
- try {
- TaskDescriptor descriptor =
- taskManager.findTask(inputTarget, inputResult);
- return new WorkItem(context, inputTarget, descriptor, inputResult,
- level + 1, workOrder);
- } on AnalysisException catch (exception, stackTrace) {
- this.exception = new CaughtException(exception, stackTrace);
- return null;
+ if (context.aboutToComputeResult(inputEntry, inputResult)) {
+ inputState = CacheState.VALID;
+ builder.currentValue = inputEntry.getValue(inputResult);
+ } else {
+ try {
+ TaskDescriptor descriptor =
+ taskManager.findTask(inputTarget, inputResult);
+ return new WorkItem(context, inputTarget, descriptor, inputResult,
+ level + 1, workOrder);
+ } on AnalysisException catch (exception, stackTrace) {
+ this.exception = new CaughtException(exception, stackTrace);
+ return null;
+ }
}
} else {
builder.currentValue = inputEntry.getValue(inputResult);
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 5b9acfe..ebc5a4c 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -52,7 +52,7 @@
/// Valid error `severity`s.
static final List<String> severities =
- ErrorSeverity.values.map((s) => s.name).toList();
+ new List.unmodifiable(severityMap.keys);
/// Ways to say `include`.
static const List<String> includeSynonyms = const ['include', 'true'];
@@ -121,17 +121,22 @@
/// Report an unsupported [node] value, defined in the given [scopeName].
void reportError(ErrorReporter reporter, String scopeName, YamlNode node) {
- reporter.reportErrorForSpan(
- code, node.span, [scopeName, node.value, proposal]);
+ reporter
+ .reportErrorForSpan(code, node.span, [scopeName, node.value, proposal]);
}
}
/// Validates `analyzer` error filter options.
class ErrorFilterOptionValidator extends OptionsValidator {
- /// Pretty list of legal includes.
- static final String legalIncludes = StringUtilities.printListOfQuotedNames(
+ /// Legal values.
+ static final List<String> legalValues =
new List.from(AnalyzerOptions.ignoreSynonyms)
- ..addAll(AnalyzerOptions.includeSynonyms));
+ ..addAll(AnalyzerOptions.includeSynonyms)
+ ..addAll(AnalyzerOptions.severities);
+
+ /// Pretty String listing legal values.
+ static final String legalValueString =
+ StringUtilities.printListOfQuotedNames(legalValues);
/// Lazily populated set of error codes (hashed for speedy lookup).
static HashSet<String> _errorCodes;
@@ -170,12 +175,14 @@
}
if (v is YamlScalar) {
value = toLowerCase(v.value);
- if (!AnalyzerOptions.ignoreSynonyms.contains(value) &&
- !AnalyzerOptions.includeSynonyms.contains(value)) {
+ if (!legalValues.contains(value)) {
reporter.reportErrorForSpan(
AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES,
- v.span,
- [AnalyzerOptions.errors, v.value?.toString(), legalIncludes]);
+ v.span, [
+ AnalyzerOptions.errors,
+ v.value?.toString(),
+ legalValueString
+ ]);
}
}
});
@@ -451,7 +458,8 @@
void setProcessors(AnalysisContext context, Object codes) {
ErrorConfig config = new ErrorConfig(codes);
- context.setConfigurationData(CONFIGURED_ERROR_PROCESSORS, config.processors);
+ context.setConfigurationData(
+ CONFIGURED_ERROR_PROCESSORS, config.processors);
}
void setStrongMode(AnalysisContext context, Object strongMode) {
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 7ab2b51..607b92c 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.27.1
+version: 0.27.1+2
author: Dart Team <misc@dartlang.org>
description: Static analyzer for Dart.
homepage: http://www.dartlang.org
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 6f3aa5d..bb6c95a 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -6356,7 +6356,8 @@
void _assertHasDocRange(
Element element, int expectedOffset, int expectedLength) {
- SourceRange docRange = element.docRange;
+ // Cast to dynamic here to avoid a hint about @deprecated docRange.
+ SourceRange docRange = (element as dynamic).docRange;
expect(docRange, isNotNull);
expect(docRange.offset, expectedOffset);
expect(docRange.length, expectedLength);
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index 5ee43e4..3dfae2b 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:unittest/unittest.dart';
@@ -17,6 +18,19 @@
main() {
initializeTestEnvironment();
runReflectiveTests(DeclarationResolverTest);
+ runReflectiveTests(StrongModeDeclarationResolverTest);
+}
+
+CompilationUnit _cloneResolveUnit(CompilationUnit unit) {
+ CompilationUnit clonedUnit = AstCloner.clone(unit);
+ new DeclarationResolver().resolve(clonedUnit, unit.element);
+ return clonedUnit;
+}
+
+SimpleIdentifier _findSimpleIdentifier(
+ AstNode root, String code, String search) {
+ return EngineTestCase.findNode(
+ root, code, search, (n) => n is SimpleIdentifier);
}
@reflectiveTest
@@ -32,11 +46,11 @@
''';
CompilationUnit unit = resolveSource(code);
PropertyAccessorElement getterElement =
- findSimpleIdentifier(unit, code, 'zzz =>').staticElement;
+ _findSimpleIdentifier(unit, code, 'zzz =>').staticElement;
expect(getterElement.isGetter, isTrue);
// re-resolve
CompilationUnit unit2 = _cloneResolveUnit(unit);
- SimpleIdentifier getterName = findSimpleIdentifier(unit2, code, 'zzz =>');
+ SimpleIdentifier getterName = _findSimpleIdentifier(unit2, code, 'zzz =>');
expect(getterName.staticElement, same(getterElement));
}
@@ -46,11 +60,11 @@
''';
CompilationUnit unit = resolveSource(code);
PropertyAccessorElement setterElement =
- findSimpleIdentifier(unit, code, 'zzz(_)').staticElement;
+ _findSimpleIdentifier(unit, code, 'zzz(_)').staticElement;
expect(setterElement.isSetter, isTrue);
// re-resolve
CompilationUnit unit2 = _cloneResolveUnit(unit);
- SimpleIdentifier getterName = findSimpleIdentifier(unit2, code, 'zzz(_)');
+ SimpleIdentifier getterName = _findSimpleIdentifier(unit2, code, 'zzz(_)');
expect(getterName.staticElement, same(setterElement));
}
@@ -62,10 +76,10 @@
''';
CompilationUnit unit = resolveSource(code);
FunctionElement getterElement =
- findSimpleIdentifier(unit, code, 'zzz =>').staticElement;
+ _findSimpleIdentifier(unit, code, 'zzz =>').staticElement;
// re-resolve
CompilationUnit unit2 = _cloneResolveUnit(unit);
- SimpleIdentifier getterName = findSimpleIdentifier(unit2, code, 'zzz =>');
+ SimpleIdentifier getterName = _findSimpleIdentifier(unit2, code, 'zzz =>');
expect(getterName.staticElement, same(getterElement));
}
@@ -77,22 +91,67 @@
''';
CompilationUnit unit = resolveSource(code);
FunctionElement setterElement =
- findSimpleIdentifier(unit, code, 'zzz(x)').staticElement;
+ _findSimpleIdentifier(unit, code, 'zzz(x)').staticElement;
// re-resolve
CompilationUnit unit2 = _cloneResolveUnit(unit);
- SimpleIdentifier setterName = findSimpleIdentifier(unit2, code, 'zzz(x)');
+ SimpleIdentifier setterName = _findSimpleIdentifier(unit2, code, 'zzz(x)');
expect(setterName.staticElement, same(setterElement));
}
+}
- static SimpleIdentifier findSimpleIdentifier(
- AstNode root, String code, String search) {
- return EngineTestCase.findNode(
- root, code, search, (n) => n is SimpleIdentifier);
+/**
+ * Strong mode DeclarationResolver tests
+ */
+@reflectiveTest
+class StrongModeDeclarationResolverTest extends ResolverTestCase {
+ @override
+ void setUp() {
+ resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
}
- static CompilationUnit _cloneResolveUnit(CompilationUnit unit) {
- CompilationUnit clonedUnit = AstCloner.clone(unit);
- new DeclarationResolver().resolve(clonedUnit, unit.element);
- return clonedUnit;
+ void test_genericFunction_typeParameter() {
+ String code = r'''
+/*=T*/ max/*<T>*/(/*=T*/ x, /*=T*/ y) => null;
+''';
+ CompilationUnit unit = resolveSource(code);
+ FunctionDeclaration node = _findSimpleIdentifier(unit, code, 'max').parent;
+ TypeParameter t = node.functionExpression.typeParameters.typeParameters[0];
+
+ FunctionElement element = node.name.staticElement;
+ TypeParameterElement tElement = element.typeParameters[0];
+ expect(tElement, isNotNull);
+ expect(element.typeParameters.toString(), "[T]");
+ expect(element.type.toString(), "<T>(T, T) → T");
+ expect(t.element, same(tElement));
+
+ // re-resolve
+ CompilationUnit unit2 = _cloneResolveUnit(unit);
+ node = _findSimpleIdentifier(unit2, code, 'max').parent;
+ t = node.functionExpression.typeParameters.typeParameters[0];
+ expect(t.element, same(tElement));
+ }
+
+ void test_genericMethod_typeParameter() {
+ String code = r'''
+class C {
+ /*=T*/ max/*<T>*/(/*=T*/ x, /*=T*/ y) => null;
+}
+''';
+ CompilationUnit unit = resolveSource(code);
+ MethodDeclaration node = _findSimpleIdentifier(unit, code, 'max').parent;
+ TypeParameter t = node.typeParameters.typeParameters[0];
+
+ MethodElement element = node.name.staticElement;
+ TypeParameterElement tElement = element.typeParameters[0];
+ expect(tElement, isNotNull);
+ expect(element.typeParameters.toString(), "[T]");
+ expect(element.type.toString(), "<T>(T, T) → T");
+ expect(t.element, same(tElement));
+
+ // re-resolve
+ CompilationUnit unit2 = _cloneResolveUnit(unit);
+ node = _findSimpleIdentifier(unit2, code, 'max').parent;
+ t = node.typeParameters.typeParameters[0];
+ expect(t.element, same(tElement));
}
}
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index a404b92..e2b20b3 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -348,6 +348,12 @@
}
@override
+ bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
+ fail("Unexpected invocation of aboutToComputeResult");
+ return false;
+ }
+
+ @override
void addListener(AnalysisListener listener) {
fail("Unexpected invocation of addListener");
}
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index ca12036..6a52fce 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -25,7 +25,6 @@
import 'package:unittest/unittest.dart';
import '../reflective_tests.dart';
-import 'parser_test.dart';
import 'resolver_test.dart';
import 'test_support.dart';
@@ -1547,6 +1546,34 @@
''');
}
+ void test_false_method_getKeyword_add() {
+ _assertDoesNotMatchOK(
+ r'''
+class A {
+ void foo() {}
+}
+''',
+ r'''
+class A {
+ void get foo {}
+}
+''');
+ }
+
+ void test_false_method_getKeyword_remove() {
+ _assertDoesNotMatchOK(
+ r'''
+class A {
+ void get foo {}
+}
+''',
+ r'''
+class A {
+ void foo() {}
+}
+''');
+ }
+
void test_false_method_list_add() {
_assertDoesNotMatchOK(
r'''
@@ -1641,6 +1668,34 @@
''');
}
+ void test_false_method_setKeyword_add() {
+ _assertDoesNotMatchOK(
+ r'''
+class A {
+ void foo(x) {}
+}
+''',
+ r'''
+class A {
+ void set foo(x) {}
+}
+''');
+ }
+
+ void test_false_method_setKeyword_remove() {
+ _assertDoesNotMatchOK(
+ r'''
+class A {
+ void set foo(x) {}
+}
+''',
+ r'''
+class A {
+ void foo(x) {}
+}
+''');
+ }
+
void test_false_part_list_add() {
addNamedSource('/unitA.dart', 'part of lib; class A {}');
addNamedSource('/unitB.dart', 'part of lib; class B {}');
@@ -3003,7 +3058,7 @@
LibraryElement library = resolve2(source);
CompilationUnit oldUnit = resolveCompilationUnit(source, library);
// parse
- CompilationUnit newUnit = ParserTestCase.parseCompilationUnit(newContent);
+ CompilationUnit newUnit = IncrementalResolverTest._parseUnit(newContent);
// build elements
{
ElementHolder holder = new ElementHolder();
@@ -3990,6 +4045,27 @@
''');
}
+ void test_inBody_functionExpression() {
+ _resolveUnit(r'''
+class C extends D {
+ static final f = () {
+ var x = 0;
+ }();
+}
+
+class D {}
+''');
+ _updateAndValidate(r'''
+class C extends D {
+ static final f = () {
+ var x = 01;
+ }();
+}
+
+class D {}
+''');
+ }
+
void test_inBody_insertStatement() {
_resolveUnit(r'''
main() {
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 96a4b3e..0f43183 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -7038,6 +7038,30 @@
expect(declaration.propertyKeyword, isNull);
}
+ void test_parseCompilationUnitMember_function_generic_noReturnType() {
+ enableGenericMethods = true;
+ FunctionDeclaration declaration = parse("parseCompilationUnitMember",
+ <Object>[emptyCommentAndMetadata()], "f<E>() {}");
+ expect(declaration.returnType, isNull);
+ expect(declaration.functionExpression.typeParameters, isNotNull);
+ }
+
+ void test_parseCompilationUnitMember_function_generic_returnType() {
+ enableGenericMethods = true;
+ FunctionDeclaration declaration = parse("parseCompilationUnitMember",
+ <Object>[emptyCommentAndMetadata()], "E f<E>() {}");
+ expect(declaration.returnType, isNotNull);
+ expect(declaration.functionExpression.typeParameters, isNotNull);
+ }
+
+ void test_parseCompilationUnitMember_function_generic_void() {
+ enableGenericMethods = true;
+ FunctionDeclaration declaration = parse("parseCompilationUnitMember",
+ <Object>[emptyCommentAndMetadata()], "void f<T>(T t) {}");
+ expect(declaration.functionExpression, isNotNull);
+ expect(declaration.propertyKeyword, isNull);
+ }
+
void test_parseCompilationUnitMember_function_noType() {
FunctionDeclaration declaration = parse("parseCompilationUnitMember",
<Object>[emptyCommentAndMetadata()], "f() {}");
@@ -7058,14 +7082,6 @@
expect(declaration.returnType, isNotNull);
}
- void test_parseCompilationUnitMember_function_withTypeParameters() {
- enableGenericMethods = true;
- FunctionDeclaration declaration = parse("parseCompilationUnitMember",
- <Object>[emptyCommentAndMetadata()], "void f<T>(T t) {}");
- expect(declaration.functionExpression, isNotNull);
- expect(declaration.propertyKeyword, isNull);
- }
-
void test_parseCompilationUnitMember_getter_external_noType() {
FunctionDeclaration declaration = parse("parseCompilationUnitMember",
<Object>[emptyCommentAndMetadata()], "external get p;");
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 8c24fb2..1f1f2a5 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -201,8 +201,8 @@
'onValue', futureThenR, [futureElement.typeParameters[0]], null);
DartType futureRType = futureElement.type.substitute4([futureThenR.type]);
- MethodElementImpl thenMethod = ElementFactory.methodElementWithParameters(
- futureElement, "then", futureRType, [
+ MethodElementImpl thenMethod = ElementFactory
+ .methodElementWithParameters(futureElement, "then", futureRType, [
ElementFactory.requiredParameter2("onValue", thenOnValue.type),
ElementFactory.namedParameter2("onError", provider.functionType)
]);
@@ -291,8 +291,8 @@
ClassElementImpl htmlDocumentElement =
ElementFactory.classElement("HtmlDocument", documentElement.type);
htmlDocumentElement.methods = <MethodElement>[
- ElementFactory.methodElement(
- "query", elementType, <DartType>[provider.stringType])
+ ElementFactory
+ .methodElement("query", elementType, <DartType>[provider.stringType])
];
htmlUnit.types = <ClassElement>[
ElementFactory.classElement("AnchorElement", elementType),
@@ -312,8 +312,8 @@
ElementFactory.functionElement3("query", elementElement,
<ClassElement>[provider.stringType.element], ClassElement.EMPTY_LIST)
];
- TopLevelVariableElementImpl document = ElementFactory
- .topLevelVariableElement3(
+ TopLevelVariableElementImpl document =
+ ElementFactory.topLevelVariableElement3(
"document", false, true, htmlDocumentElement.type);
htmlUnit.topLevelVariables = <TopLevelVariableElement>[document];
htmlUnit.accessors = <PropertyAccessorElement>[document.getter];
@@ -5153,7 +5153,8 @@
_assertNoErrors(classA);
}
- void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_getter_method() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_getter_method() {
// class I1 { int m(); }
// class I2 { int get m; }
// class A implements I2, I1 {}
@@ -5176,7 +5177,8 @@
[StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]);
}
- void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_int_str() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_int_str() {
// class I1 { int m(); }
// class I2 { String m(); }
// class A implements I1, I2 {}
@@ -5186,8 +5188,8 @@
ElementFactory.methodElement(methodName, null, [_typeProvider.intType]);
classI1.methods = <MethodElement>[methodM1];
ClassElementImpl classI2 = ElementFactory.classElement2("I2");
- MethodElement methodM2 = ElementFactory.methodElement(
- methodName, null, [_typeProvider.stringType]);
+ MethodElement methodM2 = ElementFactory
+ .methodElement(methodName, null, [_typeProvider.stringType]);
classI2.methods = <MethodElement>[methodM2];
ClassElementImpl classA = ElementFactory.classElement2("A");
classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
@@ -5199,7 +5201,8 @@
classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]);
}
- void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_method_getter() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_method_getter() {
// class I1 { int m(); }
// class I2 { int get m; }
// class A implements I1, I2 {}
@@ -5222,7 +5225,8 @@
[StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]);
}
- void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_numOfRequiredParams() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_numOfRequiredParams() {
// class I1 { dynamic m(int, [int]); }
// class I2 { dynamic m(int, int, int); }
// class A implements I1, I2 {}
@@ -5271,14 +5275,15 @@
classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]);
}
- void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_str_int() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_str_int() {
// class I1 { int m(); }
// class I2 { String m(); }
// class A implements I2, I1 {}
ClassElementImpl classI1 = ElementFactory.classElement2("I1");
String methodName = "m";
- MethodElement methodM1 = ElementFactory.methodElement(
- methodName, null, [_typeProvider.stringType]);
+ MethodElement methodM1 = ElementFactory
+ .methodElement(methodName, null, [_typeProvider.stringType]);
classI1.methods = <MethodElement>[methodM1];
ClassElementImpl classI2 = ElementFactory.classElement2("I2");
MethodElement methodM2 =
@@ -5380,7 +5385,8 @@
_assertNoErrors(classA);
}
- void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_getters() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_getters() {
// class I1 { int get g; }
// class I2 { num get g; }
// class A implements I1, I2 {}
@@ -5404,7 +5410,8 @@
_assertNoErrors(classA);
}
- void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_methods() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_methods() {
// class I1 { dynamic m(int); }
// class I2 { dynamic m(num); }
// class A implements I1, I2 {}
@@ -5438,7 +5445,8 @@
_assertNoErrors(classA);
}
- void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_setters() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_setters() {
// class I1 { set s(int); }
// class I2 { set s(num); }
// class A implements I1, I2 {}
@@ -5463,7 +5471,8 @@
_assertNoErrors(classA);
}
- void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_getters() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_getters() {
// class A {}
// class B extends A {}
// class C extends B {}
@@ -5502,7 +5511,8 @@
_assertNoErrors(classD);
}
- void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_methods() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_methods() {
// class A {}
// class B extends A {}
// class C extends B {}
@@ -5556,7 +5566,8 @@
_assertNoErrors(classD);
}
- void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_setters() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_setters() {
// class A {}
// class B extends A {}
// class C extends B {}
@@ -5596,7 +5607,8 @@
_assertNoErrors(classD);
}
- void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_2_methods() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_2_methods() {
// class I1 { int m(); }
// class I2 { int m([int]); }
// class A implements I1, I2 {}
@@ -5623,7 +5635,8 @@
_assertNoErrors(classA);
}
- void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_3_methods() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_3_methods() {
// class I1 { int m(); }
// class I2 { int m([int]); }
// class I3 { int m([int, int]); }
@@ -5668,7 +5681,8 @@
_assertNoErrors(classA);
}
- void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_4_methods() {
+ void
+ test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_4_methods() {
// class I1 { int m(); }
// class I2 { int m(); }
// class I3 { int m([int]); }
@@ -9370,7 +9384,9 @@
expect(declarations, hasLength(2));
Element expectedElement = (declarations[0] as TopLevelVariableDeclaration)
.variables
- .variables[0].name.staticElement;
+ .variables[0]
+ .name
+ .staticElement;
EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement,
PropertyInducingElement, expectedElement);
expectedElement = (expectedElement as PropertyInducingElement).getter;
@@ -9561,7 +9577,9 @@
expect(declarations, hasLength(2));
Element expectedElement = (declarations[0] as TopLevelVariableDeclaration)
.variables
- .variables[0].name.staticElement;
+ .variables[0]
+ .name
+ .staticElement;
EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement,
PropertyInducingElement, expectedElement);
expectedElement = (expectedElement as PropertyInducingElement).getter;
@@ -11782,19 +11800,27 @@
@reflectiveTest
class StrongModeDownwardsInferenceTest extends ResolverTestCase {
TypeAssertions _assertions;
- AsserterBuilder<Element, DartType> _hasElement;
- AsserterBuilder<DartType, DartType> _isType;
- AsserterBuilder2<Asserter<DartType>, Asserter<DartType>,
- DartType> _isFunction2Of;
- AsserterBuilderBuilder<Asserter<DartType>, List<Asserter<DartType>>,
- DartType> _isInstantiationOf;
+
+ Asserter<DartType> _isDynamic;
+ Asserter<InterfaceType> _isFutureOfDynamic;
+ Asserter<InterfaceType> _isFutureOfInt;
Asserter<DartType> _isInt;
Asserter<DartType> _isNum;
Asserter<DartType> _isString;
- Asserter<DartType> _isDynamic;
+
+ AsserterBuilder2<Asserter<DartType>, Asserter<DartType>, DartType>
+ _isFunction2Of;
+ AsserterBuilder<List<Asserter<DartType>>, InterfaceType> _isFutureOf;
+ AsserterBuilderBuilder<Asserter<DartType>, List<Asserter<DartType>>, DartType>
+ _isInstantiationOf;
AsserterBuilder<Asserter<DartType>, InterfaceType> _isListOf;
- AsserterBuilder2<Asserter<DartType>, Asserter<DartType>,
- InterfaceType> _isMapOf;
+ AsserterBuilder2<Asserter<DartType>, Asserter<DartType>, InterfaceType>
+ _isMapOf;
+ AsserterBuilder<List<Asserter<DartType>>, InterfaceType> _isStreamOf;
+ AsserterBuilder<DartType, DartType> _isType;
+
+ AsserterBuilder<Element, DartType> _hasElement;
+ AsserterBuilder<DartType, DartType> _sameElement;
@override
void setUp() {
@@ -11812,6 +11838,187 @@
_isListOf = _assertions.isListOf;
_isMapOf = _assertions.isMapOf;
_isFunction2Of = _assertions.isFunction2Of;
+ _sameElement = _assertions.sameElement;
+ _isFutureOf = _isInstantiationOf(_sameElement(typeProvider.futureType));
+ _isFutureOfDynamic = _isFutureOf([_isDynamic]);
+ _isFutureOfInt = _isFutureOf([_isInt]);
+ _isStreamOf = _isInstantiationOf(_sameElement(typeProvider.streamType));
+ }
+
+ void test_async_method_propagation() {
+ String code = r'''
+ import "dart:async";
+ class A {
+ Future f0() => new Future.value(3);
+ Future f1() async => new Future.value(3);
+ Future f2() async => await new Future.value(3);
+
+ Future<int> f3() => new Future.value(3);
+ Future<int> f4() async => new Future.value(3);
+ Future<int> f5() async => await new Future.value(3);
+
+ Future g0() { return new Future.value(3); }
+ Future g1() async { return new Future.value(3); }
+ Future g2() async { return await new Future.value(3); }
+
+ Future<int> g3() { return new Future.value(3); }
+ Future<int> g4() async { return new Future.value(3); }
+ Future<int> g5() async { return await new Future.value(3); }
+ }
+ ''';
+ CompilationUnit unit = resolveSource(code);
+
+ void check(String name, Asserter<InterfaceType> typeTest) {
+ MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name);
+ FunctionBody body = test.body;
+ Expression returnExp;
+ if (body is ExpressionFunctionBody) {
+ returnExp = body.expression;
+ } else {
+ ReturnStatement stmt = (body as BlockFunctionBody).block.statements[0];
+ returnExp = stmt.expression;
+ }
+ DartType type = returnExp.staticType;
+ if (returnExp is AwaitExpression) {
+ type = returnExp.expression.staticType;
+ }
+ typeTest(type);
+ }
+
+ check("f0", _isFutureOfDynamic);
+ check("f1", _isFutureOfDynamic);
+ check("f2", _isFutureOfDynamic);
+
+ check("f3", _isFutureOfInt);
+ // This should be int when we handle the implicit Future<T> | T union
+ // https://github.com/dart-lang/sdk/issues/25322
+ check("f4", _isFutureOfDynamic);
+ check("f5", _isFutureOfInt);
+
+ check("g0", _isFutureOfDynamic);
+ check("g1", _isFutureOfDynamic);
+ check("g2", _isFutureOfDynamic);
+
+ check("g3", _isFutureOfInt);
+ // This should be int when we handle the implicit Future<T> | T union
+ // https://github.com/dart-lang/sdk/issues/25322
+ check("g4", _isFutureOfDynamic);
+ check("g5", _isFutureOfInt);
+ }
+
+ void test_async_propagation() {
+ String code = r'''
+ import "dart:async";
+
+ Future f0() => new Future.value(3);
+ Future f1() async => new Future.value(3);
+ Future f2() async => await new Future.value(3);
+
+ Future<int> f3() => new Future.value(3);
+ Future<int> f4() async => new Future.value(3);
+ Future<int> f5() async => await new Future.value(3);
+
+ Future g0() { return new Future.value(3); }
+ Future g1() async { return new Future.value(3); }
+ Future g2() async { return await new Future.value(3); }
+
+ Future<int> g3() { return new Future.value(3); }
+ Future<int> g4() async { return new Future.value(3); }
+ Future<int> g5() async { return await new Future.value(3); }
+ ''';
+ CompilationUnit unit = resolveSource(code);
+
+ void check(String name, Asserter<InterfaceType> typeTest) {
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name);
+ FunctionBody body = test.functionExpression.body;
+ Expression returnExp;
+ if (body is ExpressionFunctionBody) {
+ returnExp = body.expression;
+ } else {
+ ReturnStatement stmt = (body as BlockFunctionBody).block.statements[0];
+ returnExp = stmt.expression;
+ }
+ DartType type = returnExp.staticType;
+ if (returnExp is AwaitExpression) {
+ type = returnExp.expression.staticType;
+ }
+ typeTest(type);
+ }
+
+ check("f0", _isFutureOfDynamic);
+ check("f1", _isFutureOfDynamic);
+ check("f2", _isFutureOfDynamic);
+
+ check("f3", _isFutureOfInt);
+ // This should be int when we handle the implicit Future<T> | T union
+ // https://github.com/dart-lang/sdk/issues/25322
+ check("f4", _isFutureOfDynamic);
+ check("f5", _isFutureOfInt);
+
+ check("g0", _isFutureOfDynamic);
+ check("g1", _isFutureOfDynamic);
+ check("g2", _isFutureOfDynamic);
+
+ check("g3", _isFutureOfInt);
+ // This should be int when we handle the implicit Future<T> | T union
+ // https://github.com/dart-lang/sdk/issues/25322
+ check("g4", _isFutureOfDynamic);
+ check("g5", _isFutureOfInt);
+ }
+
+ void test_async_star_method_propagation() {
+ String code = r'''
+ import "dart:async";
+ class A {
+ Stream g0() async* { yield []; }
+ Stream g1() async* { yield* new Stream(); }
+
+ Stream<List<int>> g2() async* { yield []; }
+ Stream<List<int>> g3() async* { yield* new Stream(); }
+ }
+ ''';
+ CompilationUnit unit = resolveSource(code);
+
+ void check(String name, Asserter<InterfaceType> typeTest) {
+ MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name);
+ BlockFunctionBody body = test.body;
+ YieldStatement stmt = body.block.statements[0];
+ Expression exp = stmt.expression;
+ typeTest(exp.staticType);
+ }
+
+ check("g0", _isListOf(_isDynamic));
+ check("g1", _isStreamOf([_isDynamic]));
+
+ check("g2", _isListOf(_isInt));
+ check("g3", _isStreamOf([_isListOf(_isInt)]));
+ }
+
+ void test_async_star_propagation() {
+ String code = r'''
+ import "dart:async";
+
+ Stream g0() async* { yield []; }
+ Stream g1() async* { yield* new Stream(); }
+
+ Stream<List<int>> g2() async* { yield []; }
+ Stream<List<int>> g3() async* { yield* new Stream(); }
+ ''';
+ CompilationUnit unit = resolveSource(code);
+
+ void check(String name, Asserter<InterfaceType> typeTest) {
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name);
+ BlockFunctionBody body = test.functionExpression.body;
+ YieldStatement stmt = body.block.statements[0];
+ Expression exp = stmt.expression;
+ typeTest(exp.staticType);
+ }
+
+ check("g0", _isListOf(_isDynamic));
+ check("g1", _isStreamOf([_isDynamic]));
+
+ check("g2", _isListOf(_isInt));
+ check("g3", _isStreamOf([_isListOf(_isInt)]));
}
void test_cascadeExpression() {
@@ -12751,6 +12958,61 @@
Expression exp = invocation.argumentList.arguments[0];
_isListOf(_isString)(exp.staticType);
}
+
+ void test_sync_star_method_propagation() {
+ String code = r'''
+ import "dart:async";
+ class A {
+ Iterable f0() sync* { yield []; }
+ Iterable f1() sync* { yield* new List(); }
+
+ Iterable<List<int>> f2() sync* { yield []; }
+ Iterable<List<int>> f3() sync* { yield* new List(); }
+ }
+ ''';
+ CompilationUnit unit = resolveSource(code);
+
+ void check(String name, Asserter<InterfaceType> typeTest) {
+ MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name);
+ BlockFunctionBody body = test.body;
+ YieldStatement stmt = body.block.statements[0];
+ Expression exp = stmt.expression;
+ typeTest(exp.staticType);
+ }
+
+ check("f0", _isListOf(_isDynamic));
+ check("f1", _isListOf(_isDynamic));
+
+ check("f2", _isListOf(_isInt));
+ check("f3", _isListOf(_isListOf(_isInt)));
+ }
+
+ void test_sync_star_propagation() {
+ String code = r'''
+ import "dart:async";
+
+ Iterable f0() sync* { yield []; }
+ Iterable f1() sync* { yield* new List(); }
+
+ Iterable<List<int>> f2() sync* { yield []; }
+ Iterable<List<int>> f3() sync* { yield* new List(); }
+ ''';
+ CompilationUnit unit = resolveSource(code);
+
+ void check(String name, Asserter<InterfaceType> typeTest) {
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name);
+ BlockFunctionBody body = test.functionExpression.body;
+ YieldStatement stmt = body.block.statements[0];
+ Expression exp = stmt.expression;
+ typeTest(exp.staticType);
+ }
+
+ check("f0", _isListOf(_isDynamic));
+ check("f1", _isListOf(_isDynamic));
+
+ check("f2", _isListOf(_isInt));
+ check("f3", _isListOf(_isListOf(_isInt)));
+ }
}
/**
@@ -14025,7 +14287,8 @@
code, typeProvider.dynamicType, typeProvider.intType);
}
- void test_finalPropertyInducingVariable_classMember_instance_propagatedTarget() {
+ void
+ test_finalPropertyInducingVariable_classMember_instance_propagatedTarget() {
addNamedSource(
"/lib.dart",
r'''
@@ -14244,7 +14507,8 @@
expect(vParameter.identifier.propagatedType, same(stringType));
}
- void test_functionExpression_asInvocationArgument_functionExpressionInvocation() {
+ void
+ test_functionExpression_asInvocationArgument_functionExpressionInvocation() {
String code = r'''
main() {
(f(String value)) {} ((v) {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index cffd7d9..642b60b 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -6,7 +6,7 @@
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/builder.dart';
+import 'package:analyzer/src/summary/base.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/resynthesize.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
@@ -349,9 +349,11 @@
// TODO(paulberry): test evaluationResult
}
- void compareTypeImpls(TypeImpl resynthesized, TypeImpl original) {
- expect(resynthesized.element.location, original.element.location);
- expect(resynthesized.name, original.name);
+ void compareTypeImpls(
+ TypeImpl resynthesized, TypeImpl original, String desc) {
+ expect(resynthesized.element.location, original.element.location,
+ reason: desc);
+ expect(resynthesized.name, original.name, reason: desc);
}
void compareTypeParameterElements(TypeParameterElementImpl resynthesized,
@@ -366,7 +368,7 @@
expect(resynthesized, isNull, reason: desc);
} else if (resynthesized is InterfaceTypeImpl &&
original is InterfaceTypeImpl) {
- compareTypeImpls(resynthesized, original);
+ compareTypeImpls(resynthesized, original, desc);
expect(resynthesized.typeArguments.length, original.typeArguments.length);
for (int i = 0; i < resynthesized.typeArguments.length; i++) {
compareTypes(resynthesized.typeArguments[i], original.typeArguments[i],
@@ -374,7 +376,7 @@
}
} else if (resynthesized is TypeParameterTypeImpl &&
original is TypeParameterTypeImpl) {
- compareTypeImpls(resynthesized, original);
+ compareTypeImpls(resynthesized, original, desc);
} else if (resynthesized is DynamicTypeImpl &&
original is DynamicTypeImpl) {
expect(resynthesized, same(original));
@@ -383,17 +385,38 @@
expect(resynthesized, same(original));
} else if (resynthesized is FunctionTypeImpl &&
original is FunctionTypeImpl) {
- compareTypeImpls(resynthesized, original);
+ compareTypeImpls(resynthesized, original, desc);
if (original.element.isSynthetic &&
original.element is FunctionTypeAliasElementImpl &&
resynthesized.element is FunctionTypeAliasElementImpl) {
compareFunctionTypeAliasElements(
resynthesized.element, original.element, desc);
}
+ expect(resynthesized.typeArguments.length, original.typeArguments.length,
+ reason: desc);
for (int i = 0; i < resynthesized.typeArguments.length; i++) {
compareTypes(resynthesized.typeArguments[i], original.typeArguments[i],
'$desc type argument ${original.typeArguments[i].name}');
}
+ if (original.typeParameters == null) {
+ expect(resynthesized.typeParameters, isNull, reason: desc);
+ } else {
+ expect(resynthesized.typeParameters, isNotNull, reason: desc);
+ expect(
+ resynthesized.typeParameters.length, original.typeParameters.length,
+ reason: desc);
+ for (int i = 0; i < resynthesized.typeParameters.length; i++) {
+ compareTypeParameterElements(resynthesized.typeParameters[i],
+ original.typeParameters[i], '$desc type parameter $i');
+ }
+ }
+ expect(resynthesized.boundTypeParameters.length,
+ original.boundTypeParameters.length,
+ reason: desc);
+ for (int i = 0; i < resynthesized.boundTypeParameters.length; i++) {
+ compareTypeParameterElements(resynthesized.boundTypeParameters[i],
+ original.boundTypeParameters[i], '$desc bound type parameter $i');
+ }
} else if (resynthesized is VoidTypeImpl && original is VoidTypeImpl) {
expect(resynthesized, same(original));
} else if (resynthesized.runtimeType != original.runtimeType) {
@@ -463,6 +486,7 @@
}
SummaryResynthesizer resynthesizer = new SummaryResynthesizer(
analysisContext,
+ analysisContext.typeProvider,
getPrelinkedSummary,
getUnlinkedSummary,
analysisContext.sourceFactory);
@@ -599,6 +623,14 @@
checkLibrary('class C { int get x => null; get y => null; }');
}
+ test_class_implicitField_getterFirst() {
+ checkLibrary('class C { int get x => 0; void set x(int value) {} }');
+ }
+
+ test_class_implicitField_setterFirst() {
+ checkLibrary('class C { void set x(int value) {} int get x => 0; }');
+ }
+
test_class_interfaces() {
checkLibrary('class C implements D, E {} class D {} class E {}');
}
@@ -942,6 +974,13 @@
checkLibrary('import "a.dart"; C c; E e; F f;');
}
+ test_type_reference_to_import_part2() {
+ addLibrarySource('/a.dart', 'library l; part "p1.dart"; part "p2.dart";');
+ addNamedSource('/p1.dart', 'part of l; class C1 {}');
+ addNamedSource('/p2.dart', 'part of l; class C2 {}');
+ checkLibrary('import "a.dart"; C1 c1; C2 c2;');
+ }
+
test_type_reference_to_import_part_in_subdir() {
addLibrarySource('/a/b.dart', 'library l; part "c.dart";');
addNamedSource(
diff --git a/pkg/analyzer/test/src/summary/summary_test.dart b/pkg/analyzer/test/src/summary/summary_test.dart
index a658d2b..e9d46b4 100644
--- a/pkg/analyzer/test/src/summary/summary_test.dart
+++ b/pkg/analyzer/test/src/summary/summary_test.dart
@@ -5,11 +5,18 @@
library analyzer.test.src.summary.summary_test;
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_engine_io.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/builder.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/summary/base.dart';
import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/public_namespace_computer.dart'
+ as public_namespace;
import 'package:analyzer/src/summary/summarize_elements.dart'
as summarize_elements;
import 'package:unittest/unittest.dart';
@@ -27,10 +34,54 @@
*/
@reflectiveTest
class SummarizeElementsTest extends ResolverTestCase with SummaryTest {
+ final BuilderContext builderContext = new BuilderContext();
+
+ /**
+ * The list of absolute unit URIs corresponding to the compilation units in
+ * [unlinkedUnits].
+ */
+ List<String> unitUris;
+
@override
bool get checkAstDerivedData => false;
/**
+ * Convert a summary object (or a portion of one) into a canonical form that
+ * can be easily compared using [expect]. If [orderByName] is true, and the
+ * object is a [List], it is sorted by the `name` field of its elements.
+ */
+ Object canonicalize(Object obj, {bool orderByName: false}) {
+ if (obj is SummaryClass) {
+ Map<String, Object> result = <String, Object>{};
+ obj.toMap().forEach((String key, Object value) {
+ bool orderByName = false;
+ if (obj is UnlinkedPublicNamespace && key == 'names') {
+ orderByName = true;
+ }
+ result[key] = canonicalize(value, orderByName: orderByName);
+ });
+ return result;
+ } else if (obj is List) {
+ List<Object> result = <Object>[];
+ for (Object item in obj) {
+ result.add(canonicalize(item));
+ }
+ if (orderByName) {
+ result.sort((Object a, Object b) {
+ if (a is Map && b is Map) {
+ return Comparable.compare(a['name'], b['name']);
+ } else {
+ return 0;
+ }
+ });
+ }
+ return result;
+ } else {
+ return obj;
+ }
+ }
+
+ /**
* Serialize the library containing the given class [element], then
* deserialize it and return the summary of the class.
*/
@@ -41,10 +92,9 @@
/**
* Serialize the given [library] element, then deserialize it and store the
- * resulting summary in [lib].
+ * resulting summary in [prelinked] and [unlinkedUnits].
*/
void serializeLibraryElement(LibraryElement library) {
- BuilderContext builderContext = new BuilderContext();
summarize_elements.LibrarySerializationResult serializedLib =
summarize_elements.serializeLibrary(
builderContext, library, typeProvider);
@@ -54,6 +104,7 @@
.map((UnlinkedUnitBuilder b) =>
new UnlinkedUnit.fromBuffer(b.toBuffer()))
.toList();
+ unitUris = serializedLib.unitUris;
}
@override
@@ -71,6 +122,7 @@
expect(unlinkedUnits[i].references.length,
prelinked.units[i].references.length);
}
+ verifyPublicNamespace();
}
@override
@@ -86,6 +138,30 @@
expect(cls.supertype, isNull);
expect(cls.hasNoSupertype, isTrue);
}
+
+ /**
+ * Verify that [public_namespace.computePublicNamespace] produces data that's
+ * equivalent to that produced by [summarize_elements.serializeLibrary].
+ */
+ void verifyPublicNamespace() {
+ for (int i = 0; i < unlinkedUnits.length; i++) {
+ Source source = analysisContext.sourceFactory.forUri(unitUris[i]);
+ String text = analysisContext.getContents(source).data;
+ CharacterReader reader = new CharSequenceReader(text);
+ Scanner scanner =
+ new Scanner(source, reader, AnalysisErrorListener.NULL_LISTENER);
+ Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
+ parser.parseGenericMethods = true;
+ CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
+ UnlinkedPublicNamespace namespace =
+ new UnlinkedPublicNamespace.fromBuffer(public_namespace
+ .computePublicNamespace(builderContext, unit)
+ .toBuffer());
+ expect(canonicalize(namespace),
+ canonicalize(unlinkedUnits[i].publicNamespace),
+ reason: 'publicNamespace(${unitUris[i]})');
+ }
+ }
}
/**
@@ -135,16 +211,6 @@
addNamedSource(String filePath, String contents);
/**
- * Verify that the [combinatorName] correctly represents the given [expected]
- * name.
- */
- void checkCombinatorName(
- UnlinkedCombinatorName combinatorName, String expected) {
- expect(combinatorName, new isInstanceOf<UnlinkedCombinatorName>());
- expect(combinatorName.name, expected);
- }
-
- /**
* Verify that the [dependency]th element of the dependency table represents
* a file reachable via the given [absoluteUri] and [relativeUri].
*/
@@ -239,7 +305,8 @@
* specified they are assumed to refer to the defining compilation unit.
* [expectedTargetUnit] is the index of the compilation unit in which the
* target of the [typeRef] is expected to appear; if not specified it is
- * assumed to be the defining compilation unit.
+ * assumed to be the defining compilation unit. [numTypeParameters] is the
+ * number of type parameters of the thing being referred to.
*/
void checkTypeRef(UnlinkedTypeRef typeRef, String absoluteUri,
String relativeUri, String expectedName,
@@ -248,7 +315,8 @@
PrelinkedReferenceKind expectedKind: PrelinkedReferenceKind.classOrEnum,
int expectedTargetUnit: 0,
PrelinkedUnit prelinkedSourceUnit,
- UnlinkedUnit unlinkedSourceUnit}) {
+ UnlinkedUnit unlinkedSourceUnit,
+ int numTypeParameters: 0}) {
prelinkedSourceUnit ??= definingUnit;
unlinkedSourceUnit ??= unlinkedUnits[0];
expect(typeRef, new isInstanceOf<UnlinkedTypeRef>());
@@ -284,6 +352,7 @@
}
expect(referenceResolution.kind, expectedKind);
expect(referenceResolution.unit, expectedTargetUnit);
+ expect(referenceResolution.numTypeParameters, numTypeParameters);
}
/**
@@ -492,7 +561,8 @@
UnlinkedTypeRef serializeTypeText(String text,
{String otherDeclarations: '', bool allowErrors: false}) {
return serializeVariableText('$otherDeclarations\n$text v;',
- allowErrors: allowErrors).type;
+ allowErrors: allowErrors)
+ .type;
}
/**
@@ -646,8 +716,12 @@
test_class_alias_concrete() {
UnlinkedClass cls =
- serializeClassText('class C = D with E; class D {} class E {}');
+ serializeClassText('class C = _D with _E; class _D {} class _E {}');
expect(cls.isAbstract, false);
+ expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+ PrelinkedReferenceKind.classOrEnum);
+ expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
}
test_class_alias_flag() {
@@ -680,6 +754,26 @@
expect(cls.executables, isEmpty);
}
+ test_class_alias_private() {
+ serializeClassText('class _C = _D with _E; class _D {} class _E {}', '_C');
+ expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+ }
+
+ test_class_alias_reference_generic() {
+ UnlinkedTypeRef typeRef = serializeTypeText('C',
+ otherDeclarations: 'class C<D, E> = F with G; class F {} class G {}');
+ checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2);
+ }
+
+ test_class_alias_reference_generic_imported() {
+ addNamedSource(
+ '/lib.dart', 'class C<D, E> = F with G; class F {} class G {}');
+ UnlinkedTypeRef typeRef =
+ serializeTypeText('C', otherDeclarations: 'import "lib.dart";');
+ checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'C',
+ numTypeParameters: 2);
+ }
+
test_class_alias_supertype() {
UnlinkedClass cls =
serializeClassText('class C = D with E; class D {} class E {}');
@@ -690,6 +784,10 @@
test_class_concrete() {
UnlinkedClass cls = serializeClassText('class C {}');
expect(cls.isAbstract, false);
+ expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+ PrelinkedReferenceKind.classOrEnum);
+ expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
}
test_class_interface() {
@@ -764,6 +862,25 @@
expect(cls.isMixinApplication, false);
}
+ test_class_private() {
+ serializeClassText('class _C {}', '_C');
+ expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+ }
+
+ test_class_reference_generic() {
+ UnlinkedTypeRef typeRef =
+ serializeTypeText('C', otherDeclarations: 'class C<D, E> {}');
+ checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2);
+ }
+
+ test_class_reference_generic_imported() {
+ addNamedSource('/lib.dart', 'class C<D, E> {}');
+ UnlinkedTypeRef typeRef =
+ serializeTypeText('C', otherDeclarations: 'import "lib.dart";');
+ checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'C',
+ numTypeParameters: 2);
+ }
+
test_class_superclass() {
UnlinkedClass cls = serializeClassText('class C {}');
expect(cls.supertype, isNull);
@@ -783,7 +900,7 @@
expect(cls.typeParameters[0].name, 'T');
expect(cls.typeParameters[0].bound, isNotNull);
checkTypeRef(cls.typeParameters[0].bound, 'dart:core', 'dart:core', 'List',
- allowTypeParameters: true);
+ allowTypeParameters: true, numTypeParameters: 1);
}
test_class_type_param_f_bound() {
@@ -901,7 +1018,7 @@
checkDynamicTypeRef(parameter.type);
}
- test_constructor_initializing_formal_function_typed_no_prameters() {
+ test_constructor_initializing_formal_function_typed_no_parameters() {
UnlinkedExecutable executable = findExecutable('',
executables: serializeClassText('class C { C(this.x()); final x; }')
.executables);
@@ -909,7 +1026,7 @@
expect(parameter.parameters, isEmpty);
}
- test_constructor_initializing_formal_function_typed_prameter() {
+ test_constructor_initializing_formal_function_typed_parameter() {
UnlinkedExecutable executable = findExecutable('',
executables: serializeClassText('class C { C(this.x(a)); final x; }')
.executables);
@@ -917,7 +1034,7 @@
expect(parameter.parameters, hasLength(1));
}
- test_constructor_initializing_formal_function_typed_prameter_order() {
+ test_constructor_initializing_formal_function_typed_parameter_order() {
UnlinkedExecutable executable = findExecutable('',
executables: serializeClassText('class C { C(this.x(a, b)); final x; }')
.executables);
@@ -980,6 +1097,15 @@
expect(parameter.kind, UnlinkedParamKind.required);
}
+ test_constructor_initializing_formal_typedef() {
+ UnlinkedExecutable executable = findExecutable('',
+ executables: serializeClassText(
+ 'typedef F<T>(T x); class C<X> { C(this.f); F<X> f; }')
+ .executables);
+ UnlinkedParam parameter = executable.parameters[0];
+ expect(parameter.parameters, hasLength(1));
+ }
+
test_constructor_named() {
UnlinkedExecutable executable = findExecutable('foo',
executables: serializeClassText('class C { C.foo(); }').executables);
@@ -1008,7 +1134,7 @@
UnlinkedExecutable executable = findExecutable('',
executables: serializeClassText('class C<T, U> { C(); }').executables);
checkTypeRef(executable.returnType, null, null, 'C',
- allowTypeParameters: true);
+ allowTypeParameters: true, numTypeParameters: 2);
expect(executable.returnType.typeArguments, hasLength(2));
{
UnlinkedTypeRef typeRef = executable.returnType.typeArguments[0];
@@ -1129,6 +1255,10 @@
expect(e.name, 'E');
expect(e.values, hasLength(1));
expect(e.values[0].name, 'v1');
+ expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+ PrelinkedReferenceKind.classOrEnum);
+ expect(unlinkedUnits[0].publicNamespace.names[0].name, 'E');
}
test_enum_order() {
@@ -1138,6 +1268,11 @@
expect(e.values[1].name, 'v2');
}
+ test_enum_private() {
+ serializeEnumText('enum _E { v1 }', '_E');
+ expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+ }
+
test_executable_abstract() {
UnlinkedExecutable executable =
serializeClassText('abstract class C { f(); }').executables[0];
@@ -1156,6 +1291,10 @@
expect(executable.hasImplicitReturnType, isTrue);
checkDynamicTypeRef(executable.returnType);
expect(executable.isExternal, isFalse);
+ expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+ PrelinkedReferenceKind.other);
+ expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f');
}
test_executable_function_explicit_return() {
@@ -1170,6 +1309,11 @@
expect(executable.isExternal, isTrue);
}
+ test_executable_function_private() {
+ serializeExecutableText('_f() {}', '_f');
+ expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+ }
+
test_executable_getter() {
UnlinkedExecutable executable = serializeExecutableText('int get f => 1;');
expect(executable.kind, UnlinkedExecutableKind.getter);
@@ -1177,6 +1321,10 @@
expect(executable.isExternal, isFalse);
expect(findVariable('f'), isNull);
expect(findExecutable('f='), isNull);
+ expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+ PrelinkedReferenceKind.other);
+ expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f');
}
test_executable_getter_external() {
@@ -1185,6 +1333,11 @@
expect(executable.isExternal, isTrue);
}
+ test_executable_getter_private() {
+ serializeExecutableText('int get _f => 1;', '_f');
+ expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+ }
+
test_executable_getter_type() {
UnlinkedExecutable executable = serializeExecutableText('int get f => 1;');
checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'int');
@@ -1347,7 +1500,8 @@
test_executable_operator_index_set() {
UnlinkedExecutable executable = serializeClassText(
- 'class C { void operator[]=(int i, bool v) => null; }').executables[0];
+ 'class C { void operator[]=(int i, bool v) => null; }')
+ .executables[0];
expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
expect(executable.name, '[]=');
expect(executable.hasImplicitReturnType, false);
@@ -1496,6 +1650,10 @@
expect(executable.isExternal, isFalse);
expect(findVariable('f'), isNull);
expect(findExecutable('f'), isNull);
+ expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+ PrelinkedReferenceKind.other);
+ expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f=');
}
test_executable_setter_external() {
@@ -1512,6 +1670,11 @@
checkDynamicTypeRef(executable.returnType);
}
+ test_executable_setter_private() {
+ serializeExecutableText('void set _f(value) {}', '_f=');
+ expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+ }
+
test_executable_setter_type() {
UnlinkedExecutable executable =
serializeExecutableText('void set f(int value) {}', 'f=');
@@ -1528,62 +1691,88 @@
expect(executable.isStatic, isTrue);
}
- test_executable_type_param_f_bound() {
- // TODO(paulberry): also test top level executables.
+ test_executable_type_param_f_bound_function() {
+ UnlinkedExecutable ex =
+ serializeExecutableText('void f<T, U extends List<T>>() {}');
+ UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
+ checkParamTypeRef(typeArgument, 2);
+ }
+
+ test_executable_type_param_f_bound_method() {
UnlinkedExecutable ex =
serializeMethodText('void f<T, U extends List<T>>() {}');
UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
checkParamTypeRef(typeArgument, 2);
}
- test_executable_type_param_f_bound_self_ref() {
- // TODO(paulberry): also test top level executables.
+ test_executable_type_param_f_bound_self_ref_function() {
+ UnlinkedExecutable ex =
+ serializeExecutableText('void f<T, U extends List<U>>() {}');
+ UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
+ checkParamTypeRef(typeArgument, 1);
+ }
+
+ test_executable_type_param_f_bound_self_ref_method() {
UnlinkedExecutable ex =
serializeMethodText('void f<T, U extends List<U>>() {}');
UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
checkParamTypeRef(typeArgument, 1);
}
- test_executable_type_param_in_parameter() {
- // TODO(paulberry): also test top level executables.
+ test_executable_type_param_in_parameter_function() {
+ UnlinkedExecutable ex = serializeExecutableText('void f<T>(T t) {}');
+ checkParamTypeRef(ex.parameters[0].type, 1);
+ }
+
+ test_executable_type_param_in_parameter_method() {
UnlinkedExecutable ex = serializeMethodText('void f<T>(T t) {}');
checkParamTypeRef(ex.parameters[0].type, 1);
}
- test_executable_type_param_in_return_type() {
- // TODO(paulberry): also test top level executables.
+ test_executable_type_param_in_return_type_function() {
+ UnlinkedExecutable ex = serializeExecutableText('T f<T>() => null;');
+ checkParamTypeRef(ex.returnType, 1);
+ }
+
+ test_executable_type_param_in_return_type_method() {
UnlinkedExecutable ex = serializeMethodText('T f<T>() => null;');
checkParamTypeRef(ex.returnType, 1);
}
test_export_hide_order() {
serializeLibraryText('export "dart:async" hide Future, Stream;');
- expect(unlinkedUnits[0].exports, hasLength(1));
- expect(unlinkedUnits[0].exports[0].combinators, hasLength(1));
- expect(unlinkedUnits[0].exports[0].combinators[0].shows, isEmpty);
- expect(unlinkedUnits[0].exports[0].combinators[0].hides, hasLength(2));
- checkCombinatorName(
- unlinkedUnits[0].exports[0].combinators[0].hides[0], 'Future');
- checkCombinatorName(
- unlinkedUnits[0].exports[0].combinators[0].hides[1], 'Stream');
+ expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+ expect(
+ unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows,
+ isEmpty);
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides,
+ hasLength(2));
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[0],
+ 'Future');
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[1],
+ 'Stream');
}
test_export_no_combinators() {
serializeLibraryText('export "dart:async";');
- expect(unlinkedUnits[0].exports, hasLength(1));
- expect(unlinkedUnits[0].exports[0].combinators, isEmpty);
+ expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators, isEmpty);
}
test_export_show_order() {
serializeLibraryText('export "dart:async" show Future, Stream;');
- expect(unlinkedUnits[0].exports, hasLength(1));
- expect(unlinkedUnits[0].exports[0].combinators, hasLength(1));
- expect(unlinkedUnits[0].exports[0].combinators[0].shows, hasLength(2));
- expect(unlinkedUnits[0].exports[0].combinators[0].hides, isEmpty);
- checkCombinatorName(
- unlinkedUnits[0].exports[0].combinators[0].shows[0], 'Future');
- checkCombinatorName(
- unlinkedUnits[0].exports[0].combinators[0].shows[1], 'Stream');
+ expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+ expect(
+ unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows,
+ hasLength(2));
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides,
+ isEmpty);
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[0],
+ 'Future');
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[1],
+ 'Stream');
}
test_export_uri() {
@@ -1591,8 +1780,8 @@
String uriString = '"a.dart"';
String libraryText = 'export $uriString;';
serializeLibraryText(libraryText);
- expect(unlinkedUnits[0].exports, hasLength(1));
- expect(unlinkedUnits[0].exports[0].uri, 'a.dart');
+ expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.exports[0].uri, 'a.dart');
}
test_field() {
@@ -1662,10 +1851,8 @@
expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
expect(unlinkedUnits[0].imports[0].combinators[0].shows, isEmpty);
expect(unlinkedUnits[0].imports[0].combinators[0].hides, hasLength(2));
- checkCombinatorName(
- unlinkedUnits[0].imports[0].combinators[0].hides[0], 'Future');
- checkCombinatorName(
- unlinkedUnits[0].imports[0].combinators[0].hides[1], 'Stream');
+ expect(unlinkedUnits[0].imports[0].combinators[0].hides[0], 'Future');
+ expect(unlinkedUnits[0].imports[0].combinators[0].hides[1], 'Stream');
}
test_import_implicit() {
@@ -1735,17 +1922,25 @@
expect(unlinkedUnits[0].imports[0].prefixReference, 0);
}
+ test_import_prefix_not_in_public_namespace() {
+ serializeLibraryText('import "dart:async" as a; a.Future v;');
+ expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
+ expect(unlinkedUnits[0].publicNamespace.names[0].name, 'v');
+ expect(unlinkedUnits[0].publicNamespace.names[1].name, 'v=');
+ }
+
test_import_prefix_reference() {
UnlinkedVariable variable =
serializeVariableText('import "dart:async" as a; a.Future v;');
checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future',
- expectedPrefix: 'a');
+ expectedPrefix: 'a', numTypeParameters: 1);
}
test_import_reference() {
UnlinkedVariable variable =
serializeVariableText('import "dart:async"; Future v;');
- checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future');
+ checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future',
+ numTypeParameters: 1);
}
test_import_reference_merged_no_prefix() {
@@ -1756,8 +1951,10 @@
Future f;
Stream s;
''');
- checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future');
- checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream');
+ checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future',
+ numTypeParameters: 1);
+ checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream',
+ numTypeParameters: 1);
}
test_import_reference_merged_prefixed() {
@@ -1769,9 +1966,9 @@
a.Stream s;
''');
checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future',
- expectedPrefix: 'a');
+ expectedPrefix: 'a', numTypeParameters: 1);
checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream',
- expectedPrefix: 'a');
+ expectedPrefix: 'a', numTypeParameters: 1);
}
test_import_show_order() {
@@ -1783,10 +1980,8 @@
expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
expect(unlinkedUnits[0].imports[0].combinators[0].shows, hasLength(2));
expect(unlinkedUnits[0].imports[0].combinators[0].hides, isEmpty);
- checkCombinatorName(
- unlinkedUnits[0].imports[0].combinators[0].shows[0], 'Future');
- checkCombinatorName(
- unlinkedUnits[0].imports[0].combinators[0].shows[1], 'Stream');
+ expect(unlinkedUnits[0].imports[0].combinators[0].shows[0], 'Future');
+ expect(unlinkedUnits[0].imports[0].combinators[0].shows[1], 'Stream');
}
test_import_uri() {
@@ -1812,7 +2007,7 @@
test_parts_defining_compilation_unit() {
serializeLibraryText('');
expect(prelinked.units, hasLength(1));
- expect(unlinkedUnits[0].parts, isEmpty);
+ expect(unlinkedUnits[0].publicNamespace.parts, isEmpty);
}
test_parts_included() {
@@ -1821,14 +2016,22 @@
String libraryText = 'library my.lib; part $partString;';
serializeLibraryText(libraryText);
expect(prelinked.units, hasLength(2));
- expect(unlinkedUnits[0].parts, hasLength(1));
- expect(unlinkedUnits[0].parts[0].uri, 'part1.dart');
+ expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.parts[0].uri, 'part1.dart');
+ }
+
+ test_public_namespace_of_part() {
+ addNamedSource('/a.dart', 'part of foo; class C {}');
+ serializeLibraryText('library foo; part "a.dart";');
+ expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+ expect(unlinkedUnits[1].publicNamespace.names, hasLength(1));
+ expect(unlinkedUnits[1].publicNamespace.names[0].name, 'C');
}
test_type_arguments_explicit() {
UnlinkedTypeRef typeRef = serializeTypeText('List<int>');
checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
- allowTypeParameters: true);
+ allowTypeParameters: true, numTypeParameters: 1);
expect(typeRef.typeArguments, hasLength(1));
checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
}
@@ -1836,7 +2039,7 @@
test_type_arguments_explicit_dynamic() {
UnlinkedTypeRef typeRef = serializeTypeText('List<dynamic>');
checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
- allowTypeParameters: true);
+ allowTypeParameters: true, numTypeParameters: 1);
expect(typeRef.typeArguments, isEmpty);
}
@@ -1845,7 +2048,8 @@
serializeTypeText('F<dynamic>', otherDeclarations: 'typedef T F<T>();');
checkTypeRef(typeRef, null, null, 'F',
allowTypeParameters: true,
- expectedKind: PrelinkedReferenceKind.typedef);
+ expectedKind: PrelinkedReferenceKind.typedef,
+ numTypeParameters: 1);
expect(typeRef.typeArguments, isEmpty);
}
@@ -1854,7 +2058,8 @@
serializeTypeText('F<int>', otherDeclarations: 'typedef T F<T>();');
checkTypeRef(typeRef, null, null, 'F',
allowTypeParameters: true,
- expectedKind: PrelinkedReferenceKind.typedef);
+ expectedKind: PrelinkedReferenceKind.typedef,
+ numTypeParameters: 1);
expect(typeRef.typeArguments, hasLength(1));
checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
}
@@ -1862,7 +2067,7 @@
test_type_arguments_implicit() {
UnlinkedTypeRef typeRef = serializeTypeText('List');
checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
- allowTypeParameters: true);
+ allowTypeParameters: true, numTypeParameters: 1);
expect(typeRef.typeArguments, isEmpty);
}
@@ -1871,14 +2076,15 @@
serializeTypeText('F', otherDeclarations: 'typedef T F<T>();');
checkTypeRef(typeRef, null, null, 'F',
allowTypeParameters: true,
- expectedKind: PrelinkedReferenceKind.typedef);
+ expectedKind: PrelinkedReferenceKind.typedef,
+ numTypeParameters: 1);
expect(typeRef.typeArguments, isEmpty);
}
test_type_arguments_order() {
UnlinkedTypeRef typeRef = serializeTypeText('Map<int, Object>');
checkTypeRef(typeRef, 'dart:core', 'dart:core', 'Map',
- allowTypeParameters: true);
+ allowTypeParameters: true, numTypeParameters: 2);
expect(typeRef.typeArguments, hasLength(2));
checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'dart:core', 'Object');
@@ -1992,15 +2198,14 @@
}
test_type_reference_to_part() {
- addNamedSource('/a.dart', 'part of foo; class C {}');
- checkTypeRef(
- serializeTypeText('C',
- otherDeclarations: 'library foo; part "a.dart";'),
- null,
- null,
- 'C',
+ addNamedSource('/a.dart', 'part of foo; class C { C(); }');
+ serializeLibraryText('library foo; part "a.dart"; C c;');
+ UnlinkedClass classA = findClass('C', unit: unlinkedUnits[1]);
+ checkTypeRef(classA.executables.single.returnType, null, null, 'C',
expectedKind: PrelinkedReferenceKind.classOrEnum,
- expectedTargetUnit: 1);
+ expectedTargetUnit: 1,
+ prelinkedSourceUnit: prelinked.units[1],
+ unlinkedSourceUnit: unlinkedUnits[1]);
}
test_type_reference_to_typedef() {
@@ -2030,6 +2235,10 @@
test_typedef_name() {
UnlinkedTypedef type = serializeTypedefText('typedef F();');
expect(type.name, 'F');
+ expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+ expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+ PrelinkedReferenceKind.typedef);
+ expect(unlinkedUnits[0].publicNamespace.names[0].name, 'F');
}
test_typedef_param_none() {
@@ -2044,6 +2253,26 @@
expect(type.parameters[1].name, 'y');
}
+ test_typedef_private() {
+ serializeTypedefText('typedef _F();', '_F');
+ expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+ }
+
+ test_typedef_reference_generic() {
+ UnlinkedTypeRef typeRef =
+ serializeTypeText('F', otherDeclarations: 'typedef void F<A, B>();');
+ checkTypeRef(typeRef, null, null, 'F',
+ numTypeParameters: 2, expectedKind: PrelinkedReferenceKind.typedef);
+ }
+
+ test_typedef_reference_generic_imported() {
+ addNamedSource('/lib.dart', 'typedef void F<A, B>();');
+ UnlinkedTypeRef typeRef =
+ serializeTypeText('F', otherDeclarations: 'import "lib.dart";');
+ checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'F',
+ numTypeParameters: 2, expectedKind: PrelinkedReferenceKind.typedef);
+ }
+
test_typedef_return_type_explicit() {
UnlinkedTypedef type = serializeTypedefText('typedef int F();');
checkTypeRef(type.returnType, 'dart:core', 'dart:core', 'int');
@@ -2075,6 +2304,13 @@
serializeVariableText('int i;', variableName: 'i');
expect(findExecutable('i'), isNull);
expect(findExecutable('i='), isNull);
+ expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
+ expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+ PrelinkedReferenceKind.other);
+ expect(unlinkedUnits[0].publicNamespace.names[0].name, 'i');
+ expect(unlinkedUnits[0].publicNamespace.names[1].kind,
+ PrelinkedReferenceKind.other);
+ expect(unlinkedUnits[0].publicNamespace.names[1].name, 'i=');
}
test_variable_const() {
@@ -2151,4 +2387,9 @@
serializeVariableText('int i;', variableName: 'i');
checkTypeRef(variable.type, 'dart:core', 'dart:core', 'int');
}
+
+ test_varible_private() {
+ serializeVariableText('int _i;', variableName: '_i');
+ expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+ }
}
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
new file mode 100644
index 0000000..189d00f
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.src.serialization.test_all;
+
+import 'package:unittest/unittest.dart';
+
+import '../../utils.dart';
+import 'resynthesize_test.dart' as resynthesize_test;
+import 'summary_test.dart' as summary_test;
+
+/// Utility for manually running all tests.
+main() {
+ initializeTestEnvironment();
+ group('summary tests', () {
+ resynthesize_test.main();
+ summary_test.main();
+ });
+}
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index fd4fee2..b81e72a 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -147,6 +147,19 @@
Source source;
LibrarySpecificUnit target;
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT1);
+ expect(outputs[RESOLVED_UNIT1], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT1], isTrue);
+ }
+
test_perform_find_constants() {
_performBuildTask('''
const x = 1;
@@ -189,10 +202,11 @@
}
class B = Object with A;
''');
- expect(outputs, hasLength(3));
+ expect(outputs, hasLength(4));
expect(outputs[COMPILATION_UNIT_CONSTANTS], isNotNull);
expect(outputs[COMPILATION_UNIT_ELEMENT], isNotNull);
expect(outputs[RESOLVED_UNIT1], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT1], isTrue);
}
test_perform_reuseElement() {
@@ -470,6 +484,19 @@
@reflectiveTest
class BuildEnumMemberElementsTaskTest extends _AbstractDartTaskTest {
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT2);
+ expect(outputs[RESOLVED_UNIT2], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT2], isTrue);
+ }
+
test_perform() {
Source source = newSource(
'/test.dart',
@@ -1344,6 +1371,19 @@
enableStrongMode();
}
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT5);
+ expect(outputs[RESOLVED_UNIT5], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT5], isTrue);
+ }
+
test_perform() {
AnalysisTarget source = newSource(
'/test.dart',
@@ -2024,6 +2064,19 @@
@reflectiveTest
class EvaluateUnitConstantsTaskTest extends _AbstractDartTaskTest {
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT11);
+ expect(outputs[RESOLVED_UNIT11], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT11], isTrue);
+ }
+
test_perform() {
Source source = newSource(
'/test.dart',
@@ -2488,6 +2541,19 @@
@reflectiveTest
class InferInstanceMembersInUnitTaskTest extends _AbstractDartTaskTest {
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT9);
+ expect(outputs[RESOLVED_UNIT9], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT9], isTrue);
+ }
+
void test_perform() {
enableStrongMode();
AnalysisTarget source = newSource(
@@ -2589,6 +2655,19 @@
@reflectiveTest
class InferStaticVariableTypesInUnitTaskTest extends _AbstractDartTaskTest {
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT7);
+ expect(outputs[RESOLVED_UNIT7], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT7], isTrue);
+ }
+
void test_perform_const_field() {
enableStrongMode();
AnalysisTarget source = newSource(
@@ -3204,6 +3283,19 @@
@reflectiveTest
class PropagateVariableTypesInUnitTaskTest extends _AbstractDartTaskTest {
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT6);
+ expect(outputs[RESOLVED_UNIT6], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT6], isTrue);
+ }
+
void test_perform_cycle() {
AnalysisTarget source = newSource(
'/test.dart',
@@ -3329,6 +3421,19 @@
enableStrongMode();
}
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT8);
+ expect(outputs[RESOLVED_UNIT8], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT8], isTrue);
+ }
+
// Test inference of instance fields across units
void test_perform_inference_cross_unit_instance() {
List<Source> sources = newSources({
@@ -3423,7 +3528,7 @@
computeResult(
new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT8);
- // A.a2 should now be fully resolved and inferred.
+ // A.a2 should now be fully resolved and inferred (but not re-resolved).
assertVariableDeclarationTypes(
AstFinder.getFieldInClass(unit0, "A", "a2"), dynamicType, dynamicType);
}
@@ -3535,7 +3640,7 @@
computeResult(
new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT8);
- // A.a2 should now be fully resolved and inferred.
+ // A.a2 should now be fully resolved and inferred (but not re-resolved).
assertVariableDeclarationTypes(
AstFinder.getFieldInClass(unit0, "A", "a2"), dynamicType, dynamicType);
@@ -3634,6 +3739,19 @@
@reflectiveTest
class ResolveUnitTaskTest extends _AbstractDartTaskTest {
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT10);
+ expect(outputs[RESOLVED_UNIT10], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT10], isTrue);
+ }
+
void test_perform() {
AnalysisTarget source = newSource(
'/test.dart',
@@ -3697,6 +3815,19 @@
@reflectiveTest
class ResolveUnitTypeNamesTaskTest extends _AbstractDartTaskTest {
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT3);
+ expect(outputs[RESOLVED_UNIT3], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT3], isTrue);
+ }
+
test_perform() {
Source source = newSource(
'/test.dart',
@@ -3796,6 +3927,19 @@
expect(variable.isPotentiallyMutatedInScope, mutatedInScope);
}
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT4);
+ expect(outputs[RESOLVED_UNIT4], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT4], isTrue);
+ }
+
test_perform_buildClosureLibraryElements() {
Source source = newSource(
'/test.dart',
@@ -4414,6 +4558,19 @@
enableStrongMode();
}
+ test_created_resolved_unit() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+library lib;
+class A {}
+''');
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ computeResult(target, RESOLVED_UNIT);
+ expect(outputs[RESOLVED_UNIT], isNotNull);
+ expect(outputs[CREATED_RESOLVED_UNIT], isTrue);
+ }
+
void test_perform_recordDynamicInvoke() {
enableStrongMode();
AnalysisTarget source = newSource(
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index b0f8181..221636a 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -36,6 +36,7 @@
void setUp() {
context = new _InternalAnalysisContextMock();
analysisDriver = new AnalysisDriver(taskManager, workManagers, context);
+ when(context.aboutToComputeResult(anyObject, anyObject)).thenReturn(false);
}
}
@@ -698,6 +699,61 @@
expect(result, isNull);
expect(item.exception, isNotNull);
}
+
+ test_gatherInputs_aboutToComputeResult_hasResult() {
+ AnalysisTarget target = new TestSource();
+ ResultDescriptor resultA = new ResultDescriptor('resultA', null);
+ ResultDescriptor resultB = new ResultDescriptor('resultB', null);
+ // prepare tasks
+ TaskDescriptor task1 = new TaskDescriptor(
+ 'task',
+ (context, target) =>
+ new TestAnalysisTask(context, target, results: [resultA]),
+ (target) => {},
+ [resultA]);
+ TaskDescriptor task2 = new TaskDescriptor(
+ 'task',
+ (context, target) => new TestAnalysisTask(context, target),
+ (target) => {'one': resultA.of(target)},
+ [resultB]);
+ taskManager.addTaskDescriptor(task1);
+ taskManager.addTaskDescriptor(task2);
+ // configure mocks
+ when(context.aboutToComputeResult(anyObject, resultA)).thenReturn(true);
+ // gather inputs
+ WorkItem item = new WorkItem(context, target, task2, null, 0, null);
+ WorkItem inputItem = item.gatherInputs(taskManager, []);
+ expect(inputItem, isNull);
+ }
+
+ test_gatherInputs_aboutToComputeResult_noResult() {
+ AnalysisTarget target = new TestSource();
+ ResultDescriptor resultA = new ResultDescriptor('resultA', null);
+ ResultDescriptor resultB = new ResultDescriptor('resultB', null);
+ // prepare tasks
+ TaskDescriptor task1 = new TaskDescriptor(
+ 'task',
+ (context, target) =>
+ new TestAnalysisTask(context, target, results: [resultA]),
+ (target) => {},
+ [resultA]);
+ TaskDescriptor task2 = new TaskDescriptor(
+ 'task',
+ (context, target) => new TestAnalysisTask(context, target),
+ (target) => {'one': resultA.of(target)},
+ [resultB]);
+ taskManager.addTaskDescriptor(task1);
+ taskManager.addTaskDescriptor(task2);
+ // configure ResultProvider
+ // configure mocks
+ when(context.aboutToComputeResult(anyObject, resultA)).thenReturn(false);
+ // gather inputs
+ WorkItem item = new WorkItem(context, target, task2, null, 0, null);
+ WorkItem inputItem = item.gatherInputs(taskManager, []);
+ expect(inputItem, isNotNull);
+ expect(inputItem.target, target);
+ expect(inputItem.descriptor, task1);
+ }
}
@reflectiveTest
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 6d35a3e..c3f670b 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -237,6 +237,9 @@
analyzer:
errors:
unused_local_variable: ignore
+ invalid_assignment: warning
+ missing_return: error
+ dead_code: info
''',
[]);
}
diff --git a/pkg/analyzer/test/src/test_all.dart b/pkg/analyzer/test/src/test_all.dart
index b97bc81..14226d8 100644
--- a/pkg/analyzer/test/src/test_all.dart
+++ b/pkg/analyzer/test/src/test_all.dart
@@ -9,6 +9,7 @@
import '../utils.dart';
import 'context/test_all.dart' as context;
import 'plugin/plugin_config_test.dart' as plugin;
+import 'summary/test_all.dart' as summary;
import 'task/test_all.dart' as task;
import 'util/test_all.dart' as util;
@@ -18,6 +19,7 @@
group('src tests', () {
context.main();
plugin.main();
+ summary.main();
task.main();
util.main();
});
diff --git a/pkg/analyzer/tool/generate_files b/pkg/analyzer/tool/generate_files
index 1e0322f..4f0ea0d 100755
--- a/pkg/analyzer/tool/generate_files
+++ b/pkg/analyzer/tool/generate_files
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
diff --git a/pkg/analyzer/tool/summary/build_sdk_summary.dart b/pkg/analyzer/tool/summary/build_sdk_summary.dart
new file mode 100644
index 0000000..52862e3
--- /dev/null
+++ b/pkg/analyzer/tool/summary/build_sdk_summary.dart
@@ -0,0 +1,89 @@
+import 'dart:io';
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/java_io.dart';
+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/base.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/summarize_elements.dart';
+
+main(List<String> args) {
+ if (args.length < 1 || args.length > 2) {
+ _printUsage();
+ return;
+ }
+ //
+ // Prepare output file path.
+ //
+ String outputFilePath = args[0];
+ if (FileSystemEntity.isDirectorySync(outputFilePath)) {
+ print("'$outputFilePath' is a directory.");
+ _printUsage();
+ return;
+ }
+ //
+ // Prepare SDK path.
+ //
+ String sdkPath;
+ if (args.length == 2) {
+ sdkPath = args[1];
+ if (!FileSystemEntity.isDirectorySync('$sdkPath/lib')) {
+ print("'$sdkPath/lib' does not exist.");
+ _printUsage();
+ return;
+ }
+ } else {
+ sdkPath = DirectoryBasedDartSdk.defaultSdkDirectory.getAbsolutePath();
+ }
+ //
+ // Prepare SDK.
+ //
+ DirectoryBasedDartSdk sdk = new DirectoryBasedDartSdk(new JavaFile(sdkPath));
+ AnalysisContext context = sdk.context;
+ //
+ // Serialize each SDK library.
+ //
+ List<String> prelinkedLibraryUris = <String>[];
+ List<PrelinkedLibraryBuilder> prelinkedLibraries =
+ <PrelinkedLibraryBuilder>[];
+ List<String> unlinkedUnitUris = <String>[];
+ List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[];
+ BuilderContext builderContext = new BuilderContext();
+ for (SdkLibrary lib in sdk.sdkLibraries) {
+ print('Resolving and serializing: ${lib.shortName}');
+ Source librarySource = sdk.mapDartUri(lib.shortName);
+ LibraryElement libraryElement =
+ context.computeLibraryElement(librarySource);
+ LibrarySerializationResult libraryResult =
+ serializeLibrary(builderContext, libraryElement, context.typeProvider);
+ prelinkedLibraryUris.add(lib.shortName);
+ prelinkedLibraries.add(libraryResult.prelinked);
+ unlinkedUnitUris.addAll(libraryResult.unitUris);
+ unlinkedUnits.addAll(libraryResult.unlinkedUnits);
+ }
+ //
+ // Write the whole SDK bundle.
+ //
+ SdkBundleBuilder sdkBundle = encodeSdkBundle(builderContext,
+ prelinkedLibraryUris: prelinkedLibraryUris,
+ prelinkedLibraries: prelinkedLibraries,
+ unlinkedUnitUris: unlinkedUnitUris,
+ unlinkedUnits: unlinkedUnits);
+ File file = new File(outputFilePath);
+ file.writeAsBytesSync(sdkBundle.toBuffer(), mode: FileMode.WRITE_ONLY);
+}
+
+/**
+ * The name of the SDK summary builder application.
+ */
+const BINARY_NAME = "build_sdk_summary";
+
+/**
+ * Print information about how to use the SDK summary builder.
+ */
+void _printUsage() {
+ print('Usage: $BINARY_NAME output_file_path [sdk_path]');
+}
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index 03593db..9ff31d6 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -13,7 +13,7 @@
* - A "builder" class which can be used to generate serialized summary data.
* This class has write-only semantics.
*
- * Each of the "builder" classess has a single `finish` method which finalizes
+ * Each of the "builder" classes has a single `finish` method which finalizes
* the entity being built and returns it as an [Object]. This object should
* only be passed to other builders (or to [BuilderContext.getBuffer]);
* otherwise the client should treat it as opaque, since it exposes
@@ -54,10 +54,11 @@
CharacterReader idlReader = new CharSequenceReader(idlText);
Scanner scanner = new Scanner(idlSource, idlReader, errorListener);
Token tokenStream = scanner.tokenize();
+ LineInfo lineInfo = new LineInfo(scanner.lineStarts);
Parser parser = new Parser(idlSource, new BooleanErrorListener());
CompilationUnit idlParsed = parser.parseCompilationUnit(tokenStream);
_CodeGenerator codeGenerator = new _CodeGenerator();
- codeGenerator.processCompilationUnit(idlParsed);
+ codeGenerator.processCompilationUnit(lineInfo, idlParsed);
return codeGenerator._outBuffer.toString();
});
@@ -83,18 +84,22 @@
*/
void checkIdl() {
_idl.classes.forEach((String name, idlModel.ClassDeclaration cls) {
- cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ String fieldName = field.name;
+ idlModel.FieldType type = field.type;
if (type.isList) {
if (_idl.classes.containsKey(type.typeName)) {
// List of classes is ok
} else if (type.typeName == 'int') {
// List of ints is ok
+ } else if (type.typeName == 'String') {
+ // List of strings is ok
} else {
throw new Exception(
'$name.$fieldName: illegal type (list of ${type.typeName})');
}
}
- });
+ }
});
}
@@ -152,7 +157,7 @@
* Process the AST in [idlParsed] and store the resulting semantic model in
* [_idl]. Also perform some error checking.
*/
- void extractIdl(CompilationUnit idlParsed) {
+ void extractIdl(LineInfo lineInfo, CompilationUnit idlParsed) {
_idl = new idlModel.Idl();
for (CompilationUnitMember decl in idlParsed.declarations) {
if (decl is ClassDeclaration) {
@@ -163,9 +168,10 @@
isTopLevel = true;
}
}
+ String doc = _getNodeDoc(lineInfo, decl);
idlModel.ClassDeclaration cls =
- new idlModel.ClassDeclaration(isTopLevel);
- _idl.classes[decl.name.name] = cls;
+ new idlModel.ClassDeclaration(doc, decl.name.name, isTopLevel);
+ _idl.classes[cls.name] = cls;
for (ClassMember classMember in decl.members) {
if (classMember is FieldDeclaration) {
TypeName type = classMember.fields.type;
@@ -179,23 +185,27 @@
if (type.typeArguments != null) {
throw new Exception('Cannot handle type arguments in `$type`');
}
+ String doc = _getNodeDoc(lineInfo, classMember);
idlModel.FieldType fieldType =
new idlModel.FieldType(type.name.name, isList);
for (VariableDeclaration field in classMember.fields.variables) {
- cls.fields[field.name.name] = fieldType;
+ cls.fields.add(new idlModel.FieldDeclaration(
+ doc, field.name.name, fieldType));
}
} else {
throw new Exception('Unexpected class member `$classMember`');
}
}
} else if (decl is EnumDeclaration) {
- idlModel.EnumDeclaration enm = new idlModel.EnumDeclaration();
- _idl.enums[decl.name.name] = enm;
+ String doc = _getNodeDoc(lineInfo, decl);
+ idlModel.EnumDeclaration enm =
+ new idlModel.EnumDeclaration(doc, decl.name.name);
+ _idl.enums[enm.name] = enm;
for (EnumConstantDeclaration constDecl in decl.constants) {
enm.values.add(constDecl.name.name);
}
} else if (decl is TopLevelVariableDeclaration) {
- // Ignore top leve variable declarations; they are present just to make
+ // Ignore top level variable declarations; they are present just to make
// the IDL analyze without warnings.
} else {
throw new Exception('Unexpected declaration `$decl`');
@@ -228,12 +238,18 @@
}
}
+ void outDoc(String documentation) {
+ if (documentation != null) {
+ documentation.split('\n').forEach(out);
+ }
+ }
+
/**
* Entry point to the code generator. Interpret the AST in [idlParsed],
* generate code, and output it to [_outBuffer].
*/
- void processCompilationUnit(CompilationUnit idlParsed) {
- extractIdl(idlParsed);
+ void processCompilationUnit(LineInfo lineInfo, CompilationUnit idlParsed) {
+ extractIdl(lineInfo, idlParsed);
checkIdl();
out('// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file');
out('// for details. All rights reserved. Use of this source code is governed by a');
@@ -245,9 +261,10 @@
out('library analyzer.src.summary.format;');
out();
out("import 'dart:convert';");
- out("import 'builder.dart' as builder;");
+ out("import 'base.dart' as base;");
out();
_idl.enums.forEach((String name, idlModel.EnumDeclaration enm) {
+ outDoc(enm.documentation);
out('enum $name {');
indent(() {
for (String value in enm.values) {
@@ -258,22 +275,29 @@
out();
});
_idl.classes.forEach((String name, idlModel.ClassDeclaration cls) {
- out('class $name {');
+ outDoc(cls.documentation);
+ out('class $name extends base.SummaryClass {');
indent(() {
- cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ String fieldName = field.name;
+ idlModel.FieldType type = field.type;
out('${dartType(type)} _$fieldName;');
- });
+ }
out();
out('$name.fromJson(Map json)');
indent(() {
List<String> initializers = <String>[];
- cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ String fieldName = field.name;
+ idlModel.FieldType type = field.type;
String convert = 'json[${quoted(fieldName)}]';
- if (type.isList && type.typeName == 'int') {
- // No conversion necessary.
- } else if (type.isList) {
- convert =
- '$convert?.map((x) => new ${type.typeName}.fromJson(x))?.toList()';
+ if (type.isList) {
+ if (type.typeName == 'int' || type.typeName == 'String') {
+ // No conversion necessary.
+ } else {
+ convert =
+ '$convert?.map((x) => new ${type.typeName}.fromJson(x))?.toList()';
+ }
} else if (_idl.classes.containsKey(type.typeName)) {
convert =
'$convert == null ? null : new ${type.typeName}.fromJson($convert)';
@@ -282,7 +306,7 @@
'$convert == null ? null : ${type.typeName}.values[$convert]';
}
initializers.add('_$fieldName = $convert');
- });
+ }
for (int i = 0; i < initializers.length; i++) {
String prefix = i == 0 ? ': ' : ' ';
String suffix = i == initializers.length - 1 ? ';' : ',';
@@ -290,13 +314,29 @@
}
});
out();
+ out('@override');
+ out('Map<String, Object> toMap() => {');
+ indent(() {
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ String fieldName = field.name;
+ out('${quoted(fieldName)}: $fieldName,');
+ }
+ });
+ out('};');
+ out();
if (cls.isTopLevel) {
out('$name.fromBuffer(List<int> buffer) : this.fromJson(JSON.decode(UTF8.decode(buffer)));');
out();
}
- cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+ cls.fields.asMap().forEach((index, field) {
+ String fieldName = field.name;
+ idlModel.FieldType type = field.type;
+ if (index != 0) {
+ out();
+ }
String def = defaultValue(type);
String defaultSuffix = def == null ? '' : ' ?? $def';
+ outDoc(field.documentation);
out('${dartType(type)} get $fieldName => _$fieldName$defaultSuffix;');
});
});
@@ -309,9 +349,12 @@
out();
out('bool _finished = false;');
out();
- out('${name}Builder(builder.BuilderContext context);');
- cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+ out('${name}Builder(base.BuilderContext context);');
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ String fieldName = field.name;
+ idlModel.FieldType type = field.type;
out();
+ outDoc(field.documentation);
String conversion = '_value';
String condition = '';
if (type.isList) {
@@ -332,14 +375,18 @@
indent(() {
out('assert(!_finished);');
out('assert(!_json.containsKey(${quoted(fieldName)}));');
- out('if (_value != null$condition) {');
+ if (condition.isEmpty) {
+ out('if (_value != null) {');
+ } else {
+ out('if (!(_value == null$condition)) {');
+ }
indent(() {
out('_json[${quoted(fieldName)}] = $conversion;');
});
out('}');
});
out('}');
- });
+ }
if (cls.isTopLevel) {
out();
out('List<int> toBuffer() => UTF8.encode(JSON.encode(finish()));');
@@ -355,12 +402,13 @@
});
out('}');
out();
- out('${name}Builder encode$name(builder.BuilderContext builderContext, {${builderParams.join(', ')}}) {');
+ out('${name}Builder encode$name(base.BuilderContext builderContext, {${builderParams.join(', ')}}) {');
indent(() {
out('${name}Builder builder = new ${name}Builder(builderContext);');
- cls.fields.forEach((String fieldName, idlModel.FieldType type) {
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ String fieldName = field.name;
out('builder.$fieldName = $fieldName;');
- });
+ }
out('return builder;');
});
out('}');
@@ -374,4 +422,27 @@
String quoted(String s) {
return JSON.encode(s);
}
+
+ /**
+ * Return the documentation text of the given [node], or `null` if the [node]
+ * does not have a comment. Each line is `\n` separated.
+ */
+ String _getNodeDoc(LineInfo lineInfo, AnnotatedNode node) {
+ Comment comment = node.documentationComment;
+ if (comment != null &&
+ comment.isDocumentation &&
+ comment.tokens.length == 1 &&
+ comment.tokens.first.type == TokenType.MULTI_LINE_COMMENT) {
+ Token token = comment.tokens.first;
+ int column = lineInfo.getLocation(token.offset).columnNumber;
+ String indent = ' ' * (column - 1);
+ return token.lexeme.split('\n').map((String line) {
+ if (line.startsWith(indent)) {
+ line = line.substring(indent.length);
+ }
+ return line;
+ }).join('\n');
+ }
+ return null;
+ }
}
diff --git a/pkg/analyzer/tool/summary/idl.dart b/pkg/analyzer/tool/summary/idl.dart
index 117dfe4..28d0da5 100644
--- a/pkg/analyzer/tool/summary/idl.dart
+++ b/pkg/analyzer/tool/summary/idl.dart
@@ -98,7 +98,7 @@
List<PrelinkedDependency> dependencies;
/**
- * For each import in [UnlinkedLibrary.imports], an index into [dependencies]
+ * For each import in [UnlinkedUnit.imports], an index into [dependencies]
* of the library being imported.
*
* TODO(paulberry): if [dependencies] is removed, this can be removed as
@@ -130,6 +130,12 @@
* represent parts in the order of the corresponding `part` declarations.
*/
int unit;
+
+ /**
+ * If the entity being referred to is generic, the number of type parameters
+ * it accepts. Otherwise zero.
+ */
+ int numTypeParameters;
}
/**
@@ -175,6 +181,32 @@
}
/**
+ * Information about SDK.
+ */
+@topLevel
+class SdkBundle {
+ /**
+ * The list of URIs of items in [prelinkedLibraries], e.g. `dart:core`.
+ */
+ List<String> prelinkedLibraryUris;
+
+ /**
+ * Pre-linked libraries.
+ */
+ List<PrelinkedLibrary> prelinkedLibraries;
+
+ /**
+ * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
+ */
+ List<String> unlinkedUnitUris;
+
+ /**
+ * Unlinked information for the compilation units constituting the SDK.
+ */
+ List<UnlinkedUnit> unlinkedUnits;
+}
+
+/**
* Unlinked summary information about a class declaration.
*/
class UnlinkedClass {
@@ -240,23 +272,12 @@
/**
* List of names which are shown. Empty if this is a `hide` combinator.
*/
- List<UnlinkedCombinatorName> shows;
+ List<String> shows;
/**
* List of names which are hidden. Empty if this is a `show` combinator.
*/
- List<UnlinkedCombinatorName> hides;
-}
-
-/**
- * Unlinked summary information about a single name in a `show` or `hide`
- * combinator.
- */
-class UnlinkedCombinatorName {
- /**
- * The name itself.
- */
- String name;
+ List<String> hides;
}
/**
@@ -516,6 +537,58 @@
}
/**
+ * Unlinked summary information about a specific name contributed by a
+ * compilation unit to a library's public namespace.
+ *
+ * TODO(paulberry): add a count of generic parameters, so that resynthesis
+ * doesn't have to peek into the library to obtain this info.
+ *
+ * TODO(paulberry): for classes, add info about static members and
+ * constructors, since this will be needed to prelink info about constants.
+ *
+ * TODO(paulberry): some of this information is redundant with information
+ * elsewhere in the summary. Consider reducing the redundancy to reduce
+ * summary size.
+ */
+class UnlinkedPublicName {
+ /**
+ * The name itself.
+ */
+ String name;
+
+ /**
+ * The kind of object referred to by the name.
+ */
+ PrelinkedReferenceKind kind;
+}
+
+/**
+ * Unlinked summary information about what a compilation unit contributes to a
+ * library's public namespace. This is the subset of [UnlinkedUnit] that is
+ * required from dependent libraries in order to perform prelinking.
+ */
+@topLevel
+class UnlinkedPublicNamespace {
+ /**
+ * Public names defined in the compilation unit.
+ *
+ * TODO(paulberry): consider sorting these names to reduce unnecessary
+ * relinking.
+ */
+ List<UnlinkedPublicName> names;
+
+ /**
+ * Export declarations in the compilation unit.
+ */
+ List<UnlinkedExport> exports;
+
+ /**
+ * Part declarations in the compilation unit.
+ */
+ List<UnlinkedPart> parts;
+}
+
+/**
* Unlinked summary information about a name referred to in one library that
* might be defined in another.
*/
@@ -629,6 +702,11 @@
String libraryName;
/**
+ * Unlinked public namespace of this compilation unit.
+ */
+ UnlinkedPublicNamespace publicNamespace;
+
+ /**
* Top level and prefixed names referred to by this compilation unit. The
* zeroth element of this array is always populated and always represents a
* reference to the pseudo-type "dynamic".
@@ -652,21 +730,11 @@
List<UnlinkedExecutable> executables;
/**
- * Export declarations in the compilation unit.
- */
- List<UnlinkedExport> exports;
-
- /**
* Import declarations in the compilation unit.
*/
List<UnlinkedImport> imports;
/**
- * Part declarations in the compilation unit.
- */
- List<UnlinkedPart> parts;
-
- /**
* Typedefs declared in the compilation unit.
*/
List<UnlinkedTypedef> typedefs;
diff --git a/pkg/analyzer/tool/summary/idl_model.dart b/pkg/analyzer/tool/summary/idl_model.dart
index e298b97..07be039 100644
--- a/pkg/analyzer/tool/summary/idl_model.dart
+++ b/pkg/analyzer/tool/summary/idl_model.dart
@@ -12,28 +12,62 @@
/**
* Information about a single class defined in the IDL.
*/
-class ClassDeclaration {
+class ClassDeclaration extends Declaration {
/**
* Fields defined in the class.
*/
- final Map<String, FieldType> fields = <String, FieldType>{};
+ final List<FieldDeclaration> fields = <FieldDeclaration>[];
/**
* Indicates whether the class has the `topLevel` annotation.
*/
final bool isTopLevel;
- ClassDeclaration(this.isTopLevel);
+ ClassDeclaration(String documentation, String name, this.isTopLevel)
+ : super(documentation, name);
+}
+
+/**
+ * Information about a declaration in the IDL.
+ */
+class Declaration {
+ /**
+ * The optional documentation, may be `null`.
+ */
+ final String documentation;
+
+ /**
+ * The name of the declaration.
+ */
+ final String name;
+
+ Declaration(this.documentation, this.name);
}
/**
* Information about a single enum defined in the IDL.
*/
-class EnumDeclaration {
+class EnumDeclaration extends Declaration {
/**
* List of enumerated values.
*/
final List<String> values = <String>[];
+
+ EnumDeclaration(String documentation, String name)
+ : super(documentation, name);
+}
+
+/**
+ * Information about a single class field defined in the IDL.
+ */
+class FieldDeclaration extends Declaration {
+ /**
+ * The file of the field.
+ */
+ final FieldType type;
+
+ FieldDeclaration(String documentation, String name, this.type)
+ : super(documentation, name);
}
/**
diff --git a/pkg/analyzer/tool/task_dependency_graph/generate.dart b/pkg/analyzer/tool/task_dependency_graph/generate.dart
index 91560b2..9b960f3 100644
--- a/pkg/analyzer/tool/task_dependency_graph/generate.dart
+++ b/pkg/analyzer/tool/task_dependency_graph/generate.dart
@@ -127,9 +127,8 @@
DartSdk sdk = DirectoryBasedDartSdk.defaultSdk;
context = AnalysisEngine.instance.createAnalysisContext();
String packageRootPath;
- if (Platform.packageRoot.isNotEmpty) {
- Uri packageRootUri = Uri.parse(Platform.packageRoot);
- packageRootPath = packageRootUri.toFilePath();
+ if (Platform.packageRoot != null) {
+ packageRootPath = Uri.parse(Platform.packageRoot).toFilePath();
} else {
packageRootPath = path.join(rootDir, 'packages');
}
diff --git a/pkg/analyzer/tool/task_dependency_graph/tasks.dot b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
index baacc31..49a1c1a 100644
--- a/pkg/analyzer/tool/task_dependency_graph/tasks.dot
+++ b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
@@ -15,9 +15,11 @@
BUILD_LIBRARY_ERRORS [shape=box]
BuildCompilationUnitElementTask -> COMPILATION_UNIT_CONSTANTS
BuildCompilationUnitElementTask -> COMPILATION_UNIT_ELEMENT
+ BuildCompilationUnitElementTask -> CREATED_RESOLVED_UNIT1
BuildCompilationUnitElementTask -> RESOLVED_UNIT1
BuildDirectiveElementsTask -> BUILD_DIRECTIVES_ERRORS
BuildDirectiveElementsTask -> LIBRARY_ELEMENT2
+ BuildEnumMemberElementsTask -> CREATED_RESOLVED_UNIT2
BuildEnumMemberElementsTask -> RESOLVED_UNIT2
BuildExportNamespaceTask -> LIBRARY_ELEMENT4
BuildLibraryElementTask -> BUILD_LIBRARY_ERRORS
@@ -40,6 +42,25 @@
CONTAINING_LIBRARIES [shape=box]
CONTENT -> ScanDartTask
CONTENT [shape=box]
+ CREATED_RESOLVED_UNIT [shape=box]
+ CREATED_RESOLVED_UNIT1 [shape=box]
+ CREATED_RESOLVED_UNIT10 [shape=box]
+ CREATED_RESOLVED_UNIT11 [shape=box]
+ CREATED_RESOLVED_UNIT2 [shape=box]
+ CREATED_RESOLVED_UNIT3 [shape=box]
+ CREATED_RESOLVED_UNIT4 [shape=box]
+ CREATED_RESOLVED_UNIT5 [shape=box]
+ CREATED_RESOLVED_UNIT6 [shape=box]
+ CREATED_RESOLVED_UNIT7 -> ResolveInstanceFieldsInUnitTask
+ CREATED_RESOLVED_UNIT7 [shape=box]
+ CREATED_RESOLVED_UNIT8 -> InferInstanceMembersInUnitTask
+ CREATED_RESOLVED_UNIT8 [shape=box]
+ CREATED_RESOLVED_UNIT9 -> InferInstanceMembersInUnitTask
+ CREATED_RESOLVED_UNIT9 -> InferStaticVariableTypeTask
+ CREATED_RESOLVED_UNIT9 -> PartiallyResolveUnitReferencesTask
+ CREATED_RESOLVED_UNIT9 -> ResolveInstanceFieldsInUnitTask
+ CREATED_RESOLVED_UNIT9 -> ResolveUnitTask
+ CREATED_RESOLVED_UNIT9 [shape=box]
ComputeConstantDependenciesTask -> CONSTANT_DEPENDENCIES
ComputeConstantValueTask -> CONSTANT_VALUE
ComputeInferableStaticVariableDependenciesTask -> INFERABLE_STATIC_VARIABLE_DEPENDENCIES
@@ -63,6 +84,7 @@
EXPORTED_LIBRARIES [shape=box]
EXPORT_SOURCE_CLOSURE -> BuildExportNamespaceTask
EXPORT_SOURCE_CLOSURE [shape=box]
+ EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT11
EvaluateUnitConstantsTask -> RESOLVED_UNIT11
GatherUsedImportedElementsTask -> USED_IMPORTED_ELEMENTS
GatherUsedLocalElementsTask -> USED_LOCAL_ELEMENTS
@@ -88,8 +110,10 @@
INFERRED_STATIC_VARIABLE -> InferStaticVariableTypesInUnitTask
INFERRED_STATIC_VARIABLE [shape=box]
IS_LAUNCHABLE [shape=box]
+ InferInstanceMembersInUnitTask -> CREATED_RESOLVED_UNIT9
InferInstanceMembersInUnitTask -> RESOLVED_UNIT9
InferStaticVariableTypeTask -> INFERRED_STATIC_VARIABLE
+ InferStaticVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT7
InferStaticVariableTypesInUnitTask -> RESOLVED_UNIT7
LIBRARY_CYCLE [shape=box]
LIBRARY_CYCLE_DEPENDENCIES -> InferInstanceMembersInUnitTask
@@ -170,12 +194,14 @@
ParseDartTask -> PARSE_ERRORS
ParseDartTask -> SOURCE_KIND
ParseDartTask -> UNITS
+ PartiallyResolveUnitReferencesTask -> CREATED_RESOLVED_UNIT5
PartiallyResolveUnitReferencesTask -> INFERABLE_STATIC_VARIABLES_IN_UNIT
PartiallyResolveUnitReferencesTask -> PROPAGABLE_VARIABLES_IN_UNIT
PartiallyResolveUnitReferencesTask -> RESOLVED_UNIT5
PropagateVariableTypeTask -> PROPAGATED_VARIABLE
PropagateVariableTypesInLibraryClosureTask -> LIBRARY_ELEMENT7
PropagateVariableTypesInLibraryTask -> LIBRARY_ELEMENT6
+ PropagateVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT6
PropagateVariableTypesInUnitTask -> RESOLVED_UNIT6
READY_LIBRARY_ELEMENT2 -> ComputeLibraryCycleTask
READY_LIBRARY_ELEMENT2 -> ReadyLibraryElement2Task
@@ -233,10 +259,6 @@
RESOLVED_UNIT7 [shape=box]
RESOLVED_UNIT8 -> InferInstanceMembersInUnitTask
RESOLVED_UNIT8 [shape=box]
- RESOLVED_UNIT9 -> InferInstanceMembersInUnitTask
- RESOLVED_UNIT9 -> InferStaticVariableTypeTask
- RESOLVED_UNIT9 -> PartiallyResolveUnitReferencesTask
- RESOLVED_UNIT9 -> ResolveInstanceFieldsInUnitTask
RESOLVED_UNIT9 -> ResolveUnitTask
RESOLVED_UNIT9 [shape=box]
RESOLVE_TYPE_NAMES_ERRORS -> LibraryUnitErrorsTask
@@ -249,16 +271,20 @@
ReadyResolvedUnit10Task -> READY_RESOLVED_UNIT10
ReadyResolvedUnit11Task -> READY_RESOLVED_UNIT11
ReadyResolvedUnitTask -> READY_RESOLVED_UNIT
+ ResolveInstanceFieldsInUnitTask -> CREATED_RESOLVED_UNIT8
ResolveInstanceFieldsInUnitTask -> RESOLVED_UNIT8
ResolveLibraryReferencesTask -> LIBRARY_ELEMENT8
ResolveLibraryReferencesTask -> REFERENCED_NAMES
ResolveLibraryTask -> LIBRARY_ELEMENT
ResolveLibraryTypeNamesTask -> LIBRARY_ELEMENT5
ResolveUnitTask -> CONSTANT_EXPRESSIONS_DEPENDENCIES
+ ResolveUnitTask -> CREATED_RESOLVED_UNIT10
ResolveUnitTask -> RESOLVED_UNIT10
ResolveUnitTask -> RESOLVE_UNIT_ERRORS
+ ResolveUnitTypeNamesTask -> CREATED_RESOLVED_UNIT3
ResolveUnitTypeNamesTask -> RESOLVED_UNIT3
ResolveUnitTypeNamesTask -> RESOLVE_TYPE_NAMES_ERRORS
+ ResolveVariableReferencesTask -> CREATED_RESOLVED_UNIT4
ResolveVariableReferencesTask -> RESOLVED_UNIT4
ResolveVariableReferencesTask -> VARIABLE_REFERENCE_ERRORS
SCAN_ERRORS -> dartErrorsForSource
@@ -270,6 +296,7 @@
ScanDartTask -> LINE_INFO
ScanDartTask -> SCAN_ERRORS
ScanDartTask -> TOKEN_STREAM
+ StrongModeVerifyUnitTask -> CREATED_RESOLVED_UNIT
StrongModeVerifyUnitTask -> RESOLVED_UNIT
StrongModeVerifyUnitTask -> STRONG_MODE_ERRORS
TOKEN_STREAM -> ParseDartTask
diff --git a/pkg/analyzer_cli/lib/src/perf_report.dart b/pkg/analyzer_cli/lib/src/perf_report.dart
index 03791d8..208e560 100644
--- a/pkg/analyzer_cli/lib/src/perf_report.dart
+++ b/pkg/analyzer_cli/lib/src/perf_report.dart
@@ -9,6 +9,7 @@
import 'package:analyzer/src/generated/utilities_general.dart'
show PerformanceTag;
+import 'package:analyzer/task/model.dart' show AnalysisTask;
import 'package:analyzer_cli/src/options.dart' show CommandLineOptions;
const _JSON = const JsonEncoder.withIndent(" ");
@@ -70,13 +71,36 @@
}
perfTagsJson['other'] = otherTime;
- var json = <String, dynamic>{
+ // Generate task table.
+ var taskRows = <_TaskRow>[];
+ int totalTaskTime = 0;
+ for (var key in AnalysisTask.stopwatchMap.keys) {
+ var time = AnalysisTask.stopwatchMap[key].elapsedMilliseconds;
+ if (time == 0) continue;
+ totalTaskTime += time;
+ var count = AnalysisTask.countMap[key];
+ taskRows.add(new _TaskRow(key.toString(), time, count));
+ }
+ taskRows.sort((a, b) => b.time.compareTo(a.time));
+
+ var reportJson = <String, dynamic>{
'perfReportVersion': 0,
'platform': platformJson,
'options': optionsJson,
'totalElapsedTime': totalTime,
- 'performanceTags': perfTagsJson
+ 'totalTaskTime': totalTaskTime,
+ 'performanceTags': perfTagsJson,
+ 'tasks': taskRows.map((r) => r.toJson()).toList(),
};
- return _JSON.convert(json);
+ return _JSON.convert(reportJson);
+}
+
+class _TaskRow {
+ final String name;
+ final int time;
+ final int count;
+ _TaskRow(this.name, this.time, this.count);
+
+ Map toJson() => <String, dynamic>{'name': name, 'time': time, 'count': count};
}
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 27b844f..f777c0a 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -72,6 +72,8 @@
static const Name CALL_NAME = Names.call;
static const Name length = const PublicName(Identifiers.length);
+
+ static const Name runtimeType_ = const PublicName(Identifiers.runtimeType_);
}
/// [Selector]s commonly used.
@@ -114,13 +116,15 @@
static final Selector index = new Selector.index();
+ static final Selector runtimeType_ = new Selector.getter(Names.runtimeType_);
+
/// List of all the selectors held in static fields.
///
/// These objects are shared between different runs in batch-mode and must
/// thus remain in the [Selector.canonicalizedValues] map.
static final List<Selector> ALL = <Selector>[
cancel, current, iterator, moveNext, noSuchMethod_, toString_,
- hashCode_, compareTo, equals, length, codeUnitAt, index];
+ hashCode_, compareTo, equals, length, codeUnitAt, index, runtimeType_];
}
/// [Uri]s commonly used.
diff --git a/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart b/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
new file mode 100644
index 0000000..e5caa83
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
@@ -0,0 +1,131 @@
+library dart2js.cps_ir.backward_null_check_remover;
+
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart' show Pass;
+import '../common/names.dart';
+import '../universe/selector.dart';
+import 'type_mask_system.dart';
+import 'cps_fragment.dart';
+
+/// Removes null checks that are follwed by another instruction that will
+/// perform the same check.
+///
+/// For example:
+///
+/// x.toString; // NullCheck instruction
+/// print(x.length);
+///
+/// ==>
+///
+/// print(x.length);
+///
+/// `x.length` will throw when x is null, so the original [NullCheck] is not
+/// needed. This changes the error message, but at least for now we are
+/// willing to accept this.
+///
+/// Note that code motion may not occur after this pass, since the [NullCheck]
+/// nodes are not there to restrict it.
+//
+// TODO(asgerf): It would be nice with a clear specification of when we allow
+// the wording of error message to change. E.g. "toString" is already pretty
+// bad so changing that should be ok, but changing a field access is not as
+// clear.
+//
+class BackwardNullCheckRemover extends TrampolineRecursiveVisitor
+ implements Pass {
+ String get passName => 'Backward null-check remover';
+
+ final TypeMaskSystem typeSystem;
+
+ /// When the analysis of an expression completes, [nullCheckValue] refers to
+ /// a value that is checked in the beginning of that expression.
+ Primitive nullCheckedValue;
+
+ BackwardNullCheckRemover(this.typeSystem);
+
+ void rewrite(FunctionDefinition node) {
+ visit(node);
+ }
+
+ /// Returns a reference to an operand of [prim], where [prim] throws if null
+ /// is passed into that operand.
+ Reference<Primitive> getNullCheckedOperand(Primitive prim) {
+ if (prim is NullCheck) return prim.value;
+ if (prim is GetLength) return prim.object;
+ if (prim is GetField) return prim.object;
+ if (prim is GetIndex) return prim.object;
+ if (prim is SetField) return prim.object;
+ if (prim is SetIndex) return prim.object;
+ if (prim is InvokeMethod && !nullSelectors.contains(prim.selector)) {
+ return prim.dartReceiverReference;
+ }
+ return null;
+ }
+
+ static final List<Selector> nullSelectors = <Selector>[
+ Selectors.equals, Selectors.hashCode_, Selectors.noSuchMethod_,
+ Selectors.runtimeType_];
+
+ /// It has been determined that the null check in [prim] made redundant by
+ /// [newNullCheck]. Eliminate [prim] if it is not needed any more.
+ void tryEliminateRedundantNullCheck(Primitive prim, Primitive newNullCheck) {
+ if (prim is NullCheck) {
+ Primitive value = prim.value.definition;
+ LetPrim let = prim.parent;
+ prim..replaceUsesWith(value)..destroy();
+ let.remove();
+ } else if (prim is GetLength || prim is GetField || prim is GetIndex) {
+ if (prim.hasNoEffectiveUses) {
+ destroyRefinementsOfDeadPrimitive(prim);
+ LetPrim let = prim.parent;
+ prim..destroy();
+ let.remove();
+ }
+ }
+ }
+
+ /// True if [prim] can be moved above a null check. This is safe if [prim]
+ /// cannot throw or have side effects and does not carry any path-sensitive
+ /// type information, such as [Refinement] nodes do.
+ //
+ // TODO(asgerf): This prevents elimination of the .length created for a bounds
+ // check, because there is a refinement node below it. To handle this, we
+ // would have to relocate the [Refinement] node below the new null check.
+ bool canMoveAboveNullCheck(Primitive prim) {
+ return prim.isSafeForReordering;
+ }
+
+ Expression traverseLetPrim(LetPrim node) {
+ Primitive prim = node.primitive;
+ Primitive receiver = getNullCheckedOperand(prim)?.definition;
+ if (receiver != null) {
+ pushAction(() {
+ Primitive successor = nullCheckedValue;
+ if (successor != null && receiver.sameValue(successor)) {
+ tryEliminateRedundantNullCheck(prim, successor);
+ }
+ nullCheckedValue = receiver;
+ });
+ } else if (!canMoveAboveNullCheck(prim)) {
+ pushAction(() {
+ nullCheckedValue = null;
+ });
+ }
+ return node.body;
+ }
+
+ Expression traverseContinuation(Continuation cont) {
+ pushAction(() {
+ nullCheckedValue = null;
+ });
+ return cont.body;
+ }
+
+ Expression traverseLetHandler(LetHandler node) {
+ push(node.handler);
+ pushAction(() {
+ nullCheckedValue = null;
+ });
+ return node.body;
+ }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/bounds_checker.dart b/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
index 223c24a..44cbbb0 100644
--- a/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
+++ b/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
@@ -493,7 +493,6 @@
void visitBoundsCheck(BoundsCheck node) {
if (node.checks == BoundsCheck.NONE) return;
assert(node.index != null); // Because there is at least one check.
- Primitive object = node.object.definition;
SignedVariable length = node.length == null
? null
: getValue(node.length.definition);
diff --git a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
index 5d56560..a4bd305 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
@@ -130,11 +130,14 @@
/// Inserts an invocation and returns a primitive holding the returned value.
Primitive invokeMethod(Primitive receiver,
- Selector selector,
- TypeMask mask,
- List<Primitive> arguments) {
- return letPrim(new InvokeMethod(receiver, selector, mask, arguments,
- sourceInformation));
+ Selector selector,
+ TypeMask mask,
+ List<Primitive> arguments,
+ [CallingConvention callingConvention = CallingConvention.Normal]) {
+ InvokeMethod invoke =
+ new InvokeMethod(receiver, selector, mask, arguments, sourceInformation)
+ ..callingConvention = callingConvention;
+ return letPrim(invoke);
}
/// Inserts an invocation and returns a primitive holding the returned value.
@@ -346,3 +349,17 @@
parent.body = newNode;
newNode.parent = parent;
}
+
+/// Removes all [Refinement] uses of a given primitive that has no effective
+/// uses.
+void destroyRefinementsOfDeadPrimitive(Primitive prim) {
+ while (prim.firstRef != null) {
+ Refinement refine = prim.firstRef.parent;
+ destroyRefinementsOfDeadPrimitive(refine);
+ LetPrim letPrim = refine.parent;
+ InteriorNode parent = letPrim.parent;
+ parent.body = letPrim.body;
+ letPrim.body.parent = parent;
+ prim.firstRef.unlink();
+ }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
index a80f2f7..76b2d22 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -653,14 +653,6 @@
return primitive;
}
- ir.Primitive _continueWithExpression(ir.Expression build(ir.Continuation k)) {
- ir.Parameter v = new ir.Parameter(null);
- ir.Continuation k = new ir.Continuation([v]);
- ir.Expression expression = build(k);
- add(new ir.LetCont(k, expression));
- return v;
- }
-
ir.Primitive _buildInvokeStatic(Element element,
Selector selector,
List<ir.Primitive> arguments,
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index afc4cd7..ee7a870 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -3565,10 +3565,8 @@
ConstantValue interceptorValue =
new InterceptorConstantValue(constant.representedType);
return irBuilder.buildConstant(interceptorValue);
- } else {
- internalError(argument, 'expected Type as argument');
}
- break;
+ return internalError(argument, 'expected Type as argument');
case 'JS_EFFECT':
return irBuilder.buildNullConstant();
@@ -3649,8 +3647,7 @@
CallStructure.TWO_ARGS);
default:
- giveup(node, 'unplemented native construct: ${function.name}');
- break;
+ return giveup(node, 'unplemented native construct: ${function.name}');
}
}
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
index 02b963e..e34a4a4 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -4,6 +4,7 @@
library dart2js.ir_nodes;
import 'dart:collection';
+import 'cps_fragment.dart' show CpsFragment;
import '../constants/values.dart' as values;
import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
import '../elements/elements.dart';
@@ -203,18 +204,7 @@
///
/// All primitives except [Parameter] must be bound by a [LetPrim].
abstract class Primitive extends Variable<Primitive> {
- /// The [VariableElement] or [ParameterElement] from which the primitive
- /// binding originated.
- Entity hint;
-
- /// Use the given element as a hint for naming this primitive.
- ///
- /// Has no effect if this primitive already has a non-null [element].
- void useElementAsHint(Entity hint) {
- if (this.hint == null) {
- this.hint = hint;
- }
- }
+ Primitive() : super(null);
/// True if this primitive has a value that can be used by other expressions.
bool get hasValue;
@@ -295,6 +285,23 @@
newDefinition.parent = let;
newDefinition.useElementAsHint(hint);
}
+
+ /// Replaces this definition with a CPS fragment (a term with a hole in it),
+ /// given the value to replace the uses of the definition with.
+ ///
+ /// This can be thought of as substituting:
+ ///
+ /// let x = OLD in BODY
+ /// ==>
+ /// FRAGMENT[BODY{newPrimitive/x}]
+ void replaceWithFragment(CpsFragment fragment, Primitive newPrimitive) {
+ assert(this is! Parameter);
+ replaceUsesWith(newPrimitive);
+ destroy();
+ LetPrim let = parent;
+ fragment.insertBelow(let);
+ let.remove();
+ }
}
/// A primitive that is generally not safe for elimination, but may be marked
@@ -464,6 +471,43 @@
}
}
+enum CallingConvention {
+ /// JS receiver is the Dart receiver, there are no extra arguments.
+ ///
+ /// This includes cases (e.g., static functions, constructors) where there
+ /// is no receiver.
+ ///
+ /// For example: `foo.bar$1(x)`
+ Normal,
+
+ /// JS receiver is an interceptor, the first argument is the Dart receiver.
+ ///
+ /// For example: `getInterceptor(foo).bar$1(foo, x)`
+ Intercepted,
+
+ /// JS receiver is the Dart receiver, the first argument is a dummy value.
+ ///
+ /// For example: `foo.bar$1(0, x)`
+ DummyIntercepted,
+
+ /// JS receiver is the Dart receiver, there are no extra arguments.
+ ///
+ /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)`
+ OneShotIntercepted,
+}
+
+/// Base class of function invocations.
+///
+/// This class defines the common interface of function invocations.
+abstract class InvocationPrimitive extends UnsafePrimitive {
+ Reference<Primitive> get receiver => null;
+ List<Reference<Primitive>> get arguments;
+ SourceInformation get sourceInformation;
+
+ Reference<Primitive> get dartReceiverReference => null;
+ CallingConvention get callingConvention => CallingConvention.Normal;
+}
+
/// Invoke a static function.
///
/// All optional arguments declared by [target] are passed in explicitly, and
@@ -472,7 +516,7 @@
/// Discussion:
/// All information in the [selector] is technically redundant; it will likely
/// be removed.
-class InvokeStatic extends UnsafePrimitive {
+class InvokeStatic extends InvocationPrimitive {
final FunctionElement target;
final Selector selector;
final List<Reference<Primitive>> arguments;
@@ -498,28 +542,6 @@
}
}
-enum CallingConvention {
- /// JS receiver is the Dart receiver, there are no extra arguments.
- ///
- /// For example: `foo.bar$1(x)`
- Normal,
-
- /// JS receiver is an interceptor, the first argument is the Dart receiver.
- ///
- /// For example: `getInterceptor(foo).bar$1(foo, x)`
- Intercepted,
-
- /// JS receiver is the Dart receiver, the first argument is a dummy value.
- ///
- /// For example: `foo.bar$1(0, x)`
- DummyIntercepted,
-
- /// JS receiver is the Dart receiver, there are no extra arguments.
- ///
- /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)`
- OneShotIntercepted,
-}
-
/// Invoke a method on an object.
///
/// This includes getters, setters, operators, and index getter/setters.
@@ -529,7 +551,7 @@
///
/// The [selector] records the names of named arguments. The value of named
/// arguments occur at the end of the [arguments] list, in normalized order.
-class InvokeMethod extends UnsafePrimitive {
+class InvokeMethod extends InvocationPrimitive {
Reference<Primitive> receiver;
Selector selector;
TypeMask mask;
@@ -606,7 +628,7 @@
///
/// All optional arguments declared by [target] are passed in explicitly, and
/// occur at the end of [arguments] list, in normalized order.
-class InvokeMethodDirectly extends UnsafePrimitive {
+class InvokeMethodDirectly extends InvocationPrimitive {
Reference<Primitive> receiver;
final FunctionElement target;
final Selector selector;
@@ -664,7 +686,7 @@
///
/// Note that [InvokeConstructor] does it itself allocate an object.
/// The invoked constructor will do that using [CreateInstance].
-class InvokeConstructor extends UnsafePrimitive {
+class InvokeConstructor extends InvocationPrimitive {
final DartType dartType;
final ConstructorElement target;
final List<Reference<Primitive>> arguments;
@@ -1688,13 +1710,24 @@
///
/// Is `null` until initialized by type propagation.
TypeMask type;
+
+ /// The [VariableElement] or [ParameterElement] from which the variable
+ /// binding originated.
+ Entity hint;
+
+ Variable(this.hint);
+
+ /// Use the given element as a hint for naming this primitive.
+ ///
+ /// Has no effect if this primitive already has a non-null [element].
+ void useElementAsHint(Entity hint) {
+ this.hint ??= hint;
+ }
}
/// Identifies a mutable variable.
class MutableVariable extends Variable<MutableVariable> {
- Entity hint;
-
- MutableVariable(this.hint);
+ MutableVariable(Entity hint) : super(hint);
accept(Visitor v) => v.visitMutableVariable(this);
@@ -1874,23 +1907,23 @@
T visitLetHandler(LetHandler node);
T visitLetMutable(LetMutable node);
T visitInvokeContinuation(InvokeContinuation node);
+ T visitThrow(Throw node);
+ T visitRethrow(Rethrow node);
+ T visitBranch(Branch node);
+ T visitUnreachable(Unreachable node);
+
+ // Definitions.
T visitInvokeStatic(InvokeStatic node);
T visitInvokeMethod(InvokeMethod node);
T visitInvokeMethodDirectly(InvokeMethodDirectly node);
T visitInvokeConstructor(InvokeConstructor node);
- T visitThrow(Throw node);
- T visitRethrow(Rethrow node);
- T visitBranch(Branch node);
T visitTypeCast(TypeCast node);
T visitSetMutable(SetMutable node);
T visitSetStatic(SetStatic node);
- T visitGetLazyStatic(GetLazyStatic node);
T visitSetField(SetField node);
- T visitUnreachable(Unreachable node);
+ T visitGetLazyStatic(GetLazyStatic node);
T visitAwait(Await node);
T visitYield(Yield node);
-
- // Definitions.
T visitLiteralList(LiteralList node);
T visitLiteralMap(LiteralMap node);
T visitConstant(Constant node);
@@ -2392,3 +2425,373 @@
(new RemovalVisitor()).visit(node);
}
}
+
+/// A visitor to copy instances of [Definition] or its subclasses, except for
+/// instances of [Continuation].
+///
+/// The visitor maintains a map from original definitions to their copies.
+/// When the [copy] method is called for a non-Continuation definition,
+/// a copy is created, added to the map and returned as the result. Copying a
+/// definition assumes that the definitions of all references have already
+/// been copied by the same visitor.
+class DefinitionCopyingVisitor extends Visitor<Definition> {
+ Map<Definition, Definition> _copies = <Definition, Definition>{};
+
+ /// Put a copy into the map.
+ ///
+ /// This method should be used instead of directly adding copies to the map.
+ Definition putCopy(Definition original, Definition copy) {
+ if (copy is Variable) {
+ Variable originalVariable = original;
+ copy.type = originalVariable.type;
+ copy.hint = originalVariable.hint;
+ }
+ return _copies[original] = copy;
+ }
+
+ /// Get the copy of a [Reference]'s definition from the map.
+ Definition getCopy(Reference reference) => _copies[reference.definition];
+
+ /// Map a list of [Reference]s to the list of their definition's copies.
+ List<Definition> getList(List<Reference> list) => list.map(getCopy).toList();
+
+ /// Copy a non-[Continuation] [Definition].
+ Definition copy(Definition node) {
+ assert (node is! Continuation);
+ return putCopy(node, visit(node));
+ }
+
+ Definition visit(Node node) => node.accept(this);
+
+ visitFunctionDefinition(FunctionDefinition node) {}
+ visitLetPrim(LetPrim node) {}
+ visitLetCont(LetCont node) {}
+ visitLetHandler(LetHandler node) {}
+ visitLetMutable(LetMutable node) {}
+ visitInvokeContinuation(InvokeContinuation node) {}
+ visitThrow(Throw node) {}
+ visitRethrow(Rethrow node) {}
+ visitBranch(Branch node) {}
+ visitUnreachable(Unreachable node) {}
+ visitContinuation(Continuation node) {}
+
+ Definition visitInvokeStatic(InvokeStatic node) {
+ return new InvokeStatic(node.target, node.selector, getList(node.arguments),
+ node.sourceInformation);
+ }
+
+ Definition visitInvokeMethod(InvokeMethod node) {
+ return new InvokeMethod(getCopy(node.receiver), node.selector, node.mask,
+ getList(node.arguments),
+ node.sourceInformation);
+ }
+
+ Definition visitInvokeMethodDirectly(InvokeMethodDirectly node) {
+ return new InvokeMethodDirectly(getCopy(node.receiver), node.target,
+ node.selector,
+ getList(node.arguments),
+ node.sourceInformation);
+ }
+
+ Definition visitInvokeConstructor(InvokeConstructor node) {
+ return new InvokeConstructor(node.dartType, node.target, node.selector,
+ getList(node.arguments),
+ node.sourceInformation);
+ }
+
+ Definition visitTypeCast(TypeCast node) {
+ return new TypeCast(getCopy(node.value), node.dartType,
+ getList(node.typeArguments));
+ }
+
+ Definition visitSetMutable(SetMutable node) {
+ return new SetMutable(getCopy(node.variable), getCopy(node.value));
+ }
+
+ Definition visitSetStatic(SetStatic node) {
+ return new SetStatic(node.element, getCopy(node.value),
+ node.sourceInformation);
+ }
+
+ Definition visitSetField(SetField node) {
+ return new SetField(getCopy(node.object), node.field, getCopy(node.value));
+ }
+
+ Definition visitGetLazyStatic(GetLazyStatic node) {
+ return new GetLazyStatic(node.element, node.sourceInformation);
+ }
+
+ Definition visitAwait(Await node) {
+ return new Await(getCopy(node.input));
+ }
+
+ Definition visitYield(Yield node) {
+ return new Yield(getCopy(node.input), node.hasStar);
+ }
+
+ Definition visitLiteralList(LiteralList node) {
+ return new LiteralList(node.dartType, getList(node.values));
+ }
+
+ Definition visitLiteralMap(LiteralMap node) {
+ List<LiteralMapEntry> entries = node.entries.map((LiteralMapEntry entry) {
+ return new LiteralMapEntry(getCopy(entry.key), getCopy(entry.value));
+ }).toList();
+ return new LiteralMap(node.dartType, entries);
+ }
+
+ Definition visitConstant(Constant node) {
+ return new Constant(node.value, sourceInformation: node.sourceInformation);
+ }
+
+ Definition visitGetMutable(GetMutable node) {
+ return new GetMutable(getCopy(node.variable));
+ }
+
+ Definition visitParameter(Parameter node) {
+ return new Parameter(node.hint);
+ }
+
+ Definition visitMutableVariable(MutableVariable node) {
+ return new MutableVariable(node.hint);
+ }
+
+ Definition visitGetStatic(GetStatic node) {
+ return new GetStatic(node.element, node.sourceInformation);
+ }
+
+ Definition visitInterceptor(Interceptor node) {
+ return new Interceptor(getCopy(node.input), node.sourceInformation)
+ ..interceptedClasses.addAll(node.interceptedClasses);
+ }
+
+ Definition visitCreateInstance(CreateInstance node) {
+ return new CreateInstance(node.classElement, getList(node.arguments),
+ getList(node.typeInformation),
+ node.sourceInformation);
+ }
+
+ Definition visitGetField(GetField node) {
+ return new GetField(getCopy(node.object), node.field);
+ }
+
+ Definition visitCreateBox(CreateBox node) {
+ return new CreateBox();
+ }
+
+ Definition visitReifyRuntimeType(ReifyRuntimeType node) {
+ return new ReifyRuntimeType(getCopy(node.value), node.sourceInformation);
+ }
+
+ Definition visitReadTypeVariable(ReadTypeVariable node) {
+ return new ReadTypeVariable(node.variable, getCopy(node.target),
+ node.sourceInformation);
+ }
+
+ Definition visitTypeExpression(TypeExpression node) {
+ return new TypeExpression(node.dartType, getList(node.arguments));
+ }
+
+ Definition visitCreateInvocationMirror(CreateInvocationMirror node) {
+ return new CreateInvocationMirror(node.selector, getList(node.arguments));
+ }
+
+ Definition visitTypeTest(TypeTest node) {
+ return new TypeTest(getCopy(node.value), node.dartType,
+ getList(node.typeArguments));
+ }
+
+ Definition visitTypeTestViaFlag(TypeTestViaFlag node) {
+ return new TypeTestViaFlag(getCopy(node.interceptor), node.dartType);
+ }
+
+ Definition visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+ return new ApplyBuiltinOperator(node.operator, getList(node.arguments),
+ node.sourceInformation);
+ }
+
+ Definition visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
+ return new ApplyBuiltinMethod(node.method, getCopy(node.receiver),
+ getList(node.arguments),
+ node.sourceInformation,
+ receiverIsNotNull: node.receiverIsNotNull);
+ }
+
+ Definition visitGetLength(GetLength node) {
+ return new GetLength(getCopy(node.object));
+ }
+
+ Definition visitGetIndex(GetIndex node) {
+ return new GetIndex(getCopy(node.object), getCopy(node.index));
+ }
+
+ Definition visitSetIndex(SetIndex node) {
+ return new SetIndex(getCopy(node.object), getCopy(node.index),
+ getCopy(node.value));
+ }
+
+ Definition visitRefinement(Refinement node) {
+ return new Refinement(getCopy(node.value), node.refineType);
+ }
+
+ Definition visitBoundsCheck(BoundsCheck node) {
+ if (node.hasNoChecks) {
+ return new BoundsCheck.noCheck(getCopy(node.object),
+ node.sourceInformation);
+ } else {
+ return new BoundsCheck(getCopy(node.object), getCopy(node.index),
+ getCopy(node.length),
+ node.checks,
+ node.sourceInformation);
+ }
+ }
+
+ Definition visitNullCheck(NullCheck node) {
+ return new NullCheck(getCopy(node.value), node.sourceInformation);
+ }
+
+ Definition visitForeignCode(ForeignCode node) {
+ return new ForeignCode(node.codeTemplate, node.type,
+ getList(node.arguments),
+ node.nativeBehavior,
+ dependency: node.dependency);
+ }
+}
+
+/// A trampolining visitor to copy [FunctionDefinition]s.
+class CopyingVisitor extends TrampolineRecursiveVisitor {
+ // The visitor maintains a map from original continuations to their copies.
+ Map<Continuation, Continuation> _copies = <Continuation, Continuation>{};
+
+ // The visitor uses an auxiliary visitor to copy definitions.
+ DefinitionCopyingVisitor _definitions = new DefinitionCopyingVisitor();
+
+ // While copying a block, the state of the visitor is a 'linked list' of
+ // the expressions in the block's body, with a pointer to the last element
+ // of the list.
+ Expression _first = null;
+ Expression _current = null;
+
+ void plug(Expression body) {
+ if (_first == null) {
+ _first = body;
+ } else {
+ assert(_current != null);
+ InteriorExpression interior = _current;
+ interior.body = body;
+ }
+ _current = body;
+ }
+
+ // Continuations are added to the visitor's stack to be visited after copying
+ // the current block is finished. The stack action saves the current block,
+ // copies the continuation's body, sets the body on the copy of the
+ // continuation, and restores the current block.
+ //
+ // Note that continuations are added to the copy map before the stack action
+ // to visit them is performed.
+ void push(Continuation cont) {
+ assert(!cont.isReturnContinuation);
+ _stack.add(() {
+ Expression savedFirst = _first;
+ _first = _current = null;
+ _processBlock(cont.body);
+ _copies[cont].body = _first;
+ _first = savedFirst;
+ _current = null;
+ });
+ }
+
+ FunctionDefinition copy(FunctionDefinition node) {
+ assert(_first == null && _current == null);
+ _first = _current = null;
+ // Definitions are copied where they are bound, before processing
+ // expressions in the scope of their binding.
+ Parameter thisParameter = node.thisParameter == null
+ ? null
+ : _definitions.copy(node.thisParameter);
+ List<Parameter> parameters =
+ node.parameters.map(_definitions.copy).toList();
+ // Though the return continuation's parameter does not have any uses,
+ // we still make a proper copy to ensure that hints, type, etc. are
+ // copied.
+ Parameter returnParameter =
+ _definitions.copy(node.returnContinuation.parameters.first);
+ Continuation returnContinuation = _copies[node.returnContinuation] =
+ new Continuation([returnParameter]);
+
+ visit(node.body);
+ FunctionDefinition copy = new FunctionDefinition(node.element,
+ thisParameter,
+ parameters,
+ returnContinuation,
+ _first);
+ _first = _current = null;
+ return copy;
+ }
+
+ Node visit(Node node) => node.accept(this);
+
+ Expression traverseLetCont(LetCont node) {
+ // Continuations are copied where they are bound, before processing
+ // expressions in the scope of their binding.
+ List<Continuation> continuations = node.continuations.map((Continuation c) {
+ push(c);
+ return _copies[c] =
+ new Continuation(c.parameters.map(_definitions.copy).toList());
+ }).toList();
+ plug(new LetCont.many(continuations, null));
+ return node.body;
+ }
+
+ Expression traverseLetHandler(LetHandler node) {
+ // Continuations are copied where they are bound, before processing
+ // expressions in the scope of their binding.
+ push(node.handler);
+ Continuation handler = _copies[node.handler] =
+ new Continuation(node.handler.parameters.map(_definitions.copy)
+ .toList());
+ plug(new LetHandler(handler, null));
+ return node.body;
+ }
+
+ Expression traverseLetPrim(LetPrim node) {
+ plug(new LetPrim(_definitions.copy(node.primitive)));
+ return node.body;
+ }
+
+ Expression traverseLetMutable(LetMutable node) {
+ plug(new LetMutable(_definitions.copy(node.variable),
+ _definitions.getCopy(node.value)));
+ return node.body;
+ }
+
+ // Tail expressions do not have references, so we do not need to map them
+ // to their copies.
+ visitInvokeContinuation(InvokeContinuation node) {
+ plug(new InvokeContinuation(_copies[node.continuation.definition],
+ _definitions.getList(node.arguments),
+ isRecursive: node.isRecursive,
+ isEscapingTry: node.isEscapingTry,
+ sourceInformation: node.sourceInformation));
+ }
+
+ visitThrow(Throw node) {
+ plug(new Throw(_definitions.getCopy(node.value)));
+ }
+
+ visitRethrow(Rethrow node) {
+ plug(new Rethrow());
+ }
+
+ visitBranch(Branch node) {
+ plug(new Branch.loose(_definitions.getCopy(node.condition),
+ _copies[node.trueContinuation.definition],
+ _copies[node.falseContinuation.definition])
+ ..isStrictCheck = node.isStrictCheck);
+ }
+
+ visitUnreachable(Unreachable node) {
+ plug(new Unreachable());
+ }
+}
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 bf857f9..bde9b0e 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
@@ -48,6 +48,7 @@
/// Main entry point for creating a [String] from a [Node]. All recursive
/// calls must go through this method.
String visit(Node node) {
+ if (node == null) return '**** NULL ****';
String s = node.accept(this);
return decorator(node, s);
}
@@ -112,20 +113,25 @@
}
String formatArguments(CallStructure call,
- List<Reference<Primitive>> arguments,
- [CallingConvention callingConvention = CallingConvention.Normal]) {
+ List<Reference<Primitive>> arguments,
+ [CallingConvention callingConvention = CallingConvention.Normal]) {
int positionalArgumentCount = call.positionalArgumentCount;
- if (callingConvention == CallingConvention.Intercepted) {
+ if (callingConvention == CallingConvention.Intercepted ||
+ callingConvention == CallingConvention.DummyIntercepted) {
++positionalArgumentCount;
}
List<String> args =
- arguments.getRange(0, positionalArgumentCount).map(access).toList();
+ arguments.take(positionalArgumentCount).map(access).toList();
List<String> argumentNames = call.getOrderedNamedArguments();
for (int i = 0; i < argumentNames.length; ++i) {
String name = argumentNames[i];
String arg = access(arguments[positionalArgumentCount + i]);
args.add("($name: $arg)");
}
+ // Constructors can have type parameter after the named arguments.
+ args.addAll(
+ arguments.skip(positionalArgumentCount + argumentNames.length)
+ .map(access));
return '(${args.join(' ')})';
}
@@ -170,7 +176,8 @@
String name = access(node.continuation);
if (node.isRecursive) name = 'rec $name';
String args = node.arguments.map(access).join(' ');
- return '$indentation(InvokeContinuation $name ($args))';
+ String escaping = node.isEscapingTry ? ' escape' : '';
+ return '$indentation(InvokeContinuation $name ($args)$escaping)';
}
String visitThrow(Throw node) {
diff --git a/pkg/compiler/lib/src/cps_ir/inline.dart b/pkg/compiler/lib/src/cps_ir/inline.dart
new file mode 100644
index 0000000..d3d2672
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/inline.dart
@@ -0,0 +1,515 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library cps_ir.optimization.inline;
+
+import 'cps_fragment.dart';
+import 'cps_ir_builder.dart' show ThisParameterLocal;
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart';
+import 'type_mask_system.dart' show TypeMaskSystem;
+import '../dart_types.dart' show DartType, GenericType;
+import '../world.dart' show World;
+import '../elements/elements.dart';
+import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import '../js_backend/codegen/task.dart' show CpsFunctionCompiler;
+import '../types/types.dart' show
+ FlatTypeMask, ForwardingTypeMask, TypeMask, UnionTypeMask;
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/selector.dart' show Selector;
+
+/// Inlining stack entries.
+///
+/// During inlining, a stack is used to detect cycles in the call graph.
+class StackEntry {
+ // Dynamically resolved calls might be targeting an adapter function that
+ // fills in optional arguments not passed at the call site. Therefore these
+ // calls are represented by the eventual target and the call structure at
+ // the call site, which together identify the target. Statically resolved
+ // calls are represented by the target element and a null call structure.
+ final ExecutableElement target;
+ final CallStructure callStructure;
+
+ StackEntry(this.target, this.callStructure);
+
+ bool match(ExecutableElement otherTarget, CallStructure otherCallStructure) {
+ if (target != otherTarget) return false;
+ if (callStructure == null) return otherCallStructure == null;
+ return otherCallStructure != null &&
+ callStructure.match(otherCallStructure);
+ }
+}
+
+/// Inlining cache entries.
+class CacheEntry {
+ // The cache maps a function element to a list of entries, where each entry
+ // is a tuple of (call structure, abstract receiver, abstract arguments)
+ // along with the inlining decision and optional IR function definition.
+ final CallStructure callStructure;
+ final TypeMask receiver;
+ final List<TypeMask> arguments;
+
+ final bool decision;
+ final FunctionDefinition function;
+
+ CacheEntry(this.callStructure, this.receiver, this.arguments, this.decision,
+ this.function);
+
+ bool match(CallStructure otherCallStructure, TypeMask otherReceiver,
+ List<TypeMask> otherArguments) {
+ if (callStructure == null) {
+ if (otherCallStructure != null) return false;
+ } else if (otherCallStructure == null ||
+ !callStructure.match(otherCallStructure)) {
+ return false;
+ }
+
+ if (receiver != otherReceiver) return false;
+ assert(arguments.length == otherArguments.length);
+ for (int i = 0; i < arguments.length; ++i) {
+ if (arguments[i] != otherArguments[i]) return false;
+ }
+ return true;
+ }
+}
+
+/// An inlining cache.
+///
+/// During inlining a cache is used to remember inlining decisions for shared
+/// parts of the call graph, to avoid exploring them more than once.
+///
+/// The cache maps a tuple of (function element, call structure,
+/// abstract receiver, abstract arguments) to a boolean inlining decision and
+/// an IR function definition if the decision is positive.
+class InliningCache {
+ static const int ABSENT = -1;
+ static const int NO_INLINE = 0;
+
+ final Map<ExecutableElement, List<CacheEntry>> map =
+ <ExecutableElement, List<CacheEntry>>{};
+
+ // When function definitions are put into or removed from the cache, they are
+ // copied because the compiler passes will mutate them.
+ final CopyingVisitor copier = new CopyingVisitor();
+
+ void _putInternal(ExecutableElement element, CallStructure callStructure,
+ TypeMask receiver,
+ List<TypeMask> arguments,
+ bool decision,
+ FunctionDefinition function) {
+ map.putIfAbsent(element, () => <CacheEntry>[])
+ .add(new CacheEntry(callStructure, receiver, arguments, decision,
+ function));
+ }
+
+ /// Put a positive inlining decision in the cache.
+ ///
+ /// A positive inlining decision maps to an IR function definition.
+ void putPositive(ExecutableElement element, CallStructure callStructure,
+ TypeMask receiver,
+ List<TypeMask> arguments,
+ FunctionDefinition function) {
+ _putInternal(element, callStructure, receiver, arguments, true,
+ copier.copy(function));
+ }
+
+ /// Put a negative inlining decision in the cache.
+ void putNegative(ExecutableElement element,
+ CallStructure callStructure,
+ TypeMask receiver,
+ List<TypeMask> arguments) {
+ _putInternal(element, callStructure, receiver, arguments, false, null);
+ }
+
+ /// Look up a tuple in the cache.
+ ///
+ /// A positive lookup result return the IR function definition. A negative
+ /// lookup result returns [NO_INLINE]. If there is no cached result,
+ /// [ABSENT] is returned.
+ get(ExecutableElement element, CallStructure callStructure, TypeMask receiver,
+ List<TypeMask> arguments) {
+ List<CacheEntry> entries = map[element];
+ if (entries != null) {
+ for (CacheEntry entry in entries) {
+ if (entry.match(callStructure, receiver, arguments)) {
+ if (entry.decision) {
+ FunctionDefinition function = copier.copy(entry.function);
+ ParentVisitor.setParents(function);
+ return function;
+ }
+ return NO_INLINE;
+ }
+ }
+ }
+ return ABSENT;
+ }
+}
+
+class Inliner implements Pass {
+ get passName => 'Inline calls';
+
+ final CpsFunctionCompiler functionCompiler;
+
+ final InliningCache cache = new InliningCache();
+
+ final List<StackEntry> stack = <StackEntry>[];
+
+ Inliner(this.functionCompiler);
+
+ bool isCalledOnce(Element element) {
+ return functionCompiler.compiler.typesTask.typesInferrer.isCalledOnce(
+ element);
+ }
+
+ void rewrite(FunctionDefinition node, [CallStructure callStructure]) {
+ Element function = node.element;
+
+ // Inlining in asynchronous or generator functions is disabled. Inlining
+ // triggers a bug in the async rewriter.
+ // TODO(kmillikin): Fix the bug and eliminate this restriction if it makes
+ // sense.
+ if (function is FunctionElement &&
+ function.asyncMarker != AsyncMarker.SYNC) {
+ return;
+ }
+
+ stack.add(new StackEntry(function, callStructure));
+ new InliningVisitor(this).visit(node);
+ assert(stack.last.match(function, callStructure));
+ stack.removeLast();
+ new ShrinkingReducer().rewrite(node);
+ }
+}
+
+/// Compute an abstract size of an IR function definition.
+///
+/// The size represents the cost of inlining at a call site.
+class SizeVisitor extends TrampolineRecursiveVisitor {
+ int size = 0;
+
+ void countArgument(Reference<Primitive> argument, Parameter parameter) {
+ // If a parameter is unused and the corresponding argument has only the
+ // one use at the invocation, then inlining the call might enable
+ // elimination of the argument. This 'pays for itself' by decreasing the
+ // cost of inlining at the call site.
+ if (argument != null &&
+ argument.definition.hasExactlyOneUse &&
+ parameter.hasNoUses) {
+ --size;
+ }
+ }
+
+ static int sizeOf(InvocationPrimitive invoke, FunctionDefinition function) {
+ SizeVisitor visitor = new SizeVisitor();
+ visitor.visit(function);
+ visitor.countArgument(invoke.receiver, function.thisParameter);
+ for (int i = 0; i < invoke.arguments.length; ++i) {
+ visitor.countArgument(invoke.arguments[i], function.parameters[i]);
+ }
+ return visitor.size;
+ }
+
+ // Inlining a function incurs a cost equal to the number of primitives and
+ // non-jump tail expressions.
+ // TODO(kmillikin): Tune the size computation and size bound.
+ processLetPrim(LetPrim node) => ++size;
+ processLetMutable(LetMutable node) => ++size;
+ processBranch(Branch node) => ++size;
+ processThrow(Throw nose) => ++size;
+ processRethrow(Rethrow node) => ++size;
+}
+
+class InliningVisitor extends TrampolineRecursiveVisitor {
+ final Inliner _inliner;
+
+ // A successful inlining attempt returns the [Primitive] that represents the
+ // result of the inlined call or null. If the result is non-null, the body
+ // of the inlined function is available in this field.
+ CpsFragment _fragment;
+
+ InliningVisitor(this._inliner);
+
+ JavaScriptBackend get backend => _inliner.functionCompiler.backend;
+ TypeMaskSystem get typeSystem => _inliner.functionCompiler.typeSystem;
+ World get world => _inliner.functionCompiler.compiler.world;
+
+ FunctionDefinition compileToCpsIr(AstElement element) {
+ return _inliner.functionCompiler.compileToCpsIr(element);
+ }
+
+ void optimizeBeforeInlining(FunctionDefinition function) {
+ _inliner.functionCompiler.optimizeCpsBeforeInlining(function);
+ }
+
+ void applyCpsPass(Pass pass, FunctionDefinition function) {
+ return _inliner.functionCompiler.applyCpsPass(pass, function);
+ }
+
+ bool isRecursive(Element target, CallStructure callStructure) {
+ return _inliner.stack.any((StackEntry s) => s.match(target, callStructure));
+ }
+
+ @override
+ Expression traverseLetPrim(LetPrim node) {
+ // A successful inlining attempt will set the node's body to null, so it is
+ // read before visiting the primitive.
+ Expression next = node.body;
+ Primitive replacement = visit(node.primitive);
+ if (replacement != null) {
+ node.primitive.replaceWithFragment(_fragment, replacement);
+ }
+ return next;
+ }
+
+ TypeMask abstractType(Reference<Primitive> ref) {
+ return ref.definition.type ?? typeSystem.dynamicType;
+ }
+
+ /// Build the IR term for the function that adapts a call site targeting a
+ /// function that takes optional arguments not passed at the call site.
+ FunctionDefinition buildAdapter(InvokeMethod node, FunctionElement target) {
+ Parameter thisParameter = new Parameter(new ThisParameterLocal(target))
+ ..type = node.receiver.definition.type;
+ List<Parameter> parameters = new List<Parameter>.generate(
+ node.arguments.length,
+ (int index) {
+ // TODO(kmillikin): Use a hint for the parameter names.
+ return new Parameter(null)
+ ..type = node.arguments[index].definition.type;
+ });
+ Continuation returnContinuation = new Continuation.retrn();
+ CpsFragment cps = new CpsFragment();
+
+ FunctionSignature signature = target.functionSignature;
+ int requiredParameterCount = signature.requiredParameterCount;
+ if (node.callingConvention == CallingConvention.Intercepted ||
+ node.callingConvention == CallingConvention.DummyIntercepted) {
+ ++requiredParameterCount;
+ }
+ List<Primitive> arguments = new List<Primitive>.generate(
+ requiredParameterCount,
+ (int index) => parameters[index]);
+
+ int parameterIndex = requiredParameterCount;
+ CallStructure newCallStructure;
+ if (signature.optionalParametersAreNamed) {
+ List<String> incomingNames =
+ node.selector.callStructure.getOrderedNamedArguments();
+ List<String> outgoingNames = <String>[];
+ int nameIndex = 0;
+ signature.orderedOptionalParameters.forEach((ParameterElement formal) {
+ if (nameIndex < incomingNames.length &&
+ formal.name == incomingNames[nameIndex]) {
+ arguments.add(parameters[parameterIndex++]);
+ ++nameIndex;
+ } else {
+ Constant defaultValue = cps.makeConstant(
+ backend.constants.getConstantValueForVariable(formal));
+ defaultValue.type = typeSystem.getParameterType(formal);
+ arguments.add(defaultValue);
+ }
+ outgoingNames.add(formal.name);
+ });
+ newCallStructure =
+ new CallStructure(signature.parameterCount, outgoingNames);
+ } else {
+ signature.forEachOptionalParameter((ParameterElement formal) {
+ if (parameterIndex < parameters.length) {
+ arguments.add(parameters[parameterIndex++]);
+ } else {
+ Constant defaultValue = cps.makeConstant(
+ backend.constants.getConstantValueForVariable(formal));
+ defaultValue.type = typeSystem.getParameterType(formal);
+ arguments.add(defaultValue);
+ }
+ });
+ newCallStructure = new CallStructure(signature.parameterCount);
+ }
+
+ Selector newSelector =
+ new Selector(node.selector.kind, node.selector.memberName,
+ newCallStructure);
+ Primitive result = cps.invokeMethod(thisParameter, newSelector, node.mask,
+ arguments, node.callingConvention);
+ result.type = typeSystem.getInvokeReturnType(node.selector, node.mask);
+ cps.invokeContinuation(returnContinuation, <Primitive>[result]);
+ return new FunctionDefinition(target, thisParameter, parameters,
+ returnContinuation,
+ cps.root);
+ }
+
+ // Given an invocation and a known target, possibly perform inlining.
+ //
+ // An optional call structure indicates a dynamic call. Calls that are
+ // already resolved statically have a null call structure.
+ //
+ // The [Primitive] representing the result of the inlined call is returned
+ // if the call was inlined, and the inlined function body is available in
+ // [_fragment]. If the call was not inlined, null is returned.
+ Primitive tryInlining(InvocationPrimitive invoke, FunctionElement target,
+ CallStructure callStructure) {
+ // Quick checks: do not inline or even cache calls to targets without an
+ // AST node or targets that are asynchronous or generator functions.
+ if (!target.hasNode) return null;
+ if (target.asyncMarker != AsyncMarker.SYNC) return null;
+
+ Reference<Primitive> dartReceiver = invoke.dartReceiverReference;
+ TypeMask abstractReceiver =
+ dartReceiver == null ? null : abstractType(dartReceiver);
+ List<TypeMask> abstractArguments =
+ invoke.arguments.map(abstractType).toList();
+ var cachedResult = _inliner.cache.get(target, callStructure,
+ abstractReceiver,
+ abstractArguments);
+
+ // Negative inlining result in the cache.
+ if (cachedResult == InliningCache.NO_INLINE) return null;
+
+ // Positive inlining result in the cache.
+ if (cachedResult is FunctionDefinition) {
+ FunctionDefinition function = cachedResult;
+ _fragment = new CpsFragment(invoke.sourceInformation);
+ Primitive receiver = invoke.receiver?.definition;
+ List<Primitive> arguments =
+ invoke.arguments.map((Reference ref) => ref.definition).toList();
+ // Add a null check to the inlined function body if necessary. The
+ // cached function body does not contain the null check.
+ if (dartReceiver != null && abstractReceiver.isNullable) {
+ Primitive check = nullReceiverGuard(
+ invoke, _fragment, dartReceiver.definition, abstractReceiver);
+ if (invoke.callingConvention == CallingConvention.Intercepted) {
+ arguments[0] = check;
+ } else {
+ receiver = check;
+ }
+ }
+ return _fragment.inlineFunction(function, receiver, arguments,
+ hint: invoke.hint);
+ }
+
+ // We have not seen this combination of target and abstract arguments
+ // before. Make an inlining decision.
+ assert(cachedResult == InliningCache.ABSENT);
+ Primitive doNotInline() {
+ _inliner.cache.putNegative(target, callStructure, abstractReceiver,
+ abstractArguments);
+ return null;
+ }
+ if (backend.annotations.noInline(target)) return doNotInline();
+ if (isRecursive(target, callStructure)) return doNotInline();
+
+ FunctionDefinition function;
+ if (callStructure != null &&
+ target.functionSignature.parameterCount !=
+ callStructure.argumentCount) {
+ // The argument count at the call site does not match the target's
+ // formal parameter count. Build the IR term for an adapter function
+ // body.
+ function = buildAdapter(invoke, target);
+ } else {
+ function = _inliner.functionCompiler.compileToCpsIr(target);
+ void setValue(Variable variable, Reference<Primitive> value) {
+ variable.type = value.definition.type;
+ }
+ if (invoke.receiver != null) {
+ setValue(function.thisParameter, invoke.receiver);
+ }
+ for (int i = 0; i < invoke.arguments.length; ++i) {
+ setValue(function.parameters[i], invoke.arguments[i]);
+ }
+ optimizeBeforeInlining(function);
+ }
+
+ // Inline calls in the body.
+ _inliner.rewrite(function, callStructure);
+
+ // Compute the size.
+ // TODO(kmillikin): Tune the size bound.
+ int size = SizeVisitor.sizeOf(invoke, function);
+ if (!_inliner.isCalledOnce(target) && size > 11) return doNotInline();
+
+ _inliner.cache.putPositive(target, callStructure, abstractReceiver,
+ abstractArguments, function);
+ _fragment = new CpsFragment(invoke.sourceInformation);
+ Primitive receiver = invoke.receiver?.definition;
+ List<Primitive> arguments =
+ invoke.arguments.map((Reference ref) => ref.definition).toList();
+ if (dartReceiver != null && abstractReceiver.isNullable) {
+ Primitive check =
+ _fragment.letPrim(new NullCheck(dartReceiver.definition,
+ invoke.sourceInformation));
+ check.type = abstractReceiver.nonNullable();
+ if (invoke.callingConvention == CallingConvention.Intercepted) {
+ arguments[0] = check;
+ } else {
+ receiver = check;
+ }
+ }
+ return _fragment.inlineFunction(function, receiver, arguments,
+ hint: invoke.hint);
+ }
+
+ Primitive nullReceiverGuard(InvocationPrimitive invoke,
+ CpsFragment fragment,
+ Primitive dartReceiver,
+ TypeMask abstractReceiver) {
+ Selector selector = invoke is InvokeMethod ? invoke.selector : null;
+ if (typeSystem.isDefinitelyNum(abstractReceiver, allowNull: true)) {
+ Primitive condition = _fragment.letPrim(
+ new ApplyBuiltinOperator(BuiltinOperator.IsNotNumber,
+ <Primitive>[dartReceiver],
+ invoke.sourceInformation));
+ condition.type = typeSystem.boolType;
+ Primitive check = _fragment.letPrim(
+ new NullCheck.guarded(
+ condition, dartReceiver, selector, invoke.sourceInformation));
+ check.type = abstractReceiver.nonNullable();
+ return check;
+ }
+
+ Primitive check = _fragment.letPrim(
+ new NullCheck(dartReceiver, invoke.sourceInformation));
+ check.type = abstractReceiver.nonNullable();
+ return check;
+ }
+
+
+ @override
+ Primitive visitInvokeStatic(InvokeStatic node) {
+ return tryInlining(node, node.target, null);
+ }
+
+ @override
+ Primitive visitInvokeMethod(InvokeMethod node) {
+ Primitive receiver = node.dartReceiver;
+ Element element = world.locateSingleElement(node.selector, receiver.type);
+ if (element == null || element is! FunctionElement) return null;
+ if (node.selector.isGetter != element.isGetter) return null;
+ if (node.selector.isSetter != element.isSetter) return null;
+ if (node.selector.name != element.name) return null;
+
+ return tryInlining(node, element.asFunctionElement(),
+ node.selector.callStructure);
+ }
+
+ @override
+ Primitive visitInvokeMethodDirectly(InvokeMethodDirectly node) {
+ if (node.selector.isGetter != node.target.isGetter) return null;
+ if (node.selector.isSetter != node.target.isSetter) return null;
+ return tryInlining(node, node.target, null);
+ }
+
+ @override
+ Primitive visitInvokeConstructor(InvokeConstructor node) {
+ if (node.dartType is GenericType) {
+ // We cannot inline a constructor invocation containing type arguments
+ // because CreateInstance in the body does not know the type arguments.
+ // We would incorrectly instantiate a class like A instead of A<B>.
+ // TODO(kmillikin): try to fix this.
+ GenericType generic = node.dartType;
+ if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null;
+ }
+ return tryInlining(node, node.target, null);
+ }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
index 66fe170..99d1807 100644
--- a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
+++ b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
@@ -9,7 +9,6 @@
import '../common/names.dart';
import '../types/types.dart' show TypeMask;
import 'type_mask_system.dart';
-import 'cps_fragment.dart';
/// Inserts [Refinement] nodes in the IR to allow for sparse path-sensitive
/// type analysis in the [TypePropagator] pass.
diff --git a/pkg/compiler/lib/src/cps_ir/loop_effects.dart b/pkg/compiler/lib/src/cps_ir/loop_effects.dart
index 6679336..c7680b0 100644
--- a/pkg/compiler/lib/src/cps_ir/loop_effects.dart
+++ b/pkg/compiler/lib/src/cps_ir/loop_effects.dart
@@ -2,7 +2,6 @@
import 'cps_ir_nodes.dart';
import 'loop_hierarchy.dart';
-import 'type_mask_system.dart';
import '../universe/side_effects.dart';
import '../elements/elements.dart';
import '../world.dart';
diff --git a/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart b/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
index 9f05e39..19b79d4 100644
--- a/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
@@ -14,7 +14,6 @@
import '../js_backend/js_backend.dart' show JavaScriptBackend;
import '../types/types.dart' show TypeMask;
import '../io/source_information.dart' show SourceInformation;
-import '../universe/selector.dart';
/// Replaces `getInterceptor` calls with interceptor constants when possible,
/// or with "almost constant" expressions like "x && CONST" when the input
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index ccbee6f..0ca2173 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -18,7 +18,9 @@
export 'redundant_refinement.dart' show RedundantRefinementEliminator;
export 'optimize_interceptors.dart' show OptimizeInterceptors;
export 'bounds_checker.dart' show BoundsChecker;
+export 'backward_null_check_remover.dart' show BackwardNullCheckRemover;
export 'gvn.dart' show GVN;
+export 'inline.dart' show Inliner;
export 'eagerly_load_statics.dart' show EagerlyLoadStatics;
export 'parent_visitor.dart' show ParentVisitor;
diff --git a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
index 422db14..f7365b4 100644
--- a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
+++ b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
@@ -166,6 +166,17 @@
InvokeContinuation invoke = cont.body;
Continuation wrappedCont = invoke.continuation.definition;
+ // If the invocation of wrappedCont is escaping, then all invocations of
+ // cont will be as well, after the reduction.
+ if (invoke.isEscapingTry) {
+ Reference current = cont.firstRef;
+ while (current != null) {
+ InvokeContinuation owner = current.parent;
+ owner.isEscapingTry = true;
+ current = current.next;
+ }
+ }
+
// Replace all occurrences with the wrapped continuation.
cont.replaceUsesWith(wrappedCont);
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 86333da..3b340b2 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -38,9 +38,6 @@
import 'cps_fragment.dart';
import 'cps_ir_nodes.dart';
import 'type_mask_system.dart';
-import '../closure.dart' show
- ClosureFieldElement,
- BoxLocal;
class ConstantPropagationLattice {
final TypeMaskSystem typeSystem;
@@ -49,11 +46,12 @@
final AbstractConstantValue anything;
final AbstractConstantValue nullValue;
- ConstantPropagationLattice(TypeMaskSystem typeSystem,
- this.constantSystem,
- this.dartTypes)
- : this.typeSystem = typeSystem,
- anything = new AbstractConstantValue.nonConstant(typeSystem.dynamicType),
+ ConstantPropagationLattice(CpsFunctionCompiler functionCompiler)
+ : typeSystem = functionCompiler.typeSystem,
+ constantSystem = functionCompiler.compiler.backend.constantSystem,
+ dartTypes = functionCompiler.compiler.types,
+ anything = new AbstractConstantValue.nonConstant(
+ functionCompiler.typeSystem.dynamicType),
nullValue = new AbstractConstantValue.constantValue(
new NullConstantValue(), new TypeMask.empty());
@@ -711,25 +709,18 @@
* by Wegman, Zadeck.
*/
class TypePropagator extends Pass {
- String get passName => 'Sparse constant propagation';
+ String get passName => 'Type propagation';
- final dart2js.Compiler _compiler;
final CpsFunctionCompiler _functionCompiler;
+ final Map<Variable, ConstantValue> _values= <Variable, ConstantValue>{};
final ConstantPropagationLattice _lattice;
- final InternalErrorFunction _internalError;
- final Map<Variable, ConstantValue> _values = <Variable, ConstantValue>{};
- final TypeMaskSystem _typeSystem;
- TypePropagator(dart2js.Compiler compiler,
- TypeMaskSystem typeSystem,
- this._functionCompiler)
- : _compiler = compiler,
- _internalError = compiler.reporter.internalError,
- _typeSystem = typeSystem,
- _lattice = new ConstantPropagationLattice(
- typeSystem,
- compiler.backend.constantSystem,
- compiler.types);
+ TypePropagator(CpsFunctionCompiler functionCompiler)
+ : _functionCompiler = functionCompiler,
+ _lattice = new ConstantPropagationLattice(functionCompiler);
+
+ dart2js.Compiler get _compiler => _functionCompiler.compiler;
+ InternalErrorFunction get _internalError => _compiler.reporter.internalError;
@override
void rewrite(FunctionDefinition root) {
@@ -1268,7 +1259,6 @@
Primitive index = node.dartArgument(0);
if (lattice.isDefinitelyString(receiverValue) &&
lattice.isDefinitelyInt(getValue(index))) {
- SourceInformation sourceInfo = node.sourceInformation;
CpsFragment cps = new CpsFragment(node.sourceInformation);
receiver = makeBoundsCheck(cps, receiver, index);
ApplyBuiltinOperator get =
@@ -1368,7 +1358,6 @@
allowNull: true)) {
return null;
}
- SourceInformation sourceInfo = node.sourceInformation;
switch (node.selector.name) {
case 'length':
if (!node.selector.isGetter) return null;
@@ -1416,8 +1405,6 @@
}
bool isFixedLength =
lattice.isDefinitelyFixedArray(listValue, allowNull: true);
- bool isMutable =
- lattice.isDefinitelyMutableArray(listValue, allowNull: true);
bool isExtendable =
lattice.isDefinitelyExtendableArray(listValue, allowNull: true);
SourceInformation sourceInfo = node.sourceInformation;
@@ -1673,11 +1660,11 @@
/// Returns the first parent of [node] that is not a pure expression.
InteriorNode getEffectiveParent(Expression node) {
while (true) {
- Node parent = node.parent;
+ InteriorNode parent = node.parent;
if (parent is LetCont ||
parent is LetPrim && parent.primitive.isSafeForReordering ||
parent is LetPrim && parent.primitive is Refinement) {
- node = parent;
+ node = parent as dynamic; // Make analyzer accept cross cast.
} else {
return parent;
}
@@ -1786,18 +1773,6 @@
return null;
}
- void destroyRefinementsOfDeadPrimitive(Primitive prim) {
- while (prim.firstRef != null) {
- Refinement refine = prim.firstRef.parent;
- destroyRefinementsOfDeadPrimitive(refine);
- LetPrim letPrim = refine.parent;
- InteriorNode parent = letPrim.parent;
- parent.body = letPrim.body;
- letPrim.body.parent = parent;
- prim.firstRef.unlink();
- }
- }
-
/// Inlines a single-use closure if it leaves the closure object with only
/// field accesses. This is optimized later by [ScalarReplacer].
CpsFragment specializeSingleUseClosureCall(InvokeMethod node) {
@@ -2604,31 +2579,38 @@
void visit(Node node) { node.accept(this); }
void visitFunctionDefinition(FunctionDefinition node) {
- int firstActualParameter = 0;
- if (backend.isInterceptedMethod(node.element)) {
- if (typeSystem.methodUsesReceiverArgument(node.element)) {
+ bool isIntercepted = backend.isInterceptedMethod(node.element);
+
+ // If the abstract value of the function parameters is Nothing, use the
+ // inferred parameter type. Otherwise (e.g., when inlining) do not
+ // change the abstract value.
+ if (node.thisParameter != null && getValue(node.thisParameter).isNothing) {
+ if (isIntercepted &&
+ typeSystem.methodUsesReceiverArgument(node.element)) {
setValue(node.thisParameter, nonConstant(typeSystem.nonNullType));
- setValue(node.parameters[0],
- nonConstant(typeSystem.getReceiverType(node.element)));
} else {
setValue(node.thisParameter,
- nonConstant(typeSystem.getReceiverType(node.element)));
+ nonConstant(typeSystem.getReceiverType(node.element)));
+ }
+ }
+ if (isIntercepted && getValue(node.parameters[0]).isNothing) {
+ if (typeSystem.methodUsesReceiverArgument(node.element)) {
+ setValue(node.parameters[0],
+ nonConstant(typeSystem.getReceiverType(node.element)));
+ } else {
setValue(node.parameters[0], nonConstant());
}
- firstActualParameter = 1;
- } else if (node.thisParameter != null) {
- setValue(node.thisParameter,
- nonConstant(typeSystem.getReceiverType(node.element)));
}
bool hasParameterWithoutValue = false;
- for (Parameter param in node.parameters.skip(firstActualParameter)) {
- // TODO(karlklose): remove reference to the element model.
- TypeMask type = param.hint is ParameterElement
- ? typeSystem.getParameterType(param.hint)
- : typeSystem.dynamicType;
- setValue(param, lattice.fromMask(type));
- if (type.isEmpty && !type.isNullable) {
- hasParameterWithoutValue = true;
+ for (Parameter param in node.parameters.skip(isIntercepted ? 1 : 0)) {
+ if (getValue(param).isNothing) {
+ TypeMask type = param.hint is ParameterElement
+ ? typeSystem.getParameterType(param.hint)
+ : typeSystem.dynamicType;
+ setValue(param, lattice.fromMask(type));
+ if (type.isEmpty && !type.isNullable) {
+ hasParameterWithoutValue = true;
+ }
}
}
if (!hasParameterWithoutValue) { // Don't analyze unreachable code.
diff --git a/pkg/compiler/lib/src/js/placeholder_safety.dart b/pkg/compiler/lib/src/js/placeholder_safety.dart
index 67ff563..b103489 100644
--- a/pkg/compiler/lib/src/js/placeholder_safety.dart
+++ b/pkg/compiler/lib/src/js/placeholder_safety.dart
@@ -303,6 +303,7 @@
case 'Array':
case 'Date':
case 'Function':
+ case 'Math':
case 'Number':
case 'Object':
case 'RegExp':
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 78f61cb..33430be 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -66,18 +66,22 @@
final GenericTask treeBuilderTask;
final GenericTask treeOptimizationTask;
+ Inliner inliner;
+
CpsFunctionCompiler(Compiler compiler, JavaScriptBackend backend,
SourceInformationStrategy sourceInformationFactory)
: fallbackCompiler =
new ssa.SsaFunctionCompiler(backend, sourceInformationFactory),
cpsBuilderTask = new IrBuilderTask(compiler, sourceInformationFactory),
- this.sourceInformationFactory = sourceInformationFactory,
+ sourceInformationFactory = sourceInformationFactory,
constantSystem = backend.constantSystem,
compiler = compiler,
glue = new Glue(compiler),
cpsOptimizationTask = new GenericTask('CPS optimization', compiler),
treeBuilderTask = new GenericTask('Tree builder', compiler),
- treeOptimizationTask = new GenericTask('Tree optimization', compiler);
+ treeOptimizationTask = new GenericTask('Tree optimization', compiler) {
+ inliner = new Inliner(this);
+ }
String get name => 'CPS Ir pipeline';
@@ -87,9 +91,9 @@
/// Generates JavaScript code for `work.element`.
js.Fun compile(CodegenWorkItem work) {
+ if (typeSystem == null) typeSystem = new TypeMaskSystem(compiler);
AstElement element = work.element;
return reporter.withCurrentElement(element, () {
- typeSystem = new TypeMaskSystem(compiler);
try {
// TODO(karlklose): remove this fallback when we do not need it for
// testing anymore.
@@ -102,7 +106,9 @@
tracer.traceCompilation(element.name, null);
}
cps.FunctionDefinition cpsFunction = compileToCpsIr(element);
- cpsFunction = optimizeCpsIr(cpsFunction);
+ optimizeCpsBeforeInlining(cpsFunction);
+ applyCpsPass(inliner, cpsFunction);
+ optimizeCpsAfterInlining(cpsFunction);
cpsIntegrityChecker = null;
tree_ir.FunctionDefinition treeFunction = compileToTreeIr(cpsFunction);
treeFunction = optimizeTreeIr(treeFunction);
@@ -200,14 +206,19 @@
return true; // So this can be used from assert().
}
- cps.FunctionDefinition optimizeCpsIr(cps.FunctionDefinition cpsFunction) {
+ void optimizeCpsBeforeInlining(cps.FunctionDefinition cpsFunction) {
cpsOptimizationTask.measure(() {
applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
applyCpsPass(new InsertRefinements(typeSystem), cpsFunction);
- applyCpsPass(new TypePropagator(compiler, typeSystem, this), cpsFunction);
+ applyCpsPass(new TypePropagator(this), cpsFunction);
applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
applyCpsPass(new ShrinkingReducer(), cpsFunction);
+ });
+ }
+
+ void optimizeCpsAfterInlining(cps.FunctionDefinition cpsFunction) {
+ cpsOptimizationTask.measure(() {
applyCpsPass(new RedundantRefinementEliminator(typeSystem), cpsFunction);
applyCpsPass(new EagerlyLoadStatics(), cpsFunction);
applyCpsPass(new GVN(compiler, typeSystem), cpsFunction);
@@ -220,9 +231,9 @@
applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
applyCpsPass(new ShrinkingReducer(), cpsFunction);
applyCpsPass(new OptimizeInterceptors(backend), cpsFunction);
+ applyCpsPass(new BackwardNullCheckRemover(typeSystem), cpsFunction);
applyCpsPass(new ShrinkingReducer(), cpsFunction);
});
- return cpsFunction;
}
tree_ir.FunctionDefinition compileToTreeIr(cps.FunctionDefinition cpsNode) {
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 57b54fd..11a80a4 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -355,7 +355,7 @@
static const String DART_STRING_CLASS = "ConstantStringMap";
static const String DART_PROTO_CLASS = "ConstantProtoMap";
static const String DART_GENERAL_CLASS = "GeneralConstantMap";
- static const String LENGTH_NAME = "length";
+ static const String LENGTH_NAME = "_length";
static const String JS_OBJECT_NAME = "_jsObject";
static const String KEYS_NAME = "_keys";
static const String PROTO_VALUE = "_protoValue";
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 6fa2ccf..fa3b79b 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -21,6 +21,9 @@
final String setterPrefix = 's';
final String callPrefix = ''; // this will create function names $<n>
+ jsAst.Name get staticsPropertyName =>
+ _staticsPropertyName ??= getFreshName(instanceScope, 'static');
+
FrequencyBasedNamer(Compiler compiler) : super(compiler) {
fieldRegistry = new _FieldNamingRegistry(this);
}
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 4cd691e..bd55710 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -356,6 +356,11 @@
jsAst.Name _literalSetterPrefix;
jsAst.Name _literalLazyGetterPrefix;
+ jsAst.Name _staticsPropertyName;
+
+ jsAst.Name get staticsPropertyName =>
+ _staticsPropertyName ??= new StringBackedName('static');
+
// Name of property in a class description for the native dispatch metadata.
final String nativeSpecProperty = '%';
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
index f625c8a..06aa189 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
@@ -328,8 +328,9 @@
}
if (!statics.isEmpty) {
- classBuilder.addPropertyByName('static',
- new jsAst.ObjectInitializer(statics));
+ classBuilder.addProperty(
+ namer.staticsPropertyName, // 'static' or its minified name.
+ new jsAst.ObjectInitializer(statics, isOneLiner: false));
}
// TODO(ahe): This method (generateClass) should return a jsAst.Expression.
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
index 9ad63ab..ecd8a4b 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
@@ -102,6 +102,8 @@
'mangledNames': mangledNamesAccess,
'mangledGlobalNames': mangledGlobalNamesAccess,
'statics': staticsAccess,
+ 'staticsPropertyName': namer.staticsPropertyName,
+ 'staticsPropertyNameString': js.quoteName(namer.staticsPropertyName),
'typeInformation': typeInformationAccess,
'globalFunctions': globalFunctionsAccess,
'enabledInvokeOn': compiler.enabledInvokeOn,
@@ -526,10 +528,10 @@
for (var i = 0; i < properties.length; i++) {
var property = properties[i];
var firstChar = property.charCodeAt(0);
- if (property === "static") {
- processStatics(#statics[cls] = descriptor.static,
+ if (property === #staticsPropertyNameString) {
+ processStatics(#statics[cls] = descriptor.#staticsPropertyName,
processedClasses);
- delete descriptor.static;
+ delete descriptor.#staticsPropertyName;
} else if (firstChar === 43) { // 43 is "+".
mangledNames[previousProperty] = property.substring(1);
var flag = descriptor[property];
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index f38dcf3..32b508f 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -239,11 +239,16 @@
/// If the given expression always returns the value of one of its
/// subexpressions, and that subexpression is a variable use, returns that
/// variable. Otherwise `null`.
- Variable getRightHand(Expression e) {
+ Variable getRightHandVariable(Expression e) {
Expression value = getValueSubexpression(e);
return value is VariableUse ? value.variable : null;
}
+ Constant getRightHandConstant(Expression e) {
+ Expression value = getValueSubexpression(e);
+ return value is Constant ? value : null;
+ }
+
/// True if the given expression (taken from [constantEnvironment]) uses a
/// variable that might have been reassigned since [node] was evaluated.
bool hasUnsafeVariableUse(Expression node) {
@@ -322,7 +327,7 @@
//
// { E.foo = x; bar(x) } ==> bar(E.foo = x)
//
- if (getRightHand(binding) == node.variable) {
+ if (getRightHandVariable(binding) == node.variable) {
environment.removeLast();
--node.variable.readCount;
return visitExpression(binding);
@@ -585,8 +590,15 @@
return node;
}
+ bool isNullConstant(Expression node) {
+ return node is Constant && node.value.isNull;
+ }
+
Statement visitReturn(Return node) {
- node.value = visitExpression(node.value);
+ if (!isNullConstant(node.value)) {
+ // Do not chain assignments into a null return.
+ node.value = visitExpression(node.value);
+ }
return node;
}
@@ -709,6 +721,12 @@
}
Expression visitConstant(Constant node) {
+ if (!environment.isEmpty) {
+ Constant constant = getRightHandConstant(environment.last);
+ if (constant != null && constant.value == node.value) {
+ return visitExpression(environment.removeLast());
+ }
+ }
return node;
}
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index c36a394..6c4297e 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -53,6 +53,7 @@
<cps_ir.Primitive, Variable>{};
final Map<cps_ir.MutableVariable, Variable> mutable2variable =
<cps_ir.MutableVariable, Variable>{};
+ final Set<cps_ir.Constant> inlinedConstants = new Set<cps_ir.Constant>();
// Continuations with more than one use are replaced with Tree labels. This
// is the mapping from continuations to labels.
@@ -109,6 +110,9 @@
/// returned expression must be used in the tree.
Expression getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference) {
cps_ir.Primitive prim = reference.definition.effectiveDefinition;
+ if (prim is cps_ir.Constant && inlinedConstants.contains(prim)) {
+ return new Constant(prim.value);
+ }
if (thisParameter != null && prim == thisParameter) {
return new This();
}
@@ -279,6 +283,53 @@
return prim.accept(this);
}
+ /************************ CONSTANT COPYING *****************************/
+
+ /// Estimate of the number of characters needed to emit a use of the given
+ /// constant.
+ int constantSize(PrimitiveConstantValue value) {
+ // TODO(asgerf): We could interface with the emitter to get the exact size.
+ if (value is StringConstantValue) {
+ // Account for the quotes, but ignore the cost of encoding non-ASCII
+ // characters to avoid traversing the string and depending on encoding.
+ return value.length + 2;
+ } else if (value is BoolConstantValue) {
+ return 2; // Printed as !0 and !1 when minified
+ } else {
+ // TODO(asgerf): Get the exact length of numbers using '1e10' notation.
+ return '${value.primitiveValue}'.length;
+ }
+ }
+
+ /// The number of uses [prim] has, or `-1` if it is used in a phi assignment.
+ int countNonPhiUses(cps_ir.Primitive prim) {
+ int count = 0;
+ for (cps_ir.Reference ref = prim.firstRef; ref != null; ref = ref.next) {
+ cps_ir.Node use = ref.parent;
+ if (use is cps_ir.InvokeContinuation) {
+ return -1;
+ }
+ count++;
+ }
+ return count;
+ }
+
+ /// True if the given [constant] should be copied to every use site.
+ bool shouldCopyToUses(cps_ir.Constant constant) {
+ if (!constant.value.isPrimitive) return false;
+ if (constant.hasAtMostOneUse) return true;
+ int uses = countNonPhiUses(constant);
+ if (uses == -1) return false; // Copying might prevent elimination of a phi.
+ int size = constantSize(constant.value);
+ // Compare the expected code size output of copying vs sharing.
+ const int USE = 2; // Minified locals usually have length 2.
+ const int ASSIGN = USE + 2; // Variable and '=' and ';'
+ const int BIAS = 2; // Artificial bias to slightly favor copying.
+ int costOfSharing = USE * uses + size + ASSIGN + BIAS;
+ int costOfCopying = size * uses;
+ return costOfCopying <= costOfSharing;
+ }
+
/************************ INTERIOR EXPRESSIONS ************************/
//
// Visit methods for interior expressions must return a function:
@@ -287,6 +338,10 @@
//
NodeCallback visitLetPrim(cps_ir.LetPrim node) {
+ if (node.primitive is cps_ir.Constant && shouldCopyToUses(node.primitive)) {
+ inlinedConstants.add(node.primitive);
+ return (Statement next) => next;
+ }
Variable variable = getVariable(node.primitive);
var value = translatePrimitive(node.primitive);
if (value is Expression) {
diff --git a/pkg/js_ast/lib/src/printer.dart b/pkg/js_ast/lib/src/printer.dart
index d5c1d9b..edd4189 100644
--- a/pkg/js_ast/lib/src/printer.dart
+++ b/pkg/js_ast/lib/src/printer.dart
@@ -1069,22 +1069,31 @@
// Print all the properties on one line until we see a function-valued
// property. Ideally, we would use a proper pretty-printer to make the
// decision based on layout.
+ bool exitOneLinerMode(Expression value) {
+ return
+ value is Fun ||
+ value is ArrayInitializer && value.elements.any((e) => e is Fun);
+ }
+
+ bool isOneLiner = node.isOneLiner || shouldCompressOutput;
List<Property> properties = node.properties;
out("{");
indentMore();
for (int i = 0; i < properties.length; i++) {
+ Node value = properties[i].value;
+ if (isOneLiner && exitOneLinerMode(value)) isOneLiner = false;
if (i != 0) {
out(",");
- if (node.isOneLiner) spaceOut();
+ if (isOneLiner) spaceOut();
}
- if (!node.isOneLiner) {
+ if (!isOneLiner) {
forceLine();
indent();
}
visit(properties[i]);
}
indentLess();
- if (!node.isOneLiner && !properties.isEmpty) {
+ if (!isOneLiner && !properties.isEmpty) {
lineOut();
indent();
}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 0d48659..c821f54 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -65,6 +65,7 @@
analyzer/test/src/context/cache_test: Pass, Slow # Issue 21628
analyzer/test/src/context/context_test: Pass, Timeout # dartbug.com/23658
analyzer/test/src/dart/element/element_test: Pass, Slow # Issue 21628
+analyzer/test/src/summary/resynthesize_test: Pass, Slow
analyzer/test/src/summary/summary_test: Pass, Slow # Issue 21628
analyzer/test/src/task/dart_test: Pass, Slow # Issue 21628
analyzer/test/src/task/dart_work_manager_test: Pass, Slow # Issue 21628
@@ -164,6 +165,11 @@
[ $use_repository_packages ]
analyzer/test/*: PubGetError
+[ $compiler == dart2js && $cps_ir && $host_checked == false ]
+analyzer/test/dart/element/element_test: Pass, Slow # Times out due to inlining, but see issue 24485
+analyzer/test/src/summary/resynthesize_test: Pass, Slow # Times out due to inlining, but see issue 24485
+analyzer/test/src/task/strong_mode_test: Pass, Slow # Times out due to inlining, but see issue 24485
+
[ $compiler == dart2js && $cps_ir && $host_checked ]
analyzer/test/enum_test: Crash # Issue 24485
analyzer/test/generated/all_the_rest_test: Crash # Issue 24485
diff --git a/runtime/bin/embedded_dart_io.cc b/runtime/bin/embedded_dart_io.cc
index 1b3f40b..9e38f02 100644
--- a/runtime/bin/embedded_dart_io.cc
+++ b/runtime/bin/embedded_dart_io.cc
@@ -5,6 +5,7 @@
#include "bin/embedded_dart_io.h"
#include "bin/eventhandler.h"
+#include "bin/utils.h"
#include "bin/thread.h"
namespace dart {
@@ -13,6 +14,7 @@
void BootstrapDartIo() {
// Bootstrap 'dart:io' event handler.
Thread::InitOnce();
+ TimerUtils::InitOnce();
EventHandler::Start();
}
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 773c0af..93611a4 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -19,6 +19,7 @@
#include "bin/file.h"
#include "bin/log.h"
#include "bin/thread.h"
+#include "bin/utils.h"
#include "bin/vmservice_impl.h"
#include "platform/globals.h"
@@ -1017,6 +1018,7 @@
Thread::InitOnce();
DartUtils::SetOriginalWorkingDirectory();
// Start event handler.
+ TimerUtils::InitOnce();
EventHandler::Start();
vm_options.AddArgument("--load_deferred_eagerly");
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 7fc19c4..71a6b65 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -71,6 +71,12 @@
static bool has_run_precompiled_snapshot = false;
+// Value of the --gen/run_precompiled_snapshot flag.
+// (This pointer points into an argv buffer and does not need to be
+// free'd.)
+static const char* precompiled_snapshot_directory = NULL;
+
+
// Global flag that is used to indicate that we want to compile everything in
// the same way as precompilation before main, then continue running in the
// same process.
@@ -109,7 +115,7 @@
// Global flag that is used to indicate that the VM should do a clean
// shutdown.
-static bool do_vm_shutdown = false;
+static bool do_vm_shutdown = true;
static void ErrorExit(int exit_code, const char* format, ...) {
va_list arguments;
@@ -304,16 +310,18 @@
static bool ProcessGenPrecompiledSnapshotOption(
const char* arg,
CommandLineOptions* vm_options) {
- ASSERT(arg != NULL);
- if (*arg != '\0') {
- return false;
- }
// Ensure that we are not already running using a full snapshot.
if (isolate_snapshot_buffer != NULL) {
Log::PrintErr("Precompiled snapshots must be generated with"
" dart_no_snapshot.\n");
return false;
}
+ ASSERT(arg != NULL);
+ if ((arg[0] == '=') || (arg[0] == ':')) {
+ precompiled_snapshot_directory = &arg[1];
+ } else {
+ precompiled_snapshot_directory = arg;
+ }
has_gen_precompiled_snapshot = true;
vm_options->AddArgument("--precompilation");
return true;
@@ -324,8 +332,10 @@
const char* arg,
CommandLineOptions* vm_options) {
ASSERT(arg != NULL);
- if (*arg != '\0') {
- return false;
+ precompiled_snapshot_directory = arg;
+ if ((precompiled_snapshot_directory[0] == '=') ||
+ (precompiled_snapshot_directory[0] == ':')) {
+ precompiled_snapshot_directory = &precompiled_snapshot_directory[1];
}
has_run_precompiled_snapshot = true;
vm_options->AddArgument("--precompilation");
@@ -1009,34 +1019,67 @@
}
-static void WriteSnapshotFile(const char* filename,
- const uint8_t* buffer,
- const intptr_t size) {
- File* file = File::Open(filename, File::kWriteTruncate);
+static void WritePrecompiledSnapshotFile(const char* filename,
+ const uint8_t* buffer,
+ const intptr_t size) {
+ char* concat = NULL;
+ const char* qualified_filename;
+ if (strlen(precompiled_snapshot_directory) > 0) {
+ intptr_t len = snprintf(NULL, 0, "%s/%s",
+ precompiled_snapshot_directory, filename);
+ concat = new char[len + 1];
+ snprintf(concat, len + 1, "%s/%s",
+ precompiled_snapshot_directory, filename);
+ qualified_filename = concat;
+ } else {
+ qualified_filename = filename;
+ }
+
+ File* file = File::Open(qualified_filename, File::kWriteTruncate);
ASSERT(file != NULL);
if (!file->WriteFully(buffer, size)) {
ErrorExit(kErrorExitCode,
"Unable to open file %s for writing snapshot\n",
- filename);
+ qualified_filename);
}
delete file;
+ if (concat != NULL) {
+ delete concat;
+ }
}
-static void ReadSnapshotFile(const char* filename,
- const uint8_t** buffer) {
- void* file = DartUtils::OpenFile(filename, false);
+static void ReadPrecompiledSnapshotFile(const char* filename,
+ const uint8_t** buffer) {
+ char* concat = NULL;
+ const char* qualified_filename;
+ if (strlen(precompiled_snapshot_directory) > 0) {
+ intptr_t len = snprintf(NULL, 0, "%s/%s",
+ precompiled_snapshot_directory, filename);
+ concat = new char[len + 1];
+ snprintf(concat, len + 1, "%s/%s",
+ precompiled_snapshot_directory, filename);
+ qualified_filename = concat;
+ } else {
+ qualified_filename = filename;
+ }
+
+ void* file = DartUtils::OpenFile(qualified_filename, false);
if (file == NULL) {
ErrorExit(kErrorExitCode,
- "Error: Unable to open file %s for reading snapshot\n", filename);
+ "Error: Unable to open file %s for reading snapshot\n",
+ qualified_filename);
}
intptr_t len = -1;
DartUtils::ReadFile(buffer, &len, file);
if (*buffer == NULL || len == -1) {
ErrorExit(kErrorExitCode,
- "Error: Unable to read snapshot file %s\n", filename);
+ "Error: Unable to read snapshot file %s\n", qualified_filename);
}
DartUtils::CloseFile(file);
+ if (concat != NULL) {
+ delete concat;
+ }
}
@@ -1190,7 +1233,6 @@
{ "dart:io", "_ProcessStartStatus", "set:_errorMessage" },
{ "dart:io", "_SecureFilterImpl", "get:ENCRYPTED_SIZE" },
{ "dart:io", "_SecureFilterImpl", "get:SIZE" },
- { "dart:vmservice_io", "::", "_addResource" },
{ "dart:vmservice_io", "::", "main" },
{ "dart:vmservice_io", "::", "boot" },
{ NULL, NULL, NULL } // Must be terminated with NULL entries.
@@ -1215,15 +1257,15 @@
&instructions_buffer,
&instructions_size);
CHECK_RESULT(result);
- WriteSnapshotFile(kPrecompiledVmIsolateName,
- vm_isolate_buffer,
- vm_isolate_size);
- WriteSnapshotFile(kPrecompiledIsolateName,
- isolate_buffer,
- isolate_size);
- WriteSnapshotFile(kPrecompiledInstructionsName,
- instructions_buffer,
- instructions_size);
+ WritePrecompiledSnapshotFile(kPrecompiledVmIsolateName,
+ vm_isolate_buffer,
+ vm_isolate_size);
+ WritePrecompiledSnapshotFile(kPrecompiledIsolateName,
+ isolate_buffer,
+ isolate_size);
+ WritePrecompiledSnapshotFile(kPrecompiledInstructionsName,
+ instructions_buffer,
+ instructions_size);
} else {
if (has_compile_all) {
result = Dart_CompileAll();
@@ -1420,14 +1462,17 @@
Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
// Start event handler.
+ TimerUtils::InitOnce();
EventHandler::Start();
const uint8_t* instructions_snapshot = NULL;
if (has_run_precompiled_snapshot) {
instructions_snapshot = reinterpret_cast<const uint8_t*>(
LoadLibrarySymbol(kPrecompiledLibraryName, kPrecompiledSymbolName));
- ReadSnapshotFile(kPrecompiledVmIsolateName, &vm_isolate_snapshot_buffer);
- ReadSnapshotFile(kPrecompiledIsolateName, &isolate_snapshot_buffer);
+ ReadPrecompiledSnapshotFile(kPrecompiledVmIsolateName,
+ &vm_isolate_snapshot_buffer);
+ ReadPrecompiledSnapshotFile(kPrecompiledIsolateName,
+ &isolate_snapshot_buffer);
}
// Initialize the Dart VM.
diff --git a/runtime/bin/platform.cc b/runtime/bin/platform.cc
index ec75ee9..f2f16be 100644
--- a/runtime/bin/platform.cc
+++ b/runtime/bin/platform.cc
@@ -45,12 +45,28 @@
void FUNCTION_NAME(Platform_ExecutableName)(Dart_NativeArguments args) {
ASSERT(Platform::GetExecutableName() != NULL);
+ if (Dart_IsRunningPrecompiledCode()) {
+ // This is a work-around to be able to use most of the existing test suite
+ // for precompilation. Many tests do something like Process.run(
+ // Platform.executable, some_other_script.dart). But with precompilation
+ // the script is already fixed, so the spawned process runs the same script
+ // again and we have a fork-bomb.
+ Dart_ThrowException(Dart_NewStringFromCString(
+ "Platform.executable not supported under precompilation"));
+ UNREACHABLE();
+ }
Dart_SetReturnValue(
args, Dart_NewStringFromCString(Platform::GetExecutableName()));
}
void FUNCTION_NAME(Platform_ResolvedExecutableName)(Dart_NativeArguments args) {
+ if (Dart_IsRunningPrecompiledCode()) {
+ Dart_ThrowException(Dart_NewStringFromCString(
+ "Platform.resolvedExecutable not supported under precompilation"));
+ UNREACHABLE();
+ }
+
if (Platform::GetResolvedExecutableName() != NULL) {
Dart_SetReturnValue(
args, Dart_NewStringFromCString(Platform::GetResolvedExecutableName()));
diff --git a/runtime/bin/utils.h b/runtime/bin/utils.h
index a1714c2..cbc2bab 100644
--- a/runtime/bin/utils.h
+++ b/runtime/bin/utils.h
@@ -98,6 +98,7 @@
class TimerUtils {
public:
+ static void InitOnce();
static int64_t GetCurrentMonotonicMicros();
static int64_t GetCurrentMonotonicMillis();
static void Sleep(int64_t millis);
diff --git a/runtime/bin/utils_android.cc b/runtime/bin/utils_android.cc
index db9eb75..e36ac11 100644
--- a/runtime/bin/utils_android.cc
+++ b/runtime/bin/utils_android.cc
@@ -71,6 +71,9 @@
return false;
}
+void TimerUtils::InitOnce() {
+}
+
int64_t TimerUtils::GetCurrentMonotonicMillis() {
return GetCurrentMonotonicMicros() / 1000;
}
diff --git a/runtime/bin/utils_linux.cc b/runtime/bin/utils_linux.cc
index 419df95..ea6ef8c 100644
--- a/runtime/bin/utils_linux.cc
+++ b/runtime/bin/utils_linux.cc
@@ -69,6 +69,9 @@
return false;
}
+void TimerUtils::InitOnce() {
+}
+
int64_t TimerUtils::GetCurrentMonotonicMillis() {
return GetCurrentMonotonicMicros() / 1000;
}
diff --git a/runtime/bin/utils_macos.cc b/runtime/bin/utils_macos.cc
index 80cd038..5ac414f 100644
--- a/runtime/bin/utils_macos.cc
+++ b/runtime/bin/utils_macos.cc
@@ -74,6 +74,13 @@
return false;
}
+static mach_timebase_info_data_t timebase_info;
+
+void TimerUtils::InitOnce() {
+ kern_return_t kr = mach_timebase_info(&timebase_info);
+ ASSERT(KERN_SUCCESS == kr);
+}
+
int64_t TimerUtils::GetCurrentMonotonicMillis() {
return GetCurrentMonotonicMicros() / 1000;
}
@@ -94,17 +101,7 @@
origin += boottime.tv_usec;
return now - origin;
#else
- static mach_timebase_info_data_t timebase_info;
- if (timebase_info.denom == 0) {
- // Zero-initialization of statics guarantees that denom will be 0 before
- // calling mach_timebase_info. mach_timebase_info will never set denom to
- // 0 as that would be invalid, so the zero-check can be used to determine
- // whether mach_timebase_info has already been called. This is
- // recommended by Apple's QA1398.
- kern_return_t kr = mach_timebase_info(&timebase_info);
- ASSERT(KERN_SUCCESS == kr);
- }
-
+ ASSERT(timebase_info.denom != 0);
// timebase_info converts absolute time tick units into nanoseconds. Convert
// to microseconds.
int64_t result = mach_absolute_time() / kNanosecondsPerMicrosecond;
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index ae12f4b..116ae56 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -187,12 +187,21 @@
return (time.t_ - kTimeEpoc) / kTimeScaler;
}
+static int64_t qpc_ticks_per_second = 0;
+
+void TimerUtils::InitOnce() {
+ LARGE_INTEGER ticks_per_sec;
+ if (!QueryPerformanceFrequency(&ticks_per_sec)) {
+ qpc_ticks_per_second = 0;
+ } else {
+ qpc_ticks_per_second = static_cast<int64_t>(ticks_per_sec.QuadPart);
+ }
+}
+
int64_t TimerUtils::GetCurrentMonotonicMillis() {
return GetCurrentMonotonicMicros() / 1000;
}
-static int64_t qpc_ticks_per_second = 0;
-
int64_t TimerUtils::GetCurrentMonotonicMicros() {
if (qpc_ticks_per_second == 0) {
// QueryPerformanceCounter not supported, fallback.
diff --git a/runtime/bin/vmservice_dartium.cc b/runtime/bin/vmservice_dartium.cc
index aa5a62a..0ff30a7 100644
--- a/runtime/bin/vmservice_dartium.cc
+++ b/runtime/bin/vmservice_dartium.cc
@@ -9,6 +9,7 @@
#include "bin/eventhandler.h"
#include "bin/platform.h"
#include "bin/thread.h"
+#include "bin/utils.h"
#include "bin/vmservice_impl.h"
#include "zlib/zlib.h"
@@ -34,6 +35,7 @@
}
DartUtils::SetOriginalWorkingDirectory();
Thread::InitOnce();
+ TimerUtils::InitOnce();
EventHandler::Start();
}
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index f46a66a..2715abc 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -89,14 +89,6 @@
};
-void TriggerResourceLoad(Dart_NativeArguments args) {
- Dart_Handle library = Dart_RootLibrary();
- ASSERT(!Dart_IsError(library));
- Dart_Handle result = VmService::LoadResources(library);
- ASSERT(!Dart_IsError(result));
-}
-
-
void NotifyServerState(Dart_NativeArguments args) {
Dart_EnterScope();
const char* ip_chars;
@@ -131,7 +123,6 @@
static VmServiceIONativeEntry _VmServiceIONativeEntries[] = {
- {"VMServiceIO_TriggerResourceLoad", 0, TriggerResourceLoad},
{"VMServiceIO_NotifyServerState", 2, NotifyServerState},
};
@@ -327,63 +318,6 @@
}
-Dart_Handle VmService::LoadResource(Dart_Handle library,
- const char* resource_name) {
- // Prepare for invoke call.
- Dart_Handle name = Dart_NewStringFromCString(resource_name);
- RETURN_ERROR_HANDLE(name);
- const char* data_buffer = NULL;
- int data_buffer_length = Resources::ResourceLookup(resource_name,
- &data_buffer);
- if (data_buffer_length == Resources::kNoSuchInstance) {
- printf("Could not find %s %s\n", resource_name, resource_name);
- }
- ASSERT(data_buffer_length != Resources::kNoSuchInstance);
- Dart_Handle data_list = Dart_NewTypedData(Dart_TypedData_kUint8,
- data_buffer_length);
- RETURN_ERROR_HANDLE(data_list);
- Dart_TypedData_Type type = Dart_TypedData_kInvalid;
- void* data_list_buffer = NULL;
- intptr_t data_list_buffer_length = 0;
- Dart_Handle result = Dart_TypedDataAcquireData(data_list, &type,
- &data_list_buffer,
- &data_list_buffer_length);
- RETURN_ERROR_HANDLE(result);
- ASSERT(data_buffer_length == data_list_buffer_length);
- ASSERT(data_list_buffer != NULL);
- ASSERT(type == Dart_TypedData_kUint8);
- memmove(data_list_buffer, &data_buffer[0], data_buffer_length);
- result = Dart_TypedDataReleaseData(data_list);
- RETURN_ERROR_HANDLE(result);
-
- // Make invoke call.
- const intptr_t kNumArgs = 3;
- Dart_Handle compressed = Dart_True();
- Dart_Handle args[kNumArgs] = { name, data_list, compressed };
- result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"),
- kNumArgs, args);
- return result;
-}
-
-
-Dart_Handle VmService::LoadResources(Dart_Handle library) {
- Dart_Handle result = Dart_Null();
- intptr_t prefixLen = strlen(kLibrarySourceNamePrefix);
- for (intptr_t i = 0; Resources::Path(i) != NULL; i++) {
- const char* path = Resources::Path(i);
- // If it doesn't begin with kLibrarySourceNamePrefix it is a frontend
- // resource.
- if (strncmp(path, kLibrarySourceNamePrefix, prefixLen) != 0) {
- result = LoadResource(library, path);
- if (Dart_IsError(result)) {
- break;
- }
- }
- }
- return result;
-}
-
-
Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle url) {
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index 590aece..1780013 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -35,7 +35,6 @@
private:
static const intptr_t kServerIpStringBufferSize = 256;
- friend void TriggerResourceLoad(Dart_NativeArguments args);
friend void NotifyServerState(Dart_NativeArguments args);
static void SetServerIPAndPort(const char* ip, intptr_t port);
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 227c84f..222ef79 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -2819,4 +2819,7 @@
uint8_t** instructions_snapshot_buffer,
intptr_t* instructions_snapshot_size);
+
+DART_EXPORT bool Dart_IsRunningPrecompiledCode();
+
#endif /* INCLUDE_DART_API_H_ */ /* NOLINT */
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index d8693a1..72fcc3e 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -155,17 +155,14 @@
}
-DEFINE_NATIVE_ENTRY(Object_instanceOf, 5) {
+DEFINE_NATIVE_ENTRY(Object_instanceOf, 4) {
const Instance& instance =
Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
- // Instantiator at position 1 is not used. It is passed along so that the call
- // can be easily converted to an optimized implementation. Instantiator is
- // used to populate the subtype cache.
const TypeArguments& instantiator_type_arguments =
- TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(2));
+ TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(1));
const AbstractType& type =
- AbstractType::CheckedHandle(zone, arguments->NativeArgAt(3));
- const Bool& negate = Bool::CheckedHandle(zone, arguments->NativeArgAt(4));
+ AbstractType::CheckedHandle(zone, arguments->NativeArgAt(2));
+ const Bool& negate = Bool::CheckedHandle(zone, arguments->NativeArgAt(3));
ASSERT(type.IsFinalized());
ASSERT(!type.IsMalformed());
ASSERT(!type.IsMalbounded());
@@ -267,15 +264,12 @@
}
-DEFINE_NATIVE_ENTRY(Object_as, 4) {
+DEFINE_NATIVE_ENTRY(Object_as, 3) {
const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
- // Instantiator at position 1 is not used. It is passed along so that the call
- // can be easily converted to an optimized implementation. Instantiator is
- // used to populate the subtype cache.
const TypeArguments& instantiator_type_arguments =
- TypeArguments::CheckedHandle(arguments->NativeArgAt(2));
+ TypeArguments::CheckedHandle(arguments->NativeArgAt(1));
const AbstractType& type =
- AbstractType::CheckedHandle(arguments->NativeArgAt(3));
+ AbstractType::CheckedHandle(arguments->NativeArgAt(2));
ASSERT(type.IsFinalized());
ASSERT(!type.IsMalformed());
ASSERT(!type.IsMalbounded());
diff --git a/runtime/lib/object_patch.dart b/runtime/lib/object_patch.dart
index be42a57..b61b6a6 100644
--- a/runtime/lib/object_patch.dart
+++ b/runtime/lib/object_patch.dart
@@ -53,10 +53,7 @@
// Call this function instead of inlining instanceof, thus collecting
// type feedback and reducing code size of unoptimized code.
- bool _instanceOf(instantiator,
- instantiator_type_arguments,
- type,
- bool negate)
+ bool _instanceOf(instantiator_type_arguments, type, bool negate)
native "Object_instanceOf";
bool _instanceOfDouble(bool negate) native "Object_instanceOfDouble";
@@ -67,7 +64,7 @@
// Call this function instead of inlining 'as', thus collecting type
// feedback. Returns receiver.
- _as(instantiator, instantiator_type_arguments, type) native "Object_as";
+ _as(instantiator_type_arguments, type) native "Object_as";
static _symbolMapToStringMap(Map<Symbol, dynamic> map) {
var result = new Map<String, dynamic>();
diff --git a/runtime/lib/stopwatch.cc b/runtime/lib/stopwatch.cc
index ce8951de..934aba5 100644
--- a/runtime/lib/stopwatch.cc
+++ b/runtime/lib/stopwatch.cc
@@ -10,14 +10,12 @@
namespace dart {
DEFINE_NATIVE_ENTRY(Stopwatch_now, 0) {
- // TODO(iposva): investigate other hi-res time sources such as cycle count.
- return Integer::New(OS::GetCurrentMonotonicMicros());
+ return Integer::New(OS::GetCurrentMonotonicTicks());
}
DEFINE_NATIVE_ENTRY(Stopwatch_frequency, 0) {
- // TODO(iposva): investigate other hi-res time sources such as cycle count.
- return Integer::New(1000000);
+ return Integer::New(OS::GetCurrentMonotonicFrequency());
}
} // namespace dart
diff --git a/runtime/lib/timeline.cc b/runtime/lib/timeline.cc
index f0e5982..3d307da 100644
--- a/runtime/lib/timeline.cc
+++ b/runtime/lib/timeline.cc
@@ -49,8 +49,9 @@
return Object::null();
}
- if (!isolate->GetDartStream()->Enabled()) {
- // Dart stream is not enabled for this isolate, do nothing.
+ TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+ if (event == NULL) {
+ // Stream was turned off.
return Object::null();
}
@@ -58,7 +59,13 @@
OSThread* os_thread = thread->os_thread();
ASSERT(os_thread != NULL);
int64_t tid = OSThread::ThreadIdToIntPtr(os_thread->trace_id());
-
+ // Convert phase to a C string and perform a sanity check.
+ const char* phase_string = phase.ToCString();
+ ASSERT(phase_string != NULL);
+ ASSERT((phase_string[0] == 'n') ||
+ (phase_string[0] == 'b') ||
+ (phase_string[0] == 'e'));
+ ASSERT(phase_string[1] == '\0');
char* json = OS::SCreate(zone,
"{\"name\":\"%s\",\"cat\":\"%s\",\"tid\":%" Pd64 ",\"pid\":%" Pd64 ","
"\"ts\":%" Pd64 ",\"ph\":\"%s\",\"id\":%" Pd64 ", \"args\":%s}",
@@ -67,18 +74,26 @@
tid,
pid,
start.AsInt64Value(),
- phase.ToCString(),
+ phase_string,
id.AsInt64Value(),
args.ToCString());
- TimelineEvent* event = isolate->GetDartStream()->StartEvent();
- if (event == NULL) {
- // Stream was turned off.
- return Object::null();
+ switch (phase_string[0]) {
+ case 'n':
+ event->AsyncInstant("", id.AsInt64Value(), start.AsInt64Value());
+ break;
+ case 'b':
+ event->AsyncBegin("", id.AsInt64Value(), start.AsInt64Value());
+ break;
+ case 'e':
+ event->AsyncEnd("", id.AsInt64Value(), start.AsInt64Value());
+ break;
+ default:
+ UNREACHABLE();
}
+
// json was allocated in the zone and a copy will be stored in event.
- event->SerializedJSON(json);
- event->Complete();
+ event->CompleteWithPreSerializedJSON(json);
return Object::null();
}
@@ -96,8 +111,9 @@
return Object::null();
}
- if (!isolate->GetDartStream()->Enabled()) {
- // Dart stream is not enabled for this isolate, do nothing.
+ TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+ if (event == NULL) {
+ // Stream was turned off.
return Object::null();
}
@@ -118,14 +134,9 @@
duration,
args.ToCString());
- TimelineEvent* event = isolate->GetDartStream()->StartEvent();
- if (event == NULL) {
- // Stream was turned off.
- return Object::null();
- }
+ event->Duration("", start.AsInt64Value(), end.AsInt64Value());
// json was allocated in the zone and a copy will be stored in event.
- event->SerializedJSON(json);
- event->Complete();
+ event->CompleteWithPreSerializedJSON(json);
return Object::null();
}
@@ -142,8 +153,9 @@
return Object::null();
}
- if (!isolate->GetDartStream()->Enabled()) {
- // Dart stream is not enabled for this isolate, do nothing.
+ TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+ if (event == NULL) {
+ // Stream was turned off.
return Object::null();
}
@@ -162,14 +174,9 @@
start.AsInt64Value(),
args.ToCString());
- TimelineEvent* event = isolate->GetDartStream()->StartEvent();
- if (event == NULL) {
- // Stream was turned off.
- return Object::null();
- }
+ event->Instant("", start.AsInt64Value());
// json was allocated in the zone and a copy will be stored in event.
- event->SerializedJSON(json);
- event->Complete();
+ event->CompleteWithPreSerializedJSON(json);
return Object::null();
}
diff --git a/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart b/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
index 3de30cb..63277b7 100644
--- a/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
@@ -32,6 +32,35 @@
return false;
}
+int timeOrigin(List<Map> events) {
+ if (events.length == 0) {
+ return 0;
+ }
+ int smallest = events[0]['ts'];
+ for (var i = 0; i < events.length; i++) {
+ Map event = events[i];
+ if (event['ts'] < smallest) {
+ smallest = event['ts'];
+ }
+ }
+ return smallest;
+}
+
+int timeDuration(List<Map> events, int timeOrigin) {
+ if (events.length == 0) {
+ return 0;
+ }
+ int biggestDuration = events[0]['ts'] - timeOrigin;
+ for (var i = 0; i < events.length; i++) {
+ Map event = events[i];
+ int duration = event['ts'] - timeOrigin;
+ if (duration > biggestDuration) {
+ biggestDuration = duration;
+ }
+ }
+ return biggestDuration;
+}
+
void allEventsHaveIsolateNumber(List<Map> events) {
for (Map event in events) {
if (event['ph'] == 'M') {
@@ -61,6 +90,7 @@
Map result = await vm.invokeRpcNoUpgrade('_getVMTimeline', {});
expect(result['type'], equals('_Timeline'));
expect(result['traceEvents'], new isInstanceOf<List>());
+ final int numEvents = result['traceEvents'].length;
List<Map> dartEvents = filterForDartEvents(result['traceEvents']);
expect(dartEvents.length, equals(5));
allEventsHaveIsolateNumber(dartEvents);
@@ -71,6 +101,19 @@
expect(eventsContains(dartEvents, 'e', 'TASK1'), isTrue);
expect(eventsContains(dartEvents, 'n', 'ITASK'), isTrue);
expect(eventsContains(dartEvents, 'q', 'ITASK'), isFalse);
+ // Calculate the time Window of Dart events.
+ int origin = timeOrigin(dartEvents);
+ int extent = timeDuration(dartEvents, origin);
+ // Query for the timeline with the time window for Dart events.
+ result = await vm.invokeRpcNoUpgrade('_getVMTimeline', {
+ 'timeOriginMicros': origin,
+ 'timeExtentMicros': extent
+ });
+ // Verify that we received fewer events than before.
+ expect(result['traceEvents'].length, lessThan(numEvents));
+ // Verify that we have the same number of Dart events.
+ List<Map> dartEvents2 = filterForDartEvents(result['traceEvents']);
+ expect(dartEvents2.length, dartEvents.length);
},
];
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 0044c29..7562cf4 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -2,7 +2,7 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-[ $compiler == none && $runtime == vm ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) ]
evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
@@ -21,5 +21,5 @@
[ $arch == arm ]
process_service_test: Pass, Fail # Issue 24344
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
*: Skip # Issue 24651
\ No newline at end of file
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 21a91f8..7a914be 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -14,6 +14,8 @@
dart/data_uri_import_test/none: SkipByDesign
+dart/spawn_shutdown_test: Skip # Issue 25351
+
[ $mode == debug ]
# This is a benchmark that is not informative in debug mode.
cc/CorelibIsolateStartup: Skip
@@ -57,7 +59,7 @@
# Data uri's not supported by dart2js or the analyzer.
dart/data_uri*test: Skip
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
dart/data_uri_import_test/wrongmime: RuntimeError, OK # VM is more restrictive than the browser
dart/data_uri_import_test/nomime: RuntimeError, OK
dart/data_uri_import_test/nocharset: RuntimeError, OK
@@ -78,10 +80,16 @@
dart/spawn_infinite_loop_test: Skip # VM shutdown test
dart/spawn_shutdown_test: Skip # VM Shutdown test
-[ $runtime == vm && $mode == debug && $builder_tag == asan ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $builder_tag == asan ]
cc/Dart2JSCompileAll: Skip # Timeout.
[ $noopt ]
-dart/redirection_type_shuffling_test: CompileTimeError # Imports dart:mirrors
dart/byte_array_test: Crash # Incompatible flag --disable_alloc_stubs_after_gc
+
+[ $noopt || $compiler == precompiler ]
+dart/redirection_type_shuffling_test: CompileTimeError # Imports dart:mirrors
dart/inline_stack_frame_test: Fail # Issue 24783 - inlined frames missing
+
+[ $runtime == dart_precompiled ]
+dart/optimized_stacktrace_test: Fail
+dart/data_uri_spawn_test: RuntimeError # Isolate.spawnUri
diff --git a/runtime/tools/bmu_benchmark_gallery.sh b/runtime/tools/bmu_benchmark_gallery.sh
index 18feef0..3c1d76b 100644
--- a/runtime/tools/bmu_benchmark_gallery.sh
+++ b/runtime/tools/bmu_benchmark_gallery.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index c32632d..d31948a 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1562,6 +1562,7 @@
bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
ASSERT(!Thread::CanLoadFromThread(object));
if (!constant_pool_allowed()) {
return false;
@@ -1578,6 +1579,7 @@
Condition cond,
bool is_unique,
Register pp) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
// Load common VM constants from the thread. This works also in places where
// no constant pool is set up (e.g. intrinsic code).
if (Thread::CanLoadFromThread(object)) {
@@ -1636,12 +1638,14 @@
void Assembler::PushObject(const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
LoadObject(IP, object);
Push(IP);
}
void Assembler::CompareObject(Register rn, const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
ASSERT(rn != IP);
if (object.IsSmi()) {
CompareImmediate(rn, reinterpret_cast<int32_t>(object.raw()));
@@ -1900,6 +1904,7 @@
const Address& dest,
const Object& value,
FieldContent old_content) {
+ ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
ASSERT(value.IsSmi() || value.InVMHeap() ||
(value.IsOld() && value.IsNotTemporaryScopedHandle()));
// No store buffer update.
@@ -1912,6 +1917,7 @@
int32_t offset,
const Object& value,
FieldContent old_content) {
+ ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
int32_t ignored = 0;
if (Address::CanHoldStoreOffset(kWord, offset - kHeapObjectTag, &ignored)) {
StoreIntoObjectNoBarrier(object, FieldAddress(object, offset), value,
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 14a51cd..062ad4b 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -367,6 +367,7 @@
bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
ASSERT(!Thread::CanLoadFromThread(object));
if (!constant_pool_allowed()) {
return false;
@@ -401,6 +402,7 @@
void Assembler::LoadObjectHelper(Register dst,
const Object& object,
bool is_unique) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
if (Thread::CanLoadFromThread(object)) {
ldr(dst, Address(THR, Thread::OffsetFromThread(object)));
} else if (CanLoadFromObjectPool(object)) {
@@ -439,6 +441,7 @@
void Assembler::CompareObject(Register reg, const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
if (Thread::CanLoadFromThread(object)) {
ldr(TMP, Address(THR, Thread::OffsetFromThread(object)));
CompareRegisters(reg, TMP);
@@ -933,6 +936,7 @@
void Assembler::StoreIntoObjectNoBarrier(Register object,
const Address& dest,
const Object& value) {
+ ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
ASSERT(value.IsSmi() || value.InVMHeap() ||
(value.IsOld() && value.IsNotTemporaryScopedHandle()));
// No store buffer update.
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index c4ee937..8d3fb09 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -2163,6 +2163,7 @@
void Assembler::LoadObject(Register dst, const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
if (object.IsSmi() || object.InVMHeap()) {
movl(dst, Immediate(reinterpret_cast<int32_t>(object.raw())));
} else {
@@ -2176,6 +2177,7 @@
void Assembler::LoadObjectSafely(Register dst, const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
if (Assembler::IsSafe(object)) {
LoadObject(dst, object);
} else {
@@ -2187,6 +2189,7 @@
void Assembler::PushObject(const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
if (object.IsSmi() || object.InVMHeap()) {
pushl(Immediate(reinterpret_cast<int32_t>(object.raw())));
} else {
@@ -2200,6 +2203,7 @@
void Assembler::CompareObject(Register reg, const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
if (object.IsSmi() || object.InVMHeap()) {
cmpl(reg, Immediate(reinterpret_cast<int32_t>(object.raw())));
} else {
@@ -2398,6 +2402,7 @@
void Assembler::UnverifiedStoreOldObject(const Address& dest,
const Object& value) {
+ ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
ASSERT(value.IsOld());
ASSERT(!value.InVMHeap());
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
@@ -2411,6 +2416,7 @@
const Address& dest,
const Object& value,
FieldContent old_content) {
+ ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
VerifyHeapWord(dest, old_content);
if (value.IsSmi() || value.InVMHeap()) {
Immediate imm_value(reinterpret_cast<int32_t>(value.raw()));
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index 9f63660..0f15e3f 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -532,6 +532,7 @@
bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
ASSERT(!Thread::CanLoadFromThread(object));
if (!constant_pool_allowed()) {
return false;
@@ -546,6 +547,7 @@
void Assembler::LoadObjectHelper(Register rd,
const Object& object,
bool is_unique) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
ASSERT(!in_delay_slot_);
if (Thread::CanLoadFromThread(object)) {
// Load common VM constants from the thread. This works also in places where
@@ -603,6 +605,7 @@
void Assembler::PushObject(const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
ASSERT(!in_delay_slot_);
LoadObject(TMP, object);
Push(TMP);
@@ -729,6 +732,7 @@
void Assembler::StoreIntoObjectNoBarrier(Register object,
const Address& dest,
const Object& value) {
+ ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
ASSERT(!in_delay_slot_);
ASSERT(value.IsSmi() || value.InVMHeap() ||
(value.IsOld() && value.IsNotTemporaryScopedHandle()));
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index b3a1d09..85b83a9 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -2737,6 +2737,7 @@
bool Assembler::CanLoadFromObjectPool(const Object& object) const {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
ASSERT(!Thread::CanLoadFromThread(object));
if (!constant_pool_allowed()) {
return false;
@@ -2772,6 +2773,7 @@
void Assembler::LoadObjectHelper(Register dst,
const Object& object,
bool is_unique) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
if (Thread::CanLoadFromThread(object)) {
movq(dst, Address(THR, Thread::OffsetFromThread(object)));
} else if (CanLoadFromObjectPool(object)) {
@@ -2809,6 +2811,7 @@
void Assembler::StoreObject(const Address& dst, const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
if (Thread::CanLoadFromThread(object)) {
movq(TMP, Address(THR, Thread::OffsetFromThread(object)));
movq(dst, TMP);
@@ -2823,6 +2826,7 @@
void Assembler::PushObject(const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
if (Thread::CanLoadFromThread(object)) {
pushq(Address(THR, Thread::OffsetFromThread(object)));
} else if (CanLoadFromObjectPool(object)) {
@@ -2836,6 +2840,7 @@
void Assembler::CompareObject(Register reg, const Object& object) {
+ ASSERT(!object.IsICData() || ICData::Cast(object).IsOriginal());
if (Thread::CanLoadFromThread(object)) {
cmpq(reg, Address(THR, Thread::OffsetFromThread(object)));
} else if (CanLoadFromObjectPool(object)) {
@@ -3062,6 +3067,7 @@
const Address& dest,
const Object& value,
FieldContent old_content) {
+ ASSERT(!value.IsICData() || ICData::Cast(value).IsOriginal());
VerifyHeapWord(dest, old_content);
if (VerifiedMemory::enabled()) {
const Register temp = RCX;
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 3d2254f..a3b3952 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -20,13 +20,13 @@
V(Object_toString, 1) \
V(Object_noSuchMethod, 6) \
V(Object_runtimeType, 1) \
- V(Object_instanceOf, 5) \
+ V(Object_instanceOf, 4) \
V(Object_instanceOfNum, 2) \
V(Object_instanceOfInt, 2) \
V(Object_instanceOfSmi, 2) \
V(Object_instanceOfDouble, 2) \
V(Object_instanceOfString, 2) \
- V(Object_as, 4) \
+ V(Object_as, 3) \
V(Function_apply, 2) \
V(FunctionImpl_equals, 2) \
V(FunctionImpl_hashCode, 1) \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 1151e2d..8ef3511 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -35,9 +35,12 @@
// Only methods which owner classes where subclasses can be invalid.
// TODO(srdjan): Be even more precise by recording the exact CHA optimization.
static void RemoveCHAOptimizedCode(
+ const Class& subclass,
const GrowableArray<intptr_t>& added_subclass_to_cids) {
ASSERT(FLAG_use_cha_deopt);
- if (added_subclass_to_cids.is_empty()) return;
+ if (added_subclass_to_cids.is_empty()) {
+ return;
+ }
// Switch all functions' code to unoptimized.
const ClassTable& class_table = *Isolate::Current()->class_table();
Class& cls = Class::Handle();
@@ -45,7 +48,7 @@
intptr_t cid = added_subclass_to_cids[i];
cls = class_table.At(cid);
ASSERT(!cls.IsNull());
- cls.DisableCHAOptimizedCode();
+ cls.DisableCHAOptimizedCode(subclass);
}
}
@@ -2412,7 +2415,7 @@
GrowableArray<intptr_t> cids;
CollectFinalizedSuperClasses(cls, &cids);
CollectImmediateSuperInterfaces(cls, &cids);
- RemoveCHAOptimizedCode(cids);
+ RemoveCHAOptimizedCode(cls, cids);
}
if (cls.is_enum_class()) {
AllocateEnumValues(cls);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index b981608..d7c92d7 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -57,9 +57,10 @@
DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls");
DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks.");
-DECLARE_FLAG(int, deoptimization_counter_threshold);
+DECLARE_FLAG(int, max_deoptimization_counter_threshold);
DECLARE_FLAG(bool, enable_inlining_annotations);
DECLARE_FLAG(bool, trace_compiler);
+DECLARE_FLAG(bool, trace_optimizing_compiler);
DECLARE_FLAG(bool, warn_on_javascript_compatibility);
DECLARE_FLAG(int, max_polymorphic_checks);
@@ -338,11 +339,9 @@
// case it contains just the result of the class subtype test, not including
// the evaluation of type arguments.
// This operation is currently very slow (lookup of code is not efficient yet).
-// 'instantiator' can be null, in which case inst_targ
static void UpdateTypeTestCache(
const Instance& instance,
const AbstractType& type,
- const Instance& instantiator,
const TypeArguments& instantiator_type_arguments,
const Bool& result,
const SubtypeTestCache& new_cache) {
@@ -447,18 +446,16 @@
// Tested instance may not be null, because the null test is inlined.
// Arg0: instance being checked.
// Arg1: type.
-// Arg2: instantiator (or null).
-// Arg3: type arguments of the instantiator of the type.
-// Arg4: SubtypeTestCache.
+// Arg2: type arguments of the instantiator of the type.
+// Arg3: SubtypeTestCache.
// Return value: true or false, or may throw a type error in checked mode.
-DEFINE_RUNTIME_ENTRY(Instanceof, 5) {
+DEFINE_RUNTIME_ENTRY(Instanceof, 4) {
const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0));
const AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(1));
- const Instance& instantiator = Instance::CheckedHandle(arguments.ArgAt(2));
const TypeArguments& instantiator_type_arguments =
- TypeArguments::CheckedHandle(arguments.ArgAt(3));
+ TypeArguments::CheckedHandle(arguments.ArgAt(2));
const SubtypeTestCache& cache =
- SubtypeTestCache::CheckedHandle(arguments.ArgAt(4));
+ SubtypeTestCache::CheckedHandle(arguments.ArgAt(3));
ASSERT(type.IsFinalized());
ASSERT(!type.IsDynamicType()); // No need to check assignment.
ASSERT(!type.IsMalformed()); // Already checked in code generator.
@@ -482,8 +479,8 @@
Symbols::Empty(), bound_error_message);
UNREACHABLE();
}
- UpdateTypeTestCache(instance, type, instantiator,
- instantiator_type_arguments, result, cache);
+ UpdateTypeTestCache(
+ instance, type, instantiator_type_arguments, result, cache);
arguments.SetReturn(result);
}
@@ -492,22 +489,19 @@
// can therefore be assigned.
// Arg0: instance being assigned.
// Arg1: type being assigned to.
-// Arg2: instantiator (or null).
-// Arg3: type arguments of the instantiator of the type being assigned to.
-// Arg4: name of variable being assigned to.
-// Arg5: SubtypeTestCache.
+// Arg2: type arguments of the instantiator of the type being assigned to.
+// Arg3: name of variable being assigned to.
+// Arg4: SubtypeTestCache.
// Return value: instance if a subtype, otherwise throw a TypeError.
-DEFINE_RUNTIME_ENTRY(TypeCheck, 6) {
+DEFINE_RUNTIME_ENTRY(TypeCheck, 5) {
const Instance& src_instance = Instance::CheckedHandle(arguments.ArgAt(0));
const AbstractType& dst_type =
AbstractType::CheckedHandle(arguments.ArgAt(1));
- const Instance& dst_instantiator =
- Instance::CheckedHandle(arguments.ArgAt(2));
const TypeArguments& instantiator_type_arguments =
- TypeArguments::CheckedHandle(arguments.ArgAt(3));
- const String& dst_name = String::CheckedHandle(arguments.ArgAt(4));
+ TypeArguments::CheckedHandle(arguments.ArgAt(2));
+ const String& dst_name = String::CheckedHandle(arguments.ArgAt(3));
const SubtypeTestCache& cache =
- SubtypeTestCache::CheckedHandle(arguments.ArgAt(5));
+ SubtypeTestCache::CheckedHandle(arguments.ArgAt(4));
ASSERT(!dst_type.IsDynamicType()); // No need to check assignment.
ASSERT(!dst_type.IsMalformed()); // Already checked in code generator.
ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator.
@@ -565,9 +559,8 @@
dst_name, bound_error_message);
UNREACHABLE();
}
- UpdateTypeTestCache(src_instance, dst_type,
- dst_instantiator, instantiator_type_arguments,
- Bool::True(), cache);
+ UpdateTypeTestCache(
+ src_instance, dst_type, instantiator_type_arguments, Bool::True(), cache);
arguments.SetReturn(src_instance);
}
@@ -684,7 +677,7 @@
target_code);
caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
if (FLAG_trace_patching) {
- OS::PrintErr("PatchStaticCall: patching caller pc %#" Px ""
+ THR_Print("PatchStaticCall: patching caller pc %#" Px ""
" to '%s' new entry point %#" Px " (%s)\n",
caller_frame->pc(),
target_function.ToFullyQualifiedCString(),
@@ -1252,7 +1245,6 @@
static bool CanOptimizeFunction(const Function& function, Thread* thread) {
- const intptr_t kLowInvocationCount = -100000000;
Isolate* isolate = thread->isolate();
if (isolate->debugger()->IsStepping() ||
isolate->debugger()->HasBreakpoint(function, thread->zone())) {
@@ -1262,17 +1254,19 @@
return false;
}
if (function.deoptimization_counter() >=
- FLAG_deoptimization_counter_threshold) {
+ FLAG_max_deoptimization_counter_threshold) {
if (FLAG_trace_failed_optimization_attempts ||
FLAG_stop_on_excessive_deoptimization) {
- OS::PrintErr("Too Many Deoptimizations: %s\n",
+ THR_Print("Too many deoptimizations: %s\n",
function.ToFullyQualifiedCString());
if (FLAG_stop_on_excessive_deoptimization) {
FATAL("Stop on excessive deoptimization");
}
}
- // TODO(srdjan): Investigate excessive deoptimization.
- function.set_usage_counter(kLowInvocationCount);
+ // The function will not be optimized any longer. This situation can occur
+ // mostly with small optimization counter thresholds.
+ function.SetIsOptimizable(false);
+ function.set_usage_counter(INT_MIN);
return false;
}
if (FLAG_optimization_filter != NULL) {
@@ -1294,16 +1288,17 @@
}
delete[] filter;
if (!found) {
- function.set_usage_counter(kLowInvocationCount);
+ function.set_usage_counter(INT_MIN);
return false;
}
}
if (!function.IsOptimizable()) {
+ // Huge methods (code size above --huge_method_cutoff_in_code_size) become
+ // non-optimizable only after the code has been generated.
if (FLAG_trace_failed_optimization_attempts) {
- OS::PrintErr("Not Optimizable: %s\n", function.ToFullyQualifiedCString());
+ THR_Print("Not optimizable: %s\n", function.ToFullyQualifiedCString());
}
- // TODO(5442338): Abort as this should not happen.
- function.set_usage_counter(kLowInvocationCount);
+ function.set_usage_counter(INT_MIN);
return false;
}
return true;
@@ -1506,7 +1501,7 @@
// Reset usage counter for reoptimization before calling optimizer to
// prevent recursive triggering of function optimization.
function.set_usage_counter(0);
- if (FLAG_trace_compiler) {
+ if (FLAG_trace_compiler || FLAG_trace_optimizing_compiler) {
if (function.HasOptimizedCode()) {
THR_Print("ReCompiling function: '%s' \n",
function.ToFullyQualifiedCString());
@@ -1714,6 +1709,9 @@
// Copies saved registers and caller's frame into temporary buffers.
// Returns the stack size of unoptimized frame.
+// The calling code must be optimized, but its function may not have
+// have optimized code if the code is OSR code, or if the code was invalidated
+// through class loading/finalization or field guard.
DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
2,
uword saved_registers_address,
@@ -1735,6 +1733,16 @@
ASSERT(caller_frame != NULL);
const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
ASSERT(optimized_code.is_optimized());
+ const Function& top_function =
+ Function::Handle(thread->zone(), optimized_code.function());
+ const bool deoptimizing_code = top_function.HasOptimizedCode();
+ if (FLAG_trace_deoptimization) {
+ const Function& function = Function::Handle(optimized_code.function());
+ THR_Print("== Deoptimizing code for '%s', %s, %s\n",
+ function.ToFullyQualifiedCString(),
+ deoptimizing_code ? "code & frame" : "frame",
+ is_lazy_deopt ? "lazy-deopt" : "");
+ }
// Copy the saved registers from the stack.
fpu_register_t* fpu_registers;
@@ -1748,7 +1756,8 @@
DeoptContext::kDestIsOriginalFrame,
fpu_registers,
cpu_registers,
- is_lazy_deopt != 0);
+ is_lazy_deopt != 0,
+ deoptimizing_code);
isolate->set_deopt_context(deopt_context);
// Stack size (FP - SP) in bytes.
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 17edba2..be9c996 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -46,7 +46,7 @@
"Do common subexpression elimination.");
DEFINE_FLAG(bool, constant_propagation, true,
"Do conditional constant propagation/unreachable code elimination.");
-DEFINE_FLAG(int, deoptimization_counter_threshold, 16,
+DEFINE_FLAG(int, max_deoptimization_counter_threshold, 16,
"How many times we allow deoptimization before we disallow optimization.");
DEFINE_FLAG(bool, disassemble, false, "Disassemble dart code.");
DEFINE_FLAG(bool, disassemble_optimized, false, "Disassemble optimized code.");
@@ -60,6 +60,8 @@
DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis");
DEFINE_FLAG(bool, reorder_basic_blocks, true, "Enable basic-block reordering.");
DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations.");
+DEFINE_FLAG(bool, trace_optimizing_compiler, false,
+ "Trace only optimizing compiler operations.");
DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler.");
DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining");
DEFINE_FLAG(bool, verify_compiler, false,
@@ -68,6 +70,7 @@
"Max number of attempts with speculative inlining (precompilation only)");
DECLARE_FLAG(bool, background_compilation);
+DECLARE_FLAG(bool, huge_method_cutoff_in_code_size);
DECLARE_FLAG(bool, load_deferred_eagerly);
DECLARE_FLAG(bool, trace_failed_optimization_attempts);
DECLARE_FLAG(bool, trace_inlining_intervals);
@@ -396,31 +399,216 @@
}
+class CompileParsedFunctionHelper : public ValueObject {
+ public:
+ CompileParsedFunctionHelper(ParsedFunction* parsed_function,
+ bool optimized,
+ intptr_t osr_id)
+ : parsed_function_(parsed_function),
+ optimized_(optimized),
+ osr_id_(osr_id),
+ thread_(Thread::Current()),
+ cha_invalidation_gen_at_start_(isolate()->cha_invalidation_gen()),
+ field_invalidation_gen_at_start_(isolate()->field_invalidation_gen()),
+ prefix_invalidation_gen_at_start_(
+ isolate()->prefix_invalidation_gen()) {
+ }
+
+ bool Compile(CompilationPipeline* pipeline);
+
+ private:
+ ParsedFunction* parsed_function() const { return parsed_function_; }
+ bool optimized() const { return optimized_; }
+ intptr_t osr_id() const { return osr_id_; }
+ Thread* thread() const { return thread_; }
+ Isolate* isolate() const { return thread_->isolate(); }
+ uint32_t cha_invalidation_gen_at_start() const {
+ return cha_invalidation_gen_at_start_;
+ }
+ uint32_t field_invalidation_gen_at_start() const {
+ return field_invalidation_gen_at_start_;
+ }
+ uint32_t prefix_invalidation_gen_at_start() const {
+ return prefix_invalidation_gen_at_start_;
+ }
+ void FinalizeCompilation(Assembler* assembler,
+ FlowGraphCompiler* graph_compiler,
+ FlowGraph* flow_graph);
+
+ ParsedFunction* parsed_function_;
+ const bool optimized_;
+ const intptr_t osr_id_;
+ Thread* const thread_;
+ const uint32_t cha_invalidation_gen_at_start_;
+ const uint32_t field_invalidation_gen_at_start_;
+ const uint32_t prefix_invalidation_gen_at_start_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompileParsedFunctionHelper);
+};
+
+
+void CompileParsedFunctionHelper::FinalizeCompilation(
+ Assembler* assembler,
+ FlowGraphCompiler* graph_compiler,
+ FlowGraph* flow_graph) {
+ const Function& function = parsed_function()->function();
+ Zone* const zone = thread()->zone();
+
+ CSTAT_TIMER_SCOPE(thread(), codefinalizer_timer);
+ // CreateDeoptInfo uses the object pool and needs to be done before
+ // FinalizeCode.
+ const Array& deopt_info_array =
+ Array::Handle(zone, graph_compiler->CreateDeoptInfo(assembler));
+ INC_STAT(thread(), total_code_size,
+ deopt_info_array.Length() * sizeof(uword));
+ // Allocates instruction object. Since this occurs only at safepoint,
+ // there can be no concurrent access to the instruction page.
+ const Code& code = Code::Handle(
+ Code::FinalizeCode(function, assembler, optimized()));
+ code.set_is_optimized(optimized());
+ code.set_owner(function);
+ if (!function.IsOptimizable()) {
+ // A function with huge unoptimized code can become non-optimizable
+ // after generating unoptimized code.
+ function.set_usage_counter(INT_MIN);
+ }
+
+ const Array& intervals = graph_compiler->inlined_code_intervals();
+ INC_STAT(thread(), total_code_size,
+ intervals.Length() * sizeof(uword));
+ code.SetInlinedIntervals(intervals);
+
+ const Array& inlined_id_array =
+ Array::Handle(zone, graph_compiler->InliningIdToFunction());
+ INC_STAT(thread(), total_code_size,
+ inlined_id_array.Length() * sizeof(uword));
+ code.SetInlinedIdToFunction(inlined_id_array);
+
+ const Array& caller_inlining_id_map_array =
+ Array::Handle(zone, graph_compiler->CallerInliningIdMap());
+ INC_STAT(thread(), total_code_size,
+ caller_inlining_id_map_array.Length() * sizeof(uword));
+ code.SetInlinedCallerIdMap(caller_inlining_id_map_array);
+
+ graph_compiler->FinalizePcDescriptors(code);
+ code.set_deopt_info_array(deopt_info_array);
+
+ graph_compiler->FinalizeStackmaps(code);
+ graph_compiler->FinalizeVarDescriptors(code);
+ graph_compiler->FinalizeExceptionHandlers(code);
+ graph_compiler->FinalizeStaticCallTargetsTable(code);
+
+ if (optimized()) {
+ // Installs code while at safepoint.
+ if (thread()->IsMutatorThread()) {
+ const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
+ function.InstallOptimizedCode(code, is_osr);
+ } else {
+ // Background compilation.
+ // Before installing code check generation counts if the code may
+ // have become invalid.
+ const bool trace_compiler =
+ FLAG_trace_compiler || FLAG_trace_optimizing_compiler;
+ bool code_is_valid = true;
+ if (!thread()->cha()->leaf_classes().is_empty()) {
+ if (cha_invalidation_gen_at_start() !=
+ isolate()->cha_invalidation_gen()) {
+ code_is_valid = false;
+ if (trace_compiler) {
+ THR_Print("--> FAIL: CHA invalidation.");
+ }
+ }
+ }
+ if (!flow_graph->guarded_fields()->is_empty()) {
+ if (field_invalidation_gen_at_start() !=
+ isolate()->field_invalidation_gen()) {
+ code_is_valid = false;
+ if (trace_compiler) {
+ THR_Print("--> FAIL: Field invalidation.");
+ }
+ }
+ }
+ if (parsed_function()->HasDeferredPrefixes()) {
+ if (prefix_invalidation_gen_at_start() !=
+ isolate()->prefix_invalidation_gen()) {
+ code_is_valid = false;
+ if (trace_compiler) {
+ THR_Print("--> FAIL: Prefix invalidation.");
+ }
+ }
+ }
+ if (code_is_valid) {
+ const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
+ ASSERT(!is_osr); // OSR is compiled in background.
+ function.InstallOptimizedCode(code, is_osr);
+ }
+ if (function.usage_counter() < 0) {
+ // Reset to 0 so that it can be recompiled if needed.
+ function.set_usage_counter(0);
+ }
+ }
+
+ // Register code with the classes it depends on because of CHA and
+ // fields it depends on because of store guards, unless we cannot
+ // deopt.
+ if (Compiler::allow_recompilation()) {
+ // Deoptimize field dependent code first, before registering
+ // this yet uninstalled code as dependent on a field.
+ // TODO(srdjan): Debugging dart2js crashes;
+ // FlowGraphOptimizer::VisitStoreInstanceField populates
+ // deoptimize_dependent_code() list, currently disabled.
+ for (intptr_t i = 0;
+ i < flow_graph->deoptimize_dependent_code().length();
+ i++) {
+ const Field* field = flow_graph->deoptimize_dependent_code()[i];
+ field->DeoptimizeDependentCode();
+ }
+ for (intptr_t i = 0;
+ i < thread()->cha()->leaf_classes().length();
+ ++i) {
+ thread()->cha()->leaf_classes()[i]->RegisterCHACode(code);
+ }
+ for (intptr_t i = 0;
+ i < flow_graph->guarded_fields()->length();
+ i++) {
+ const Field* field = (*flow_graph->guarded_fields())[i];
+ field->RegisterDependentCode(code);
+ }
+ }
+ } else { // not optimized.
+ if (!Compiler::always_optimize() &&
+ (function.ic_data_array() == Array::null())) {
+ function.SaveICDataMap(
+ graph_compiler->deopt_id_to_ic_data(),
+ Array::Handle(zone, graph_compiler->edge_counters_array()));
+ }
+ function.set_unoptimized_code(code);
+ function.AttachCode(code);
+ }
+ if (parsed_function()->HasDeferredPrefixes()) {
+ ASSERT(!FLAG_load_deferred_eagerly);
+ ZoneGrowableArray<const LibraryPrefix*>* prefixes =
+ parsed_function()->deferred_prefixes();
+ for (intptr_t i = 0; i < prefixes->length(); i++) {
+ (*prefixes)[i]->RegisterDependentCode(code);
+ }
+ }
+}
+
+
// Return false if bailed out.
// If optimized_result_code is not NULL then it is caller's responsibility
// to install code.
-static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline,
- ParsedFunction* parsed_function,
- bool optimized,
- intptr_t osr_id) {
- const Function& function = parsed_function->function();
- if (optimized && !function.IsOptimizable()) {
+bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
+ const Function& function = parsed_function()->function();
+ if (optimized() && !function.IsOptimizable()) {
return false;
}
bool is_compiled = false;
- Thread* const thread = Thread::Current();
- Zone* const zone = thread->zone();
- Isolate* const isolate = thread->isolate();
- TimelineStream* compiler_timeline = isolate->GetCompilerStream();
- CSTAT_TIMER_SCOPE(thread, codegen_timer);
- HANDLESCOPE(thread);
-
- // Get current generation count so that we can check and ensure that the code
- // was not invalidated while we were compiling in the background.
- uint32_t cha_invalidation_gen_at_start = isolate->cha_invalidation_gen();
- uint32_t field_invalidation_gen_at_start = isolate->field_invalidation_gen();
- uint32_t prefix_invalidation_gen_at_start =
- isolate->prefix_invalidation_gen();
+ Zone* const zone = thread()->zone();
+ TimelineStream* compiler_timeline = isolate()->GetCompilerStream();
+ CSTAT_TIMER_SCOPE(thread(), codegen_timer);
+ HANDLESCOPE(thread());
// We may reattempt compilation if the function needs to be assembled using
// far branches on ARM and MIPS. In the else branch of the setjmp call,
@@ -436,8 +624,8 @@
GrowableArray<intptr_t> inlining_black_list;
while (!done) {
- const intptr_t prev_deopt_id = thread->deopt_id();
- thread->set_deopt_id(0);
+ const intptr_t prev_deopt_id = thread()->deopt_id();
+ thread()->set_deopt_id(0);
LongJumpScope jump;
const intptr_t val = setjmp(*jump.Set());
if (val == 0) {
@@ -445,19 +633,19 @@
// Class hierarchy analysis is registered with the isolate in the
// constructor and unregisters itself upon destruction.
- CHA cha(thread);
+ CHA cha(thread());
// TimerScope needs an isolate to be properly terminated in case of a
// LongJump.
{
- CSTAT_TIMER_SCOPE(thread, graphbuilder_timer);
+ CSTAT_TIMER_SCOPE(thread(), graphbuilder_timer);
ZoneGrowableArray<const ICData*>* ic_data_array =
new(zone) ZoneGrowableArray<const ICData*>();
- if (optimized) {
+ if (optimized()) {
// Extract type feedback before the graph is built, as the graph
// builder uses it to attach it to nodes.
ASSERT(function.deoptimization_counter() <
- FLAG_deoptimization_counter_threshold);
+ FLAG_max_deoptimization_counter_threshold);
// 'Freeze' ICData in background compilation so that it does not
// change while compiling.
@@ -474,22 +662,22 @@
}
}
- TimelineDurationScope tds(thread,
+ TimelineDurationScope tds(thread(),
compiler_timeline,
"BuildFlowGraph");
flow_graph = pipeline->BuildFlowGraph(zone,
- parsed_function,
+ parsed_function(),
*ic_data_array,
- osr_id);
+ osr_id());
}
const bool print_flow_graph =
(FLAG_print_flow_graph ||
- (optimized && FLAG_print_flow_graph_optimized)) &&
+ (optimized() && FLAG_print_flow_graph_optimized)) &&
FlowGraphPrinter::ShouldPrint(function);
if (print_flow_graph) {
- if (osr_id == Compiler::kNoOSRDeoptId) {
+ if (osr_id() == Compiler::kNoOSRDeoptId) {
FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
} else {
FlowGraphPrinter::PrintGraph("For OSR", flow_graph);
@@ -498,19 +686,19 @@
BlockScheduler block_scheduler(flow_graph);
const bool reorder_blocks =
- FlowGraph::ShouldReorderBlocks(function, optimized);
+ FlowGraph::ShouldReorderBlocks(function, optimized());
if (reorder_blocks) {
- TimelineDurationScope tds(thread,
+ TimelineDurationScope tds(thread(),
compiler_timeline,
"BlockScheduler::AssignEdgeWeights");
block_scheduler.AssignEdgeWeights();
}
- if (optimized) {
- TimelineDurationScope tds(thread,
+ if (optimized()) {
+ TimelineDurationScope tds(thread(),
compiler_timeline,
"ComputeSSA");
- CSTAT_TIMER_SCOPE(thread, ssa_timer);
+ CSTAT_TIMER_SCOPE(thread(), ssa_timer);
// Transform to SSA (virtual register 0 and no inlining arguments).
flow_graph->ComputeSSA(0, NULL);
DEBUG_ASSERT(flow_graph->VerifyUseLists());
@@ -527,14 +715,14 @@
// Collect all instance fields that are loaded in the graph and
// have non-generic type feedback attached to them that can
// potentially affect optimizations.
- if (optimized) {
- TimelineDurationScope tds(thread,
+ if (optimized()) {
+ TimelineDurationScope tds(thread(),
compiler_timeline,
"OptimizationPasses");
inline_id_to_function.Add(&function);
// Top scope function has no caller (-1).
caller_inline_id.Add(-1);
- CSTAT_TIMER_SCOPE(thread, graphoptimizer_timer);
+ CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer);
FlowGraphOptimizer optimizer(flow_graph,
use_speculative_inlining,
@@ -560,10 +748,10 @@
// Inlining (mutates the flow graph)
if (FLAG_use_inlining) {
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"Inlining");
- CSTAT_TIMER_SCOPE(thread, graphinliner_timer);
+ CSTAT_TIMER_SCOPE(thread(), graphinliner_timer);
// Propagate types to create more inlining opportunities.
FlowGraphTypePropagator::Propagate(flow_graph);
DEBUG_ASSERT(flow_graph->VerifyUseLists());
@@ -587,7 +775,7 @@
DEBUG_ASSERT(flow_graph->VerifyUseLists());
{
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"ApplyClassIds");
// Use propagated class-ids to optimize further.
@@ -609,7 +797,7 @@
DEBUG_ASSERT(flow_graph->VerifyUseLists());
{
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"BranchSimplifier");
BranchSimplifier::Simplify(flow_graph);
@@ -620,7 +808,7 @@
}
if (FLAG_constant_propagation) {
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"ConstantPropagation");
ConstantPropagator::Optimize(flow_graph);
@@ -649,7 +837,7 @@
DEBUG_ASSERT(flow_graph->VerifyUseLists());
{
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"SelectRepresentations");
// Where beneficial convert Smi operations into Int32 operations.
@@ -664,7 +852,7 @@
}
{
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"CommonSubexpressionElinination");
if (FLAG_common_subexpression_elimination ||
@@ -704,14 +892,14 @@
DEBUG_ASSERT(flow_graph->VerifyUseLists());
{
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"DeadStoreElimination");
DeadStoreElimination::Optimize(flow_graph);
}
if (FLAG_range_analysis) {
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"RangeAnalysis");
// Propagate types after store-load-forwarding. Some phis may have
@@ -727,7 +915,7 @@
}
if (FLAG_constant_propagation) {
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"ConstantPropagator::OptimizeBranches");
// Constant propagation can use information from range analysis to
@@ -743,7 +931,7 @@
DEBUG_ASSERT(flow_graph->VerifyUseLists());
{
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"TryCatchAnalyzer::Optimize");
// Optimize try-blocks.
@@ -756,7 +944,7 @@
optimizer.EliminateEnvironments();
{
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"EliminateDeadPhis");
DeadCodeElimination::EliminateDeadPhis(flow_graph);
@@ -772,7 +960,7 @@
AllocationSinking* sinking = NULL;
if (FLAG_allocation_sinking &&
(flow_graph->graph_entry()->SuccessorCount() == 1)) {
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"AllocationSinking::Optimize");
// TODO(fschneider): Support allocation sinking with try-catch.
@@ -788,7 +976,7 @@
DEBUG_ASSERT(flow_graph->VerifyUseLists());
{
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"SelectRepresentations");
// Ensure that all phis inserted by optimization passes have
@@ -808,7 +996,7 @@
if (sinking != NULL) {
TimelineDurationScope tds2(
- thread,
+ thread(),
compiler_timeline,
"AllocationSinking::DetachMaterializations");
// Remove all MaterializeObject instructions inserted by allocation
@@ -823,7 +1011,7 @@
FlowGraphInliner::CollectGraphInfo(flow_graph, true);
{
- TimelineDurationScope tds2(thread,
+ TimelineDurationScope tds2(thread(),
compiler_timeline,
"AllocateRegisters");
// Perform register allocation on the SSA graph.
@@ -832,7 +1020,7 @@
}
if (reorder_blocks) {
- TimelineDurationScope tds(thread,
+ TimelineDurationScope tds(thread(),
compiler_timeline,
"BlockScheduler::ReorderBlocks");
block_scheduler.ReorderBlocks();
@@ -846,168 +1034,48 @@
ASSERT(inline_id_to_function.length() == caller_inline_id.length());
Assembler assembler(use_far_branches);
FlowGraphCompiler graph_compiler(&assembler, flow_graph,
- *parsed_function, optimized,
+ *parsed_function(), optimized(),
inline_id_to_function,
caller_inline_id);
{
- CSTAT_TIMER_SCOPE(thread, graphcompiler_timer);
- TimelineDurationScope tds(thread,
+ CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer);
+ TimelineDurationScope tds(thread(),
compiler_timeline,
"CompileGraph");
graph_compiler.CompileGraph();
pipeline->FinalizeCompilation();
}
{
- TimelineDurationScope tds(thread,
+ TimelineDurationScope tds(thread(),
compiler_timeline,
"FinalizeCompilation");
// This part of compilation must be at a safepoint.
- if (!Thread::Current()->IsMutatorThread()) {
+ if (!thread()->IsMutatorThread()) {
// Stop mutator thread before creating the instruction object and
// installing code.
// Mutator thread may not run code while we are creating the
// instruction object, since the creation of instruction object
// changes code page access permissions (makes them temporary not
// executable).
- isolate->thread_registry()->SafepointThreads();
+ isolate()->thread_registry()->SafepointThreads();
}
- CSTAT_TIMER_SCOPE(thread, codefinalizer_timer);
- // CreateDeoptInfo uses the object pool and needs to be done before
- // FinalizeCode.
- const Array& deopt_info_array =
- Array::Handle(zone, graph_compiler.CreateDeoptInfo(&assembler));
- INC_STAT(thread, total_code_size,
- deopt_info_array.Length() * sizeof(uword));
- // Allocates instruction object. Since this occurs only at safepoint,
- // there can be no concurrent access to the instruction page.
- const Code& code = Code::Handle(
- Code::FinalizeCode(function, &assembler, optimized));
- code.set_is_optimized(optimized);
- code.set_owner(function);
- const Array& intervals = graph_compiler.inlined_code_intervals();
- INC_STAT(thread, total_code_size,
- intervals.Length() * sizeof(uword));
- code.SetInlinedIntervals(intervals);
+ FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
- const Array& inlined_id_array =
- Array::Handle(zone, graph_compiler.InliningIdToFunction());
- INC_STAT(thread, total_code_size,
- inlined_id_array.Length() * sizeof(uword));
- code.SetInlinedIdToFunction(inlined_id_array);
-
- const Array& caller_inlining_id_map_array =
- Array::Handle(zone, graph_compiler.CallerInliningIdMap());
- INC_STAT(thread, total_code_size,
- caller_inlining_id_map_array.Length() * sizeof(uword));
- code.SetInlinedCallerIdMap(caller_inlining_id_map_array);
-
- graph_compiler.FinalizePcDescriptors(code);
- code.set_deopt_info_array(deopt_info_array);
-
- graph_compiler.FinalizeStackmaps(code);
- graph_compiler.FinalizeVarDescriptors(code);
- graph_compiler.FinalizeExceptionHandlers(code);
- graph_compiler.FinalizeStaticCallTargetsTable(code);
-
- if (optimized) {
- // Installs code while at safepoint.
- if (thread->IsMutatorThread()) {
- const bool is_osr = osr_id != Compiler::kNoOSRDeoptId;
- function.InstallOptimizedCode(code, is_osr);
- } else {
- // Background compilation.
- // Before installing code check generation counts if the code may
- // have become invalid.
- bool code_is_valid = true;
- if (!thread->cha()->leaf_classes().is_empty()) {
- if (cha_invalidation_gen_at_start !=
- isolate->cha_invalidation_gen()) {
- code_is_valid = false;
- }
- }
- if (!flow_graph->guarded_fields()->is_empty()) {
- if (field_invalidation_gen_at_start !=
- isolate->field_invalidation_gen()) {
- code_is_valid = false;
- }
- }
- if (parsed_function->HasDeferredPrefixes()) {
- if (prefix_invalidation_gen_at_start !=
- isolate->prefix_invalidation_gen()) {
- code_is_valid = false;
- }
- }
- if (code_is_valid) {
- const bool is_osr = osr_id != Compiler::kNoOSRDeoptId;
- ASSERT(!is_osr); // OSR is compiled in background.
- function.InstallOptimizedCode(code, is_osr);
- }
- if (function.usage_counter() < 0) {
- // Reset to 0 so that it can be recompiled if needed.
- function.set_usage_counter(0);
- }
- }
-
- // Register code with the classes it depends on because of CHA and
- // fields it depends on because of store guards, unless we cannot
- // deopt.
- if (Compiler::allow_recompilation()) {
- // Deoptimize field dependent code first, before registering
- // this yet uninstalled code as dependent on a field.
- // TODO(srdjan): Debugging dart2js crashes;
- // FlowGraphOptimizer::VisitStoreInstanceField populates
- // deoptimize_dependent_code() list, currently disabled.
- for (intptr_t i = 0;
- i < flow_graph->deoptimize_dependent_code().length();
- i++) {
- const Field* field = flow_graph->deoptimize_dependent_code()[i];
- field->DeoptimizeDependentCode();
- }
- for (intptr_t i = 0;
- i < thread->cha()->leaf_classes().length();
- ++i) {
- thread->cha()->leaf_classes()[i]->RegisterCHACode(code);
- }
- for (intptr_t i = 0;
- i < flow_graph->guarded_fields()->length();
- i++) {
- const Field* field = (*flow_graph->guarded_fields())[i];
- field->RegisterDependentCode(code);
- }
- }
- } else { // not optimized.
- if (!Compiler::always_optimize() &&
- (function.ic_data_array() == Array::null())) {
- function.SaveICDataMap(
- graph_compiler.deopt_id_to_ic_data(),
- Array::Handle(zone, graph_compiler.edge_counters_array()));
- }
- function.set_unoptimized_code(code);
- function.AttachCode(code);
- }
- if (parsed_function->HasDeferredPrefixes()) {
- ASSERT(!FLAG_load_deferred_eagerly);
- ZoneGrowableArray<const LibraryPrefix*>* prefixes =
- parsed_function->deferred_prefixes();
- for (intptr_t i = 0; i < prefixes->length(); i++) {
- (*prefixes)[i]->RegisterDependentCode(code);
- }
- }
- if (!Thread::Current()->IsMutatorThread()) {
+ if (!thread()->IsMutatorThread()) {
// Background compilation.
- isolate->thread_registry()->ResumeAllThreads();
+ isolate()->thread_registry()->ResumeAllThreads();
}
}
// Mark that this isolate now has compiled code.
- isolate->set_has_compiled_code(true);
+ isolate()->set_has_compiled_code(true);
// Exit the loop and the function with the correct result value.
is_compiled = true;
done = true;
} else {
// We bailed out or we encountered an error.
const Error& error = Error::Handle(
- isolate->object_store()->sticky_error());
+ isolate()->object_store()->sticky_error());
if (error.raw() == Object::branch_offset_error().raw()) {
// Compilation failed due to an out of range branch offset in the
@@ -1030,7 +1098,7 @@
const intptr_t max_attempts = FLAG_max_speculative_inlining_attempts;
if (inlining_black_list.length() >= max_attempts) {
use_speculative_inlining = false;
- if (FLAG_trace_compiler) {
+ if (FLAG_trace_compiler || FLAG_trace_optimizing_compiler) {
THR_Print("Disabled speculative inlining after %" Pd " attempts.\n",
inlining_black_list.length());
}
@@ -1048,12 +1116,12 @@
// Clear the error if it was not a real error, but just a bailout.
if (error.IsLanguageError() &&
(LanguageError::Cast(error).kind() == Report::kBailout)) {
- isolate->object_store()->clear_sticky_error();
+ isolate()->object_store()->clear_sticky_error();
}
is_compiled = false;
}
// Reset global isolate state.
- thread->set_deopt_id(prev_deopt_id);
+ thread()->set_deopt_id(prev_deopt_id);
}
return is_compiled;
}
@@ -1235,12 +1303,15 @@
Isolate* const isolate = thread->isolate();
StackZone stack_zone(thread);
Zone* const zone = stack_zone.GetZone();
- Timer per_compile_timer(FLAG_trace_compiler, "Compilation time");
+ const bool trace_compiler =
+ FLAG_trace_compiler ||
+ (FLAG_trace_optimizing_compiler && optimized);
+ Timer per_compile_timer(trace_compiler, "Compilation time");
per_compile_timer.Start();
ParsedFunction* parsed_function = new(zone) ParsedFunction(
thread, Function::ZoneHandle(zone, function.raw()));
- if (FLAG_trace_compiler) {
+ if (trace_compiler) {
THR_Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n",
(osr_id == Compiler::kNoOSRDeoptId ? "" : "osr "),
(optimized ? "optimized " : ""),
@@ -1262,15 +1333,13 @@
num_tokens_after - num_tokens_before);
}
- const bool success = CompileParsedFunctionHelper(pipeline,
- parsed_function,
- optimized,
- osr_id);
+ CompileParsedFunctionHelper helper(parsed_function, optimized, osr_id);
+ const bool success = helper.Compile(pipeline);
if (!success) {
if (optimized) {
ASSERT(!Compiler::always_optimize()); // Optimized is the only code.
// Optimizer bailed out. Disable optimizations and never try again.
- if (FLAG_trace_compiler) {
+ if (trace_compiler) {
THR_Print("--> disabling optimizations for '%s'\n",
function.ToFullyQualifiedCString());
} else if (FLAG_trace_failed_optimization_attempts) {
@@ -1291,7 +1360,7 @@
per_compile_timer.Stop();
- if (FLAG_trace_compiler) {
+ if (trace_compiler && success) {
THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n",
function.ToFullyQualifiedCString(),
Code::Handle(function.CurrentCode()).EntryPoint(),
@@ -1421,10 +1490,8 @@
if (setjmp(*jump.Set()) == 0) {
// Non-optimized code generator.
DartCompilationPipeline pipeline;
- CompileParsedFunctionHelper(&pipeline,
- parsed_function,
- false,
- kNoOSRDeoptId);
+ CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
+ helper.Compile(&pipeline);
if (FLAG_disassemble) {
DisassembleCode(parsed_function->function(), false);
}
@@ -1509,11 +1576,8 @@
parsed_function->AllocateVariables();
// Non-optimized code generator.
DartCompilationPipeline pipeline;
- CompileParsedFunctionHelper(&pipeline,
- parsed_function,
- false, // optimized
- kNoOSRDeoptId);
-
+ CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
+ helper.Compile(&pipeline);
const Function& initializer = parsed_function->function();
field.SetPrecompiledInitializer(initializer);
}
@@ -1540,10 +1604,8 @@
parsed_function->AllocateVariables();
// Non-optimized code generator.
DartCompilationPipeline pipeline;
- CompileParsedFunctionHelper(&pipeline,
- parsed_function,
- false, // optimized
- kNoOSRDeoptId);
+ CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
+ helper.Compile(&pipeline);
initializer = parsed_function->function().raw();
Code::Handle(initializer.unoptimized_code()).set_var_descriptors(
Object::empty_var_descriptors());
@@ -1610,10 +1672,8 @@
// Non-optimized code generator.
DartCompilationPipeline pipeline;
- CompileParsedFunctionHelper(&pipeline,
- parsed_function,
- false,
- kNoOSRDeoptId);
+ CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId);
+ helper.Compile(&pipeline);
Code::Handle(func.unoptimized_code()).set_var_descriptors(
Object::empty_var_descriptors());
@@ -1754,7 +1814,8 @@
while (running_) {
// Maybe something is already in the queue, check first before waiting
// to be notified.
- Thread::EnterIsolateAsHelper(isolate_);
+ bool result = Thread::EnterIsolateAsHelper(isolate_);
+ ASSERT(result);
{
Thread* thread = Thread::Current();
StackZone stack_zone(thread);
diff --git a/runtime/vm/constant_propagator.cc b/runtime/vm/constant_propagator.cc
index 1b70c96..8792cf5 100644
--- a/runtime/vm/constant_propagator.cc
+++ b/runtime/vm/constant_propagator.cc
@@ -764,8 +764,7 @@
if (value.IsInstance()) {
const Instance& instance = Instance::Cast(value);
const AbstractType& checked_type = instr->type();
- if (instr->instantiator()->BindsToConstantNull() &&
- instr->instantiator_type_arguments()->BindsToConstantNull()) {
+ if (instr->instantiator_type_arguments()->BindsToConstantNull()) {
const TypeArguments& checked_type_arguments = TypeArguments::Handle();
Error& bound_error = Error::Handle();
bool is_instance = instance.IsInstanceOf(checked_type,
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc
index 8fede58..42dff5e 100644
--- a/runtime/vm/coverage.cc
+++ b/runtime/vm/coverage.cc
@@ -191,6 +191,7 @@
}
}
+ // TODO(turnidge): This looks like it prints closures many, many times.
const GrowableObjectArray& closures = GrowableObjectArray::Handle(
thread->isolate()->object_store()->closure_functions());
pos_to_line.Clear();
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 7568924..a9ddae5 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -38,7 +38,7 @@
DECLARE_FLAG(bool, trace_time_all);
DEFINE_FLAG(bool, keep_code, false,
"Keep deoptimized code for profiling.");
-DEFINE_FLAG(bool, shutdown, false, "Do a clean shutdown of the VM");
+DEFINE_FLAG(bool, shutdown, true, "Do a clean shutdown of the VM");
Isolate* Dart::vm_isolate_ = NULL;
ThreadPool* Dart::thread_pool_ = NULL;
@@ -228,7 +228,8 @@
{
// Set the VM isolate as current isolate when shutting down
// Metrics so that we can use a StackZone.
- Thread::EnterIsolate(vm_isolate_);
+ bool result = Thread::EnterIsolate(vm_isolate_);
+ ASSERT(result);
Metric::Cleanup();
Thread::ExitIsolate();
}
@@ -251,8 +252,17 @@
delete thread_pool_;
thread_pool_ = NULL;
+ // Disable creation of any new OSThread structures which means no more new
+ // threads can do an EnterIsolate. This must come after isolate shutdown
+ // because new threads may need to be spawned to shutdown the isolates.
+ // This must come after deletion of the thread pool to avoid a race in which
+ // a thread spawned by the thread pool does not exit through the thread
+ // pool, messing up its bookkeeping.
+ OSThread::DisableOSThreadCreation();
+
// Set the VM isolate as current isolate.
- Thread::EnterIsolate(vm_isolate_);
+ bool result = Thread::EnterIsolate(vm_isolate_);
+ ASSERT(result);
ShutdownIsolate();
vm_isolate_ = NULL;
@@ -270,6 +280,9 @@
} else {
// Shutdown the service isolate.
ServiceIsolate::Shutdown();
+
+ // Disable thread creation.
+ OSThread::DisableOSThreadCreation();
}
CodeObservers::DeleteAll();
@@ -407,7 +420,8 @@
void Dart::ShutdownIsolate(Isolate* isolate) {
ASSERT(Isolate::Current() == NULL);
// We need to enter the isolate in order to shut it down.
- Thread::EnterIsolate(isolate);
+ bool result = Thread::EnterIsolate(isolate);
+ ASSERT(result);
ShutdownIsolate();
// Since the isolate is shutdown and deleted, there is no need to
// exit the isolate here.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index a61715b..fdb1d53 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1311,7 +1311,9 @@
if (iso->HasMutatorThread()) {
FATAL("Multiple mutators within one isolate is not supported.");
}
- Thread::EnterIsolate(iso);
+ if (!Thread::EnterIsolate(iso)) {
+ FATAL("Unable to Enter Isolate as Dart VM is shutting down");
+ }
}
@@ -1527,7 +1529,9 @@
while (!data.done) {
ml.Wait();
}
- Thread::EnterIsolate(I);
+ if (!Thread::EnterIsolate(I)) {
+ FATAL("Inconsistent state, VM shutting down while in run loop.");
+ }
}
if (I->object_store()->sticky_error() != Object::null()) {
Dart_Handle error = Api::NewHandle(T, I->object_store()->sticky_error());
@@ -5970,4 +5974,9 @@
return Api::Success();
}
+
+DART_EXPORT bool Dart_IsRunningPrecompiledCode() {
+ return Dart::IsRunningPrecompiledCode();
+}
+
} // namespace dart
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index a9efd83..9ba75da 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -1444,7 +1444,8 @@
DeoptContext::kDestIsAllocated,
NULL,
NULL,
- true);
+ true,
+ false /* deoptimizing_code */);
isolate->set_deopt_context(deopt_context);
deopt_context->FillDestFrame();
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index 3d86592..71a734a 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -173,16 +173,18 @@
*reinterpret_cast<RawObject**>(dest_addr) = code.raw();
if (FLAG_trace_deoptimization_verbose) {
- OS::PrintErr("materializing pc marker at 0x%" Px ": %s, %s\n",
- reinterpret_cast<uword>(slot()), code.ToCString(),
- function.ToCString());
+ THR_Print("materializing pc marker at 0x%" Px ": %s, %s\n",
+ reinterpret_cast<uword>(slot()), code.ToCString(),
+ function.ToCString());
}
// Increment the deoptimization counter. This effectively increments each
// function occurring in the optimized frame.
- function.set_deoptimization_counter(function.deoptimization_counter() + 1);
+ if (deopt_context->deoptimizing_code()) {
+ function.set_deoptimization_counter(function.deoptimization_counter() + 1);
+ }
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
- OS::PrintErr("Deoptimizing %s (count %d)\n",
+ THR_Print("Deoptimizing '%s' (count %d)\n",
function.ToFullyQualifiedCString(),
function.deoptimization_counter());
}
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 658e973..4970e59 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -27,7 +27,8 @@
DestFrameOptions dest_options,
fpu_register_t* fpu_registers,
intptr_t* cpu_registers,
- bool is_lazy_deopt)
+ bool is_lazy_deopt,
+ bool deoptimizing_code)
: code_(code.raw()),
object_pool_(code.GetObjectPool()),
deopt_info_(TypedData::null()),
@@ -47,7 +48,8 @@
deferred_slots_(NULL),
deferred_objects_count_(0),
deferred_objects_(NULL),
- is_lazy_deopt_(is_lazy_deopt) {
+ is_lazy_deopt_(is_lazy_deopt),
+ deoptimizing_code_(deoptimizing_code) {
const TypedData& deopt_info = TypedData::Handle(
code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason_, &deopt_flags_));
ASSERT(!deopt_info.IsNull());
@@ -103,7 +105,7 @@
}
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
- OS::PrintErr(
+ THR_Print(
"Deoptimizing (reason %d '%s') at pc %#" Px " '%s' (count %d)\n",
deopt_reason(),
DeoptReasonToCString(deopt_reason()),
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index 79c206e..acbf92b 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -23,6 +23,7 @@
class TimelineEvent;
// Holds all data relevant for execution of deoptimization instructions.
+// Structure is allocated in C-heap.
class DeoptContext {
public:
enum DestFrameOptions {
@@ -30,12 +31,14 @@
kDestIsAllocated // Write deopt frame to a buffer.
};
+ // If 'deoptimizing_code' is false, only frame is being deoptimized.
DeoptContext(const StackFrame* frame,
const Code& code,
DestFrameOptions dest_options,
fpu_register_t* fpu_registers,
intptr_t* cpu_registers,
- bool is_lazy_deopt);
+ bool is_lazy_deopt,
+ bool deoptimizing_code);
virtual ~DeoptContext();
// Returns the offset of the dest fp from the dest sp. Used in
@@ -97,6 +100,8 @@
bool is_lazy_deopt() const { return is_lazy_deopt_; }
+ bool deoptimizing_code() const { return deoptimizing_code_; }
+
ICData::DeoptReasonId deopt_reason() const { return deopt_reason_; }
bool HasDeoptFlag(ICData::DeoptFlags flag) {
return (deopt_flags_ & flag) != 0;
@@ -232,6 +237,7 @@
DeferredObject** deferred_objects_;
const bool is_lazy_deopt_;
+ const bool deoptimizing_code_;
DISALLOW_COPY_AND_ASSIGN(DeoptContext);
};
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 82bc544..99563bb 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -624,10 +624,6 @@
library = Library::IsolateLibrary();
class_name = &Symbols::IsolateSpawnException();
break;
- case kIsolateUnhandledException:
- library = Library::IsolateLibrary();
- class_name = &Symbols::IsolateUnhandledException();
- break;
case kJavascriptIntegerOverflowError:
library = Library::CoreLibrary();
class_name = &Symbols::JavascriptIntegerOverflowError();
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 0bd97f8..4282bb5 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -60,7 +60,6 @@
kOutOfMemory,
kNullThrown,
kIsolateSpawn,
- kIsolateUnhandledException,
kJavascriptIntegerOverflowError,
kJavascriptCompatibilityError,
kAssertion,
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 57b5d65..fc3264f 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -1469,7 +1469,6 @@
void EffectGraphVisitor::BuildTypecheckPushArguments(
intptr_t token_pos,
- PushArgumentInstr** push_instantiator_result,
PushArgumentInstr** push_instantiator_type_arguments_result) {
const Class& instantiator_class = Class::Handle(
Z, owner()->function().Owner());
@@ -1479,15 +1478,11 @@
Value* instantiator = BuildInstantiator(instantiator_class);
if (instantiator == NULL) {
// No instantiator when inside factory.
- *push_instantiator_result = PushArgument(BuildNullValue());
instantiator_type_arguments =
BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL);
} else {
- instantiator = Bind(BuildStoreExprTemp(instantiator));
- *push_instantiator_result = PushArgument(instantiator);
- Value* loaded = Bind(BuildLoadExprTemp());
- instantiator_type_arguments =
- BuildInstantiatorTypeArguments(token_pos, instantiator_class, loaded);
+ instantiator_type_arguments = BuildInstantiatorTypeArguments(
+ token_pos, instantiator_class, instantiator);
}
*push_instantiator_type_arguments_result =
PushArgument(instantiator_type_arguments);
@@ -1497,7 +1492,6 @@
void EffectGraphVisitor::BuildTypecheckArguments(
intptr_t token_pos,
- Value** instantiator_result,
Value** instantiator_type_arguments_result) {
Value* instantiator = NULL;
Value* instantiator_type_arguments = NULL;
@@ -1508,17 +1502,12 @@
instantiator = BuildInstantiator(instantiator_class);
if (instantiator == NULL) {
// No instantiator when inside factory.
- instantiator = BuildNullValue();
instantiator_type_arguments =
BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL);
} else {
- // Preserve instantiator.
- instantiator = Bind(BuildStoreExprTemp(instantiator));
- Value* loaded = Bind(BuildLoadExprTemp());
- instantiator_type_arguments =
- BuildInstantiatorTypeArguments(token_pos, instantiator_class, loaded);
+ instantiator_type_arguments = BuildInstantiatorTypeArguments(
+ token_pos, instantiator_class, instantiator);
}
- *instantiator_result = instantiator;
*instantiator_type_arguments_result = instantiator_type_arguments;
}
@@ -1535,21 +1524,16 @@
const AbstractType& dst_type,
const String& dst_name) {
// Build the type check computation.
- Value* instantiator = NULL;
Value* instantiator_type_arguments = NULL;
if (dst_type.IsInstantiated()) {
- instantiator = BuildNullValue();
instantiator_type_arguments = BuildNullValue();
} else {
- BuildTypecheckArguments(token_pos,
- &instantiator,
- &instantiator_type_arguments);
+ BuildTypecheckArguments(token_pos, &instantiator_type_arguments);
}
const intptr_t deopt_id = Thread::Current()->GetNextDeoptId();
return new(Z) AssertAssignableInstr(token_pos,
value,
- instantiator,
instantiator_type_arguments,
dst_type,
dst_name,
@@ -1651,20 +1635,15 @@
}
PushArgumentInstr* push_left = PushArgument(for_left_value.value());
- PushArgumentInstr* push_instantiator = NULL;
PushArgumentInstr* push_type_args = NULL;
if (type.IsInstantiated()) {
- push_instantiator = PushArgument(BuildNullValue());
push_type_args = PushArgument(BuildNullValue());
} else {
- BuildTypecheckPushArguments(node->token_pos(),
- &push_instantiator,
- &push_type_args);
+ BuildTypecheckPushArguments(node->token_pos(), &push_type_args);
}
ZoneGrowableArray<PushArgumentInstr*>* arguments =
- new(Z) ZoneGrowableArray<PushArgumentInstr*>(5);
+ new(Z) ZoneGrowableArray<PushArgumentInstr*>(4);
arguments->Add(push_left);
- arguments->Add(push_instantiator);
arguments->Add(push_type_args);
ASSERT(!node->right()->AsTypeNode()->type().IsNull());
Value* type_const = Bind(new(Z) ConstantInstr(type));
@@ -1708,20 +1687,15 @@
}
}
PushArgumentInstr* push_left = PushArgument(for_value.value());
- PushArgumentInstr* push_instantiator = NULL;
PushArgumentInstr* push_type_args = NULL;
if (type.IsInstantiated()) {
- push_instantiator = PushArgument(BuildNullValue());
push_type_args = PushArgument(BuildNullValue());
} else {
- BuildTypecheckPushArguments(node->token_pos(),
- &push_instantiator,
- &push_type_args);
+ BuildTypecheckPushArguments(node->token_pos(), &push_type_args);
}
ZoneGrowableArray<PushArgumentInstr*>* arguments =
- new(Z) ZoneGrowableArray<PushArgumentInstr*>(4);
+ new(Z) ZoneGrowableArray<PushArgumentInstr*>(3);
arguments->Add(push_left);
- arguments->Add(push_instantiator);
arguments->Add(push_type_args);
Value* type_arg = Bind(new(Z) ConstantInstr(type));
arguments->Add(PushArgument(type_arg));
@@ -1749,10 +1723,10 @@
right->Visit(&for_right_value);
Append(for_right_value);
StrictCompareInstr* comp = new(Z) StrictCompareInstr(token_pos,
- kind,
- for_left_value.value(),
- for_right_value.value(),
- true); // Number check.
+ kind,
+ for_left_value.value(),
+ for_right_value.value(),
+ true); // Number check.
return comp;
}
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index bae0a52..5511db4 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -332,10 +332,8 @@
void BuildTypecheckPushArguments(
intptr_t token_pos,
- PushArgumentInstr** push_instantiator,
PushArgumentInstr** push_instantiator_type_arguments);
void BuildTypecheckArguments(intptr_t token_pos,
- Value** instantiator,
Value** instantiator_type_arguments);
Value* BuildInstantiator(const Class& instantiator_class);
Value* BuildInstantiatorTypeArguments(intptr_t token_pos,
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 8c6fa8e..da0639c 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -49,6 +49,7 @@
DECLARE_FLAG(bool, background_compilation);
DECLARE_FLAG(bool, code_comments);
+DECLARE_FLAG(bool, collect_dynamic_function_names);
DECLARE_FLAG(bool, deoptimize_alot);
DECLARE_FLAG(int, deoptimize_every);
DECLARE_FLAG(charp, deoptimize_filter);
@@ -77,6 +78,12 @@
DECLARE_FLAG(bool, enable_mirrors);
DECLARE_FLAG(bool, link_natives_lazily);
DECLARE_FLAG(bool, trace_compiler);
+DECLARE_FLAG(int, inlining_hotness);
+DECLARE_FLAG(int, inlining_size_threshold);
+DECLARE_FLAG(int, inlining_callee_size_threshold);
+DECLARE_FLAG(int, inline_getters_setters_smaller_than);
+DECLARE_FLAG(int, inlining_depth_threshold);
+DECLARE_FLAG(int, inlining_caller_size_threshold);
bool FLAG_precompilation = false;
static void PrecompilationModeHandler(bool value) {
@@ -117,9 +124,21 @@
FLAG_fields_may_be_reset = true;
FLAG_allow_absolute_addresses = false;
+ // There is no counter feedback in precompilation, so ignore the counter
+ // when making inlining decisions.
+ FLAG_inlining_hotness = 0;
+ // Use smaller thresholds in precompilation as we are compiling everything
+ // with the optimizing compiler instead of only hot functions.
+ FLAG_inlining_size_threshold = 5;
+ FLAG_inline_getters_setters_smaller_than = 5;
+ FLAG_inlining_callee_size_threshold = 20;
+ FLAG_inlining_depth_threshold = 2;
+ FLAG_inlining_caller_size_threshold = 1000;
+
// Background compilation relies on two-stage compilation pipeline,
// while precompilation has only one.
FLAG_background_compilation = false;
+ FLAG_collect_dynamic_function_names = true;
}
}
@@ -1118,7 +1137,8 @@
intptr_t token_pos,
intptr_t argument_count,
LocationSummary* locs,
- const ICData& ic_data) {
+ const ICData& ic_data_in) {
+ const ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original());
if (Compiler::always_optimize()) {
EmitSwitchableInstanceCall(ic_data, argument_count,
deopt_id, token_pos, locs);
@@ -1185,7 +1205,8 @@
intptr_t argument_count,
const Array& argument_names,
LocationSummary* locs,
- const ICData& ic_data) {
+ const ICData& ic_data_in) {
+ const ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original());
const Array& arguments_descriptor = Array::ZoneHandle(
ic_data.IsNull() ? ArgumentsDescriptor::New(argument_count,
argument_names)
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 1d18f03..0254855 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -462,7 +462,7 @@
// Skip check if destination is a dynamic type.
if (type.IsTypeParameter()) {
const TypeParameter& type_param = TypeParameter::Cast(type);
- // Load instantiator (or null) and instantiator type arguments on stack.
+ // Load instantiator type arguments on stack.
__ ldr(R1, Address(SP, 0)); // Get instantiator type arguments.
// R1: instantiator type arguments.
// Check if type arguments are null, i.e. equivalent to vector of dynamic.
@@ -587,7 +587,6 @@
// Inputs:
// - R0: object.
// - R1: instantiator type arguments or raw_null.
-// - R2: instantiator or raw_null.
// Returns:
// - true or false in R0.
void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
@@ -597,8 +596,8 @@
LocationSummary* locs) {
ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
- // Preserve instantiator (R2) and its type arguments (R1).
- __ PushList((1 << R1) | (1 << R2));
+ // Preserve instantiator type arguments (R1).
+ __ Push(R1);
Label is_instance, is_not_instance;
// If type is instantiated and non-parameterized, we can inline code
@@ -624,19 +623,18 @@
Label done;
if (!test_cache.IsNull()) {
// Generate runtime call.
- // Load instantiator (R2) and its type arguments (R1).
- __ ldm(IA, SP, (1 << R1) | (1 << R2));
+ // Load instantiator type arguments (R1).
+ __ ldr(R1, Address(SP, 0 * kWordSize));
__ PushObject(Object::null_object()); // Make room for the result.
__ Push(R0); // Push the instance.
__ PushObject(type); // Push the type.
- // Push instantiator (R2) and its type arguments (R1).
- __ PushList((1 << R1) | (1 << R2));
+ __ Push(R1); // Push instantiator type arguments (R1).
__ LoadUniqueObject(R0, test_cache);
__ Push(R0);
- GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
+ GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 4, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// instanceof runtime call will be left as the result of the operation.
- __ Drop(5);
+ __ Drop(4);
if (negate_result) {
__ Pop(R1);
__ LoadObject(R0, Bool::True());
@@ -655,8 +653,8 @@
__ Bind(&is_instance);
__ LoadObject(R0, Bool::Get(!negate_result));
__ Bind(&done);
- // Remove instantiator (R2) and its type arguments (R1).
- __ Drop(2);
+ // Remove instantiator type arguments (R1).
+ __ Drop(1);
}
@@ -667,7 +665,6 @@
// Inputs:
// - R0: instance being type checked.
// - R1: instantiator type arguments or raw_null.
-// - R2: instantiator or raw_null.
// Returns:
// - object in R0 for successful assignable check (or throws TypeError).
// Performance notes: positive checks must be quick, negative checks can be slow
@@ -683,8 +680,8 @@
// Assignable check is skipped in FlowGraphBuilder, not here.
ASSERT(dst_type.IsMalformedOrMalbounded() ||
(!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
- // Preserve instantiator (R2) and its type arguments (R1).
- __ PushList((1 << R1) | (1 << R2));
+ // Preserve instantiator type arguments (R1).
+ __ Push(R1);
// A null object is always assignable and is returned as result.
Label is_assignable, runtime_call;
__ CompareObject(R0, Object::null_object());
@@ -705,8 +702,8 @@
__ bkpt(0);
__ Bind(&is_assignable); // For a null object.
- // Restore instantiator (R2) and its type arguments (R1).
- __ PopList((1 << R1) | (1 << R2));
+ // Restore instantiator type arguments (R1).
+ __ Pop(R1);
return;
}
@@ -716,25 +713,24 @@
&is_assignable, &runtime_call);
__ Bind(&runtime_call);
- // Load instantiator (R2) and its type arguments (R1).
- __ ldm(IA, SP, (1 << R1) | (1 << R2));
+ // Load instantiator type arguments (R1).
+ __ ldr(R1, Address(SP, 0 * kWordSize));
__ PushObject(Object::null_object()); // Make room for the result.
__ Push(R0); // Push the source object.
__ PushObject(dst_type); // Push the type of the destination.
- // Push instantiator (R2) and its type arguments (R1).
- __ PushList((1 << R1) | (1 << R2));
+ __ Push(R1); // Push instantiator type arguments (R1).
__ PushObject(dst_name); // Push the name of the destination.
__ LoadUniqueObject(R0, test_cache);
__ Push(R0);
- GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+ GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// type check runtime call is the checked value.
- __ Drop(6);
+ __ Drop(5);
__ Pop(R0);
__ Bind(&is_assignable);
- // Restore instantiator (R2) and its type arguments (R1).
- __ PopList((1 << R1) | (1 << R2));
+ // Restore instantiator type arguments (R1).
+ __ Pop(R1);
}
@@ -987,8 +983,8 @@
if (CanOptimizeFunction() &&
function.IsOptimizable() &&
(!is_optimizing() || may_reoptimize())) {
+ __ Comment("Invocation Count Check");
const Register function_reg = R8;
-
// The pool pointer is not setup before entering the Dart frame.
// Temporarily setup pool pointer for this dart function.
__ LoadPoolPointer(new_pp);
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 44f1463..d8283b1 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -454,7 +454,7 @@
// Skip check if destination is a dynamic type.
if (type.IsTypeParameter()) {
const TypeParameter& type_param = TypeParameter::Cast(type);
- // Load instantiator (or null) and instantiator type arguments on stack.
+ // Load instantiator type arguments on stack.
__ ldr(R1, Address(SP)); // Get instantiator type arguments.
// R1: instantiator type arguments.
// Check if type arguments are null, i.e. equivalent to vector of dynamic.
@@ -579,7 +579,6 @@
// Inputs:
// - R0: object.
// - R1: instantiator type arguments or raw_null.
-// - R2: instantiator or raw_null.
// Returns:
// - true or false in R0.
void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
@@ -589,8 +588,7 @@
LocationSummary* locs) {
ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
- // Preserve instantiator (R2) and its type arguments (R1).
- __ Push(R2);
+ // Preserve instantiator type arguments (R1).
__ Push(R1);
Label is_instance, is_not_instance;
@@ -619,19 +617,16 @@
// Generate runtime call.
// Load instantiator (R2) and its type arguments (R1).
__ ldr(R1, Address(SP, 0 * kWordSize));
- __ ldr(R2, Address(SP, 1 * kWordSize));
__ PushObject(Object::null_object()); // Make room for the result.
__ Push(R0); // Push the instance.
__ PushObject(type); // Push the type.
- // Push instantiator (R2) and its type arguments (R1).
- __ Push(R2);
- __ Push(R1);
+ __ Push(R1); // Push instantiator type arguments (R1).
__ LoadUniqueObject(R0, test_cache);
__ Push(R0);
- GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
+ GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 4, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// instanceof runtime call will be left as the result of the operation.
- __ Drop(5);
+ __ Drop(4);
if (negate_result) {
__ Pop(R1);
__ LoadObject(R0, Bool::True());
@@ -650,8 +645,8 @@
__ Bind(&is_instance);
__ LoadObject(R0, Bool::Get(!negate_result));
__ Bind(&done);
- // Remove instantiator (R2) and its type arguments (R1).
- __ Drop(2);
+ // Remove instantiator type arguments (R1).
+ __ Drop(1);
}
@@ -662,7 +657,6 @@
// Inputs:
// - R0: instance being type checked.
// - R1: instantiator type arguments or raw_null.
-// - R2: instantiator or raw_null.
// Returns:
// - object in R0 for successful assignable check (or throws TypeError).
// Performance notes: positive checks must be quick, negative checks can be slow
@@ -678,8 +672,7 @@
// Assignable check is skipped in FlowGraphBuilder, not here.
ASSERT(dst_type.IsMalformedOrMalbounded() ||
(!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
- // Preserve instantiator (R2) and its type arguments (R1).
- __ Push(R2);
+ // Preserve instantiator type arguments (R1).
__ Push(R1);
// A null object is always assignable and is returned as result.
Label is_assignable, runtime_call;
@@ -701,9 +694,8 @@
__ brk(0);
__ Bind(&is_assignable); // For a null object.
- // Restore instantiator (R2) and its type arguments (R1).
+ // Restore instantiator type arguments (R1).
__ Pop(R1);
- __ Pop(R2);
return;
}
@@ -713,28 +705,23 @@
&is_assignable, &runtime_call);
__ Bind(&runtime_call);
- // Load instantiator (R2) and its type arguments (R1).
- __ ldr(R1, Address(SP));
- __ ldr(R2, Address(SP, 1 * kWordSize));
+ __ ldr(R1, Address(SP)); // Load instantiator type arguments (R1).
__ PushObject(Object::null_object()); // Make room for the result.
__ Push(R0); // Push the source object.
__ PushObject(dst_type); // Push the type of the destination.
- // Push instantiator (R2) and its type arguments (R1).
- __ Push(R2);
- __ Push(R1);
+ __ Push(R1); // Push instantiator type arguments (R1).
__ PushObject(dst_name); // Push the name of the destination.
__ LoadUniqueObject(R0, test_cache);
__ Push(R0);
- GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+ GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// type check runtime call is the checked value.
- __ Drop(6);
+ __ Drop(5);
__ Pop(R0);
__ Bind(&is_assignable);
- // Restore instantiator (R2) and its type arguments (R1).
+ // Restore instantiator type arguments (R1).
__ Pop(R1);
- __ Pop(R2);
}
@@ -985,6 +972,7 @@
if (CanOptimizeFunction() &&
function.IsOptimizable() &&
(!is_optimizing() || may_reoptimize())) {
+ __ Comment("Invocation Count Check");
const Register function_reg = R6;
new_pp = R13;
// The pool pointer is not setup before entering the Dart frame.
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index af8e5b7..53a26cc 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -470,7 +470,7 @@
Immediate(reinterpret_cast<intptr_t>(Object::null()));
if (type.IsTypeParameter()) {
const TypeParameter& type_param = TypeParameter::Cast(type);
- // Load instantiator (or null) and instantiator type arguments on stack.
+ // Load instantiator type arguments on stack.
__ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
// EDX: instantiator type arguments.
// Check if type arguments are null, i.e. equivalent to vector of dynamic.
@@ -595,8 +595,7 @@
// Inputs:
// - EAX: object.
// - EDX: instantiator type arguments or raw_null.
-// - ECX: instantiator or raw_null.
-// Clobbers ECX and EDX.
+// Clobbers EDX.
// Returns:
// - true or false in EAX.
void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
@@ -609,7 +608,6 @@
const Immediate& raw_null =
Immediate(reinterpret_cast<intptr_t>(Object::null()));
Label is_instance, is_not_instance;
- __ pushl(ECX); // Store instantiator on stack.
__ pushl(EDX); // Store instantiator type arguments.
// If type is instantiated and non-parameterized, we can inline code
// checking whether the tested instance is a Smi.
@@ -635,22 +633,20 @@
if (!test_cache.IsNull()) {
// Generate runtime call.
__ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
- __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
__ PushObject(Object::null_object()); // Make room for the result.
__ pushl(EAX); // Push the instance.
__ PushObject(type); // Push the type.
- __ pushl(ECX); // Instantiator.
__ pushl(EDX); // Instantiator type arguments.
__ LoadObject(EAX, test_cache);
__ pushl(EAX);
GenerateRuntimeCall(token_pos,
deopt_id,
kInstanceofRuntimeEntry,
- 5,
+ 4,
locs);
// Pop the parameters supplied to the runtime entry. The result of the
// instanceof runtime call will be left as the result of the operation.
- __ Drop(5);
+ __ Drop(4);
if (negate_result) {
__ popl(EDX);
__ LoadObject(EAX, Bool::True());
@@ -670,7 +666,6 @@
__ LoadObject(EAX, Bool::Get(!negate_result));
__ Bind(&done);
__ popl(EDX); // Remove pushed instantiator type arguments.
- __ popl(ECX); // Remove pushed instantiator.
}
@@ -681,7 +676,6 @@
// Inputs:
// - EAX: object.
// - EDX: instantiator type arguments or raw_null.
-// - ECX: instantiator or raw_null.
// Returns:
// - object in EAX for successful assignable check (or throws TypeError).
// Performance notes: positive checks must be quick, negative checks can be slow
@@ -697,7 +691,6 @@
// Assignable check is skipped in FlowGraphBuilder, not here.
ASSERT(dst_type.IsMalformedOrMalbounded() ||
(!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
- __ pushl(ECX); // Store instantiator.
__ pushl(EDX); // Store instantiator type arguments.
// A null object is always assignable and is returned as result.
const Immediate& raw_null =
@@ -722,7 +715,6 @@
__ Bind(&is_assignable); // For a null object.
__ popl(EDX); // Remove pushed instantiator type arguments.
- __ popl(ECX); // Remove pushed instantiator.
return;
}
@@ -733,24 +725,21 @@
__ Bind(&runtime_call);
__ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
- __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
__ PushObject(Object::null_object()); // Make room for the result.
__ pushl(EAX); // Push the source object.
__ PushObject(dst_type); // Push the type of the destination.
- __ pushl(ECX); // Instantiator.
__ pushl(EDX); // Instantiator type arguments.
__ PushObject(dst_name); // Push the name of the destination.
__ LoadObject(EAX, test_cache);
__ pushl(EAX);
- GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+ GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// type check runtime call is the checked value.
- __ Drop(6);
+ __ Drop(5);
__ popl(EAX);
__ Bind(&is_assignable);
__ popl(EDX); // Remove pushed instantiator type arguments.
- __ popl(ECX); // Remove pushed instantiator.
}
@@ -1012,6 +1001,7 @@
if (CanOptimizeFunction() &&
function.IsOptimizable() &&
(!is_optimizing() || may_reoptimize())) {
+ __ Comment("Invocation Count Check");
const Register function_reg = EBX;
__ LoadObject(function_reg, function);
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index b569456..55a3dfc 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -450,7 +450,7 @@
// Skip check if destination is a dynamic type.
if (type.IsTypeParameter()) {
const TypeParameter& type_param = TypeParameter::Cast(type);
- // Load instantiator (or null) and instantiator type arguments on stack.
+ // Load instantiator type arguments on stack.
__ lw(A1, Address(SP, 0)); // Get instantiator type arguments.
// A1: instantiator type arguments.
// Check if type arguments are null, i.e. equivalent to vector of dynamic.
@@ -575,7 +575,6 @@
// Inputs:
// - A0: object.
// - A1: instantiator type arguments or raw_null.
-// - A2: instantiator or raw_null.
// Returns:
// - true or false in V0.
void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
@@ -585,9 +584,8 @@
LocationSummary* locs) {
ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
- // Preserve instantiator (A2) and its type arguments (A1).
- __ addiu(SP, SP, Immediate(-2 * kWordSize));
- __ sw(A2, Address(SP, 1 * kWordSize));
+ // Preserve instantiator type arguments (A1).
+ __ addiu(SP, SP, Immediate(-1 * kWordSize));
__ sw(A1, Address(SP, 0 * kWordSize));
Label is_instance, is_not_instance;
@@ -614,25 +612,23 @@
Label done;
if (!test_cache.IsNull()) {
// Generate runtime call.
- // Load instantiator (A2) and its type arguments (A1).
+ // Load instantiator type arguments (A1).
__ lw(A1, Address(SP, 0 * kWordSize));
- __ lw(A2, Address(SP, 1 * kWordSize));
- __ addiu(SP, SP, Immediate(-6 * kWordSize));
+ __ addiu(SP, SP, Immediate(-5 * kWordSize));
__ LoadObject(TMP, Object::null_object());
- __ sw(TMP, Address(SP, 5 * kWordSize)); // Make room for the result.
- __ sw(A0, Address(SP, 4 * kWordSize)); // Push the instance.
+ __ sw(TMP, Address(SP, 4 * kWordSize)); // Make room for the result.
+ __ sw(A0, Address(SP, 3 * kWordSize)); // Push the instance.
__ LoadObject(TMP, type);
- __ sw(TMP, Address(SP, 3 * kWordSize)); // Push the type.
- __ sw(A2, Address(SP, 2 * kWordSize)); // Push instantiator.
+ __ sw(TMP, Address(SP, 2 * kWordSize)); // Push the type.
__ sw(A1, Address(SP, 1 * kWordSize)); // Push type arguments.
__ LoadUniqueObject(A0, test_cache);
__ sw(A0, Address(SP, 0 * kWordSize));
- GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
+ GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 4, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// instanceof runtime call will be left as the result of the operation.
- __ lw(T0, Address(SP, 5 * kWordSize));
- __ addiu(SP, SP, Immediate(6 * kWordSize));
+ __ lw(T0, Address(SP, 4 * kWordSize));
+ __ addiu(SP, SP, Immediate(5 * kWordSize));
if (negate_result) {
__ LoadObject(V0, Bool::True());
__ bne(T0, V0, &done);
@@ -649,8 +645,8 @@
__ Bind(&is_instance);
__ LoadObject(V0, Bool::Get(!negate_result));
__ Bind(&done);
- // Remove instantiator (A2) and its type arguments (A1).
- __ Drop(2);
+ // Remove instantiator type arguments (A1).
+ __ Drop(1);
}
@@ -661,7 +657,6 @@
// Inputs:
// - A0: instance being type checked.
// - A1: instantiator type arguments or raw_null.
-// - A2: instantiator or raw_null.
// Returns:
// - object in A0 for successful assignable check (or throws TypeError).
// Clobbers: T0, T1, T2
@@ -679,9 +674,9 @@
// Assignable check is skipped in FlowGraphBuilder, not here.
ASSERT(dst_type.IsMalformedOrMalbounded() ||
(!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
- // Preserve instantiator and its type arguments.
- __ addiu(SP, SP, Immediate(-2 * kWordSize));
- __ sw(A2, Address(SP, 1 * kWordSize));
+ // Preserve instantiator type arguments.
+ __ addiu(SP, SP, Immediate(-1 * kWordSize));
+ __ sw(A1, Address(SP, 0 * kWordSize));
// A null object is always assignable and is returned as result.
Label is_assignable, runtime_call;
@@ -709,10 +704,9 @@
__ break_(0);
__ Bind(&is_assignable); // For a null object.
- // Restore instantiator and its type arguments.
+ // Restore instantiator type arguments.
__ lw(A1, Address(SP, 0 * kWordSize));
- __ lw(A2, Address(SP, 1 * kWordSize));
- __ addiu(SP, SP, Immediate(2 * kWordSize));
+ __ addiu(SP, SP, Immediate(1 * kWordSize));
return;
}
@@ -722,34 +716,31 @@
&is_assignable, &runtime_call);
__ Bind(&runtime_call);
- // Load instantiator (A2) and its type arguments (A1).
+ // Load instantiator type arguments (A1).
__ lw(A1, Address(SP, 0 * kWordSize));
- __ lw(A2, Address(SP, 1 * kWordSize));
- __ addiu(SP, SP, Immediate(-7 * kWordSize));
+ __ addiu(SP, SP, Immediate(-6 * kWordSize));
__ LoadObject(TMP, Object::null_object());
- __ sw(TMP, Address(SP, 6 * kWordSize)); // Make room for the result.
- __ sw(A0, Address(SP, 5 * kWordSize)); // Push the source object.
+ __ sw(TMP, Address(SP, 5 * kWordSize)); // Make room for the result.
+ __ sw(A0, Address(SP, 4 * kWordSize)); // Push the source object.
__ LoadObject(TMP, dst_type);
- __ sw(TMP, Address(SP, 4 * kWordSize)); // Push the type of the destination.
- __ sw(A2, Address(SP, 3 * kWordSize)); // Push instantiator.
+ __ sw(TMP, Address(SP, 3 * kWordSize)); // Push the type of the destination.
__ sw(A1, Address(SP, 2 * kWordSize)); // Push type arguments.
__ LoadObject(TMP, dst_name);
__ sw(TMP, Address(SP, 1 * kWordSize)); // Push the name of the destination.
__ LoadUniqueObject(T0, test_cache);
__ sw(T0, Address(SP, 0 * kWordSize));
- GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+ GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// type check runtime call is the checked value.
- __ lw(A0, Address(SP, 6 * kWordSize));
- __ addiu(SP, SP, Immediate(7 * kWordSize));
+ __ lw(A0, Address(SP, 5 * kWordSize));
+ __ addiu(SP, SP, Immediate(6 * kWordSize));
__ Bind(&is_assignable);
- // Restore instantiator and its type arguments.
+ // Restore instantiator type arguments.
__ lw(A1, Address(SP, 0 * kWordSize));
- __ lw(A2, Address(SP, 1 * kWordSize));
- __ addiu(SP, SP, Immediate(2 * kWordSize));
+ __ addiu(SP, SP, Immediate(1 * kWordSize));
}
@@ -1003,6 +994,7 @@
if (CanOptimizeFunction() &&
function.IsOptimizable() &&
(!is_optimizing() || may_reoptimize())) {
+ __ Comment("Invocation Count Check");
const Register function_reg = T0;
// Temporarily setup pool pointer for this dart function.
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 5f38396..fc3d951 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -463,7 +463,7 @@
// Skip check if destination is a dynamic type.
if (type.IsTypeParameter()) {
const TypeParameter& type_param = TypeParameter::Cast(type);
- // Load instantiator (or null) and instantiator type arguments on stack.
+ // Load instantiator type arguments on stack.
__ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
// RDX: instantiator type arguments.
// Check if type arguments are null, i.e. equivalent to vector of dynamic.
@@ -589,8 +589,7 @@
// Inputs:
// - RAX: object.
// - RDX: instantiator type arguments or raw_null.
-// - RCX: instantiator or raw_null.
-// Clobbers RCX and RDX.
+// Clobbers RDX.
// Returns:
// - true or false in RAX.
void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
@@ -601,7 +600,6 @@
ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
Label is_instance, is_not_instance;
- __ pushq(RCX); // Store instantiator on stack.
__ pushq(RDX); // Store instantiator type arguments.
// If type is instantiated and non-parameterized, we can inline code
// checking whether the tested instance is a Smi.
@@ -627,22 +625,20 @@
if (!test_cache.IsNull()) {
// Generate runtime call.
__ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
- __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator.
__ PushObject(Object::null_object()); // Make room for the result.
__ pushq(RAX); // Push the instance.
__ PushObject(type); // Push the type.
- __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null.
__ pushq(RDX); // Instantiator type arguments.
__ LoadUniqueObject(RAX, test_cache);
__ pushq(RAX);
GenerateRuntimeCall(token_pos,
deopt_id,
kInstanceofRuntimeEntry,
- 5,
+ 4,
locs);
// Pop the parameters supplied to the runtime entry. The result of the
// instanceof runtime call will be left as the result of the operation.
- __ Drop(5);
+ __ Drop(4);
if (negate_result) {
__ popq(RDX);
__ LoadObject(RAX, Bool::True());
@@ -662,7 +658,6 @@
__ LoadObject(RAX, Bool::Get(!negate_result));
__ Bind(&done);
__ popq(RDX); // Remove pushed instantiator type arguments.
- __ popq(RCX); // Remove pushed instantiator.
}
@@ -673,7 +668,6 @@
// Inputs:
// - RAX: object.
// - RDX: instantiator type arguments or raw_null.
-// - RCX: instantiator or raw_null.
// Returns:
// - object in RAX for successful assignable check (or throws TypeError).
// Performance notes: positive checks must be quick, negative checks can be slow
@@ -689,7 +683,6 @@
// Assignable check is skipped in FlowGraphBuilder, not here.
ASSERT(dst_type.IsMalformedOrMalbounded() ||
(!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
- __ pushq(RCX); // Store instantiator.
__ pushq(RDX); // Store instantiator type arguments.
// A null object is always assignable and is returned as result.
Label is_assignable, runtime_call;
@@ -712,7 +705,6 @@
__ Bind(&is_assignable); // For a null object.
__ popq(RDX); // Remove pushed instantiator type arguments.
- __ popq(RCX); // Remove pushed instantiator.
return;
}
@@ -723,24 +715,21 @@
__ Bind(&runtime_call);
__ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
- __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator.
__ PushObject(Object::null_object()); // Make room for the result.
__ pushq(RAX); // Push the source object.
__ PushObject(dst_type); // Push the type of the destination.
- __ pushq(RCX); // Instantiator.
__ pushq(RDX); // Instantiator type arguments.
__ PushObject(dst_name); // Push the name of the destination.
__ LoadUniqueObject(RAX, test_cache);
__ pushq(RAX);
- GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
+ GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// type check runtime call is the checked value.
- __ Drop(6);
+ __ Drop(5);
__ popq(RAX);
__ Bind(&is_assignable);
__ popq(RDX); // Remove pushed instantiator type arguments.
- __ popq(RCX); // Remove pushed instantiator.
}
@@ -1015,6 +1004,7 @@
if (CanOptimizeFunction() &&
function.IsOptimizable() &&
(!is_optimizing() || may_reoptimize())) {
+ __ Comment("Invocation Count Check");
const Register function_reg = RDI;
// Load function object using the callee's pool pointer.
__ LoadFunctionFromCalleePool(function_reg, function, new_pp);
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 7cd46a0..bc5d7bc 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -59,7 +59,7 @@
"Enable inlining annotations");
DECLARE_FLAG(bool, compiler_stats);
-DECLARE_FLAG(int, deoptimization_counter_threshold);
+DECLARE_FLAG(int, max_deoptimization_counter_threshold);
DECLARE_FLAG(bool, polymorphic_with_deopt);
DECLARE_FLAG(bool, print_flow_graph);
DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -639,7 +639,7 @@
// Abort if this function has deoptimized too much.
if (function.deoptimization_counter() >=
- FLAG_deoptimization_counter_threshold) {
+ FLAG_max_deoptimization_counter_threshold) {
function.set_is_inlinable(false);
TRACE_INLINING(THR_Print(" Bailout: deoptimization threshold\n"));
PRINT_INLINING_TREE("Deoptimization threshold exceeded",
@@ -1692,7 +1692,7 @@
}
const ICData& old_checks = call_->ic_data();
const ICData& new_checks = ICData::ZoneHandle(
- ICData::New(Function::Handle(old_checks.owner()),
+ ICData::New(Function::Handle(old_checks.Owner()),
String::Handle(old_checks.target_name()),
Array::Handle(old_checks.arguments_descriptor()),
old_checks.deopt_id(),
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 8a20b88..f10e60c 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -276,7 +276,12 @@
}
// Check if getter or setter in function's class and class is currently leaf.
- if (FLAG_guess_icdata_cid &&
+ // Do not run the optimization below if in background compilation since
+ // resolution of getter functions may create new signature classes.
+ // TODO(regis): Remove test for background compilation once signature classes
+ // are not generated any longer.
+ if (thread()->IsMutatorThread() &&
+ FLAG_guess_icdata_cid &&
((call->token_kind() == Token::kGET) ||
(call->token_kind() == Token::kSET))) {
const Class& owner_class = Class::Handle(Z, function().Owner());
@@ -319,7 +324,7 @@
// not found in the ICData.
if (!function.IsNull()) {
const ICData& new_ic_data = ICData::ZoneHandle(Z, ICData::New(
- Function::Handle(Z, ic_data.owner()),
+ Function::Handle(Z, ic_data.Owner()),
String::Handle(Z, ic_data.target_name()),
Object::empty_array(), // Dummy argument descriptor.
ic_data.deopt_id(),
@@ -1303,7 +1308,6 @@
// the index is not a smi.
const AbstractType& value_type =
AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2));
- Definition* instantiator = NULL;
Definition* type_args = NULL;
switch (array_cid) {
case kArrayCid:
@@ -1321,7 +1325,6 @@
NULL,
FlowGraph::kValue);
- instantiator = array;
type_args = load_type_args;
break;
}
@@ -1339,7 +1342,7 @@
// Fall through.
case kTypedDataFloat32ArrayCid:
case kTypedDataFloat64ArrayCid: {
- type_args = instantiator = flow_graph_->constant_null();
+ type_args = flow_graph_->constant_null();
ASSERT((array_cid != kTypedDataFloat32ArrayCid &&
array_cid != kTypedDataFloat64ArrayCid) ||
value_type.IsDoubleType());
@@ -1347,14 +1350,14 @@
break;
}
case kTypedDataFloat32x4ArrayCid: {
- type_args = instantiator = flow_graph_->constant_null();
+ type_args = flow_graph_->constant_null();
ASSERT((array_cid != kTypedDataFloat32x4ArrayCid) ||
value_type.IsFloat32x4Type());
ASSERT(value_type.IsInstantiated());
break;
}
case kTypedDataFloat64x2ArrayCid: {
- type_args = instantiator = flow_graph_->constant_null();
+ type_args = flow_graph_->constant_null();
ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) ||
value_type.IsFloat64x2Type());
ASSERT(value_type.IsInstantiated());
@@ -1367,7 +1370,6 @@
AssertAssignableInstr* assert_value =
new(Z) AssertAssignableInstr(token_pos,
new(Z) Value(stored_value),
- new(Z) Value(instantiator),
new(Z) Value(type_args),
value_type,
Symbols::Value(),
@@ -4051,12 +4053,10 @@
void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
ASSERT(Token::IsTypeTestOperator(call->token_kind()));
Definition* left = call->ArgumentAt(0);
- Definition* instantiator = NULL;
Definition* type_args = NULL;
AbstractType& type = AbstractType::ZoneHandle(Z);
bool negate = false;
if (call->ArgumentCount() == 2) {
- instantiator = flow_graph()->constant_null();
type_args = flow_graph()->constant_null();
if (call->function_name().raw() ==
Library::PrivateCoreLibName(Symbols::_instanceOfNum()).raw()) {
@@ -4079,10 +4079,9 @@
negate = Bool::Cast(call->ArgumentAt(1)->OriginalDefinition()
->AsConstant()->value()).value();
} else {
- instantiator = call->ArgumentAt(1);
- type_args = call->ArgumentAt(2);
- type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw();
- negate = Bool::Cast(call->ArgumentAt(4)->OriginalDefinition()
+ type_args = call->ArgumentAt(1);
+ type = AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value()).raw();
+ negate = Bool::Cast(call->ArgumentAt(3)->OriginalDefinition()
->AsConstant()->value()).value();
}
const ICData& unary_checks =
@@ -4159,7 +4158,6 @@
InstanceOfInstr* instance_of =
new(Z) InstanceOfInstr(call->token_pos(),
new(Z) Value(left),
- new(Z) Value(instantiator),
new(Z) Value(type_args),
type,
negate,
@@ -4172,10 +4170,9 @@
void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
ASSERT(Token::IsTypeCastOperator(call->token_kind()));
Definition* left = call->ArgumentAt(0);
- Definition* instantiator = call->ArgumentAt(1);
- Definition* type_args = call->ArgumentAt(2);
+ Definition* type_args = call->ArgumentAt(1);
const AbstractType& type =
- AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value());
+ AbstractType::Cast(call->ArgumentAt(2)->AsConstant()->value());
ASSERT(!type.IsMalformedOrMalbounded());
const ICData& unary_checks =
ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
@@ -4214,7 +4211,6 @@
AssertAssignableInstr* assert_as =
new(Z) AssertAssignableInstr(call->token_pos(),
new(Z) Value(left),
- new(Z) Value(instantiator),
new(Z) Value(type_args),
type,
dst_name,
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index 6b2a946..1638b3d 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -596,7 +596,8 @@
}
virtual void Run() {
- Thread::EnterIsolateAsHelper(isolate_, true);
+ bool result = Thread::EnterIsolateAsHelper(isolate_, true);
+ ASSERT(result);
{
StackZone stack_zone(Thread::Current());
Zone* zone = stack_zone.GetZone();
diff --git a/runtime/vm/gc_sweeper.cc b/runtime/vm/gc_sweeper.cc
index 6332dee..a192138 100644
--- a/runtime/vm/gc_sweeper.cc
+++ b/runtime/vm/gc_sweeper.cc
@@ -114,7 +114,8 @@
}
virtual void Run() {
- Thread::EnterIsolateAsHelper(task_isolate_);
+ bool result = Thread::EnterIsolateAsHelper(task_isolate_);
+ ASSERT(result);
GCSweeper sweeper;
HeapPage* page = first_;
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 30c4a6f..97de0b1 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -405,9 +405,6 @@
f->Print(", %s, '%s'",
dst_type().ToCString(),
dst_name().ToCString());
- f->Print(" instantiator(");
- instantiator()->PrintTo(f);
- f->Print(")");
f->Print(" instantiator_type_arguments(");
instantiator_type_arguments()->PrintTo(f);
f->Print(")");
@@ -551,9 +548,6 @@
f->Print(" %s %s",
negate_result() ? "ISNOT" : "IS",
String::Handle(type().Name()).ToCString());
- f->Print(" instantiator(");
- instantiator()->PrintTo(f);
- f->Print(")");
f->Print(" type-arg(");
instantiator_type_arguments()->PrintTo(f);
f->Print(")");
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 852efd4..c73a48f 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -1735,6 +1735,19 @@
}
+Definition* BinaryIntegerOpInstr::CreateConstantResult(FlowGraph* flow_graph,
+ const Integer& result) {
+ Definition* result_defn = flow_graph->GetConstant(result);
+ if (representation() != kTagged) {
+ result_defn = UnboxInstr::Create(representation(),
+ new Value(result_defn),
+ GetDeoptId());
+ flow_graph->InsertBefore(this, result_defn, env(), FlowGraph::kValue);
+ }
+ return result_defn;
+}
+
+
Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) {
// If both operands are constants evaluate this expression. Might
// occur due to load forwarding after constant propagation pass
@@ -1747,7 +1760,7 @@
Evaluate(Integer::Cast(left()->BoundConstant()),
Integer::Cast(right()->BoundConstant())));
if (!result.IsNull()) {
- return flow_graph->GetConstant(result);
+ return CreateConstantResult(flow_graph, result);
}
}
@@ -1872,7 +1885,7 @@
DeoptimizeInstr* deopt =
new DeoptimizeInstr(ICData::kDeoptBinarySmiOp, GetDeoptId());
flow_graph->InsertBefore(this, deopt, env(), FlowGraph::kEffect);
- return flow_graph->GetConstant(Smi::Handle(Smi::New(0)));
+ return CreateConstantResult(flow_graph, Integer::Handle(Smi::New(0)));
}
break;
@@ -1886,7 +1899,7 @@
new DeoptimizeInstr(ICData::kDeoptBinarySmiOp, GetDeoptId());
flow_graph->InsertBefore(this, deopt, env(), FlowGraph::kEffect);
}
- return flow_graph->GetConstant(Smi::Handle(Smi::New(0)));
+ return CreateConstantResult(flow_graph, Integer::Handle(Smi::New(0)));
}
break;
}
@@ -2202,11 +2215,13 @@
// Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)).
BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger();
if (box_defn != NULL) {
- if (box_defn->value()->definition()->representation() == representation()) {
+ Representation from_representation =
+ box_defn->value()->definition()->representation();
+ if (from_representation == representation()) {
return box_defn->value()->definition();
} else {
UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr(
- box_defn->value()->definition()->representation(),
+ from_representation,
representation(),
box_defn->value()->CopyWithType(),
(representation() == kUnboxedInt32) ?
@@ -2522,6 +2537,7 @@
Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) {
+ if (!HasUses()) return NULL;
bool negated = false;
Definition* replacement = CanonicalizeStrictCompare(this, &negated);
if (negated && replacement->IsComparison()) {
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 897ee3f..76840bb 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -2590,11 +2590,10 @@
};
-class AssertAssignableInstr : public TemplateDefinition<3, Throws, Pure> {
+class AssertAssignableInstr : public TemplateDefinition<2, Throws, Pure> {
public:
AssertAssignableInstr(intptr_t token_pos,
Value* value,
- Value* instantiator,
Value* instantiator_type_arguments,
const AbstractType& dst_type,
const String& dst_name,
@@ -2606,8 +2605,7 @@
ASSERT(!dst_type.IsNull());
ASSERT(!dst_name.IsNull());
SetInputAt(0, value);
- SetInputAt(1, instantiator);
- SetInputAt(2, instantiator_type_arguments);
+ SetInputAt(1, instantiator_type_arguments);
}
DECLARE_INSTRUCTION(AssertAssignable)
@@ -2615,8 +2613,7 @@
virtual bool RecomputeType();
Value* value() const { return inputs_[0]; }
- Value* instantiator() const { return inputs_[1]; }
- Value* instantiator_type_arguments() const { return inputs_[2]; }
+ Value* instantiator_type_arguments() const { return inputs_[1]; }
virtual intptr_t token_pos() const { return token_pos_; }
const AbstractType& dst_type() const { return dst_type_; }
@@ -4010,11 +4007,10 @@
};
-class InstanceOfInstr : public TemplateDefinition<3, Throws> {
+class InstanceOfInstr : public TemplateDefinition<2, Throws> {
public:
InstanceOfInstr(intptr_t token_pos,
Value* value,
- Value* instantiator,
Value* instantiator_type_arguments,
const AbstractType& type,
bool negate_result,
@@ -4025,16 +4021,14 @@
negate_result_(negate_result) {
ASSERT(!type.IsNull());
SetInputAt(0, value);
- SetInputAt(1, instantiator);
- SetInputAt(2, instantiator_type_arguments);
+ SetInputAt(1, instantiator_type_arguments);
}
DECLARE_INSTRUCTION(InstanceOf)
virtual CompileType ComputeType() const;
Value* value() const { return inputs_[0]; }
- Value* instantiator() const { return inputs_[1]; }
- Value* instantiator_type_arguments() const { return inputs_[2]; }
+ Value* instantiator_type_arguments() const { return inputs_[1]; }
bool negate_result() const { return negate_result_; }
const AbstractType& type() const { return type_; }
@@ -4049,7 +4043,6 @@
private:
const intptr_t token_pos_;
Value* value_;
- Value* instantiator_;
Value* type_arguments_;
const AbstractType& type_;
const bool negate_result_;
@@ -6849,6 +6842,8 @@
Range* range);
private:
+ Definition* CreateConstantResult(FlowGraph* graph, const Integer& result);
+
const Token::Kind op_kind_;
bool can_overflow_;
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 8d6e6c1..9120195 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -345,13 +345,12 @@
LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- const intptr_t kNumInputs = 3;
+ const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(R0)); // Value.
- summary->set_in(1, Location::RegisterLocation(R2)); // Instantiator.
- summary->set_in(2, Location::RegisterLocation(R1)); // Type arguments.
+ summary->set_in(1, Location::RegisterLocation(R1)); // Type arguments.
summary->set_out(0, Location::RegisterLocation(R0));
return summary;
}
@@ -2275,13 +2274,12 @@
LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- const intptr_t kNumInputs = 3;
+ const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(R0));
- summary->set_in(1, Location::RegisterLocation(R2));
- summary->set_in(2, Location::RegisterLocation(R1));
+ summary->set_in(1, Location::RegisterLocation(R1));
summary->set_out(0, Location::RegisterLocation(R0));
return summary;
}
@@ -2289,8 +2287,7 @@
void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(0).reg() == R0); // Value.
- ASSERT(locs()->in(1).reg() == R2); // Instantiator.
- ASSERT(locs()->in(2).reg() == R1); // Instantiator type arguments.
+ ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments.
compiler->GenerateInstanceOf(token_pos(),
deopt_id(),
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 7f85d09..05ce132 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -333,13 +333,12 @@
LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- const intptr_t kNumInputs = 3;
+ const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(R0)); // Value.
- summary->set_in(1, Location::RegisterLocation(R2)); // Instantiator.
- summary->set_in(2, Location::RegisterLocation(R1)); // Type arguments.
+ summary->set_in(1, Location::RegisterLocation(R1)); // Type arguments.
summary->set_out(0, Location::RegisterLocation(R0));
return summary;
}
@@ -1995,13 +1994,12 @@
LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- const intptr_t kNumInputs = 3;
+ const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(R0));
- summary->set_in(1, Location::RegisterLocation(R2));
- summary->set_in(2, Location::RegisterLocation(R1));
+ summary->set_in(1, Location::RegisterLocation(R1));
summary->set_out(0, Location::RegisterLocation(R0));
return summary;
}
@@ -2009,8 +2007,7 @@
void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(0).reg() == R0); // Value.
- ASSERT(locs()->in(1).reg() == R2); // Instantiator.
- ASSERT(locs()->in(2).reg() == R1); // Instantiator type arguments.
+ ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments.
compiler->GenerateInstanceOf(token_pos(),
deopt_id(),
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index b5a851f..0c2f782 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -218,13 +218,12 @@
LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- const intptr_t kNumInputs = 3;
+ const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(EAX)); // Value.
- summary->set_in(1, Location::RegisterLocation(ECX)); // Instantiator.
- summary->set_in(2, Location::RegisterLocation(EDX)); // Type arguments.
+ summary->set_in(1, Location::RegisterLocation(EDX)); // Type arguments.
summary->set_out(0, Location::RegisterLocation(EAX));
return summary;
}
@@ -2010,13 +2009,12 @@
LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- const intptr_t kNumInputs = 3;
+ const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(EAX));
- summary->set_in(1, Location::RegisterLocation(ECX));
- summary->set_in(2, Location::RegisterLocation(EDX));
+ summary->set_in(1, Location::RegisterLocation(EDX));
summary->set_out(0, Location::RegisterLocation(EAX));
return summary;
}
@@ -2024,8 +2022,7 @@
void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(0).reg() == EAX); // Value.
- ASSERT(locs()->in(1).reg() == ECX); // Instantiator.
- ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments.
+ ASSERT(locs()->in(1).reg() == EDX); // Instantiator type arguments.
compiler->GenerateInstanceOf(token_pos(),
deopt_id(),
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 16c4367..e403445 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -394,13 +394,12 @@
LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- const intptr_t kNumInputs = 3;
+ const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(A0)); // Value.
- summary->set_in(1, Location::RegisterLocation(A2)); // Instantiator.
- summary->set_in(2, Location::RegisterLocation(A1)); // Type arguments.
+ summary->set_in(1, Location::RegisterLocation(A1)); // Type arguments.
summary->set_out(0, Location::RegisterLocation(A0));
return summary;
}
@@ -2128,13 +2127,12 @@
LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- const intptr_t kNumInputs = 3;
+ const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(A0));
- summary->set_in(1, Location::RegisterLocation(A2));
- summary->set_in(2, Location::RegisterLocation(A1));
+ summary->set_in(1, Location::RegisterLocation(A1));
summary->set_out(0, Location::RegisterLocation(V0));
return summary;
}
@@ -2142,8 +2140,7 @@
void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(0).reg() == A0); // Value.
- ASSERT(locs()->in(1).reg() == A2); // Instantiator.
- ASSERT(locs()->in(2).reg() == A1); // Instantiator type arguments.
+ ASSERT(locs()->in(1).reg() == A1); // Instantiator type arguments.
__ Comment("InstanceOfInstr");
compiler->GenerateInstanceOf(token_pos(),
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 07f30fb..7ca52de 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -305,13 +305,12 @@
LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- const intptr_t kNumInputs = 3;
+ const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(RAX)); // Value.
- summary->set_in(1, Location::RegisterLocation(RCX)); // Instantiator.
- summary->set_in(2, Location::RegisterLocation(RDX)); // Type arguments.
+ summary->set_in(1, Location::RegisterLocation(RDX)); // Type arguments.
summary->set_out(0, Location::RegisterLocation(RAX));
return summary;
}
@@ -2013,13 +2012,12 @@
LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- const intptr_t kNumInputs = 3;
+ const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kCall);
summary->set_in(0, Location::RegisterLocation(RAX));
- summary->set_in(1, Location::RegisterLocation(RCX));
- summary->set_in(2, Location::RegisterLocation(RDX));
+ summary->set_in(1, Location::RegisterLocation(RDX));
summary->set_out(0, Location::RegisterLocation(RAX));
return summary;
}
@@ -2027,8 +2025,7 @@
void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(0).reg() == RAX); // Value.
- ASSERT(locs()->in(1).reg() == RCX); // Instantiator.
- ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments.
+ ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments.
compiler->GenerateInstanceOf(token_pos(),
deopt_id(),
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 0199af5..1635611 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -876,7 +876,12 @@
// TODO(5411455): For now just set the recently created isolate as
// the current isolate.
- Thread::EnterIsolate(result);
+ if (!Thread::EnterIsolate(result)) {
+ // We failed to enter the isolate, it is possible the VM is shutting down,
+ // return back a NULL so that CreateIsolate reports back an error.
+ delete result;
+ return NULL;
+ }
// Setup the isolate message handler.
MessageHandler* handler = new IsolateMessageHandler(result);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index f44c365..4e8e2ddf 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -68,7 +68,6 @@
DECLARE_FLAG(charp, coverage_dir);
DECLARE_FLAG(bool, load_deferred_eagerly);
DECLARE_FLAG(bool, show_invisible_frames);
-DECLARE_FLAG(bool, trace_compiler);
DECLARE_FLAG(bool, trace_deoptimization);
DECLARE_FLAG(bool, trace_deoptimization_verbose);
DECLARE_FLAG(bool, write_protect_code);
@@ -2347,6 +2346,12 @@
ClassFinalizer::ApplyMixinType(*this);
}
if (type_parameters() == TypeArguments::null()) {
+ const intptr_t cid = id();
+ if ((cid == kArrayCid) ||
+ (cid == kImmutableArrayCid) ||
+ (cid == kGrowableObjectArrayCid)) {
+ return 1; // List's type parameter may not have been parsed yet.
+ }
return 0;
}
REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
@@ -2797,9 +2802,10 @@
}
#endif
+
void Class::RegisterCHACode(const Code& code) {
if (FLAG_trace_cha) {
- THR_Print("RegisterCHACode %s class %s\n",
+ THR_Print("RegisterCHACode '%s' depends on class '%s'\n",
Function::Handle(code.function()).ToQualifiedCString(), ToCString());
}
DEBUG_ASSERT(IsMutatorOrAtSafepoint());
@@ -2809,9 +2815,12 @@
}
-void Class::DisableCHAOptimizedCode() {
+void Class::DisableCHAOptimizedCode(const Class& subclass) {
ASSERT(Thread::Current()->IsMutatorThread());
CHACodeArray a(*this);
+ if (FLAG_trace_deoptimization && a.HasCodes()) {
+ THR_Print("Adding subclass %s\n", subclass.ToCString());
+ }
a.DisableCode();
}
@@ -3630,7 +3639,7 @@
RawType* Class::CanonicalType() const {
- if (NumTypeArguments() == 0) {
+ if (!IsGeneric()) {
return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_);
}
Array& types = Array::Handle();
@@ -3644,7 +3653,7 @@
void Class::SetCanonicalType(const Type& type) const {
ASSERT(type.IsCanonical());
- if (NumTypeArguments() == 0) {
+ if (!IsGeneric()) {
ASSERT((canonical_types() == Object::null()) ||
(canonical_types() == type.raw())); // Set during own finalization.
set_canonical_types(type);
@@ -5820,7 +5829,7 @@
((end_token_pos() - token_pos()) < FLAG_huge_method_cutoff_in_tokens)) {
// Additional check needed for implicit getters.
return (unoptimized_code() == Object::null()) ||
- (Code::Handle(unoptimized_code()).Size() <
+ (Code::Handle(unoptimized_code()).Size() <
FLAG_huge_method_cutoff_in_code_size);
}
return false;
@@ -5837,6 +5846,7 @@
set_is_optimizable(value);
if (!value) {
set_is_inlinable(false);
+ set_usage_counter(INT_MIN);
}
}
@@ -7033,7 +7043,9 @@
ICData& ic_data = ICData::ZoneHandle(zone);
ic_data ^= saved_ic_data.At(i);
if (clone_descriptors) {
+ ICData& original_ic_data = ICData::Handle(zone, ic_data.raw());
ic_data = ICData::CloneDescriptor(ic_data);
+ ic_data.SetOriginal(original_ic_data);
}
(*deopt_id_to_ic_data)[ic_data.deopt_id()] = &ic_data;
}
@@ -7723,8 +7735,8 @@
virtual void ReportSwitchingCode(const Code& code) {
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
Function& function = Function::Handle(code.function());
- THR_Print("Switching %s to unoptimized code because guard"
- " on field %s was violated.\n",
+ THR_Print("Switching '%s' to unoptimized code because guard"
+ " on field '%s' was violated.\n",
function.ToFullyQualifiedCString(),
field_.ToCString());
}
@@ -9589,7 +9601,10 @@
ResolvedNamesMap cache(resolved_names());
bool present = false;
*obj = cache.GetOrNull(name, &present);
- ASSERT(cache.Release().raw() == resolved_names());
+ // Mutator compiler thread may add entries and therefore
+ // change 'resolved_names()' while running a background compilation;
+ // do not ASSERT that 'resolved_names()' has not changed.
+ cache.Release();
return present;
}
@@ -12176,9 +12191,41 @@
}
+RawFunction* ICData::Owner() const {
+ Object& obj = Object::Handle(raw_ptr()->owner_);
+ if (obj.IsFunction()) {
+ return Function::Cast(obj).raw();
+ } else {
+ ICData& original = ICData::Handle();
+ original ^= obj.raw();
+ return original.Owner();
+ }
+}
+
+
+RawICData* ICData::Original() const {
+ if (IsNull()) {
+ return ICData::null();
+ }
+ Object& obj = Object::Handle(raw_ptr()->owner_);
+ if (obj.IsFunction()) {
+ return this->raw();
+ } else {
+ return ICData::RawCast(obj.raw());
+ }
+}
+
+
+void ICData::SetOriginal(const ICData& value) const {
+ ASSERT(value.IsOriginal());
+ ASSERT(!value.IsNull());
+ StorePointer(&raw_ptr()->owner_, reinterpret_cast<RawObject*>(value.raw()));
+}
+
+
void ICData::set_owner(const Function& value) const {
ASSERT(!value.IsNull());
- StorePointer(&raw_ptr()->owner_, value.raw());
+ StorePointer(&raw_ptr()->owner_, reinterpret_cast<RawObject*>(value.raw()));
}
@@ -12817,7 +12864,7 @@
RawICData* ICData::NewFrom(const ICData& from, intptr_t num_args_tested) {
const ICData& result = ICData::Handle(ICData::New(
- Function::Handle(from.owner()),
+ Function::Handle(from.Owner()),
String::Handle(from.target_name()),
Array::Handle(from.arguments_descriptor()),
from.deopt_id(),
@@ -12832,7 +12879,7 @@
Zone* zone = Thread::Current()->zone();
const ICData& result = ICData::Handle(ICData::NewDescriptor(
zone,
- Function::Handle(zone, from.owner()),
+ Function::Handle(zone, from.Owner()),
String::Handle(zone, from.target_name()),
Array::Handle(zone, from.arguments_descriptor()),
from.deopt_id(),
@@ -12849,7 +12896,7 @@
JSONObject jsobj(stream);
AddCommonObjectProperties(&jsobj, "Object", ref);
jsobj.AddServiceId(*this);
- jsobj.AddProperty("_owner", Object::Handle(owner()));
+ jsobj.AddProperty("_owner", Object::Handle(Owner()));
jsobj.AddProperty("_selector", String::Handle(target_name()).ToCString());
if (ref) {
return;
@@ -12869,7 +12916,6 @@
JSONObject jsobj(&jsarray);
jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
- // TODO(turnidge): Use AddLocation instead.
jsobj.AddProperty("tokenPos", token_pos);
// TODO(rmacnak): Figure out how to stringify DeoptReasons().
// jsobj.AddProperty("deoptReasons", ...);
@@ -12897,6 +12943,35 @@
}
+void ICData::PrintToJSONArrayNew(const JSONArray& jsarray,
+ intptr_t token_pos,
+ bool is_static_call) const {
+ Isolate* isolate = Isolate::Current();
+ Class& cls = Class::Handle();
+ Function& func = Function::Handle();
+
+ JSONObject jsobj(&jsarray);
+ jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
+ jsobj.AddProperty("tokenPos", token_pos);
+ // TODO(rmacnak): Figure out how to stringify DeoptReasons().
+ // jsobj.AddProperty("deoptReasons", ...);
+
+ JSONArray cache_entries(&jsobj, "cacheEntries");
+ for (intptr_t i = 0; i < NumberOfChecks(); i++) {
+ JSONObject cache_entry(&cache_entries);
+ func = GetTargetAt(i);
+ intptr_t count = GetCountAt(i);
+ if (!is_static_call) {
+ intptr_t cid = GetReceiverClassIdAt(i);
+ cls ^= isolate->class_table()->At(cid);
+ cache_entry.AddProperty("receiver", cls);
+ }
+ cache_entry.AddProperty("target", func);
+ cache_entry.AddProperty("count", count);
+ }
+}
+
+
static Token::Kind RecognizeArithmeticOp(const String& name) {
ASSERT(name.IsSymbol());
if (name.raw() == Symbols::Plus().raw()) {
@@ -14888,7 +14963,7 @@
}
const Class& cls = Class::Handle(clazz());
Type& type = Type::Handle();
- if (cls.NumTypeArguments() == 0) {
+ if (!cls.IsGeneric()) {
type = cls.CanonicalType();
}
if (type.IsNull()) {
@@ -16149,13 +16224,20 @@
return Object::dynamic_type().raw();
}
// Fast canonical lookup/registry for simple types.
- if (cls.NumTypeArguments() == 0) {
+ if (!cls.IsGeneric()) {
type = cls.CanonicalType();
if (type.IsNull()) {
ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
- cls.set_canonical_types(*this);
- SetCanonical();
- return this->raw();
+ // Canonicalize the type arguments of the supertype, if any.
+ TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+ type_args = type_args.Canonicalize(trail);
+ set_arguments(type_args);
+ type = cls.CanonicalType(); // May be set while canonicalizing type args.
+ if (type.IsNull()) {
+ cls.set_canonical_types(*this);
+ SetCanonical();
+ return this->raw();
+ }
}
ASSERT(this->Equals(type));
ASSERT(type.IsCanonical());
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 4bf0896..b223be2 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1354,7 +1354,7 @@
// leaf method, ...).
void RegisterCHACode(const Code& code);
- void DisableCHAOptimizedCode();
+ void DisableCHAOptimizedCode(const Class& subclass);
RawArray* cha_codes() const { return raw_ptr()->cha_codes_; }
void set_cha_codes(const Array& value) const;
@@ -1748,11 +1748,20 @@
// Object holding information about an IC: test classes and their
-// corresponding targets.
+// corresponding targets. The owner of the ICData can be either the function
+// or the original ICData object. In case of background compilation we
+// copy the ICData in a child object, thus freezing it during background
+// compilation. Code may contain only original ICData objects.
class ICData : public Object {
public:
- RawFunction* owner() const {
- return raw_ptr()->owner_;
+ RawFunction* Owner() const;
+
+ RawICData* Original() const;
+
+ void SetOriginal(const ICData& value) const;
+
+ bool IsOriginal() const {
+ return Original() == this->raw();
}
RawString* target_name() const {
@@ -2017,6 +2026,9 @@
void PrintToJSONArray(const JSONArray& jsarray,
intptr_t token_pos,
bool is_static_call) const;
+ void PrintToJSONArrayNew(const JSONArray& jsarray,
+ intptr_t token_pos,
+ bool is_static_call) const;
// Initialize the preallocated empty ICData entry arrays.
static void InitOnce();
@@ -6817,7 +6829,11 @@
// An Array is raw or takes one type argument. However, its type argument
// vector may be longer than 1 due to a type optimization reusing the type
// argument vector of the instantiator.
- ASSERT(value.IsNull() || ((value.Length() >= 1) && value.IsInstantiated()));
+ ASSERT(value.IsNull() ||
+ ((value.Length() >= 1) &&
+ value.IsInstantiated() /*&& value.IsCanonical()*/));
+ // TODO(asiva): Values read from a message snapshot are not properly marked
+ // as canonical. See for example tests/isolate/mandel_isolate_test.dart.
StorePointer(&raw_ptr()->type_arguments_, value.raw());
}
@@ -6980,7 +6996,10 @@
// A GrowableObjectArray is raw or takes one type argument. However, its
// type argument vector may be longer than 1 due to a type optimization
// reusing the type argument vector of the instantiator.
- ASSERT(value.IsNull() || ((value.Length() >= 1) && value.IsInstantiated()));
+ ASSERT(value.IsNull() ||
+ ((value.Length() >= 1) &&
+ value.IsInstantiated() &&
+ value.IsCanonical()));
const Array& contents = Array::Handle(data());
contents.SetTypeArguments(value);
StorePointer(&raw_ptr()->type_arguments_, value.raw());
@@ -7528,7 +7547,11 @@
return raw_ptr()->type_arguments_;
}
virtual void SetTypeArguments(const TypeArguments& value) const {
- ASSERT(value.IsNull() || ((value.Length() >= 2) && value.IsInstantiated()));
+ ASSERT(value.IsNull() ||
+ ((value.Length() >= 2) &&
+ value.IsInstantiated() /*&& value.IsCanonical()*/));
+ // TODO(asiva): Values read from a message snapshot are not properly marked
+ // as canonical. See for example tests/isolate/message3_test.dart.
StorePointer(&raw_ptr()->type_arguments_, value.raw());
}
static intptr_t type_arguments_offset() {
@@ -7669,6 +7692,7 @@
}
static void SetTypeArguments(const Instance& closure,
const TypeArguments& value) {
+ ASSERT(value.IsNull() || value.IsCanonical());
closure.StorePointer(TypeArgumentsAddr(closure), value.raw());
}
static intptr_t type_arguments_offset() {
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 15a0021..422121e 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3023,7 +3023,7 @@
o1 = ICData::New(function, target_name, args_descriptor, id, num_args_tested);
EXPECT_EQ(1, o1.NumArgsTested());
EXPECT_EQ(id, o1.deopt_id());
- EXPECT_EQ(function.raw(), o1.owner());
+ EXPECT_EQ(function.raw(), o1.Owner());
EXPECT_EQ(0, o1.NumberOfChecks());
EXPECT_EQ(target_name.raw(), o1.target_name());
EXPECT_EQ(args_descriptor.raw(), o1.arguments_descriptor());
@@ -3062,7 +3062,7 @@
o2 = ICData::New(function, target_name, args_descriptor, 57, 2);
EXPECT_EQ(2, o2.NumArgsTested());
EXPECT_EQ(57, o2.deopt_id());
- EXPECT_EQ(function.raw(), o2.owner());
+ EXPECT_EQ(function.raw(), o2.Owner());
EXPECT_EQ(0, o2.NumberOfChecks());
GrowableArray<intptr_t> classes;
classes.Add(kSmiCid);
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index a403df2..cd570c4 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -50,6 +50,12 @@
// Returns the current time used by the tracing infrastructure.
static int64_t GetCurrentMonotonicMicros();
+ // Returns the raw clock value from the monotonic clock.
+ static int64_t GetCurrentMonotonicTicks();
+
+ // Returns the frequency of the monotonic clock.
+ static int64_t GetCurrentMonotonicFrequency();
+
// Returns a cleared aligned array of type T with n entries.
// Alignment must be >= 16 and a power of two.
template<typename T>
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 5c09baf..9dcd09e 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -179,20 +179,32 @@
}
-int64_t OS::GetCurrentMonotonicMicros() {
+int64_t OS::GetCurrentMonotonicTicks() {
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
UNREACHABLE();
return 0;
}
- // Convert to microseconds.
+ // Convert to nanoseconds.
int64_t result = ts.tv_sec;
- result *= kMicrosecondsPerSecond;
- result += (ts.tv_nsec / kNanosecondsPerMicrosecond);
+ result *= kNanosecondsPerSecond;
+ result += ts.tv_nsec;
return result;
}
+int64_t OS::GetCurrentMonotonicFrequency() {
+ return kNanosecondsPerSecond;
+}
+
+
+int64_t OS::GetCurrentMonotonicMicros() {
+ int64_t ticks = GetCurrentMonotonicTicks();
+ ASSERT(GetCurrentMonotonicFrequency() == kNanosecondsPerSecond);
+ return ticks / kNanosecondsPerMicrosecond;
+}
+
+
void* OS::AlignedAllocate(intptr_t size, intptr_t alignment) {
const int kMinimumAlignment = 16;
ASSERT(Utils::IsPowerOfTwo(alignment));
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 7924be1..244e9b7 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -396,20 +396,32 @@
}
-int64_t OS::GetCurrentMonotonicMicros() {
+int64_t OS::GetCurrentMonotonicTicks() {
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
UNREACHABLE();
return 0;
}
- // Convert to microseconds.
+ // Convert to nanoseconds.
int64_t result = ts.tv_sec;
- result *= kMicrosecondsPerSecond;
- result += (ts.tv_nsec / kNanosecondsPerMicrosecond);
+ result *= kNanosecondsPerSecond;
+ result += ts.tv_nsec;
return result;
}
+int64_t OS::GetCurrentMonotonicFrequency() {
+ return kNanosecondsPerSecond;
+}
+
+
+int64_t OS::GetCurrentMonotonicMicros() {
+ int64_t ticks = GetCurrentMonotonicTicks();
+ ASSERT(GetCurrentMonotonicFrequency() == kNanosecondsPerSecond);
+ return ticks / kNanosecondsPerMicrosecond;
+}
+
+
void* OS::AlignedAllocate(intptr_t size, intptr_t alignment) {
const int kMinimumAlignment = 16;
ASSERT(Utils::IsPowerOfTwo(alignment));
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index d2db92d..3393cb0 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -90,7 +90,10 @@
}
-int64_t OS::GetCurrentMonotonicMicros() {
+static mach_timebase_info_data_t timebase_info;
+
+
+int64_t OS::GetCurrentMonotonicTicks() {
#if TARGET_OS_IOS
// On iOS mach_absolute_time stops while the device is sleeping. Instead use
// now - KERN_BOOTTIME to get a time difference that is not impacted by clock
@@ -106,20 +109,9 @@
origin += boottime.tv_usec;
return now - origin;
#else
- static mach_timebase_info_data_t timebase_info;
- if (timebase_info.denom == 0) {
- // Zero-initialization of statics guarantees that denom will be 0 before
- // calling mach_timebase_info. mach_timebase_info will never set denom to
- // 0 as that would be invalid, so the zero-check can be used to determine
- // whether mach_timebase_info has already been called. This is
- // recommended by Apple's QA1398.
- kern_return_t kr = mach_timebase_info(&timebase_info);
- ASSERT(KERN_SUCCESS == kr);
- }
-
- // timebase_info converts absolute time tick units into nanoseconds. Convert
- // to microseconds.
- int64_t result = mach_absolute_time() / kNanosecondsPerMicrosecond;
+ ASSERT(timebase_info.denom != 0);
+ // timebase_info converts absolute time tick units into nanoseconds.
+ int64_t result = mach_absolute_time();
result *= timebase_info.numer;
result /= timebase_info.denom;
return result;
@@ -127,6 +119,26 @@
}
+int64_t OS::GetCurrentMonotonicFrequency() {
+#if TARGET_OS_IOS
+ return kMicrosecondsPerSecond;
+#else
+ return kNanosecondsPerSecond;
+#endif // TARGET_OS_IOS
+}
+
+
+int64_t OS::GetCurrentMonotonicMicros() {
+#if TARGET_OS_IOS
+ ASSERT(GetCurrentMonotonicFrequency() == kMicrosecondsPerSecond);
+ return GetCurrentMonotonicTicks();
+#else
+ ASSERT(GetCurrentMonotonicFrequency() == kNanosecondsPerSecond);
+ return GetCurrentMonotonicTicks() / kNanosecondsPerMicrosecond;
+#endif // TARGET_OS_IOS
+}
+
+
void* OS::AlignedAllocate(intptr_t size, intptr_t alignment) {
const int kMinimumAlignment = 16;
ASSERT(Utils::IsPowerOfTwo(alignment));
@@ -361,6 +373,8 @@
static bool init_once_called = false;
ASSERT(init_once_called == false);
init_once_called = true;
+ kern_return_t kr = mach_timebase_info(&timebase_info);
+ ASSERT(KERN_SUCCESS == kr);
}
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc
index 3789a60..0dcd506 100644
--- a/runtime/vm/os_thread.cc
+++ b/runtime/vm/os_thread.cc
@@ -16,6 +16,7 @@
ThreadLocalKey OSThread::thread_key_ = kUnsetThreadLocalKey;
OSThread* OSThread::thread_list_head_ = NULL;
Mutex* OSThread::thread_list_lock_ = NULL;
+bool OSThread::creation_enabled_ = false;
OSThread::OSThread() :
@@ -31,7 +32,18 @@
log_(new class Log()),
stack_base_(0),
thread_(NULL) {
- AddThreadToList(this);
+}
+
+
+OSThread* OSThread::CreateOSThread() {
+ ASSERT(thread_list_lock_ != NULL);
+ MutexLocker ml(thread_list_lock_);
+ if (!creation_enabled_) {
+ return NULL;
+ }
+ OSThread* os_thread = new OSThread();
+ AddThreadToListLocked(os_thread);
+ return os_thread;
}
@@ -92,14 +104,21 @@
thread_key_ = CreateThreadLocal(DeleteThread);
ASSERT(thread_key_ != kUnsetThreadLocalKey);
+ // Enable creation of OSThread structures in the VM.
+ EnableOSThreadCreation();
+
// Create a new OSThread strcture and set it as the TLS.
- OSThread* os_thread = new OSThread();
+ OSThread* os_thread = CreateOSThread();
+ ASSERT(os_thread != NULL);
OSThread::SetCurrent(os_thread);
os_thread->set_name("Dart_Initialize");
}
void OSThread::Cleanup() {
+ // We cannot delete the thread local key and thread list lock, yet.
+ // See the note on thread_list_lock_ in os_thread.h.
+#if 0
if (thread_list_lock_ != NULL) {
// Delete the thread local key.
ASSERT(thread_key_ != kUnsetThreadLocalKey);
@@ -111,14 +130,17 @@
delete thread_list_lock_;
thread_list_lock_ = NULL;
}
+#endif
}
OSThread* OSThread::CreateAndSetUnknownThread() {
- ASSERT(OSThread::Current() == NULL);
- OSThread* os_thread = new OSThread();
- OSThread::SetCurrent(os_thread);
- os_thread->set_name("Unknown");
+ ASSERT(OSThread::GetCurrentTLS() == NULL);
+ OSThread* os_thread = CreateOSThread();
+ if (os_thread != NULL) {
+ OSThread::SetCurrent(os_thread);
+ os_thread->set_name("Unknown");
+ }
return os_thread;
}
@@ -141,17 +163,29 @@
}
+void OSThread::DisableOSThreadCreation() {
+ MutexLocker ml(thread_list_lock_);
+ creation_enabled_ = false;
+}
+
+
+void OSThread::EnableOSThreadCreation() {
+ MutexLocker ml(thread_list_lock_);
+ creation_enabled_ = true;
+}
+
+
OSThread* OSThread::GetOSThreadFromThread(Thread* thread) {
ASSERT(thread->os_thread() != NULL);
return thread->os_thread();
}
-void OSThread::AddThreadToList(OSThread* thread) {
+void OSThread::AddThreadToListLocked(OSThread* thread) {
ASSERT(thread != NULL);
ASSERT(thread_list_lock_ != NULL);
- MutexLocker ml(thread_list_lock_);
-
+ ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
+ ASSERT(creation_enabled_);
ASSERT(thread->thread_list_next_ == NULL);
#if defined(DEBUG)
@@ -172,6 +206,7 @@
void OSThread::RemoveThreadFromList(OSThread* thread) {
+ bool final_thread = false;
{
ASSERT(thread != NULL);
ASSERT(thread_list_lock_ != NULL);
@@ -189,6 +224,7 @@
previous->thread_list_next_ = current->thread_list_next_;
}
thread->thread_list_next_ = NULL;
+ final_thread = !creation_enabled_ && (thread_list_head_ == NULL);
break;
}
previous = current;
@@ -197,7 +233,7 @@
}
// Check if this is the last thread. The last thread does a cleanup
// which removes the thread local key and the associated mutex.
- if (thread_list_head_ == NULL) {
+ if (final_thread) {
Cleanup();
}
}
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index 9371b45..84f11b6a 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -50,7 +50,10 @@
// Low-level operations on OS platform threads.
class OSThread : public BaseThread {
public:
- OSThread();
+ // The constructor of OSThread is never called directly, instead we call
+ // this factory style method 'CreateOSThread' to create OSThread structures.
+ // The method can return a NULL if the Dart VM is in shutdown mode.
+ static OSThread* CreateOSThread();
~OSThread();
ThreadId id() const {
@@ -175,12 +178,19 @@
static bool IsThreadInList(ThreadJoinId join_id);
+ static void DisableOSThreadCreation();
+ static void EnableOSThreadCreation();
+
static const intptr_t kStackSizeBuffer = (4 * KB * kWordSize);
static const ThreadId kInvalidThreadId;
static const ThreadJoinId kInvalidThreadJoinId;
private:
+ // The constructor is private as CreateOSThread should be used
+ // to create a new OSThread structure.
+ OSThread();
+
// These methods should not be used in a generic way and hence
// are private, they have been added to solve the problem of
// accessing the VM thread structure from an OSThread object
@@ -196,7 +206,7 @@
static ThreadId GetCurrentThreadTraceId();
static ThreadJoinId GetCurrentThreadJoinId();
static OSThread* GetOSThreadFromThread(Thread* thread);
- static void AddThreadToList(OSThread* thread);
+ static void AddThreadToListLocked(OSThread* thread);
static void RemoveThreadFromList(OSThread* thread);
static OSThread* CreateAndSetUnknownThread();
@@ -218,8 +228,14 @@
uword stack_base_;
Thread* thread_;
- static OSThread* thread_list_head_;
+ // thread_list_lock_ cannot have a static lifetime because the order in which
+ // destructors run is undefined. At the moment this lock cannot be deleted
+ // either since otherwise, if a thread only begins to run after we have
+ // started to run TLS destructors for a call to exit(), there will be a race
+ // on its deletion in CreateOSThread().
static Mutex* thread_list_lock_;
+ static OSThread* thread_list_head_;
+ static bool creation_enabled_;
friend class OSThreadIterator;
friend class ThreadInterrupterWin;
diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc
index 6f7ff34..c02fd9a 100644
--- a/runtime/vm/os_thread_android.cc
+++ b/runtime/vm/os_thread_android.cc
@@ -95,12 +95,14 @@
delete data;
// Create new OSThread object and set as TLS for new thread.
- OSThread* thread = new OSThread();
- OSThread::SetCurrent(thread);
- thread->set_name(name);
+ OSThread* thread = OSThread::CreateOSThread();
+ if (thread != NULL) {
+ OSThread::SetCurrent(thread);
+ thread->set_name(name);
- // Call the supplied thread start function handing it its parameters.
- function(parameter);
+ // Call the supplied thread start function handing it its parameters.
+ function(parameter);
+ }
return NULL;
}
diff --git a/runtime/vm/os_thread_linux.cc b/runtime/vm/os_thread_linux.cc
index 4a08b84..f821233 100644
--- a/runtime/vm/os_thread_linux.cc
+++ b/runtime/vm/os_thread_linux.cc
@@ -97,12 +97,14 @@
delete data;
// Create new OSThread object and set as TLS for new thread.
- OSThread* thread = new OSThread();
- OSThread::SetCurrent(thread);
- thread->set_name(name);
+ OSThread* thread = OSThread::CreateOSThread();
+ if (thread != NULL) {
+ OSThread::SetCurrent(thread);
+ thread->set_name(name);
- // Call the supplied thread start function handing it its parameters.
- function(parameter);
+ // Call the supplied thread start function handing it its parameters.
+ function(parameter);
+ }
return NULL;
}
diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc
index 2fa58d8..1964f64 100644
--- a/runtime/vm/os_thread_macos.cc
+++ b/runtime/vm/os_thread_macos.cc
@@ -88,12 +88,14 @@
delete data;
// Create new OSThread object and set as TLS for new thread.
- OSThread* thread = new OSThread();
- OSThread::SetCurrent(thread);
- thread->set_name(name);
+ OSThread* thread = OSThread::CreateOSThread();
+ if (thread != NULL) {
+ OSThread::SetCurrent(thread);
+ thread->set_name(name);
- // Call the supplied thread start function handing it its parameters.
- function(parameter);
+ // Call the supplied thread start function handing it its parameters.
+ function(parameter);
+ }
return NULL;
}
diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc
index 52fbd98..7a29d0d 100644
--- a/runtime/vm/os_thread_win.cc
+++ b/runtime/vm/os_thread_win.cc
@@ -52,12 +52,14 @@
MonitorData::GetMonitorWaitDataForThread();
// Create new OSThread object and set as TLS for new thread.
- OSThread* thread = new OSThread();
- OSThread::SetCurrent(thread);
- thread->set_name(name);
+ OSThread* thread = OSThread::CreateOSThread();
+ if (thread != NULL) {
+ OSThread::SetCurrent(thread);
+ thread->set_name(name);
- // Call the supplied thread start function handing it its parameters.
- function(parameter);
+ // Call the supplied thread start function handing it its parameters.
+ function(parameter);
+ }
// Clean up the monitor wait data for this thread.
MonitorWaitData::ThreadExit();
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index 917ee6f..1e055f4 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -123,7 +123,8 @@
static int64_t qpc_ticks_per_second = 0;
-int64_t OS::GetCurrentMonotonicMicros() {
+
+int64_t OS::GetCurrentMonotonicTicks() {
if (qpc_ticks_per_second == 0) {
// QueryPerformanceCounter not supported, fallback.
return GetCurrentTimeMicros();
@@ -131,12 +132,28 @@
// Grab performance counter value.
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
- int64_t qpc_value = static_cast<int64_t>(now.QuadPart);
+ return static_cast<int64_t>(now.QuadPart);
+}
+
+
+int64_t OS::GetCurrentMonotonicFrequency() {
+ if (qpc_ticks_per_second == 0) {
+ // QueryPerformanceCounter not supported, fallback.
+ return kMicrosecondsPerSecond;
+ }
+ return qpc_ticks_per_second;
+}
+
+
+int64_t OS::GetCurrentMonotonicMicros() {
+ int64_t ticks = GetCurrentMonotonicTicks();
+ int64_t frequency = GetCurrentMonotonicFrequency();
+
// Convert to microseconds.
- int64_t seconds = qpc_value / qpc_ticks_per_second;
- int64_t leftover_ticks = qpc_value - (seconds * qpc_ticks_per_second);
+ int64_t seconds = ticks / frequency;
+ int64_t leftover_ticks = ticks - (seconds * frequency);
int64_t result = seconds * kMicrosecondsPerSecond;
- result += ((leftover_ticks * kMicrosecondsPerSecond) / qpc_ticks_per_second);
+ result += ((leftover_ticks * kMicrosecondsPerSecond) / frequency);
return result;
}
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index 6dc7e93..5d5df0e 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -361,10 +361,10 @@
uword PageSpace::TryAllocateInternal(intptr_t size,
- HeapPage::PageType type,
- GrowthPolicy growth_policy,
- bool is_protected,
- bool is_locked) {
+ HeapPage::PageType type,
+ GrowthPolicy growth_policy,
+ bool is_protected,
+ bool is_locked) {
ASSERT(size >= kObjectAlignment);
ASSERT(Utils::IsAligned(size, kObjectAlignment));
#ifdef DEBUG
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 217354a..a0a0aec 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -48,7 +48,9 @@
DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
DEFINE_FLAG(bool, link_natives_lazily, false, "Link native calls lazily");
-DEFINE_FLAG(bool, move_super, false, "Move super initializer to end of list");
+DEFINE_FLAG(bool, move_super, true, "Move super initializer to end of list.");
+DEFINE_FLAG(bool, warn_super, false,
+ "Warning if super initializer not last in initializer list.");
DECLARE_FLAG(bool, lazy_dispatchers);
DECLARE_FLAG(bool, load_deferred_eagerly);
@@ -821,10 +823,7 @@
"ParseClass");
if (tds.enabled()) {
tds.SetNumArguments(1);
- tds.CopyArgument(
- 0,
- "class",
- const_cast<char*>(String::Handle(cls.Name()).ToCString()));
+ tds.CopyArgument(0, "class", String::Handle(cls.Name()).ToCString());
}
if (!cls.is_synthesized_class()) {
ASSERT(thread->long_jump_base()->IsSafeToJump());
@@ -945,10 +944,7 @@
Parser parser(script, parsed_function, func.token_pos());
if (tds.enabled()) {
tds.SetNumArguments(1);
- tds.CopyArgument(
- 0,
- "function",
- const_cast<char*>(String::Handle(func.name()).ToCString()));
+ tds.CopyArgument(0, "function", String::Handle(func.name()).ToCString());
}
SequenceNode* node_sequence = NULL;
switch (func.kind()) {
@@ -2816,7 +2812,9 @@
// A(x) : super(x), f = x++ { ... }
// is transformed to:
// A(x) : temp = x, f = x++, super(temp) { ... }
- ReportWarning("Super initizlizer not at end");
+ if (FLAG_warn_super) {
+ ReportWarning("Super initializer not at end");
+ }
ASSERT(super_init_index >= 0);
ArgumentListNode* ctor_args = super_init_call->arguments();
LetNode* saved_args = new(Z) LetNode(super_init_call->token_pos());
@@ -3125,7 +3123,10 @@
}
SequenceNode* init_statements = CloseBlock();
- if (is_redirecting_constructor) {
+ if (FLAG_move_super) {
+ // Ignore the phase parameter.
+ current_block_->statements->Add(init_statements);
+ } else if (is_redirecting_constructor) {
// A redirecting super constructor simply passes the phase parameter on to
// the target which executes the corresponding phase.
current_block_->statements->Add(init_statements);
@@ -3272,24 +3273,29 @@
SequenceNode* ctor_block = CloseBlock();
if (ctor_block->length() > 0) {
- // Generate guard around the constructor body code.
- LocalVariable* phase_param = LookupPhaseParameter();
- AstNode* phase_value =
- new LoadLocalNode(Scanner::kNoSourcePos, phase_param);
- AstNode* phase_check =
- new BinaryOpNode(Scanner::kNoSourcePos, Token::kBIT_AND,
- phase_value,
- new LiteralNode(Scanner::kNoSourcePos,
- Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody))));
- AstNode* comparison =
- new ComparisonNode(Scanner::kNoSourcePos,
- Token::kNE_STRICT,
- phase_check,
- new LiteralNode(body_pos,
- Smi::ZoneHandle(Smi::New(0))));
- AstNode* guarded_block_statements =
- new IfNode(Scanner::kNoSourcePos, comparison, ctor_block, NULL);
- current_block_->statements->Add(guarded_block_statements);
+ if (FLAG_move_super) {
+ // Ignore the phase parameter.
+ current_block_->statements->Add(ctor_block);
+ } else {
+ // Generate guard around the constructor body code.
+ LocalVariable* phase_param = LookupPhaseParameter();
+ AstNode* phase_value =
+ new LoadLocalNode(Scanner::kNoSourcePos, phase_param);
+ AstNode* phase_check =
+ new BinaryOpNode(Scanner::kNoSourcePos, Token::kBIT_AND,
+ phase_value,
+ new LiteralNode(Scanner::kNoSourcePos,
+ Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody))));
+ AstNode* comparison =
+ new ComparisonNode(Scanner::kNoSourcePos,
+ Token::kNE_STRICT,
+ phase_check,
+ new LiteralNode(body_pos,
+ Smi::ZoneHandle(Smi::New(0))));
+ AstNode* guarded_block_statements =
+ new IfNode(Scanner::kNoSourcePos, comparison, ctor_block, NULL);
+ current_block_->statements->Add(guarded_block_statements);
+ }
}
current_block_->statements->Add(new ReturnNode(func.end_token_pos()));
SequenceNode* statements = CloseBlock();
@@ -11196,6 +11202,26 @@
// source.
if (!FLAG_warn_on_javascript_compatibility || is_patch_source()) {
ASSERT(num_arguments == 2);
+
+ // If both arguments are constant expressions of type string,
+ // evaluate and canonicalize them.
+ // This guarantees that identical("ab", "a"+"b") is true.
+ // An alternative way to guarantee this would be to introduce
+ // an AST node that canonicalizes a value.
+ AstNode* arg0 = arguments->NodeAt(0);
+ const Instance* val0 = arg0->EvalConstExpr();
+ if ((val0 != NULL) && (val0->IsString())) {
+ AstNode* arg1 = arguments->NodeAt(1);
+ const Instance* val1 = arg1->EvalConstExpr();
+ if ((val1 != NULL) && (val1->IsString())) {
+ arguments->SetNodeAt(0,
+ new(Z) LiteralNode(arg0->token_pos(),
+ EvaluateConstExpr(arg0->token_pos(), arg0)));
+ arguments->SetNodeAt(1,
+ new(Z) LiteralNode(arg1->token_pos(),
+ EvaluateConstExpr(arg1->token_pos(), arg1)));
+ }
+ }
return new(Z) ComparisonNode(ident_pos,
Token::kEQ_STRICT,
arguments->NodeAt(0),
@@ -12052,8 +12078,10 @@
ConstantsMap constants(isolate()->object_store()->compile_time_constants());
bool is_present = false;
*value ^= constants.GetOrNull(key, &is_present);
- ASSERT(constants.Release().raw() ==
- isolate()->object_store()->compile_time_constants());
+ // Mutator compiler thread may add constants while background compiler
+ // is running , and thus change the value of 'compile_time_constants';
+ // do not assert that 'compile_time_constants' has not changed.
+ constants.Release();
if (FLAG_compiler_stats && is_present) {
isolate_->compiler_stats()->num_const_cache_hits++;
}
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 0b533f0..93d2107 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -250,8 +250,6 @@
"_JavascriptIntegerOverflowError." },
{ "dart:core", "_TypeError", "_TypeError._create" },
{ "dart:isolate", "IsolateSpawnException", "IsolateSpawnException." },
- { "dart:isolate", "_IsolateUnhandledException",
- "_IsolateUnhandledException." },
{ "dart:isolate", "::", "_getIsolateScheduleImmediateClosure" },
{ "dart:isolate", "::", "_setupHooks" },
{ "dart:isolate", "::", "_startMainIsolate" },
@@ -1087,6 +1085,7 @@
for (intptr_t j = 0; j < closures.Length(); j++) {
function ^= closures.At(j);
visitor->VisitFunction(function);
+ ASSERT(!function.HasImplicitClosureFunction());
}
}
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index ff01393..53f04b6 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -296,6 +296,18 @@
#endif
+bool SampleFilter::TimeFilterSample(Sample* sample) {
+ if ((time_origin_micros_ == -1) ||
+ (time_extent_micros_ == -1)) {
+ // No time filter passed in, always pass.
+ return true;
+ }
+ const int64_t timestamp = sample->timestamp();
+ int64_t delta = timestamp - time_origin_micros_;
+ return (delta >= 0) && (delta <= time_extent_micros_);
+}
+
+
ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate)
: SampleVisitor(isolate) {
}
@@ -1208,6 +1220,10 @@
// No frames.
continue;
}
+ if (!filter->TimeFilterSample(sample)) {
+ // Did not pass time filter.
+ continue;
+ }
if (!filter->FilterSample(sample)) {
// Did not pass filter.
continue;
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index e598e70..c755890 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -91,7 +91,15 @@
class SampleFilter : public ValueObject {
public:
- explicit SampleFilter(Isolate* isolate) : isolate_(isolate) { }
+ SampleFilter(Isolate* isolate,
+ int64_t time_origin_micros,
+ int64_t time_extent_micros)
+ : isolate_(isolate),
+ time_origin_micros_(time_origin_micros),
+ time_extent_micros_(time_extent_micros) {
+ ASSERT(time_origin_micros_ >= -1);
+ ASSERT(time_extent_micros_ >= -1);
+ }
virtual ~SampleFilter() { }
// Override this function.
@@ -104,8 +112,14 @@
return isolate_;
}
+ // Returns |true| if |sample| passes the time filter.
+ bool TimeFilterSample(Sample* sample);
+
private:
Isolate* isolate_;
+
+ int64_t time_origin_micros_;
+ int64_t time_extent_micros_;
};
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 9a0d5fc..1aba7d3 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -2304,8 +2304,12 @@
class NoAllocationSampleFilter : public SampleFilter {
public:
- explicit NoAllocationSampleFilter(Isolate* isolate)
- : SampleFilter(isolate) {
+ NoAllocationSampleFilter(Isolate* isolate,
+ int64_t time_origin_micros,
+ int64_t time_extent_micros)
+ : SampleFilter(isolate,
+ time_origin_micros,
+ time_extent_micros) {
}
bool FilterSample(Sample* sample) {
@@ -2316,10 +2320,14 @@
void ProfilerService::PrintJSON(JSONStream* stream,
Profile::TagOrder tag_order,
- intptr_t extra_tags) {
+ intptr_t extra_tags,
+ int64_t time_origin_micros,
+ int64_t time_extent_micros) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
- NoAllocationSampleFilter filter(isolate);
+ NoAllocationSampleFilter filter(isolate,
+ time_origin_micros,
+ time_extent_micros);
const bool as_timeline = false;
PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter, as_timeline);
}
@@ -2327,8 +2335,13 @@
class ClassAllocationSampleFilter : public SampleFilter {
public:
- ClassAllocationSampleFilter(Isolate* isolate, const Class& cls)
- : SampleFilter(isolate),
+ ClassAllocationSampleFilter(Isolate* isolate,
+ const Class& cls,
+ int64_t time_origin_micros,
+ int64_t time_extent_micros)
+ : SampleFilter(isolate,
+ time_origin_micros,
+ time_extent_micros),
cls_(Class::Handle(cls.raw())) {
ASSERT(!cls_.IsNull());
}
@@ -2345,20 +2358,29 @@
void ProfilerService::PrintAllocationJSON(JSONStream* stream,
Profile::TagOrder tag_order,
- const Class& cls) {
+ const Class& cls,
+ int64_t time_origin_micros,
+ int64_t time_extent_micros) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
- ClassAllocationSampleFilter filter(isolate, cls);
+ ClassAllocationSampleFilter filter(isolate,
+ cls,
+ time_origin_micros,
+ time_extent_micros);
const bool as_timeline = false;
PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline);
}
void ProfilerService::PrintTimelineJSON(JSONStream* stream,
- Profile::TagOrder tag_order) {
+ Profile::TagOrder tag_order,
+ int64_t time_origin_micros,
+ int64_t time_extent_micros) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
- NoAllocationSampleFilter filter(isolate);
+ NoAllocationSampleFilter filter(isolate,
+ time_origin_micros,
+ time_extent_micros);
const bool as_timeline = true;
PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline);
}
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index e931598..15f3f7d 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -396,14 +396,20 @@
static void PrintJSON(JSONStream* stream,
Profile::TagOrder tag_order,
- intptr_t extra_tags);
+ intptr_t extra_tags,
+ int64_t time_origin_micros,
+ int64_t time_extent_micros);
static void PrintAllocationJSON(JSONStream* stream,
Profile::TagOrder tag_order,
- const Class& cls);
+ const Class& cls,
+ int64_t time_origin_micros,
+ int64_t time_extent_micros);
static void PrintTimelineJSON(JSONStream* stream,
- Profile::TagOrder tag_order);
+ Profile::TagOrder tag_order,
+ int64_t time_origin_micros,
+ int64_t time_extent_micros);
static void ClearSamples();
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index a35da30..3533851 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -149,8 +149,13 @@
class AllocationFilter : public SampleFilter {
public:
- explicit AllocationFilter(Isolate* isolate, intptr_t cid)
- : SampleFilter(isolate),
+ AllocationFilter(Isolate* isolate,
+ intptr_t cid,
+ int64_t time_origin_micros = -1,
+ int64_t time_extent_micros = -1)
+ : SampleFilter(isolate,
+ time_origin_micros,
+ time_extent_micros),
cid_(cid),
enable_vm_ticks_(false) {
}
@@ -196,6 +201,7 @@
Library& root_library = Library::Handle();
root_library ^= Api::UnwrapHandle(lib);
+ const int64_t before_allocations_micros = Dart_TimelineGetMicros();
const Class& class_a = Class::Handle(GetClass(root_library, "A"));
EXPECT(!class_a.IsNull());
class_a.SetTraceAllocation(true);
@@ -203,14 +209,20 @@
Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
-
+ const int64_t after_allocations_micros = Dart_TimelineGetMicros();
+ const int64_t allocation_extent_micros =
+ after_allocations_micros - before_allocations_micros;
{
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile(isolate);
- AllocationFilter filter(isolate, class_a.id());
+ // Filter for the class in the time range.
+ AllocationFilter filter(isolate,
+ class_a.id(),
+ before_allocations_micros,
+ allocation_extent_micros);
profile.Build(thread, &filter, Profile::kNoTags);
// We should have 1 allocation sample.
EXPECT_EQ(1, profile.sample_count());
@@ -252,6 +264,23 @@
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(!walker.Down());
}
+
+ // Query with a time filter where no allocations occurred.
+ {
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
+ Profile profile(isolate);
+ AllocationFilter filter(isolate,
+ class_a.id(),
+ Dart_TimelineGetMicros(),
+ 16000);
+ profile.Build(thread, &filter, Profile::kNoTags);
+ // We should have no allocation samples because none occured within
+ // the specified time range.
+ EXPECT_EQ(0, profile.sample_count());
+ }
}
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index df2902c..ee5450d 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1402,10 +1402,10 @@
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->owner_);
}
- RawFunction* owner_; // Parent/calling function of this IC.
- RawString* target_name_; // Name of target function.
+ RawObject* owner_; // Parent/calling function or original IC of cloned IC.
+ RawString* target_name_; // Name of target function.
RawArray* args_descriptor_; // Arguments descriptor.
- RawArray* ic_data_; // Contains class-ids, target and count.
+ RawArray* ic_data_; // Contains class-ids, target and count.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->ic_data_);
}
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index c8c4249..4735b51 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -476,6 +476,36 @@
};
+class Int64Parameter : public MethodParameter {
+ public:
+ Int64Parameter(const char* name, bool required)
+ : MethodParameter(name, required) {
+ }
+
+ virtual bool Validate(const char* value) const {
+ if (value == NULL) {
+ return false;
+ }
+ for (const char* cp = value; *cp != '\0'; cp++) {
+ if ((*cp < '0' || *cp > '9') && (*cp != '-')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static int64_t Parse(const char* value, int64_t default_value = -1) {
+ if ((value == NULL) || (*value == '\0')) {
+ return default_value;
+ }
+ char* end_ptr = NULL;
+ int64_t result = strtoll(value, &end_ptr, 10);
+ ASSERT(*end_ptr == '\0'); // Parsed full string
+ return result;
+ }
+};
+
+
class IdParameter : public MethodParameter {
public:
IdParameter(const char* name, bool required)
@@ -2605,6 +2635,8 @@
static const MethodParameter* get_vm_timeline_params[] = {
NO_ISOLATE_PARAMETER,
+ new Int64Parameter("timeOriginMicros", false),
+ new Int64Parameter("timeExtentMicros", false),
NULL,
};
@@ -2617,7 +2649,11 @@
TimelineEventRecorder* timeline_recorder = Timeline::recorder();
// TODO(johnmccutchan): Return an error.
ASSERT(timeline_recorder != NULL);
- TimelineEventFilter filter;
+ int64_t time_origin_micros =
+ Int64Parameter::Parse(js->LookupParam("timeOriginMicros"));
+ int64_t time_extent_micros =
+ Int64Parameter::Parse(js->LookupParam("timeExtentMicros"));
+ TimelineEventFilter filter(time_origin_micros, time_extent_micros);
timeline_recorder->PrintJSON(js, &filter);
return true;
}
@@ -2733,6 +2769,8 @@
ISOLATE_PARAMETER,
new EnumParameter("tags", true, tags_enum_names),
new BoolParameter("_codeTransitionTags", false),
+ new Int64Parameter("timeOriginMicros", false),
+ new Int64Parameter("timeExtentMicros", false),
NULL,
};
@@ -2745,7 +2783,15 @@
if (BoolParameter::Parse(js->LookupParam("_codeTransitionTags"))) {
extra_tags |= ProfilerService::kCodeTransitionTagsBit;
}
- ProfilerService::PrintJSON(js, tag_order, extra_tags);
+ int64_t time_origin_micros =
+ Int64Parameter::Parse(js->LookupParam("timeOriginMicros"));
+ int64_t time_extent_micros =
+ Int64Parameter::Parse(js->LookupParam("timeExtentMicros"));
+ ProfilerService::PrintJSON(js,
+ tag_order,
+ extra_tags,
+ time_origin_micros,
+ time_extent_micros);
return true;
}
@@ -2753,6 +2799,8 @@
static const MethodParameter* get_cpu_profile_timeline_params[] = {
ISOLATE_PARAMETER,
new EnumParameter("tags", true, tags_enum_names),
+ new Int64Parameter("timeOriginMicros", false),
+ new Int64Parameter("timeExtentMicros", false),
NULL,
};
@@ -2760,7 +2808,14 @@
static bool GetCpuProfileTimeline(Thread* thread, JSONStream* js) {
Profile::TagOrder tag_order =
EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
- ProfilerService::PrintTimelineJSON(js, tag_order);
+ int64_t time_origin_micros =
+ UIntParameter::Parse(js->LookupParam("timeOriginMicros"));
+ int64_t time_extent_micros =
+ UIntParameter::Parse(js->LookupParam("timeExtentMicros"));
+ ProfilerService::PrintTimelineJSON(js,
+ tag_order,
+ time_origin_micros,
+ time_extent_micros);
return true;
}
@@ -2769,6 +2824,8 @@
ISOLATE_PARAMETER,
new EnumParameter("tags", true, tags_enum_names),
new IdParameter("classId", false),
+ new Int64Parameter("timeOriginMicros", false),
+ new Int64Parameter("timeExtentMicros", false),
NULL,
};
@@ -2776,13 +2833,21 @@
static bool GetAllocationSamples(Thread* thread, JSONStream* js) {
Profile::TagOrder tag_order =
EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values);
+ int64_t time_origin_micros =
+ Int64Parameter::Parse(js->LookupParam("timeOriginMicros"));
+ int64_t time_extent_micros =
+ Int64Parameter::Parse(js->LookupParam("timeExtentMicros"));
const char* class_id = js->LookupParam("classId");
intptr_t cid = -1;
GetPrefixedIntegerId(class_id, "classes/", &cid);
Isolate* isolate = thread->isolate();
if (IsValidClassId(isolate, cid)) {
const Class& cls = Class::Handle(GetClassForId(isolate, cid));
- ProfilerService::PrintAllocationJSON(js, tag_order, cls);
+ ProfilerService::PrintAllocationJSON(js,
+ tag_order,
+ cls,
+ time_origin_micros,
+ time_extent_micros);
} else {
PrintInvalidParamError(js, "classId");
}
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
new file mode 100644
index 0000000..242957b
--- /dev/null
+++ b/runtime/vm/source_report.cc
@@ -0,0 +1,318 @@
+// 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.
+
+#include "vm/source_report.h"
+
+#include "vm/compiler.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+
+namespace dart {
+
+SourceReport::SourceReport(ReportKind report_kind, CompileMode compile_mode)
+ : report_kind_(report_kind),
+ compile_mode_(compile_mode),
+ thread_(NULL),
+ script_(NULL),
+ start_pos_(-1),
+ end_pos_(-1),
+ next_script_index_(0) {
+}
+
+
+void SourceReport::Init(Thread* thread,
+ const Script* script,
+ intptr_t start_pos,
+ intptr_t end_pos) {
+ thread_ = thread;
+ script_ = script;
+ start_pos_ = start_pos;
+ end_pos_ = end_pos;
+ script_table_entries_.Clear();
+ script_table_.Clear();
+ next_script_index_ = 0;
+}
+
+
+bool SourceReport::ShouldSkipFunction(const Function& func) {
+ if (script_ != NULL && !script_->IsNull()) {
+ if (func.script() != script_->raw()) {
+ // The function is from the wrong script.
+ return true;
+ }
+ if (((start_pos_ > 0) && (func.end_token_pos() < start_pos_)) ||
+ ((end_pos_ > 0) && (func.token_pos() > end_pos_))) {
+ // The function does not intersect with the requested token range.
+ return true;
+ }
+ }
+
+ switch (func.kind()) {
+ case RawFunction::kRegularFunction:
+ case RawFunction::kClosureFunction:
+ case RawFunction::kGetterFunction:
+ case RawFunction::kSetterFunction:
+ case RawFunction::kConstructor:
+ break;
+ default:
+ return true;
+ }
+ if (func.is_abstract() ||
+ func.IsImplicitConstructor() ||
+ func.IsRedirectingFactory()) {
+ return true;
+ }
+ if (func.IsNonImplicitClosureFunction() &&
+ (func.context_scope() == ContextScope::null())) {
+ // TODO(iposva): This can arise if we attempt to compile an inner function
+ // before we have compiled its enclosing function or if the enclosing
+ // function failed to compile.
+ return true;
+ }
+ return false;
+}
+
+
+intptr_t SourceReport::GetScriptIndex(const Script& script) {
+ const String& url = String::Handle(zone(), script.url());
+ ScriptTableEntry* pair = script_table_.Lookup(&url);
+ if (pair != NULL) {
+ return pair->index;
+ }
+
+ ScriptTableEntry tmp;
+ tmp.key = &url;
+ tmp.index = next_script_index_++;
+ tmp.script = &script;
+ script_table_entries_.Add(tmp);
+ script_table_.Insert(&(script_table_entries_.Last()));
+ return tmp.index;
+}
+
+
+bool SourceReport::ScriptIsLoadedByLibrary(const Script& script,
+ const Library& lib) {
+ const Array& scripts = Array::Handle(zone(), lib.LoadedScripts());
+ for (intptr_t j = 0; j < scripts.Length(); j++) {
+ if (scripts.At(j) == script.raw()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void SourceReport::PrintCallSitesData(JSONObject* jsobj,
+ const Function& func,
+ const Code& code) {
+ const intptr_t begin_pos = func.token_pos();
+ const intptr_t end_pos = func.end_token_pos();
+
+ ZoneGrowableArray<const ICData*>* ic_data_array =
+ new(zone()) ZoneGrowableArray<const ICData*>();
+ func.RestoreICDataMap(ic_data_array, false /* clone descriptors */);
+ const PcDescriptors& descriptors = PcDescriptors::Handle(
+ zone(), code.pc_descriptors());
+
+ JSONArray sites(jsobj, "callSites");
+
+ PcDescriptors::Iterator iter(
+ descriptors,
+ RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall);
+ while (iter.MoveNext()) {
+ HANDLESCOPE(thread());
+ const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
+ if (!ic_data->IsNull()) {
+ const intptr_t token_pos = iter.TokenPos();
+ if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+ // Does not correspond to a valid source position.
+ continue;
+ }
+ bool is_static_call = iter.Kind() == RawPcDescriptors::kUnoptStaticCall;
+ ic_data->PrintToJSONArrayNew(sites, token_pos, is_static_call);
+ }
+ }
+}
+
+void SourceReport::PrintCoverageData(JSONObject* jsobj,
+ const Function& func,
+ const Code& code) {
+ const intptr_t begin_pos = func.token_pos();
+ const intptr_t end_pos = func.end_token_pos();
+
+ ZoneGrowableArray<const ICData*>* ic_data_array =
+ new(zone()) ZoneGrowableArray<const ICData*>();
+ func.RestoreICDataMap(ic_data_array, false /* clone descriptors */);
+ const PcDescriptors& descriptors = PcDescriptors::Handle(
+ zone(), code.pc_descriptors());
+
+ const int kCoverageNone = 0;
+ const int kCoverageMiss = 1;
+ const int kCoverageHit = 2;
+
+ intptr_t func_length = (end_pos - begin_pos) + 1;
+ GrowableArray<char> coverage(func_length);
+ coverage.SetLength(func_length);
+ for (int i = 0; i < func_length; i++) {
+ coverage[i] = kCoverageNone;
+ }
+
+ PcDescriptors::Iterator iter(
+ descriptors,
+ RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall);
+ while (iter.MoveNext()) {
+ HANDLESCOPE(thread());
+ const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
+ if (!ic_data->IsNull()) {
+ const intptr_t token_pos = iter.TokenPos();
+ if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+ // Does not correspond to a valid source position.
+ continue;
+ }
+ intptr_t count = ic_data->AggregateCount();
+ intptr_t token_offset = token_pos - begin_pos;
+ if (count > 0) {
+ coverage[token_offset] = kCoverageHit;
+ } else {
+ if (coverage[token_offset] == kCoverageNone) {
+ coverage[token_offset] = kCoverageMiss;
+ }
+ }
+ }
+ }
+
+ JSONObject cov(jsobj, "coverage");
+ {
+ JSONArray hits(&cov, "hits");
+ for (int i = 0; i < func_length; i++) {
+ if (coverage[i] == kCoverageHit) {
+ hits.AddValue(begin_pos + i); // Add the token position of the hit.
+ }
+ }
+ }
+ {
+ JSONArray misses(&cov, "misses");
+ for (int i = 0; i < func_length; i++) {
+ if (coverage[i] == kCoverageMiss) {
+ misses.AddValue(begin_pos + i); // Add the token position of the miss.
+ }
+ }
+ }
+}
+
+
+void SourceReport::PrintScriptTable(JSONArray* scripts) {
+ for (int i = 0; i < script_table_entries_.length(); i++) {
+ const Script* script = script_table_entries_[i].script;
+ scripts->AddValue(*script);
+ }
+}
+
+
+void SourceReport::VisitFunction(JSONArray* jsarr, const Function& func) {
+ if (ShouldSkipFunction(func)) {
+ return;
+ }
+
+ const Script& script = Script::Handle(zone(), func.script());
+ const intptr_t begin_pos = func.token_pos();
+ const intptr_t end_pos = func.end_token_pos();
+
+ Code& code = Code::Handle(zone(), func.unoptimized_code());
+ if (code.IsNull()) {
+ if (func.HasCode() || (compile_mode_ == kForceCompile)) {
+ if (Compiler::EnsureUnoptimizedCode(thread(), func) != Error::null()) {
+ // Ignore the error and this function entirely.
+ return;
+ }
+ code = func.unoptimized_code();
+ } else {
+ // This function has not been compiled yet.
+ JSONObject range(jsarr);
+ range.AddProperty("scriptIndex", GetScriptIndex(script));
+ range.AddProperty("startPos", begin_pos);
+ range.AddProperty("endPos", end_pos);
+ range.AddProperty("compiled", false);
+ return;
+ }
+ }
+ ASSERT(!code.IsNull());
+
+ JSONObject range(jsarr);
+ range.AddProperty("scriptIndex", GetScriptIndex(script));
+ range.AddProperty("startPos", begin_pos);
+ range.AddProperty("endPos", end_pos);
+ range.AddProperty("compiled", true);
+
+ if (report_kind_ == kCallSites) {
+ PrintCallSitesData(&range, func, code);
+ } else if (report_kind_ == kCoverage) {
+ PrintCoverageData(&range, func, code);
+ }
+}
+
+
+void SourceReport::VisitLibrary(JSONArray* jsarr, const Library& lib) {
+ Class& cls = Class::Handle(zone());
+ Array& functions = Array::Handle(zone());
+ Function& func = Function::Handle(zone());
+ ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+ while (it.HasNext()) {
+ cls = it.GetNextClass();
+ functions = cls.functions();
+ for (int i = 0; i < functions.Length(); i++) {
+ func ^= functions.At(i);
+ VisitFunction(jsarr, func);
+ }
+ }
+}
+
+
+void SourceReport::VisitClosures(JSONArray* jsarr) {
+ const GrowableObjectArray& closures = GrowableObjectArray::Handle(
+ thread()->isolate()->object_store()->closure_functions());
+
+ // We need to keep rechecking the length of the closures array, as handling
+ // a closure potentially adds new entries to the end.
+ Function& func = Function::Handle(zone());
+ for (int i = 0; i < closures.Length(); i++) {
+ func ^= closures.At(i);
+ VisitFunction(jsarr, func);
+ }
+}
+
+
+void SourceReport::PrintJSON(JSONStream* js,
+ const Script& script,
+ intptr_t start_pos, intptr_t end_pos) {
+ Init(Thread::Current(), &script, start_pos, end_pos);
+
+ JSONObject report(js);
+ report.AddProperty("type", "SourceReport");
+ {
+ JSONArray ranges(&report, "ranges");
+
+ const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+ zone(), thread()->isolate()->object_store()->libraries());
+
+ // We only visit the libraries which actually load the specified script.
+ Library& lib = Library::Handle(zone());
+ for (int i = 0; i < libs.Length(); i++) {
+ lib ^= libs.At(i);
+ if (script.IsNull() || ScriptIsLoadedByLibrary(script, lib)) {
+ VisitLibrary(&ranges, lib);
+ }
+ }
+
+ // Visit all closures for this isolate.
+ VisitClosures(&ranges);
+ }
+
+ // Print the script table.
+ JSONArray scripts(&report, "scripts");
+ PrintScriptTable(&scripts);
+}
+
+
+} // namespace dart
diff --git a/runtime/vm/source_report.h b/runtime/vm/source_report.h
new file mode 100644
index 0000000..69529d3
--- /dev/null
+++ b/runtime/vm/source_report.h
@@ -0,0 +1,106 @@
+// 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.
+
+#ifndef VM_SOURCE_REPORT_H_
+#define VM_SOURCE_REPORT_H_
+
+#include "vm/allocation.h"
+#include "vm/flags.h"
+#include "vm/hash_map.h"
+#include "vm/object.h"
+
+namespace dart {
+
+// A SourceReport object is used to generate reports about the program
+// source code, with information associated with source token
+// positions. There are multiple possible kinds of reports.
+class SourceReport {
+ public:
+ enum ReportKind {
+ kCallSites,
+ kCoverage,
+ };
+
+ enum CompileMode {
+ kNoCompile,
+ kForceCompile
+ };
+
+ explicit SourceReport(ReportKind report_kind,
+ CompileMode compile = kNoCompile);
+
+ // Generate a source report for (some subrange of) a script.
+ //
+ // If script is null, then the report is generated for all scripts
+ // in the isolate.
+ void PrintJSON(JSONStream* js, const Script& script,
+ intptr_t start_pos = -1, intptr_t end_pos = -1);
+
+ private:
+ void Init(Thread* thread, const Script* script,
+ intptr_t start_pos, intptr_t end_pos);
+
+ Thread* thread() const { return thread_; }
+ Zone* zone() const { return thread_->zone(); }
+
+ bool ShouldSkipFunction(const Function& func);
+ intptr_t GetScriptIndex(const Script& script);
+ bool ScriptIsLoadedByLibrary(const Script& script, const Library& lib);
+
+ void PrintCallSitesData(JSONObject* jsobj,
+ const Function& func, const Code& code);
+ void PrintCoverageData(JSONObject* jsobj,
+ const Function& func, const Code& code);
+ void PrintScriptTable(JSONArray* jsarr);
+
+ void VisitFunction(JSONArray* jsarr, const Function& func);
+ void VisitLibrary(JSONArray* jsarr, const Library& lib);
+ void VisitClosures(JSONArray* jsarr);
+
+ // An entry in the script table.
+ struct ScriptTableEntry {
+ ScriptTableEntry() : key(NULL), index(-1), script(NULL) {}
+
+ const String* key;
+ intptr_t index;
+ const Script* script;
+ };
+
+ // Needed for DirectChainedHashMap.
+ struct ScriptTableTrait {
+ typedef ScriptTableEntry* Value;
+ typedef const String* Key;
+ typedef ScriptTableEntry* Pair;
+
+ static Key KeyOf(Pair kv) {
+ return kv->key;
+ }
+
+ static Value ValueOf(Pair kv) {
+ return kv;
+ }
+
+ static inline intptr_t Hashcode(Key key) {
+ return key->Hash();
+ }
+
+ static inline bool IsKeyEqual(Pair kv, Key key) {
+ return kv->key->Equals(*key);
+ }
+ };
+
+ ReportKind report_kind_;
+ CompileMode compile_mode_;
+ Thread* thread_;
+ const Script* script_;
+ intptr_t start_pos_;
+ intptr_t end_pos_;
+ GrowableArray<ScriptTableEntry> script_table_entries_;
+ DirectChainedHashMap<ScriptTableTrait> script_table_;
+ intptr_t next_script_index_;
+};
+
+} // namespace dart
+
+#endif // VM_SOURCE_REPORT_H_
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
new file mode 100644
index 0000000..075ac36
--- /dev/null
+++ b/runtime/vm/source_report_test.cc
@@ -0,0 +1,412 @@
+// 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.
+
+#include "vm/source_report.h"
+#include "vm/dart_api_impl.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+static RawObject* ExecuteScript(const char* script) {
+ Dart_Handle h_lib = TestCase::LoadTestScript(script, NULL);
+ EXPECT_VALID(h_lib);
+ Library& lib = Library::Handle();
+ lib ^= Api::UnwrapHandle(h_lib);
+ EXPECT(!lib.IsNull());
+ Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
+ EXPECT_VALID(result);
+ return Api::UnwrapHandle(h_lib);
+}
+
+
+TEST_CASE(SourceReport_Coverage_NoCalls) {
+ char buffer[1024];
+ const char* kScript =
+ "main() {\n"
+ "}";
+
+ Library& lib = Library::Handle();
+ lib ^= ExecuteScript(kScript);
+ ASSERT(!lib.IsNull());
+ const Script& script = Script::Handle(lib.LookupScript(
+ String::Handle(String::New("test-lib"))));
+
+ SourceReport report(SourceReport::kCoverage);
+ JSONStream js;
+ report.PrintJSON(&js, script);
+ ElideJSONSubstring("libraries", js.ToCString(), buffer);
+ EXPECT_STREQ(
+ "{\"type\":\"SourceReport\",\"ranges\":"
+
+ // One compiled range, no hits or misses.
+ "[{\"scriptIndex\":0,\"startPos\":0,\"endPos\":5,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[],\"misses\":[]}}],"
+
+ // One script in the script table.
+ "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+ "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+ buffer);
+}
+
+
+TEST_CASE(SourceReport_Coverage_SimpleCall) {
+ char buffer[1024];
+ const char* kScript =
+ "helper0() {}\n"
+ "helper1() {}\n"
+ "main() {\n"
+ " if (true) {\n"
+ " helper0();\n"
+ " } else {\n"
+ " helper1();\n"
+ " }\n"
+ "}";
+
+ Library& lib = Library::Handle();
+ lib ^= ExecuteScript(kScript);
+ ASSERT(!lib.IsNull());
+ const Script& script = Script::Handle(lib.LookupScript(
+ String::Handle(String::New("test-lib"))));
+
+ SourceReport report(SourceReport::kCoverage);
+ JSONStream js;
+ report.PrintJSON(&js, script);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("libraries", buffer, buffer);
+ EXPECT_STREQ(
+ "{\"type\":\"SourceReport\",\"ranges\":["
+
+ // One range compiled with no hits or misses (helper0).
+ "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":4,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[],\"misses\":[]}},"
+
+ // One range not compiled (helper1).
+ "{\"scriptIndex\":0,\"startPos\":6,\"endPos\":10,\"compiled\":false},"
+
+ // One range with a hit and a miss (main).
+ "{\"scriptIndex\":0,\"startPos\":12,\"endPos\":39,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[23],\"misses\":[32]}}],"
+
+ // Only one script in the script table.
+ "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+ "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+ buffer);
+}
+
+
+TEST_CASE(SourceReport_Coverage_ForceCompile) {
+ char buffer[1024];
+ const char* kScript =
+ "helper0() {}\n"
+ "helper1() {}\n"
+ "main() {\n"
+ " if (true) {\n"
+ " helper0();\n"
+ " } else {\n"
+ " helper1();\n"
+ " }\n"
+ "}";
+
+ Library& lib = Library::Handle();
+ lib ^= ExecuteScript(kScript);
+ ASSERT(!lib.IsNull());
+ const Script& script = Script::Handle(lib.LookupScript(
+ String::Handle(String::New("test-lib"))));
+
+ SourceReport report(SourceReport::kCoverage, SourceReport::kForceCompile);
+ JSONStream js;
+ report.PrintJSON(&js, script);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("libraries", buffer, buffer);
+ EXPECT_STREQ(
+ "{\"type\":\"SourceReport\",\"ranges\":["
+
+ // One range compiled with no hits or misses (helper0).
+ "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":4,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[],\"misses\":[]}},"
+
+ // This range is compiled even though it wasn't called (helper1).
+ "{\"scriptIndex\":0,\"startPos\":6,\"endPos\":10,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[],\"misses\":[]}},"
+
+ // One range with a hit and a miss (main).
+ "{\"scriptIndex\":0,\"startPos\":12,\"endPos\":39,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[23],\"misses\":[32]}}],"
+
+ // Only one script in the script table.
+ "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+ "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+ buffer);
+}
+
+
+TEST_CASE(SourceReport_Coverage_NestedFunctions) {
+ char buffer[1024];
+ const char* kScript =
+ "helper0() {\n"
+ " nestedHelper0() {}\n"
+ " nestedHelper1() {}\n"
+ " nestedHelper0();\n"
+ "}\n"
+ "helper1() {}\n"
+ "main() {\n"
+ " if (true) {\n"
+ " helper0();\n"
+ " } else {\n"
+ " helper1();\n"
+ " }\n"
+ "}";
+
+ Library& lib = Library::Handle();
+ lib ^= ExecuteScript(kScript);
+ ASSERT(!lib.IsNull());
+ const Script& script = Script::Handle(lib.LookupScript(
+ String::Handle(String::New("test-lib"))));
+
+ SourceReport report(SourceReport::kCoverage);
+ JSONStream js;
+ report.PrintJSON(&js, script);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("libraries", buffer, buffer);
+ EXPECT_STREQ(
+ "{\"type\":\"SourceReport\",\"ranges\":["
+
+ // One range compiled with one hit (helper0).
+ "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":22,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[18],\"misses\":[]}},"
+
+ // One range not compiled (helper1).
+ "{\"scriptIndex\":0,\"startPos\":24,\"endPos\":28,\"compiled\":false},"
+
+ // One range with a hit and a miss (main).
+ "{\"scriptIndex\":0,\"startPos\":30,\"endPos\":57,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[41],\"misses\":[50]}},"
+
+ // Nested range compiled (nestedHelper0).
+ "{\"scriptIndex\":0,\"startPos\":5,\"endPos\":9,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[],\"misses\":[]}},"
+
+ // Nested range not compiled (nestedHelper1).
+ "{\"scriptIndex\":0,\"startPos\":11,\"endPos\":15,\"compiled\":false}],"
+
+ // Only one script in the script table.
+ "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+ "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+ buffer);
+}
+
+
+TEST_CASE(SourceReport_Coverage_RestrictedRange) {
+ char buffer[1024];
+ const char* kScript =
+ "helper0() {\n"
+ " nestedHelper0() {}\n"
+ " nestedHelper1() {}\n"
+ " nestedHelper0();\n"
+ "}\n"
+ "helper1() {}\n"
+ "main() {\n"
+ " if (true) {\n"
+ " helper0();\n"
+ " } else {\n"
+ " helper1();\n"
+ " }\n"
+ "}";
+
+ Library& lib = Library::Handle();
+ lib ^= ExecuteScript(kScript);
+ ASSERT(!lib.IsNull());
+ const Script& script = Script::Handle(lib.LookupScript(
+ String::Handle(String::New("test-lib"))));
+ const Function& helper = Function::Handle(
+ lib.LookupLocalFunction(String::Handle(String::New("helper0"))));
+
+ SourceReport report(SourceReport::kCoverage);
+ JSONStream js;
+ // Restrict the report to only helper0 and it's nested functions.
+ report.PrintJSON(&js, script, helper.token_pos(), helper.end_token_pos());
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("libraries", buffer, buffer);
+ EXPECT_STREQ(
+ "{\"type\":\"SourceReport\",\"ranges\":["
+
+ // One range compiled with one hit (helper0).
+ "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":22,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[18],\"misses\":[]}},"
+
+ // Nested range compiled (nestedHelper0).
+ "{\"scriptIndex\":0,\"startPos\":5,\"endPos\":9,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[],\"misses\":[]}},"
+
+ // Nested range not compiled (nestedHelper1).
+ "{\"scriptIndex\":0,\"startPos\":11,\"endPos\":15,\"compiled\":false}],"
+
+ // Only one script in the script table.
+ "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+ "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+ buffer);
+}
+
+
+TEST_CASE(SourceReport_Coverage_AllFunctions) {
+ const char* kScript =
+ "helper0() {}\n"
+ "helper1() {}\n"
+ "main() {\n"
+ " if (true) {\n"
+ " helper0();\n"
+ " } else {\n"
+ " helper1();\n"
+ " }\n"
+ "}";
+
+ Library& lib = Library::Handle();
+ lib ^= ExecuteScript(kScript);
+ ASSERT(!lib.IsNull());
+
+ SourceReport report(SourceReport::kCoverage);
+ JSONStream js;
+
+ // We generate a report with all functions in the VM.
+ Script& null_script = Script::Handle();
+ report.PrintJSON(&js, null_script);
+ const char* result = js.ToCString();
+
+ // Sanity check the header.
+ EXPECT_SUBSTRING("{\"type\":\"SourceReport\",\"ranges\":[", result);
+
+ // Make sure that the main function was found.
+ EXPECT_SUBSTRING(
+ "\"startPos\":12,\"endPos\":39,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[23],\"misses\":[32]}",
+ result);
+
+ // More than one script is referenced in the report.
+ EXPECT_SUBSTRING("\"scriptIndex\":0", result);
+ EXPECT_SUBSTRING("\"scriptIndex\":1", result);
+ EXPECT_SUBSTRING("\"scriptIndex\":2", result);
+}
+
+
+TEST_CASE(SourceReport_CallSites_SimpleCall) {
+ char buffer[1024];
+ const char* kScript =
+ "helper0() {}\n"
+ "helper1() {}\n"
+ "main() {\n"
+ " helper0();\n"
+ "}";
+
+ Library& lib = Library::Handle();
+ lib ^= ExecuteScript(kScript);
+ ASSERT(!lib.IsNull());
+ const Script& script = Script::Handle(lib.LookupScript(
+ String::Handle(String::New("test-lib"))));
+
+ SourceReport report(SourceReport::kCallSites);
+ JSONStream js;
+ report.PrintJSON(&js, script);
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("libraries", buffer, buffer);
+ EXPECT_STREQ(
+ "{\"type\":\"SourceReport\",\"ranges\":["
+
+ // One range compiled with no callsites (helper0).
+ "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":4,\"compiled\":true,"
+ "\"callSites\":[]},"
+
+ // One range not compiled (helper1).
+ "{\"scriptIndex\":0,\"startPos\":6,\"endPos\":10,\"compiled\":false},"
+
+ // One range compiled with one callsite (main).
+ "{\"scriptIndex\":0,\"startPos\":12,\"endPos\":22,\"compiled\":true,"
+ "\"callSites\":["
+ "{\"name\":\"helper0\",\"tokenPos\":17,\"cacheEntries\":["
+ "{\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
+ "\"id\":\"\",\"name\":\"\",\"uri\":\"test-lib\"},"
+ "\"_kind\":\"RegularFunction\",\"static\":true,\"const\":false,"
+ "\"_intrinsic\":false,\"_native\":false},\"count\":1}]}]}],"
+
+ // One script in the script table.
+ "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+ "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+ buffer);
+}
+
+TEST_CASE(SourceReport_CallSites_PolymorphicCall) {
+ char buffer[1024];
+ const char* kScript =
+ "class Common {\n"
+ " func() {}\n"
+ "}\n"
+ "class Uncommon {\n"
+ " func() {}\n"
+ "}\n"
+ "helper(arg) {\n"
+ " arg.func();\n"
+ "}\n"
+ "main() {\n"
+ " Common common = new Common();\n"
+ " Uncommon uncommon = new Uncommon();\n"
+ " helper(common);\n"
+ " helper(common);\n"
+ " helper(uncommon);\n"
+ "}";
+
+ Library& lib = Library::Handle();
+ lib ^= ExecuteScript(kScript);
+ ASSERT(!lib.IsNull());
+ const Script& script = Script::Handle(lib.LookupScript(
+ String::Handle(String::New("test-lib"))));
+ const Function& helper = Function::Handle(
+ lib.LookupLocalFunction(String::Handle(String::New("helper"))));
+
+ SourceReport report(SourceReport::kCallSites);
+ JSONStream js;
+ report.PrintJSON(&js, script, helper.token_pos(), helper.end_token_pos());
+ ElideJSONSubstring("classes", js.ToCString(), buffer);
+ ElideJSONSubstring("libraries", buffer, buffer);
+ EXPECT_STREQ(
+ "{\"type\":\"SourceReport\",\"ranges\":["
+
+ // One range...
+ "{\"scriptIndex\":0,\"startPos\":24,\"endPos\":37,\"compiled\":true,"
+
+ // With one call site...
+ "\"callSites\":[{\"name\":\"func\",\"tokenPos\":32,\"cacheEntries\":["
+
+ // First receiver: "Common", called twice.
+ "{\"receiver\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"Common\"},"
+
+ "\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"func\","
+ "\"owner\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"Common\"},\"_kind\":\"RegularFunction\","
+ "\"static\":false,\"const\":false,\"_intrinsic\":false,"
+ "\"_native\":false},"
+
+ "\"count\":2},"
+
+ // Second receiver: "Uncommon", called once.
+ "{\"receiver\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"Uncommon\"},"
+
+ "\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"func\","
+ "\"owner\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"Uncommon\"},\"_kind\":\"RegularFunction\","
+ "\"static\":false,\"const\":false,\"_intrinsic\":false,"
+ "\"_native\":false},"
+
+ "\"count\":1}]}]}],"
+
+ // One script in the script table.
+ "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+ "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+ buffer);
+}
+
+} // namespace dart
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index d59ea20a..310660d 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -305,7 +305,6 @@
V(OutOfMemoryError, "OutOfMemoryError") \
V(NullThrownError, "NullThrownError") \
V(IsolateSpawnException, "IsolateSpawnException") \
- V(IsolateUnhandledException, "_IsolateUnhandledException") \
V(JavascriptIntegerOverflowError, "_JavascriptIntegerOverflowError") \
V(JavascriptCompatibilityError, "_JavascriptCompatibilityError") \
V(BooleanExpression, "boolean expression") \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 134b759..2357ce6 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -172,16 +172,20 @@
}
-void Thread::EnterIsolate(Isolate* isolate) {
+bool Thread::EnterIsolate(Isolate* isolate) {
const bool kIsMutatorThread = true;
const bool kDontBypassSafepoints = false;
ThreadRegistry* tr = isolate->thread_registry();
Thread* thread = tr->Schedule(
isolate, kIsMutatorThread, kDontBypassSafepoints);
- isolate->MakeCurrentThreadMutator(thread);
- thread->set_vm_tag(VMTag::kVMTagId);
- ASSERT(thread->store_buffer_block_ == NULL);
- thread->StoreBufferAcquire();
+ if (thread != NULL) {
+ isolate->MakeCurrentThreadMutator(thread);
+ thread->set_vm_tag(VMTag::kVMTagId);
+ ASSERT(thread->store_buffer_block_ == NULL);
+ thread->StoreBufferAcquire();
+ return true;
+ }
+ return false;
}
@@ -210,16 +214,21 @@
}
-void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
+bool Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
const bool kIsNotMutatorThread = false;
ThreadRegistry* tr = isolate->thread_registry();
Thread* thread = tr->Schedule(isolate, kIsNotMutatorThread, bypass_safepoint);
- ASSERT(thread->store_buffer_block_ == NULL);
- // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge.
- thread->store_buffer_block_ =
- thread->isolate()->store_buffer()->PopEmptyBlock();
- // This thread should not be the main mutator.
- ASSERT(!thread->IsMutatorThread());
+ if (thread != NULL) {
+ ASSERT(thread->store_buffer_block_ == NULL);
+ // TODO(koda): Use StoreBufferAcquire once we properly flush
+ // before Scavenge.
+ thread->store_buffer_block_ =
+ thread->isolate()->store_buffer()->PopEmptyBlock();
+ // This thread should not be the main mutator.
+ ASSERT(!thread->IsMutatorThread());
+ return true;
+ }
+ return false;
}
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 281ac84..f85be7b 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -122,7 +122,7 @@
}
// Makes the current thread enter 'isolate'.
- static void EnterIsolate(Isolate* isolate);
+ static bool EnterIsolate(Isolate* isolate);
// Makes the current thread exit its isolate.
static void ExitIsolate();
@@ -130,7 +130,7 @@
// "helper" to gain limited concurrent access to the isolate. One example is
// SweeperTask (which uses the class table, which is copy-on-write).
// TODO(koda): Properly synchronize heap access to expand allowed operations.
- static void EnterIsolateAsHelper(Isolate* isolate,
+ static bool EnterIsolateAsHelper(Isolate* isolate,
bool bypass_safepoint = false);
static void ExitIsolateAsHelper(bool bypass_safepoint = false);
diff --git a/runtime/vm/thread_pool.cc b/runtime/vm/thread_pool.cc
index 86d2f60..19c0a4d 100644
--- a/runtime/vm/thread_pool.cc
+++ b/runtime/vm/thread_pool.cc
@@ -258,6 +258,7 @@
// Only call while holding the exit_monitor_
void ThreadPool::AddWorkerToShutdownList(Worker* worker) {
+ ASSERT(exit_monitor_.IsOwnedByCurrentThread());
worker->shutdown_next_ = shutting_down_workers_;
shutting_down_workers_ = worker;
}
@@ -267,6 +268,7 @@
bool ThreadPool::RemoveWorkerFromShutdownList(Worker* worker) {
ASSERT(worker != NULL);
ASSERT(shutting_down_workers_ != NULL);
+ ASSERT(exit_monitor_.IsOwnedByCurrentThread());
// Special case head of list.
if (shutting_down_workers_ == worker) {
diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc
index 5148808..2d2dee3 100644
--- a/runtime/vm/thread_registry.cc
+++ b/runtime/vm/thread_registry.cc
@@ -75,28 +75,29 @@
}
Thread* thread = NULL;
OSThread* os_thread = OSThread::Current();
- ASSERT(os_thread != NULL);
- ASSERT(isolate->heap() != NULL);
- // First get a Thread structure. (we special case the mutator thread
- // by reusing the cached structure, see comment in 'thread_registry.h').
- if (is_mutator) {
- if (mutator_thread_ == NULL) {
- mutator_thread_ = GetThreadFromFreelist(isolate);
+ if (os_thread != NULL) {
+ ASSERT(isolate->heap() != NULL);
+ // First get a Thread structure. (we special case the mutator thread
+ // by reusing the cached structure, see comment in 'thread_registry.h').
+ if (is_mutator) {
+ if (mutator_thread_ == NULL) {
+ mutator_thread_ = GetThreadFromFreelist(isolate);
+ }
+ thread = mutator_thread_;
+ } else {
+ thread = GetThreadFromFreelist(isolate);
+ ASSERT(thread->api_top_scope() == NULL);
}
- thread = mutator_thread_;
- } else {
- thread = GetThreadFromFreelist(isolate);
- ASSERT(thread->api_top_scope() == NULL);
+ // Now add this Thread to the active list for the isolate.
+ AddThreadToActiveList(thread);
+ // Set up other values and set the TLS value.
+ thread->isolate_ = isolate;
+ thread->heap_ = isolate->heap();
+ thread->set_os_thread(os_thread);
+ os_thread->set_thread(thread);
+ Thread::SetCurrent(thread);
+ os_thread->EnableThreadInterrupts();
}
- // Now add this Thread to the active list for the isolate.
- AddThreadToActiveList(thread);
- // Set up other values and set the TLS value.
- thread->isolate_ = isolate;
- thread->heap_ = isolate->heap();
- thread->set_os_thread(os_thread);
- os_thread->set_thread(thread);
- Thread::SetCurrent(thread);
- os_thread->EnableThreadInterrupts();
return thread;
}
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index ab28bee..64c7127 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -200,47 +200,53 @@
}
-void TimelineEvent::AsyncBegin(const char* label, int64_t async_id) {
+void TimelineEvent::AsyncBegin(const char* label,
+ int64_t async_id,
+ int64_t micros) {
Init(kAsyncBegin, label);
- set_timestamp0(OS::GetCurrentMonotonicMicros());
+ set_timestamp0(micros);
// Overload timestamp1_ with the async_id.
set_timestamp1(async_id);
}
void TimelineEvent::AsyncInstant(const char* label,
- int64_t async_id) {
+ int64_t async_id,
+ int64_t micros) {
Init(kAsyncInstant, label);
- set_timestamp0(OS::GetCurrentMonotonicMicros());
+ set_timestamp0(micros);
// Overload timestamp1_ with the async_id.
set_timestamp1(async_id);
}
void TimelineEvent::AsyncEnd(const char* label,
- int64_t async_id) {
+ int64_t async_id,
+ int64_t micros) {
Init(kAsyncEnd, label);
- set_timestamp0(OS::GetCurrentMonotonicMicros());
+ set_timestamp0(micros);
// Overload timestamp1_ with the async_id.
set_timestamp1(async_id);
}
-void TimelineEvent::DurationBegin(const char* label) {
+void TimelineEvent::DurationBegin(const char* label,
+ int64_t micros) {
Init(kDuration, label);
- set_timestamp0(OS::GetCurrentMonotonicMicros());
+ set_timestamp0(micros);
}
-void TimelineEvent::DurationEnd() {
+void TimelineEvent::DurationEnd(int64_t micros) {
ASSERT(timestamp1_ == 0);
- set_timestamp1(OS::GetCurrentMonotonicMicros());
+ set_timestamp1(micros);
}
-void TimelineEvent::Instant(const char* label) {
+void TimelineEvent::Instant(const char* label,
+ int64_t micros) {
Init(kInstant, label);
- set_timestamp0(OS::GetCurrentMonotonicMicros());
+ set_timestamp0(micros);
}
@@ -267,10 +273,11 @@
}
-void TimelineEvent::SerializedJSON(const char* json) {
- Init(kSerializedJSON, "Dart");
+void TimelineEvent::CompleteWithPreSerializedJSON(const char* json) {
+ set_pre_serialized_json(true);
SetNumArguments(1);
CopyArgument(0, "Dart", json);
+ Complete();
}
@@ -378,8 +385,31 @@
}
+bool TimelineEvent::Within(int64_t time_origin_micros,
+ int64_t time_extent_micros) {
+ if ((time_origin_micros == -1) ||
+ (time_extent_micros == -1)) {
+ // No time range specified.
+ return true;
+ }
+ if (IsFinishedDuration()) {
+ // Event is from e_t0 to e_t1.
+ int64_t e_t0 = TimeOrigin();
+ int64_t e_t1 = TimeEnd();
+ ASSERT(e_t0 <= e_t1);
+ // Range is from r_t0 to r_t1.
+ int64_t r_t0 = time_origin_micros;
+ int64_t r_t1 = time_origin_micros + time_extent_micros;
+ ASSERT(r_t0 <= r_t1);
+ return !((r_t1 < e_t0) || (e_t1 < r_t0));
+ }
+ int64_t delta = TimeOrigin() - time_origin_micros;
+ return (delta >= 0) && (delta <= time_extent_micros);
+}
+
+
const char* TimelineEvent::GetSerializedJSON() const {
- ASSERT(event_type() == kSerializedJSON);
+ ASSERT(pre_serialized_json());
ASSERT(arguments_length_ == 1);
ASSERT(arguments_ != NULL);
return arguments_[0].value;
@@ -387,7 +417,7 @@
void TimelineEvent::PrintJSON(JSONStream* stream) const {
- if (event_type() == kSerializedJSON) {
+ if (pre_serialized_json()) {
// Event has already been serialized into JSON- just append the
// raw data.
stream->AppendSerializedObject(GetSerializedJSON());
@@ -714,7 +744,12 @@
}
-TimelineEventFilter::TimelineEventFilter() {
+TimelineEventFilter::TimelineEventFilter(int64_t time_origin_micros,
+ int64_t time_extent_micros)
+ : time_origin_micros_(time_origin_micros),
+ time_extent_micros_(time_extent_micros) {
+ ASSERT(time_origin_micros_ >= -1);
+ ASSERT(time_extent_micros_ >= -1);
}
@@ -722,8 +757,13 @@
}
-IsolateTimelineEventFilter::IsolateTimelineEventFilter(Dart_Port isolate_id)
- : isolate_id_(isolate_id) {
+IsolateTimelineEventFilter::IsolateTimelineEventFilter(
+ Dart_Port isolate_id,
+ int64_t time_origin_micros,
+ int64_t time_extent_micros)
+ : TimelineEventFilter(time_origin_micros,
+ time_extent_micros),
+ isolate_id_(isolate_id) {
}
@@ -937,7 +977,9 @@
}
for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) {
TimelineEvent* event = block->At(event_idx);
- if (filter->IncludeEvent(event)) {
+ if (filter->IncludeEvent(event) &&
+ event->Within(filter->time_origin_micros(),
+ filter->time_extent_micros())) {
events->AddValue(event);
}
}
@@ -1129,10 +1171,11 @@
intptr_t length = current->length();
for (intptr_t i = 0; i < length; i++) {
TimelineEvent* event = current->At(i);
- if (!filter->IncludeEvent(event)) {
- continue;
+ if (filter->IncludeEvent(event) &&
+ event->Within(filter->time_origin_micros(),
+ filter->time_extent_micros())) {
+ events->AddValue(event);
}
- events->AddValue(event);
}
current = current->next();
}
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 40040a4..d0c43e0 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -115,17 +115,23 @@
}
// Marks the beginning of an asynchronous operation with |async_id|.
- void AsyncBegin(const char* label, int64_t async_id);
+ void AsyncBegin(const char* label,
+ int64_t async_id,
+ int64_t micros = OS::GetCurrentMonotonicMicros());
// Marks an instantaneous event associated with |async_id|.
void AsyncInstant(const char* label,
- int64_t async_id);
+ int64_t async_id,
+ int64_t micros = OS::GetCurrentMonotonicMicros());
// Marks the end of an asynchronous operation associated with |async_id|.
void AsyncEnd(const char* label,
- int64_t async_id);
+ int64_t async_id,
+ int64_t micros = OS::GetCurrentMonotonicMicros());
- void DurationBegin(const char* label);
- void DurationEnd();
- void Instant(const char* label);
+ void DurationBegin(const char* label,
+ int64_t micros = OS::GetCurrentMonotonicMicros());
+ void DurationEnd(int64_t micros = OS::GetCurrentMonotonicMicros());
+ void Instant(const char* label,
+ int64_t micros = OS::GetCurrentMonotonicMicros());
void Duration(const char* label,
int64_t start_micros,
@@ -137,7 +143,8 @@
void End(const char* label,
int64_t micros = OS::GetCurrentMonotonicMicros());
- void SerializedJSON(const char* json);
+ // Completes this event with pre-serialized JSON. Copies |json|.
+ void CompleteWithPreSerializedJSON(const char* json);
// Set the number of arguments in the event.
void SetNumArguments(intptr_t length);
@@ -236,6 +243,9 @@
}
}
+ bool Within(int64_t time_origin_micros,
+ int64_t time_extent_micros);
+
const char* GetSerializedJSON() const;
private:
@@ -259,12 +269,23 @@
timestamp1_ = value;
}
+ bool pre_serialized_json() const {
+ return PreSerializedJSON::decode(state_);
+ }
+
+ void set_pre_serialized_json(bool pre_serialized_json) {
+ state_ = PreSerializedJSON::update(pre_serialized_json, state_);
+ }
+
enum StateBits {
kEventTypeBit = 0, // reserve 4 bits for type.
- kNextBit = 4,
+ kPreSerializedJSON = 4,
+ kNextBit = 5,
};
class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {};
+ class PreSerializedJSON :
+ public BitField<bool, kPreSerializedJSON, 1> {};
int64_t timestamp0_;
int64_t timestamp1_;
@@ -522,7 +543,9 @@
class TimelineEventFilter : public ValueObject {
public:
- TimelineEventFilter();
+ TimelineEventFilter(int64_t time_origin_micros = -1,
+ int64_t time_extent_micros = -1);
+
virtual ~TimelineEventFilter();
virtual bool IncludeBlock(TimelineEventBlock* block) {
@@ -540,13 +563,25 @@
return event->IsValid();
}
+ int64_t time_origin_micros() const {
+ return time_origin_micros_;
+ }
+
+ int64_t time_extent_micros() const {
+ return time_extent_micros_;
+ }
+
private:
+ int64_t time_origin_micros_;
+ int64_t time_extent_micros_;
};
class IsolateTimelineEventFilter : public TimelineEventFilter {
public:
- explicit IsolateTimelineEventFilter(Dart_Port isolate_id);
+ explicit IsolateTimelineEventFilter(Dart_Port isolate_id,
+ int64_t time_origin_micros = -1,
+ int64_t time_extent_micros = -1);
bool IncludeBlock(TimelineEventBlock* block) {
if (block == NULL) {
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index f2cf962..67b23f1 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -416,6 +416,9 @@
'snapshot.h',
'snapshot_ids.h',
'snapshot_test.cc',
+ 'source_report.cc',
+ 'source_report.h',
+ 'source_report_test.cc',
'spaces.h',
'stack_frame.cc',
'stack_frame.h',
diff --git a/runtime/vm/weak_code.cc b/runtime/vm/weak_code.cc
index e642204..7c817d0 100644
--- a/runtime/vm/weak_code.cc
+++ b/runtime/vm/weak_code.cc
@@ -14,6 +14,11 @@
namespace dart {
+bool WeakCodeReferences::HasCodes() const {
+ return !array_.IsNull() && (array_.Length() > 0);
+}
+
+
void WeakCodeReferences::Register(const Code& value) {
if (!array_.IsNull()) {
// Try to find and reuse cleared WeakProperty to avoid allocating new one.
diff --git a/runtime/vm/weak_code.h b/runtime/vm/weak_code.h
index 4529806..ea2d9c1 100644
--- a/runtime/vm/weak_code.h
+++ b/runtime/vm/weak_code.h
@@ -31,8 +31,10 @@
void DisableCode();
+ bool HasCodes() const;
+
private:
- const Array& array_;
+ const Array& array_; // Array of Code objects.
DISALLOW_COPY_AND_ASSIGN(WeakCodeReferences);
};
diff --git a/samples/samples.status b/samples/samples.status
index 81d9654..480d3f3 100644
--- a/samples/samples.status
+++ b/samples/samples.status
@@ -24,3 +24,5 @@
[ $arch == simarm64 ]
*: Skip
+[ $runtime == dart_precompiled ]
+sample_extension: RuntimeError # Platform.executable
diff --git a/sdk/bin/dart b/sdk/bin/dart
index 999034c..7dd1e92 100755
--- a/sdk/bin/dart
+++ b/sdk/bin/dart
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2012, 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.
diff --git a/sdk/bin/dart2js b/sdk/bin/dart2js
index 485d619..988a6fe 100755
--- a/sdk/bin/dart2js
+++ b/sdk/bin/dart2js
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2012, 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.
diff --git a/sdk/bin/dart2js_developer b/sdk/bin/dart2js_developer
index 948cb4a..226d1a9 100755
--- a/sdk/bin/dart2js_developer
+++ b/sdk/bin/dart2js_developer
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2012, 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.
diff --git a/sdk/bin/dart2js_sdk b/sdk/bin/dart2js_sdk
index 36b42a4..286859a 100755
--- a/sdk/bin/dart2js_sdk
+++ b/sdk/bin/dart2js_sdk
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2012, 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.
diff --git a/sdk/bin/dartanalyzer b/sdk/bin/dartanalyzer
index 0c23848..8f2274c 100755
--- a/sdk/bin/dartanalyzer
+++ b/sdk/bin/dartanalyzer
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2013, 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.
diff --git a/sdk/bin/dartanalyzer_developer b/sdk/bin/dartanalyzer_developer
index 0eeaf73..373dc67 100755
--- a/sdk/bin/dartanalyzer_developer
+++ b/sdk/bin/dartanalyzer_developer
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
diff --git a/sdk/bin/dartanalyzer_sdk b/sdk/bin/dartanalyzer_sdk
index cc49a5c..28f37ab 100755
--- a/sdk/bin/dartanalyzer_sdk
+++ b/sdk/bin/dartanalyzer_sdk
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2013, 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.
diff --git a/sdk/bin/dartdoc b/sdk/bin/dartdoc
index 319df02..caff494 100755
--- a/sdk/bin/dartdoc
+++ b/sdk/bin/dartdoc
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# 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.
diff --git a/sdk/bin/dartfmt b/sdk/bin/dartfmt
index bc53f36..ded1eac 100755
--- a/sdk/bin/dartfmt
+++ b/sdk/bin/dartfmt
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2013, 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.
diff --git a/sdk/bin/dartfmt_sdk b/sdk/bin/dartfmt_sdk
index 0a9cbef..273733c 100755
--- a/sdk/bin/dartfmt_sdk
+++ b/sdk/bin/dartfmt_sdk
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# 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.
diff --git a/sdk/bin/pub b/sdk/bin/pub
index a03070e..50f0d1d 100755
--- a/sdk/bin/pub
+++ b/sdk/bin/pub
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2012, 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.
diff --git a/sdk/bin/pub_sdk b/sdk/bin/pub_sdk
index bf48a16..f42f609 100755
--- a/sdk/bin/pub_sdk
+++ b/sdk/bin/pub_sdk
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
diff --git a/sdk/lib/_internal/js_runtime/lib/constant_map.dart b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
index 8a6a5c9..9e98b13 100644
--- a/sdk/lib/_internal/js_runtime/lib/constant_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
@@ -67,14 +67,18 @@
// This constructor is not used for actual compile-time constants.
// The instantiation of constant maps is shortcut by the compiler.
- const ConstantStringMap._(this.length, this._jsObject, this._keys)
+ const ConstantStringMap._(this._length, this._jsObject, this._keys)
: super._();
- final int length;
+ // TODO(18131): Ensure type inference knows the precise types of the fields.
+ final int _length;
// A constant map is backed by a JavaScript object.
final _jsObject;
final List<K> _keys;
+ int get length => JS('JSUInt31', '#', _length);
+ List get _keysArray => JS('JSUnmodifiableArray', '#', _keys);
+
bool containsValue(Object needle) {
return values.any((V value) => value == needle);
}
@@ -97,7 +101,7 @@
// Use a JS 'cast' to get efficient loop. Type inferrence doesn't get this
// since constant map representation is chosen after type inferrence and the
// instantiation is shortcut by the compiler.
- var keys = JS('JSArray', '#', _keys);
+ var keys = _keysArray;
for (int i = 0; i < keys.length; i++) {
var key = keys[i];
f(key, _fetch(key));
@@ -109,7 +113,7 @@
}
Iterable<V> get values {
- return new MappedIterable<K, V>(_keys, (key) => _fetch(key));
+ return new MappedIterable<K, V>(_keysArray, (key) => _fetch(key));
}
}
@@ -135,9 +139,9 @@
ConstantStringMap<K, dynamic> _map;
_ConstantMapKeyIterable(this._map);
- Iterator<K> get iterator => _map._keys.iterator;
+ Iterator<K> get iterator => _map._keysArray.iterator;
- int get length => _map._keys.length;
+ int get length => _map._keysArray.length;
}
class GeneralConstantMap<K, V> extends ConstantMap<K, V> {
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index d6dd538..4976562 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -1932,8 +1932,7 @@
// Since we want to create a new regular expression from an unknown string,
// we must escape all regular expression syntax.
- message = JS('String', r"#.replace(new RegExp(#, 'g'), '\\$&')",
- message, ESCAPE_REGEXP);
+ message = quoteStringForRegExp(message);
// Look for the special pattern \$camelCase\$ (all the $ symbols
// have been escaped already), as we will soon be inserting
@@ -2369,20 +2368,19 @@
var arg2,
var arg3,
var arg4) {
- if (numberOfArguments == 0) {
- return JS_CALL_IN_ISOLATE(isolate, () => closure());
- } else if (numberOfArguments == 1) {
- return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1));
- } else if (numberOfArguments == 2) {
- return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2));
- } else if (numberOfArguments == 3) {
- return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3));
- } else if (numberOfArguments == 4) {
- return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3, arg4));
- } else {
- throw new Exception(
- 'Unsupported number of arguments for wrapped closure');
+ switch (numberOfArguments) {
+ case 0:
+ return JS_CALL_IN_ISOLATE(isolate, () => closure());
+ case 1:
+ return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1));
+ case 2:
+ return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2));
+ case 3:
+ return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3));
+ case 4:
+ return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3, arg4));
}
+ throw new Exception('Unsupported number of arguments for wrapped closure');
}
/**
@@ -2394,21 +2392,18 @@
var function = JS('var', r'#.$identity', closure);
if (JS('bool', r'!!#', function)) return function;
- // We use $0 and $1 to not clash with variable names used by the
- // compiler and/or minifier.
- function = JS('var',
- '(function(closure, arity, context, invoke) {'
- ' return function(a1, a2, a3, a4) {'
- ' return invoke(closure, context, arity, a1, a2, a3, a4);'
- ' };'
- '})(#,#,#,#)',
- closure,
- arity,
- // Capture the current isolate now. Remember that "#"
- // in JS is simply textual substitution of compiled
- // expressions.
- JS_CURRENT_ISOLATE_CONTEXT(),
- DART_CLOSURE_TO_JS(invokeClosure));
+ function = JS(
+ 'var',
+ r'''
+ (function(closure, arity, context, invoke) {
+ return function(a1, a2, a3, a4) {
+ return invoke(closure, context, arity, a1, a2, a3, a4);
+ };
+ })(#,#,#,#)''',
+ closure,
+ arity,
+ JS_CURRENT_ISOLATE_CONTEXT(),
+ DART_CLOSURE_TO_JS(invokeClosure));
JS('void', r'#.$identity = #', closure, function);
return function;
diff --git a/sdk/lib/_internal/js_runtime/lib/string_helper.dart b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
index 9ce91f8..24e21f7 100644
--- a/sdk/lib/_internal/js_runtime/lib/string_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
@@ -130,7 +130,12 @@
return stringReplaceRangeUnchecked(receiver, start, end, replacement);
}
-const String ESCAPE_REGEXP = r'[[\]{}()*+?.\\^$|]';
+
+/// Returns a string for a RegExp pattern that matches [string]. This is done by
+/// escaping all RegExp metacharacters.
+quoteStringForRegExp(string) {
+ return JS('String', r'#.replace(/[[\]{}()*+?.\\^$|]/g, "\\$&")', string);
+}
stringReplaceAllUnchecked(receiver, pattern, replacement) {
checkString(replacement);
@@ -149,8 +154,7 @@
return result.toString();
}
} else {
- var quoter = JS('', "new RegExp(#, 'g')", ESCAPE_REGEXP);
- var quoted = JS('String', r'#.replace(#, "\\$&")', pattern, quoter);
+ var quoted = quoteStringForRegExp(pattern);
var replacer = JS('', "new RegExp(#, 'g')", quoted);
return stringReplaceJS(receiver, replacer, replacement);
}
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart
index 15ed062..c463d8b 100644
--- a/sdk/lib/developer/timeline.dart
+++ b/sdk/lib/developer/timeline.dart
@@ -68,6 +68,9 @@
}
}
+ /// The current time stamp from the clock used by the timeline. Units are
+ /// microseconds.
+ static int get now => _getTraceClock();
static final List<_SyncBlock> _stack = new List<_SyncBlock>();
static final int _isolateId = _getIsolateNum();
static final String _isolateIdString = _isolateId.toString();
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 8acae64..883ae88 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -31962,10 +31962,11 @@
*/
Document get document => JS('Document', '#.document', this);
- WindowBase _open2(url, name) => JS('Window', '#.open(#,#)', this, url, name);
+ WindowBase _open2(url, name) =>
+ JS('Window|Null', '#.open(#,#)', this, url, name);
WindowBase _open3(url, name, options) =>
- JS('Window', '#.open(#,#,#)', this, url, name, options);
+ JS('Window|Null', '#.open(#,#,#)', this, url, name, options);
/**
* Opens a new window.
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 6b1a7f7..0d1edad 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -20360,16 +20360,9 @@
createdParametersValid = createdParametersValid && parameter.isOptional;
});
}
-
- // Get the created constructor source and look at the initializer;
- // Must call super.created() if not its as an error.
- var createdSource = methodMirror.source;
- superCreatedCalled = createdSource.contains("super.created(");
}
- if (!superCreatedCalled) {
- throw new DomException.jsInterop('created constructor initializer must call super.created()');
- } else if (!createdParametersValid) {
+ if (!createdParametersValid) {
throw new DomException.jsInterop('created constructor must have no parameters');
}
diff --git a/site/try/create_manifest.sh b/site/try/create_manifest.sh
index c445833..0f145ac 100644
--- a/site/try/create_manifest.sh
+++ b/site/try/create_manifest.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
diff --git a/tests/benchmark_smoke/benchmark_smoke.status b/tests/benchmark_smoke/benchmark_smoke.status
index d3fe9a3..a83fd89 100644
--- a/tests/benchmark_smoke/benchmark_smoke.status
+++ b/tests/benchmark_smoke/benchmark_smoke.status
@@ -2,7 +2,7 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
*: Skip
[ $compiler == dart2js && $runtime == none ]
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 64cea7e..19f53a4 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -135,7 +135,7 @@
Language/Statements/Local_Function_Declaration/reference_before_declaration_t03: MissingCompileTimeError # Issue 21050
Language/Types/Interface_Types/subtype_t27: Skip # Times out or crashes. Issue 21174
Language/Types/Interface_Types/subtype_t30: fail # Issue 14654
-Language/Types/Interface_Types/subtype_t28: Pass, Fail # Stack overflow. Issue 25282
+Language/Types/Interface_Types/subtype_t28: Pass, Fail, Crash # Stack overflow. Issue 25282
Language/Variables/final_t01: fail # Issue 21093
Language/Variables/final_t02: fail # Issue 21093
Language/Variables/local_variable_t01: MissingCompileTimeError # Issue 21050
@@ -1727,7 +1727,6 @@
LayoutTests/fast/canvas/canvas-toDataURL-crash_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/crash-set-font_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/draw-custom-focus-ring_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/drawImage-with-negative-source-destination_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/drawImage-with-valid-image_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/getPutImageDataPairTest_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/rgba-parsing_t01: RuntimeError # Please triage this failure
@@ -3167,6 +3166,7 @@
[ $compiler == dart2js && $runtime == ff && $system != windows ]
LayoutTests/fast/canvas/canvas-resetTransform_t01: RuntimeError # Please triage this failure
LayoutTests/fast/canvas/canvas-setTransform_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/drawImage-with-negative-source-destination_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLAnchorElement/set-href-attribute-pathname_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/4XPath/Core/test_parser_t01: RuntimeError # Dartium JSInterop failure
LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Dartium JSInterop failure
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index c5bfba7..0b6ea52 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -3,7 +3,12 @@
# BSD-style license that can be found in the LICENSE file.
-[ $compiler == none && ($runtime == vm || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && (($runtime == vm || $runtime == dart_precompiled) || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+
+# Failures ok in tests below. VM moves super initializer to end of list.
+Language/Classes/Constructors/Generative_Constructors/execution_t03: Fail, OK
+Language/Expressions/Instance_Creation/New/execution_t04: Fail, OK
+Language/Expressions/Instance_Creation/New/execution_t06: Fail, OK
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Issue 22200
@@ -38,7 +43,7 @@
LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # Issue 13596
LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # Issue 13596
-[ $compiler == none && $runtime == vm ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) ]
LibTest/typed_data/Float32x4/reciprocalSqrt_A01_t01: Pass, Fail # co19 issue 599
LibTest/typed_data/Float32x4/reciprocal_A01_t01: Pass, Fail # co19 issue 599
Language/Expressions/Instance_Creation/Const/abstract_class_t01: MissingCompileTimeError # Issue 22007
@@ -48,16 +53,16 @@
Language/Libraries_and_Scripts/Exports/invalid_uri_t02: Fail
Language/Libraries_and_Scripts/Parts/syntax_t06: Fail
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
LibTest/math/MutableRectangle/MutableRectangle.fromPoints_A01_t01: Pass, RuntimeError # co19-roll r607: Please triage this failure
-[ $compiler == none && $runtime == vm && $mode == debug ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $mode == debug ]
LibTest/core/List/List_class_A01_t02: Pass, Slow
-[ $compiler == none && $runtime == vm && ($arch != x64 && $arch != simarm64) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch != x64 && $arch != simarm64) ]
LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
-[ $compiler == none && $runtime == vm && $arch == mips ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $arch == mips ]
LibTest/core/double/toInt_A01_t01: Fail
# These tests take too much memory (300 MB) for our 1 GB test machine.
# co19 issue 673. http://code.google.com/p/co19/issues/detail?id=673
@@ -65,30 +70,30 @@
LibTest/collection/ListMixin/ListMixin_class_A01_t02: Skip # co19 issue 673
LibTest/collection/ListBase/ListBase_class_A01_t02: Skip # co19 issue 673
-[ $compiler == none && $runtime == vm && $arch == mips && $mode == debug ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $arch == mips && $mode == debug ]
LibTest/isolate/Isolate/spawnUri_A01_t04: Crash, Pass # Issue 17440
LibTest/isolate/Isolate/spawn_A01_t04: Crash, Pass # Issue 17440
-[ $compiler == none && $runtime == vm && ($arch == simarm || $arch == simarmv5te || $arch == simmips || $arch == simarm64) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch == simarm || $arch == simarmv5te || $arch == simmips || $arch == simarm64) ]
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
LibTest/collection/ListMixin/ListMixin_class_A01_t02: Skip # Timeout
LibTest/collection/ListBase/ListBase_class_A01_t02: Skip # Timeout
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
LibTest/isolate/Isolate/spawn_A02_t01: Skip # co19 issue 667
LibTest/html/*: SkipByDesign # dart:html not supported on VM.
LayoutTests/fast/*: SkipByDesign # DOM not supported on VM.
WebPlatformTest/*: SkipByDesign # dart:html not supported on VM.
-[ $runtime == vm && $mode == debug && $builder_tag == asan ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $builder_tag == asan ]
Language/Types/Interface_Types/subtype_t27: Skip # Issue 21174.
-[ $runtime == vm && $arch == arm ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $arch == arm ]
LibTest/typed_data/Float32x4/operator_multiplication_A01_t01: Fail # Dart issue 24416
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
# co19 update Sep 29, 2015 (3ed795ea02e022ef19c77cf1b6095b7c8f5584d0)
Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t01: MissingCompileTimeError # Please triage this failure
Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t02: MissingCompileTimeError # Please triage this failure
@@ -131,10 +136,10 @@
Language/Mixins/not_object_superclass_t01: MissingCompileTimeError # Please triage this failure
Language/Mixins/reference_to_super_t01: MissingCompileTimeError # Please triage this failure
-[ $runtime == vm && $mode == debug ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug ]
Language/Mixins/Mixin_Application/wrong_type_t02: Crash # Please triage this failure
-[ $runtime == vm && $checked ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $checked ]
Language/Errors_and_Warnings/static_warning_t01: RuntimeError # Please triage this failure
Language/Errors_and_Warnings/static_warning_t02: RuntimeError # Please triage this failure
Language/Errors_and_Warnings/static_warning_t03: RuntimeError # Please triage this failure
@@ -142,7 +147,7 @@
Language/Errors_and_Warnings/static_warning_t05: RuntimeError # Please triage this failure
Language/Errors_and_Warnings/static_warning_t06: RuntimeError # Please triage this failure
-[ $runtime == vm && $noopt ]
+[ ($noopt || $compiler == precompiler) ]
LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Timeout
LibTest/collection/ListMixin/ListMixin_class_A01_t02: Pass, Timeout
LibTest/core/Map/Map_class_A01_t04: Pass, Timeout
@@ -152,3 +157,6 @@
Language/Mixins/declaring_constructor_t01: Pass
Language/Expressions/Property_Extraction/Named_Constructor_Extraction/deferred_type_t01: Pass
Language/Metadata/*: Skip # Uses dart:mirrors
+
+[ $runtime == dart_precompiled ]
+LibTest/isolate/Isolate/spawnUri*: RuntimeError # Isolate.spawnUri
\ No newline at end of file
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index b7a65e8..70a2a3a 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -52,6 +52,12 @@
js_backend_cps_ir_closures_test: Pass, Slow
js_backend_cps_ir_constructor_test: Pass, Slow
+# Source information is not correct due to inlining.
+js_backend_cps_ir_source_information_test: Fail
+sourcemaps/source_mapping_operators_test: Fail # Issue 25304 for checked mode, was: Pass, Slow
+
+check_elements_invariants_test: Slow, Pass, Timeout # Slow due to inlining in the CPS backend
+
[ $unchecked ]
exit_code_test: Skip # This tests requires checked mode.
@@ -59,7 +65,6 @@
analyze_dart2js_helpers_test: Pass, Slow
analyze_dart2js_test: Pass, Slow
analyze_unused_dart2js_test: Pass, Slow
-check_elements_invariants_test: Slow, Pass, Timeout
deferred_mirrors_test: Pass, Slow
duplicate_library_test: Pass, Slow
exit_code_test: Pass, Slow
@@ -67,7 +72,6 @@
interop_anonymous_unreachable_test: Pass, Slow
mirror_final_field_inferrer2_test: Pass, Slow
source_map_pub_build_validity_test: Pass, Slow
-sourcemaps/source_mapping_operators_test: Pass, Slow
uri_retention_test: Pass, Slow
value_range_test: Pass, Slow
diff --git a/tests/compiler/dart2js/incremental/hello_test.dart b/tests/compiler/dart2js/incremental/hello_test.dart
index 83215dc..e47ef9d 100644
--- a/tests/compiler/dart2js/incremental/hello_test.dart
+++ b/tests/compiler/dart2js/incremental/hello_test.dart
@@ -85,8 +85,7 @@
main() {
Uri libraryRoot = Uri.base.resolve('sdk/');
- Uri packageRoot = Uri.base.resolveUri(
- new Uri.file('${Platform.packageRoot}/'));
+ Uri packageRoot = Uri.base.resolve(Platform.packageRoot);
MemorySourceFileProvider provider =
new MemorySourceFileProvider(tests);
asyncTest(() => runTests(libraryRoot, packageRoot, provider));
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
index 51d2762..614a102 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
@@ -25,15 +25,23 @@
print('($m)');
}""",r"""
function() {
- var l = [1, 2, 3], m = P.LinkedHashMap_LinkedHashMap$_literal(["s", 1]);
+ var l = [1, 2, 3], m = P.LinkedHashMap_LinkedHashMap$_literal(["s", 1]), value_ = C.JSArray_methods, res, v0, v1;
P.print("()");
P.print("(true)");
P.print("(1)");
- P.print("(" + H.S([1, 2, 3]) + ")");
- P.print("(" + H.S(P.LinkedHashMap_LinkedHashMap$_literal(["s", 1])) + ")");
+ if (!(typeof (res = value_.toString$0(v0 = [1, 2, 3])) === "string"))
+ throw H.wrapException(H.argumentErrorValue(v0));
+ P.print("(" + res + ")");
+ if (!(typeof (v1 = P.Maps_mapToString(v0 = P.LinkedHashMap_LinkedHashMap$_literal(["s", 1]))) === "string"))
+ throw H.wrapException(H.argumentErrorValue(v0));
+ P.print("(" + v1 + ")");
P.print("(1)");
- P.print("(" + H.S(l) + ")");
- P.print("(" + H.S(m) + ")");
+ if (!(typeof (res = value_.toString$0(l)) === "string"))
+ throw H.wrapException(H.argumentErrorValue(l));
+ P.print("(" + res + ")");
+ if (!(typeof (v0 = P.Maps_mapToString(m)) === "string"))
+ throw H.wrapException(H.argumentErrorValue(m));
+ P.print("(" + v0 + ")");
}"""),
const TestEntry("""
foo(a, [b = "b"]) { print(b); return b; }
@@ -49,12 +57,12 @@
""",
"""
function() {
- V.foo(0, "b");
- V.foo(1, 2);
- V.bar(3, "b", "c");
- V.bar(4, 5, "c");
- V.bar(6, "b", 7);
- V.bar(8, 9, 10);
+ P.print("b");
+ P.print(2);
+ P.print("c");
+ P.print("c");
+ P.print(7);
+ P.print(10);
}"""),
const TestEntry(
"""
@@ -77,19 +85,30 @@
""",
"""
function() {
- var a = 10, b = 1;
- P.print(b);
- P.print(a);
- P.print(a);
- P.print(V.foo(b));
+ P.print(1);
+ P.print(10);
+ P.print(10);
+ P.print(1);
+ P.print(1);
}"""),
const TestEntry(
"""
foo() { print(42); return 42; }
main() { return foo(); }
""",
- """function() {
- return V.foo();
+ """
+function() {
+ var v0 = H.S(42);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
+ return 42;
}"""),
const TestEntry("main() {}"),
const TestEntry("main() { return 42; }"),
@@ -103,7 +122,7 @@
print(new Set.from([1, 2, 3]));
}""", r"""
function() {
- P.print(P.LinkedHashSet_LinkedHashSet(null, null, null, null));
+ P.print(P._LinkedHashSet$(null));
P.print(P.LinkedHashSet_LinkedHashSet$from([1, 2, 3], null));
}"""),
// Call synthetic constructor.
@@ -118,7 +137,16 @@
print(new DateTime.now().isBefore(new DateTime.now()));
}""", r"""
function() {
- P.print(P.DateTime$now().isBefore$1(P.DateTime$now()));
+ var v0 = H.S(Date.now() < Date.now());
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
// Static calls
const TestEntry("""
@@ -126,7 +154,16 @@
main() { foo(); }
""", r"""
function() {
- V.foo();
+ var v0 = H.S(42);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
// Static getters
const TestEntry("""
@@ -134,14 +171,32 @@
main() { print(foo); }
""", r"""
function() {
- P.print($.foo);
+ var v0 = H.S($.foo);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry("""
get foo { print(42); }
main() { foo; }
""", r"""
function() {
- V.foo();
+ var v0 = H.S(42);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
// Static setters
const TestEntry("""
@@ -149,16 +204,34 @@
main() { print(foo = 42); }
""", r"""
function() {
- var v0 = 42;
- $.foo = v0;
- P.print(v0);
+ var v0;
+ $.foo = 42;
+ v0 = H.S(42);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry("""
set foo(x) { print(x); }
main() { foo = 42; }
""", r"""
function() {
- V.foo(42);
+ var v0 = H.S(42);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
// Assert
const TestEntry("""
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
index dc4552b..f3d55a0 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
@@ -81,7 +81,16 @@
""",
r"""
function() {
- P.print(122 + 1);
+ var v0 = H.S(122 + 1);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry("""
@@ -95,10 +104,19 @@
""",
r"""
function() {
- var _box_0 = {}, a = new V.main_closure(_box_0);
+ var _box_0 = {}, a = new V.main_closure(_box_0), v0;
_box_0.x = 122;
_box_0.x = _box_0.x + 1;
- P.print(a.call$0());
+ v0 = H.S(a.call$0());
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
return a;
}"""),
@@ -115,7 +133,16 @@
""",
r"""
function() {
- P.print(122 + 1);
+ var v0 = H.S(122 + 1);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry("""
@@ -132,10 +159,19 @@
""",
r"""
function() {
- var _box_0 = {}, a = new V.main_closure(_box_0);
+ var _box_0 = {}, a = new V.main_closure(_box_0), v0;
_box_0.x = 122;
_box_0.x = _box_0.x + 1;
- P.print(a.call$0().call$0());
+ v0 = H.S(a.call$0().call$0());
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
return a;
}"""),
@@ -150,13 +186,22 @@
""",
r"""
function() {
- var a = null, i = 0;
+ var a = null, i = 0, v0;
for (; i < 10; a = new V.main_closure(i), i = i + 1)
;
- P.print(a.call$0());
+ v0 = H.S(a.call$0());
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
- const TestEntry.forMethod('function(A#b)', """
+ const TestEntry("""
class A {
a() => 1;
b() => () => a();
@@ -167,7 +212,16 @@
""",
r"""
function() {
- return new V.A_b_closure(this);
+ var v0 = H.S(new V.A_b_closure(V.A$()).call$0());
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry("""
@@ -179,7 +233,8 @@
""",
r"""
function(x) {
- P.print(V.staticMethod(123));
+ P.print(123);
+ P.print(123);
}"""),
const TestEntry("""
@@ -193,7 +248,8 @@
""",
r"""
function(x) {
- P.print(V.Foo$().instanceMethod$1(123));
+ V.Foo$();
+ P.print(123);
}"""),
const TestEntry("""
@@ -208,9 +264,9 @@
""",
r"""
function(x) {
- var v0 = V.Foo$();
- P.print(v0.instanceMethod$1(123));
- P.print(v0.instanceMethod$1(321));
+ V.Foo$();
+ P.print(123);
+ P.print(321);
}"""),
const TestEntry("""
@@ -228,9 +284,11 @@
""",
r"""
function(x) {
- var notTearOff = V.Foo$().get$getter();
- P.print(notTearOff.call$1(123));
- P.print(notTearOff.call$1(321));
+ var v0 = new V.Foo_getter_closure();
+ V.Foo$();
+ P.print("getter");
+ P.print(v0.call$1(123));
+ P.print(v0.call$1(321));
}"""),
const TestEntry("""
@@ -247,7 +305,9 @@
""",
r"""
function(x) {
- P.print(V.Foo$().get$getter().call$1(123));
+ V.Foo$();
+ P.print("getter");
+ P.print(new V.Foo_getter_closure().call$1(123));
}"""),
];
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_codeUnitAt_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_codeUnitAt_test.dart
index b3f2808..9da3350 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_codeUnitAt_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_codeUnitAt_test.dart
@@ -16,7 +16,16 @@
print('A'.codeUnitAt(0));
}""",r"""
function() {
- P.print(65);
+ var v0 = H.S(65);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
index ec45a16..a3d9bcd 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
@@ -9,7 +9,7 @@
import 'js_backend_cps_ir.dart';
const List<TestEntry> tests = const [
- const TestEntry.forMethod('generative_constructor(Sub#)', """
+ const TestEntry("""
class Base {
var x;
Base(this.x);
@@ -22,11 +22,20 @@
print(new Sub(1, 2).x);
}""",
r"""
-function(x, y) {
- return new V.Sub(y, x);
+function() {
+ var v0 = H.S(1);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
- const TestEntry.forMethod('generative_constructor_body(Sub#)', """
+ const TestEntry("""
class Base {
var x;
Base(this.x);
@@ -41,11 +50,12 @@
print(new Sub(1, 2).x);
}""",
r"""
-function(x, y) {
- P.print(x);
+function() {
+ P.print(1);
+ P.print(1);
}"""),
- const TestEntry.forMethod('generative_constructor(Sub#)', """
+ const TestEntry("""
class Base0 {
Base0() {
print('Base0');
@@ -65,14 +75,13 @@
print(new Sub(1, 2).x);
}""",
r"""
-function(x, y) {
- var v0 = new V.Sub(y, x);
- v0.Base0$0();
- v0.Sub$2(x, y);
- return v0;
+function() {
+ P.print("Base0");
+ P.print(1);
+ P.print(1);
}"""),
- const TestEntry.forMethod('generative_constructor(Sub#)', """
+ const TestEntry("""
class Base0 {
Base0() {
print('Base0');
@@ -94,16 +103,16 @@
print(new Sub(1, 2).x);
}""",
r"""
-function(x, y) {
- var _box_0 = {}, v0 = new V.Sub(y, new V.Base_closure(_box_0));
- _box_0.x1 = x;
- v0.Base0$0();
- v0.Base$1(_box_0);
- v0.Sub$2(x, y);
- return v0;
+function() {
+ var _box_0 = {};
+ _box_0.x1 = 1;
+ P.print("Base0");
+ P.print(_box_0.x1);
+ P.print(1);
+ P.print(new V.Base_closure(_box_0));
}"""),
- const TestEntry.forMethod('generative_constructor(Sub#)', """
+ const TestEntry("""
foo(x) {
print(x);
}
@@ -125,12 +134,16 @@
""",
r"""
function() {
- var v0 = V.foo("y1"), v1 = V.foo("y2"), v2 = V.foo("x1"), v3 = V.foo("x3"), v4 = V.foo("x2");
- return new V.Sub(v0, v1, V.foo("y3"), v2, v4, v3);
+ V.foo("y1");
+ V.foo("y2");
+ V.foo("x1");
+ V.foo("x3");
+ V.foo("x2");
+ V.foo("y3");
}"""),
- const TestEntry.forMethod('generative_constructor(Foo#)', """
+ const TestEntry("""
class Bar {
Bar(x, {y, z: 'z', w: '_', q}) {
print(x);
@@ -149,9 +162,11 @@
""",
r"""
function() {
- var v0 = new V.Foo();
- v0.Bar$5$q$w$y$z("x", null, "w", "y", "z");
- return v0;
+ P.print("x");
+ P.print("y");
+ P.print("z");
+ P.print("w");
+ P.print(null);
}"""),
const TestEntry(r"""
class C<T> {
@@ -161,7 +176,16 @@
print(new C<int>().foo());
}""", r"""
function() {
- P.print(V.C$(P.$int).foo$0());
+ var v0 = H.S(H.createRuntimeType(H.runtimeTypeToString(H.getTypeArgumentByIndex(V.C$(P.$int), 0))));
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry(r"""
class C<T> {
@@ -171,7 +195,18 @@
print(new C<int>().foo());
}""", r"""
function() {
- P.print(V.C$().foo$0());
+ var v0;
+ V.C$();
+ v0 = H.S(C.Type_C_cdS);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry.forMethod('generative_constructor(C#)', r"""
class C<T> {
@@ -202,7 +237,7 @@
}"""),
- const TestEntry.forMethod('generative_constructor(A#)', r"""
+ const TestEntry(r"""
class A {
var x;
A() : this.b(1);
@@ -212,11 +247,20 @@
print(new A().x);
}""", r"""
function() {
- return new V.A(1);
+ var v0 = H.S(1);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
-const TestEntry.forMethod('factory_constructor(Foo#make)', r"""
+const TestEntry(r"""
class Foo {
factory Foo.make(x) {
print('Foo');
@@ -228,9 +272,9 @@
main() {
print(new Foo.make(5));
}""", r"""
-function(x) {
+function() {
P.print("Foo");
- return V.Foo$create(x);
+ P.print(new V.Foo(5));
}"""),
const TestEntry(r"""
class Foo {
@@ -242,7 +286,19 @@
print(new Foo.make(5));
}""", r"""
function() {
- P.print(V.Foo$create(5));
+ var v0 = new V.Foo(5), v1 = "Instance of '" + H.Primitives_objectTypeName(v0) + "'";
+ if (!(typeof v1 === "string"))
+ throw H.wrapException(H.argumentErrorValue(v0));
+ v0 = v1;
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry(r"""
class A {
@@ -259,7 +315,7 @@
new A(5).typevar;
}""", r"""
function() {
- V.B$(5, P.$int).get$typevar();
+ V.B$(5, P.$int);
}"""),
];
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
index 2d9e07e..62f2537 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_control_flow_test.dart
@@ -34,16 +34,22 @@
}
""", """
function() {
- L0:
+ L1:
while (true)
- while (true) {
- while (V.foo(true))
- if (V.foo(false)) {
- P.print(2);
- continue L0;
+ L0:
+ while (true)
+ while (true) {
+ P.print(true);
+ if (false) {
+ P.print(1);
+ continue L0;
+ }
+ P.print(false);
+ if (false) {
+ P.print(2);
+ continue L1;
+ }
}
- P.print(1);
- }
}"""),
const TestEntry("""
foo(a) { print(a); return a; }
@@ -56,13 +62,19 @@
print(2);
}""", """
function() {
- var i = 0;
- for (; V.foo(true) === true; i = V.foo(i)) {
- P.print(1);
- if (V.foo(false) === true)
- break;
+ while (true) {
+ P.print(true);
+ if (true === true) {
+ P.print(1);
+ P.print(false);
+ if (false !== true) {
+ P.print(0);
+ continue;
+ }
+ }
+ P.print(2);
+ return null;
}
- P.print(2);
}"""),
const TestEntry("""
foo(a) { print(a); return a; }
@@ -77,8 +89,9 @@
print(3);
}""", """
function() {
- V.foo(false);
- V.foo(true) ? P.print(1) : P.print(2);
+ P.print(false);
+ P.print(true);
+ true ? P.print(1) : P.print(2);
P.print(3);
}"""),
const TestEntry("""
@@ -96,8 +109,9 @@
print(3);
}""", """
function() {
- V.foo(false);
- if (V.foo(true)) {
+ P.print(false);
+ P.print(true);
+ if (true) {
P.print(1);
P.print(1);
} else {
@@ -127,7 +141,7 @@
}
}""","""
function() {
- V.foo();
+ P.print("2");
P.print("good");
}"""),
const TestEntry("""
@@ -138,9 +152,19 @@
}
}""",r"""
function() {
- var list = [1, 2, 3, 4, 5, 6], i = 0;
- for (; i < 6; i = i + 1)
- P.print(list[i]);
+ var list = [1, 2, 3, 4, 5, 6], i = 0, v0;
+ for (; i < 6; i = i + 1) {
+ v0 = H.S(list[i]);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
+ }
}"""),
const TestEntry("""
main() {
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_gvn_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_gvn_test.dart
index 27cfbae..604c19a 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_gvn_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_gvn_test.dart
@@ -9,7 +9,7 @@
import 'js_backend_cps_ir.dart';
const List<TestEntry> tests = const [
- const TestEntry.forMethod('function(foo)', r"""
+ const TestEntry(r"""
foo(x, list) {
var sum = 0;
for (int k = 0; k < 10; k++) {
@@ -51,18 +51,24 @@
print(foo(z, [1,2,3,4,5,6,7,8,9,10]));
}
""",r"""
-function(x, list) {
- var v0 = x.left, a = v0.left, b = v0.right, sum = 0, k = 0, c = (v0 = x.right).left, d = v0.right, v1, v2, v3, i, v4;
- v0 = a.value;
- v1 = c.value;
- v2 = b.value;
- for (v3 = d.value; k < 10; sum = sum + (i + list[v4]), k = k + 1) {
- i = v0 + v1;
- v4 = i * (v2 + v3);
- if (v4 < 0 || v4 >= 10)
- return H.ioore(list, v4);
+function() {
+ var v0 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], sum = 0, k = 0, i, v1;
+ for (; k < 10; sum = sum + (i + v0[v1]), k = k + 1) {
+ i = 1 + 20;
+ v1 = i * (10 + -10);
+ if (v1 < 0 || v1 >= 10)
+ return H.ioore(v0, v1);
}
- return sum;
+ v0 = H.S(sum);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
];
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
index 4de37b1..382736c 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
@@ -18,7 +18,16 @@
}""",
r"""
function() {
- P.print(4);
+ var v0 = H.S(4);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry("""
main() {
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_operators2_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_operators2_test.dart
index 1ced961..21ffdc5 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_operators2_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_operators2_test.dart
@@ -10,26 +10,26 @@
const List<TestEntry> tests = const [
- const TestEntry.forMethod('function(foo)',
- r"""
+ const TestEntry(r"""
foo(a, b) => ((a & 0xff0000) >> 1) & b;
main() {
print(foo(123, 234));
print(foo(0, 2));
}""", r"""
-function(a, b) {
- return (a & 16711680) >>> 1 & b;
+function() {
+ P.print((123 & 16711680) >>> 1 & 234);
+ P.print((0 & 16711680) >>> 1 & 2);
}"""),
- const TestEntry.forMethod('function(foo)',
- r"""
+ const TestEntry(r"""
foo(a) => ~a;
main() {
print(foo(1));
print(foo(10));
}""", r"""
-function(a) {
- return ~a >>> 0;
+function() {
+ P.print(~1 >>> 0);
+ P.print(~10 >>> 0);
}"""),
const TestEntry.forMethod('function(foo)',
@@ -40,29 +40,30 @@
print(foo(-100));
}""", r"""
function(a) {
- return C.JSInt_methods.$mod(a, 13);
+ var result = a % 13;
+ return result === 0 ? 0 : result > 0 ? result : 13 < 0 ? result - 13 : result + 13;
}"""),
- const TestEntry.forMethod('function(foo)',
- r"""
+ const TestEntry(r"""
foo(a) => a % 13;
main() {
print(foo(5));
print(foo(100));
}""", r"""
-function(a) {
- return a % 13;
+function() {
+ P.print(5 % 13);
+ P.print(100 % 13);
}"""),
- const TestEntry.forMethod('function(foo)',
- r"""
+ const TestEntry(r"""
foo(a) => a.remainder(13);
main() {
print(foo(5));
print(foo(-100));
}""", r"""
-function(a) {
- return a % 13;
+function() {
+ P.print(5 % 13);
+ P.print(-100 % 13);
}"""),
const TestEntry.forMethod('function(foo)',
@@ -73,18 +74,19 @@
print(foo(-100));
}""", r"""
function(a) {
- return C.JSInt_methods.$tdiv(a, 13);
+ var v0;
+ return (a | 0) === a && (13 | 0) === 13 ? a / 13 | 0 : J.getInterceptor$n(v0 = a / 13).toInt$0(v0);
}"""),
- const TestEntry.forMethod('function(foo)',
- r"""
+ const TestEntry(r"""
foo(a) => a ~/ 13;
main() {
print(foo(5));
print(foo(100));
}""", r"""
-function(a) {
- return a / 13 | 0;
+function() {
+ P.print(5 / 13 | 0);
+ P.print(100 / 13 | 0);
}"""),
const TestEntry.forMethod('function(foo)',
@@ -95,7 +97,8 @@
print(foo(8000000000));
}""", r"""
function(a) {
- return C.JSInt_methods.$tdiv(a, 13);
+ var v0;
+ return (a | 0) === a && (13 | 0) === 13 ? a / 13 | 0 : J.getInterceptor$n(v0 = a / 13).toInt$0(v0);
}"""),
];
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
index a6d7a1c..152a552 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
@@ -15,43 +15,89 @@
foo() => ++x > 10;
main() {
print(foo() ? "hello world" : "bad bad");
-}""","""
+}""",r"""
function() {
- P.print(V.foo() ? "hello world" : "bad bad");
-}"""),
- const TestEntry("""
-var x = 1;
-foo() => ++x > 10;
-main() {
- print(foo() ? "hello world" : "bad bad");
-}""","""
-function() {
- P.print(V.foo() ? "hello world" : "bad bad");
+ var v0 = $.x + 1;
+ $.x = v0;
+ v0 = v0 > 10 ? "hello world" : "bad bad";
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry("""
var x = 1;
get foo => ++x > 10;
main() {
print(foo ? "hello world" : "bad bad");
-}""","""
+}""",r"""
function() {
- P.print(V.foo() ? "hello world" : "bad bad");
+ var v0 = $.x + 1;
+ $.x = v0;
+ v0 = v0 > 10 ? "hello world" : "bad bad";
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry("""
var x = 1;
get foo => ++x > 10;
main() { print(foo && foo); }
-""", """
+""", r"""
function() {
- P.print(V.foo() ? !!V.foo() : false);
+ var v0 = $.x + 1;
+ $.x = v0;
+ if (v0 > 10) {
+ $.x = v0 = $.x + 1;
+ v0 = v0 > 10;
+ } else
+ v0 = false;
+ v0 = H.S(v0);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry("""
var x = 1;
get foo => ++x > 10;
main() { print(foo || foo); }
-""","""
+""",r"""
function() {
- P.print(V.foo() ? true : !!V.foo());
+ var v0 = $.x + 1;
+ $.x = v0;
+ if (v0 > 10)
+ v0 = true;
+ else {
+ $.x = v0 = $.x + 1;
+ v0 = v0 > 10;
+ }
+ v0 = H.S(v0);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry("""
get foo => foo;
@@ -84,9 +130,20 @@
print(list);
}""", r"""
function() {
- var list = [1, 2, 3];
+ var list = [1, 2, 3], res, v0;
list[1] = 6;
- P.print(list);
+ if (!(typeof (res = C.JSArray_methods.toString$0(list)) === "string"))
+ throw H.wrapException(H.argumentErrorValue(list));
+ v0 = res;
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
];
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart
index 4353b69..fcdc6cb 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart
@@ -14,8 +14,7 @@
const String createType = r'H.createRuntimeType';
const List<TestEntry> tests = const [
- const TestEntry.forMethod("function(C#foo)",
-r"""
+ const TestEntry(r"""
class C<T> {
foo() => print(T);
}
@@ -23,12 +22,20 @@
main() {
new C<int>().foo();
}""",
-"""
-function() {
- return P.print($createType($typeToString($getTypeArgument(this, 0))));
-}"""),
- const TestEntry.forMethod("function(C#foo)",
r"""
+function() {
+ var v0 = H.S(H.createRuntimeType(H.runtimeTypeToString(H.getTypeArgumentByIndex(V.C$(P.$int), 0))));
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
+}"""),
+ const TestEntry(r"""
class C<T, U> {
foo() => print(U);
}
@@ -38,11 +45,20 @@
main() {
new D().foo();
}""",
-"""
+r"""
function() {
- return P.print($createType($typeToString($getSubstitutedTypeArgument(this, "C", 1))));
+ var v0 = H.S(H.createRuntimeType(H.runtimeTypeToString(H.getRuntimeTypeArgument(V.D$(), "C", 1))));
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
- const TestEntry.forMethod('function(C#foo)', r"""
+ const TestEntry(r"""
class C<T> {
foo() => new D<C<T>>();
}
@@ -51,9 +67,18 @@
}
main() {
print(new C<int>().foo().bar());
-}""", """
+}""", r"""
function() {
- return V.D\$([V.C, $getTypeArgument(this, 0)]);
+ var v0 = H.S(H.createRuntimeType(H.runtimeTypeToString(H.getTypeArgumentByIndex(V.D$([V.C, H.getTypeArgumentByIndex(V.C$(P.$int), 0)]), 0))));
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
const TestEntry.forMethod('generative_constructor(C#)', r"""
class C<X, Y, Z> {
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
index 7d9283e..bb19616 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_supercall_test.dart
@@ -9,7 +9,7 @@
import 'js_backend_cps_ir.dart';
const List<TestEntry> tests = const [
- const TestEntry.forMethod('function(Sub#m)', """
+ const TestEntry("""
class Base {
m(x) {
print(x+1);
@@ -22,8 +22,19 @@
new Sub().m(100);
}""",
r"""
-function(x) {
- return V.Base.prototype.m$1.call(this, x + 10);
+function() {
+ var v0;
+ V.Sub$();
+ v0 = H.S(100 + 10 + 1);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
// Reenable when we support compiling functions that
@@ -51,7 +62,7 @@
// return V.Base.prototype.$add.call(null, v2, v1);
// }"""),
-const TestEntry.forMethod('function(Sub#m)', """
+const TestEntry("""
class Base {
var field = 123;
}
@@ -62,8 +73,17 @@
print(new Sub().m(10));
}""",
r"""
-function(x) {
- return x + this.field;
+function() {
+ var v0 = H.S(10 + V.Sub$().field);
+ if (typeof dartPrint == "function")
+ dartPrint(v0);
+ else if (typeof console == "object" && typeof console.log != "undefined")
+ console.log(v0);
+ else if (!(typeof window == "object")) {
+ if (!(typeof print == "function"))
+ throw "Unable to print message: " + String(v0);
+ print(v0);
+ }
}"""),
diff --git a/tests/compiler/dart2js/memory_compiler.dart b/tests/compiler/dart2js/memory_compiler.dart
index ce01ed0..fa69df7 100644
--- a/tests/compiler/dart2js/memory_compiler.dart
+++ b/tests/compiler/dart2js/memory_compiler.dart
@@ -265,8 +265,7 @@
List<String> options: const [],
bool showDiagnostics: true}) {
Uri libraryRoot = Uri.base.resolve('sdk/');
- Uri packageRoot = Uri.base.resolveUri(
- new Uri.file('${Platform.packageRoot}/'));
+ Uri packageRoot = Uri.base.resolve(Platform.packageRoot);
var provider = new MemorySourceFileProvider(memorySourceFiles);
var handler =
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 9a04a94..4045cfa 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -72,6 +72,7 @@
[ $compiler == dart2js && $cps_ir ]
16407_test: Pass # Please triage this failure.
+code_motion_exception_test: Fail # .toString to null check a primitive, triggered by inlining
async_stacktrace_test/asyncStar: Crash # (foo()async*{try {tr... cannot handle sync*/async* functions
deferred/deferred_class_test: RuntimeError # Z.loadLibrary is not a function
deferred/deferred_constant2_test: RuntimeError # U.loadLibrary is not a function
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index e83f9d9..ad3536a 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -6,12 +6,12 @@
*: Skip
[ $compiler == dart2js ]
-bound_closure_super_test: Fail
call_on_native_class_test: CompileTimeError # Issue 14813
native_no_such_method_exception4_frog_test: CompileTimeError # Issue 9631
native_no_such_method_exception5_frog_test: CompileTimeError # Issue 9631
-[ $compiler == dart2js ]
+[ $compiler == dart2js && $cps_ir == false ]
+bound_closure_super_test: Fail
fake_thing_test: Fail # Issue 13010
[ $compiler == dart2js && $minified ]
@@ -21,10 +21,7 @@
compute_this_script_test: Skip # Issue 17458
[ $compiler == dart2js && $cps_ir ]
+foreign_test: RuntimeError # Fails due to inlining, please triage. Expect.equals(expected: <1234567891011>, actual: <1234567891011>) fails
native_exception_test: RuntimeError # Issue 24421
-native_method_inlining_test: RuntimeError # Please triage this failure.
optimization_hints_test: RuntimeError # Please triage this failure.
-subclassing_constructor_1_test: RuntimeError # Please triage this failure.
subclassing_constructor_2_test: RuntimeError # Please triage this failure.
-subclassing_super_field_1_test: RuntimeError # Please triage this failure.
-subclassing_super_field_2_test: RuntimeError # Please triage this failure.
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 2757d9e..88b3ccd 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -2,7 +2,7 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
bool_from_environment2_test: Skip
bool_from_environment_test: Skip
from_environment_const_type_test: Skip
@@ -14,18 +14,18 @@
string_from_environment3_test: Skip
string_from_environment_test: Skip
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
unicode_test: Fail # Bug 6706
compare_to2_test: Fail # Bug 4018
symbol_test/01: Fail, Pass # bug 11669
# #void should be a valid symbol.
-[ $compiler == none || $compiler == dart2js ]
+[ ($compiler == none || $compiler == precompiler) || $compiler == dart2js ]
symbol_reserved_word_test/02: CompileTimeError # bug 20191
symbol_reserved_word_test/05: CompileTimeError # bug 20191
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
symbol_reserved_word_test/02: RuntimeError # bug 20191 / dartium/drt cannot detect CompileTimeErrors
symbol_reserved_word_test/05: RuntimeError # bug 20191 / dartium/drt cannot detect CompileTimeErrors
@@ -42,27 +42,27 @@
# With the exception of 'void', const Symbol() should not accept reserved
# words.
-[ $compiler == none || $compiler == dart2js ]
+[ ($compiler == none || $compiler == precompiler) || $compiler == dart2js ]
symbol_reserved_word_test/04: MissingCompileTimeError # bug 11669, 19972
symbol_reserved_word_test/07: MissingCompileTimeError # bug 11669, 19972
symbol_reserved_word_test/10: MissingCompileTimeError # bug 11669, 19972
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
symbol_reserved_word_test/04: Fail # bug 11669, 19972 / dartium/drt cannot detect CompileTimeErrors
symbol_reserved_word_test/07: Fail # bug 11669, 19972 / dartium/drt cannot detect CompileTimeErrors
symbol_reserved_word_test/10: Fail # bug 11669, 19972 / dartium/drt cannot detect CompileTimeErrors
# With the exception of 'void', new Symbol() should not accept reserved words.
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
symbol_reserved_word_test/06: RuntimeError # bug 11669
symbol_reserved_word_test/09: RuntimeError # bug 11669
symbol_reserved_word_test/12: RuntimeError # bug 11669
-[ $compiler == none && $runtime != dartium && $runtime != drt && $runtime != ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime != dartium && $runtime != drt && $runtime != ContentShellOnAndroid ]
symbol_test/02: MissingCompileTimeError # bug 11669
symbol_test/03: MissingCompileTimeError # bug 11669
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
symbol_test/none: Fail # bug 11669
symbol_operator_test/03: Fail # bug 11669
string_case_test/01: Fail # Bug 18061
@@ -70,10 +70,10 @@
iterable_return_type_test/01: RuntimeError # Issue 13646
iterable_return_type_test/02: RuntimeError # Issue 13646
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
main_test: Fail # Dartium needs to check for both main() and main(args).
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
core_runtime_types_test: Pass, Fail # Issue 20525
[ $runtime == ff || $runtime == jsshell ]
@@ -170,7 +170,7 @@
# The regexp tests are not verified to work on non d8/vm platforms yet.
regexp/*: Skip
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
regexp/global_test: Skip # Timeout. Issue 21709 and 21708
[ $runtime != vm && $compiler != dart2analyzer]
@@ -182,7 +182,7 @@
[ $mode == debug ]
regexp/pcre_test: Pass, Slow # Timeout. Issue 22008
-[ $runtime == vm && $arch == simarmv5te ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $arch == simarmv5te ]
int_parse_radix_test/*: Pass, Slow
big_integer_parsed_mul_div_vm_test: Pass, Slow
@@ -211,7 +211,7 @@
[ $compiler == dart2js && $cps_ir && $host_checked ]
regexp/pcre_test: Crash # Stack Overflow
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
apply3_test: CompileTimeError # Imports dart:mirrors
regexp/stack-overflow_test: RuntimeError, OK # Smaller limit with irregex interpreter
big_integer_huge_mul_vm_test: Pass, Timeout # --no_intrinsify
diff --git a/tests/corelib/string_replace_all_test.dart b/tests/corelib/string_replace_all_test.dart
index 299d56a..f63a9f7 100644
--- a/tests/corelib/string_replace_all_test.dart
+++ b/tests/corelib/string_replace_all_test.dart
@@ -46,6 +46,16 @@
// Test replacing the empty string.
Expect.equals("toAtoBtoCto", "ABC".replaceAll("", "to"));
+
+ // Pattern strings containing RegExp metacharacters - these are not
+ // interpreted as RegExps.
+ Expect.equals(r"$$", "||".replaceAll("|", r"$"));
+ Expect.equals(r"$$$$", "||".replaceAll("|", r"$$"));
+ Expect.equals(r"x$|x", "x|.|x".replaceAll("|.", r"$"));
+ Expect.equals(r"$$", "..".replaceAll(".", r"$"));
+ Expect.equals(r"[$$$$]", "[..]".replaceAll(".", r"$$"));
+ Expect.equals(r"[$]", "[..]".replaceAll("..", r"$"));
+ Expect.equals(r"$$", r"\\".replaceAll(r"\", r"$"));
}
testReplaceAllMapped() {
diff --git a/tests/html/html.status b/tests/html/html.status
index faeaa01..1783cf0 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -382,7 +382,7 @@
# 'html' tests import the HTML library, so they only make sense in
# a browser environment.
-[ $runtime == vm ]
+[ $runtime == vm || $runtime == dart_precompiled ]
*: Skip
[ $compiler == dart2js && ($runtime == drt || $runtime == ff) ]
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 04bb204..71e28ae 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -2,17 +2,17 @@
# 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.
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
browser/*: SkipByDesign # Browser specific tests
isolate_stress_test: Fail # Issue 12588: This should be able to pass when we have wrapper-less tests.
[ $runtime != vm ]
checked_test: Skip # Unsupported.
-[ $runtime == vm && $arch == mips && $mode == debug ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $arch == mips && $mode == debug ]
mandel_isolate_test: Skip # Uses 600 MB Ram on our 1 GB test device.
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
compile_time_error_test/01: Skip # Issue 12587
ping_test: Skip # Resolve test issues
ping_pause_test: Skip # Resolve test issues
@@ -20,7 +20,7 @@
message3_test/int32x4: Crash, Timeout # Issue 21818
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
*: Skip # Isolate tests are timing out flakily on Android content_shell. Issue 19795
[ $compiler == dart2js && $runtime == safarimobilesim ]
@@ -78,25 +78,25 @@
[ $compiler == dart2js && $runtime == chromeOnAndroid ]
unresolved_ports_test: Pass, Timeout # Issue 15610
-[ $compiler == none && $runtime == drt ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == drt ]
spawn_uri_nested_vm_test: Skip # Issue 14463
[ $jscl ]
spawn_uri_multi_test/none: RuntimeError # Issue 13544
-[ $compiler == none && ($runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
pause_test: Fail # Not implemented yet
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
nested_spawn2_test: Skip # Issue 19127: This test is timing out.
-[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
spawn_uri_nested_vm_test: Skip # Issue 14479: This test is timing out.
-[ $compiler == none && $runtime == dartium && $arch == x64 ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == dartium && $arch == x64 ]
isolate/spawn_uri_multi_test/01: Skip # Times out. Issue 24795
-[ $compiler == none && ( $runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ( $runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
typed_message_test: Crash, Fail # Issue 13921, 14400
message_enum_test: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
compile_time_error_test/none: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
@@ -143,9 +143,8 @@
[ $compiler == dart2js && $cps_ir ]
deferred_in_isolate2_test: RuntimeError # A.loadLibrary is not a function
-isolate_current_test: RuntimeError # Please triage this failure.
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
# Imports dart:mirrors
count_test: CompileTimeError
cross_isolate_message_test: CompileTimeError
@@ -166,3 +165,19 @@
stacktrace_message_test: CompileTimeError
static_function_test: CompileTimeError
unresolved_ports_test: CompileTimeError
+
+[ $runtime == dart_precompiled ]
+deferred_in_isolate_test: Skip # Isolate.spawnUri
+deferred_in_isolate2_test: Skip # Isolate.spawnUri
+exit_at_spawnuri_test: Skip # Isolate.spawnUri
+error_exit_at_spawnuri_test: Skip # Isolate.spawnUri
+issue_24243_parent_isolate_test: Skip # Isolate.spawnUri
+issue_21398_parent_isolate1_test: Skip # Isolate.spawnUri
+spawn_uri_exported_main_test: Skip # Isolate.spawnUri
+spawn_uri_test: Skip # Isolate.spawnUri
+spawn_uri_nested_vm_test: Skip # Isolate.spawnUri
+deferred_in_isolate_test: Skip # Isolate.spawnUri
+spawn_uri_multi_test: Skip # Isolate.spawnUri
+spawn_uri_vm_test: Skip # Isolate.spawnUri
+issue_21398_parent_isolate_test: Skip # Isolate.spawnUri
+error_at_spawnuri_test: Skip # Isolate.spawnUri
diff --git a/tests/language/const_string_test.dart b/tests/language/const_string_test.dart
index 4736ca4..13f1a9c 100644
--- a/tests/language/const_string_test.dart
+++ b/tests/language/const_string_test.dart
@@ -6,6 +6,8 @@
// Exercises compile-time string constants
+const yz = "y" + "z";
+
main() {
// Constant comparisons are independent of the quotes used.
Expect.isTrue(identical("abcd", 'abcd'));
@@ -34,4 +36,16 @@
Expect.isTrue(identical('a\'b\'cd', "a" "'b'" 'c' "d"));
Expect.isTrue(identical('a"b"cd', 'a' '"b"' 'c' "d"));
Expect.isTrue(identical("a\"b\"cd", 'a' '"b"' 'c' "d"));
+
+ const a = identical("ab", "a" + "b");
+ Expect.isTrue(a);
+
+ const b = identical("xyz", "x" + yz);
+ Expect.isTrue(b);
+
+ const c = identical("12", "1" "2");
+ Expect.isTrue(c);
+
+ const d = identical("zyz", "z$yz");
+ Expect.isTrue(d);
}
diff --git a/tests/language/language.status b/tests/language/language.status
index 79d8804..b16b0c9 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -5,15 +5,21 @@
# This directory contains tests that are intended to show the
# current state of the language.
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
built_in_identifier_prefix_test: Fail # Issue 6970
tearoff_constructor_basic_test: Skip # Crashes in checked mode -- hausner investigating
# These bugs refer currently ongoing language discussions.
-constructor_initializer_test/none: Fail # Issue 12633
constructor5_test: Fail # Issue 6422
constructor6_test: Fail # Issue 6422
-closure_in_initializer_test: Fail # Issue 6422
+
+# Failures related to super call in ctor initializer list
+super_test: Fail, OK
+final_field_initialization_order_test: Fail, OK
+field_initialization_order_test: Fail, OK
+example_constructor_test: Fail, OK
+constructor3_test: Fail, OK
+constructor2_test: Fail, OK
# Regular bugs which should be fixed.
duplicate_export_negative_test: Fail # Issue 6134
@@ -34,24 +40,24 @@
# Unsupported configuration specific imports.
config_import_test: Fail # Issue 24581
-[ $compiler == none && $runtime == vm ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) ]
class_keyword_test/02: MissingCompileTimeError # Issue 13627
unicode_bom_test: Fail # Issue 16067
vm/debug_break_enabled_vm_test/01: Crash, OK # Expected to hit breakpoint.
try_catch_optimized1_test: Skip # Srdjan investigating
-[ $compiler == none && $checked ]
+[ ($compiler == none || $compiler == precompiler) && $checked ]
type_variable_bounds4_test/01: Fail # Issue 14006
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
dynamic_prefix_core_test/01: RuntimeError # Issue 12478
multiline_strings_test: Fail # Issue 23020
-[ $compiler == none && ($runtime == vm || $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && (($runtime == vm || $runtime == dart_precompiled) || $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
dynamic_prefix_core_test/none: Fail # Issue 12478
export_ambiguous_main_negative_test: Fail # Issue 14763
-[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
assertion_test: Fail # Issue 14651.
generic_test: Fail # Issue 14651.
list_literal4_test: Fail # Issue 14651.
@@ -64,7 +70,7 @@
type_checks_in_factory_method_test: Fail # Issue 14651.
vm/type_vm_test: Fail # Issue 14651.
-[ $compiler == none && ( $runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ( $runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) ]
issue13474_test: Pass, Fail # Issue 14651.
vm/optimized_guarded_field_isolates_test: Fail # Issue 13921.
main_test/01: Fail # Issue 20028
@@ -76,36 +82,36 @@
mirror_in_static_init_test: Fail # Issue 22071
vm/debug_break_enabled_vm_test/*: Skip # Issue 14651.
-[ $compiler == none && $runtime == dartium && $system == linux && $arch != x64 ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == dartium && $system == linux && $arch != x64 ]
issue_22780_test/01 : Pass, Timeout # Issue 24473
-[ $compiler == none && $runtime == drt ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == drt ]
disassemble_test: Pass, Fail # Issue 18122
-[ $compiler == none && $runtime == vm && $arch == mips && $checked ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $arch == mips && $checked ]
generic_instanceof3_test: Pass, Crash # Issue 17440.
-[ $compiler == none && $runtime == vm && $arch == mips && $mode == debug ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $arch == mips && $mode == debug ]
stack_overflow_test: Skip # Crashes. Issue 17440.
stack_overflow_stacktrace_test: Skip # Crashes. Issue 17440.
large_class_declaration_test: SkipSlow # Times out. Issue 20352
-[ $compiler == none && ($runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) && $mode == debug ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == drt || $runtime == ContentShellOnAndroid) && $mode == debug ]
large_class_declaration_test: SkipSlow # Times out. Issue 20352
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
gc_test: SkipSlow # Times out flakily. Issue 20956
-[ $compiler == none && $runtime == vm && ( $arch == simarm || $arch == arm || $arch == simarmv5te || $arch == armv5te || $arch == simarm64 || $arch == arm64 || $arch == simmips || $arch == mips) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ( $arch == simarm || $arch == arm || $arch == simarmv5te || $arch == armv5te || $arch == simarm64 || $arch == arm64 || $arch == simmips || $arch == mips) ]
vm/load_to_load_unaligned_forwarding_vm_test: Pass, Crash # Unaligned offset. Issue 22151
-[ $compiler == none && $runtime == dartium ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == dartium ]
issue23244_test: Fail # Issue 23244
-[ $compiler == none && ($runtime == vm || $runtime == drt || $runtime == dartium) && $arch == ia32 ]
+[ ($compiler == none || $compiler == precompiler) && (($runtime == vm || $runtime == dart_precompiled) || $runtime == drt || $runtime == dartium) && $arch == ia32 ]
vm/regress_24517_test: Pass, Fail # Issue 24517.
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
# Imports dart:mirrors
const_evaluation_test: CompileTimeError
deferred_constraints_constants_test: CompileTimeError
@@ -139,3 +145,9 @@
tearoff_basic_test: RuntimeError, Crash # Conflicting flag.
vm/type_cast_vm_test: RuntimeError # Line number mismatch.
stack_trace_test: Fail # Issue 24783 - inlined frames missing
+
+[ $runtime == dart_precompiled ]
+ct_const2_test: Pass, Crash # Incompatible flag --compile_all
+hello_dart_test: Pass, Crash # Incompatible flag --compile_all
+
+implicit_closure_test: Pass, Crash # --use_slow_path
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index e872f46..2ec0676 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -165,7 +165,6 @@
const_dynamic_type_literal_test/03: CompileTimeError # Issue 23009
# Compilation errors.
-method_override5_test: RuntimeError # Issue 12809
external_test/10: CompileTimeError # Issue 12887
external_test/13: CompileTimeError # Issue 12887
external_test/20: CompileTimeError # Issue 12887
@@ -217,12 +216,12 @@
generic_field_mixin4_test: Crash # Issue 18651
generic_field_mixin5_test: Crash # Issue 18651
many_method_calls_test: Crash # Stack overflow in HGraphVisitor.visitPostDominatorTree.visitBasicBlockAndSuccessors
+method_override5_test: RuntimeError # Issue 12809
[ $compiler == dart2js && $runtime != drt && $runtime != dartium ]
issue23244_test: RuntimeError # 23244
[ $compiler == dart2js && $cps_ir ]
-assert_assignable_type_test: Crash # Internal Error: Pending statics.
async_await_syntax_test/a03a: Crash # (a03a()async*{}): cannot handle sync*/async* functions
async_await_syntax_test/a03b: Crash # (a03b()async*{}): cannot handle sync*/async* functions
async_await_syntax_test/a06a: Crash # (await for(var o in st){}): await for
@@ -336,6 +335,7 @@
regress_22443_test: RuntimeError # M.loadLibrary is not a function
regress_23408_test: RuntimeError # G.loadLibrary is not a function
regress_23500_test/01: Crash # (await for(var c in new Stream.fromIterable([] )){}): await for
+stack_trace_test: Fail # Stack trace not preserved when inlining?
super_call4_test: RuntimeError # Please triage this failure.
super_getter_setter_test: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
super_operator_index5_test: Crash # (super[0]=42): visitUnresolvedSuperIndexSet
@@ -351,6 +351,9 @@
type_variable_field_initializer_test: RuntimeError # Please triage this failure.
type_variable_nested_test: RuntimeError # Please triage this failure.
+[ $compiler == dart2js && $cps_ir && $host_checked == false ]
+regress_21795_test: RuntimeError # Due to inlining?
+
[ $compiler == dart2js && $cps_ir && $host_checked ]
async_throw_in_catch_test/forceAwait: Crash # Issue 24485
async_throw_in_catch_test/none: Crash # Issue 24485
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 8c17e5b..5a8dcdb 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -186,7 +186,7 @@
# 'js' tests import the dart:js library, so they only make sense in
# a browser environment.
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
js/*: Skip
[ $compiler == dart2js && $minified ]
@@ -223,19 +223,19 @@
# TODO(efortuna): Investigate.
async/timer_test: Fail, Pass
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
async/timer_not_available_test: Fail, OK
mirrors/native_class_test: Fail, OK # This test is meant to run in a browser.
mirrors/deferred_type_test: CompileTimeError, OK # Don't have a multitest marker for dynamic compile time errors.
-[ $compiler == none ]
+[ ($compiler == none || $compiler == precompiler) ]
async/timer_not_available_test: SkipByDesign # only meant to test when there is no way to implement timer (currently only in d8)
mirrors/symbol_validation_test: RuntimeError # Issue 13596
mirrors/mirrors_used*: SkipByDesign # Invalid tests. MirrorsUsed does not have a specification, and dart:mirrors is not required to hide declarations that are not covered by any MirrorsUsed annotation.
-[ $compiler == none && ( $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ( $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
async/schedule_microtask6_test: Fail # Issue 10910
async/timer_test: Fail, Pass # Issue 15487
async/multiple_timer_test: Fail, Pass # Issue 15487
@@ -248,14 +248,14 @@
mirrors/local_isolate_test: RuntimeError # Issue 12188
mirrors/deferred_type_test: RuntimeError, OK # Should be CompileTimeError. Issue 22072
-[ $compiler == none && $runtime == drt && $system == windows ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == drt && $system == windows ]
async/multiple_timer_test: Fail, Pass # See Issue 10982
async/timer_test: Fail, Pass # See Issue 10982
-[ $compiler == none && $runtime == drt && $checked ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == drt && $checked ]
async/slow_consumer_test: Fail, Pass # Dartium JsInterop failure, dartbug.com/24460
-[$compiler == none && $runtime == ContentShellOnAndroid ]
+[($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
async/stream_timeout_test: RuntimeError, Pass # Issue 19127
async/slow_consumer3_test: SkipSlow # Times out flakily. Issue 20956
async/slow_consumer2_test: SkipSlow # Times out flakily. Issue 20956
@@ -305,7 +305,7 @@
[ $compiler == dart2js && $mode == debug ]
mirrors/native_class_test: Pass, Slow
-[ $compiler == none && $arch == mips ]
+[ ($compiler == none || $compiler == precompiler) && $arch == mips ]
async/timer_regress22626_test: Pass, RuntimeError # Issue 22626
[ $arch == simarm || $arch == simarmv5te ]
@@ -325,16 +325,16 @@
[ $mode == debug && $arch == ia32 && $system == windows ]
convert/streamed_conversion_json_utf8_decode_test: Skip # Verification OOM.
-[ $runtime == vm && $mode == debug && $arch == x64 && $system == windows ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $arch == x64 && $system == windows ]
convert/streamed_conversion_json_utf8_decode_test: Pass, Slow
-[ $runtime == vm && $mode == release && $arch == ia32 && $system == windows ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == release && $arch == ia32 && $system == windows ]
convert/json_test: RuntimeError # Issue 24908
[ $mode == debug && $arch != ia32 && $arch != x64 && $arch != simarm && $arch != simarmv5te ]
convert/streamed_conversion_json_utf8_decode_test: Skip # Verification not yet implemented.
-[ $runtime == vm && $mode == debug && $builder_tag == asan ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $builder_tag == asan ]
mirrors/immutable_collections_test: SkipSlow # Timeout.
convert/streamed_conversion_json_utf8_decode_test: Skip # Timeout.
@@ -357,7 +357,7 @@
[ $compiler != dart2js ]
async/dart2js_uncaught_error_test: Skip # JS-integration only test
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
mirrors/*: SkipByDesign
convert/chunked_conversion_utf88_test: Pass, Timeout
convert/utf85_test: Pass, Timeout
diff --git a/tests/standalone/io/create_sample_certificates.sh b/tests/standalone/io/create_sample_certificates.sh
index 7ab6f75..cabe747 100755
--- a/tests/standalone/io/create_sample_certificates.sh
+++ b/tests/standalone/io/create_sample_certificates.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# 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.
diff --git a/tests/standalone/precompilation_dart2js_test.dart b/tests/standalone/precompilation_dart2js_test.dart
index 303c955..5d3900e 100644
--- a/tests/standalone/precompilation_dart2js_test.dart
+++ b/tests/standalone/precompilation_dart2js_test.dart
@@ -43,8 +43,7 @@
return;
}
- var pkgRoot = Uri.parse(Platform.packageRoot);
- var abs_package_root = new File.fromUri(pkgRoot).absolute.path;
+ var abs_package_root = Uri.parse(Platform.packageRoot).toFilePath();
var dart_executable =
Directory.current.path + Platform.pathSeparator + Platform.executable;
Directory tmp;
diff --git a/tests/standalone/regress_25335_test.dart b/tests/standalone/regress_25335_test.dart
new file mode 100644
index 0000000..e4551a2
--- /dev/null
+++ b/tests/standalone/regress_25335_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.
+//
+// Test that canonicalization inserts constants with correct representation.
+// VMOptions=--optimization-counter-threshold=10 --optimization-filter=bar
+
+import 'dart:typed_data';
+
+toSigned(v, width) {
+ var signMask = 1 << (width - 1);
+ return (v & (signMask - 1)) - (v & signMask);
+}
+
+foo(value) {
+ return value >> 32;
+}
+
+bar(td) {
+ return toSigned(foo(td[0]), 64);
+}
+
+main() {
+ toSigned(1 << 1, 32);
+ toSigned(1 << 32, 32);
+
+ var l = new Int64List(1);
+ l[0] = 0xf8f7f6f5f4f3f2f1;
+
+ for (var i = 0; i < 20; i++) {
+ bar(l);
+ }
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 241086a..948099d 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -17,15 +17,15 @@
javascript_compatibility_errors_test/none: Fail, OK # Not possible to exclude or annotate with '/// none:'
-[ $runtime != vm && ($runtime != drt || $compiler != none)) ]
+[ ($runtime != vm && $runtime != dart_precompiled) && ($runtime != drt || $compiler != none)) ]
no_assert_test: Fail, OK # This is testing a vm flag.
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
package/package_isolate_test: Fail # Issue 12474
io/observatory_test: Fail
package/scenarios/invalid/same_package_twice_test: Pass # Issue 24119
-[ $runtime == vm && $checked ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $checked ]
# These tests have type errors on purpose.
io/process_invalid_arguments_test: Fail, OK
io/directory_invalid_arguments_test: Fail, OK
@@ -38,13 +38,13 @@
io/file_fuzz_test: Skip
io/directory_fuzz_test: Skip
-[ $runtime == vm && $system == macos ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $system == macos ]
# This test fails with "Too many open files" on the Mac OS buildbot.
# This is expected as MacOS by default runs with a very low number
# of allowed open files ('ulimit -n' says something like 256).
io/socket_many_connections_test: Skip
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
typed_array_test: Fail # Issue 13921
typed_array_int64_uint64_test: Fail # Issue 13921
typed_data_isolate_test: SkipByDesign # This test uses dart:io
@@ -106,6 +106,7 @@
precompilation_test: Skip # Standalone only test.
precompilation_dart2js_test: Skip # Standalone only test.
noopt_test: Skip # Standalone only test.
+regress_25335_test: Skip # Int64List not supported.
[ $runtime == vm && $mode == debug ]
precompilation_dart2js_test: Pass, Slow
@@ -157,10 +158,10 @@
full_coverage_test: SkipSlow # Times out. Issue 20352
io/http_client_stays_alive_test: Skip # Timing dependent test, MIPS machine too slow.
-[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
assert_test: Fail # Issue 14651.
-[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
javascript_int_overflow_literal_test/01: Fail # Issue 14651.
javascript_int_overflow_test: Fail # Issue 14651.
@@ -205,19 +206,62 @@
[ $arch != ia32 && $arch != x64 && $arch != simarm && $arch != simarmv5te && $mode == debug ]
verified_mem_test: Skip # Not yet implemented.
-[ $runtime == vm && $mode == debug && $builder_tag == asan ]
+[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $builder_tag == asan ]
full_coverage_test: Skip # Timeout.
io/file_lock_test: Skip # Timeout.
io/test_runner_test: Skip # Timeout.
io/http_client_stays_alive_test: Skip # Timeout.
-[ $runtime == vm ]
+[ ($runtime == vm || $runtime == dart_precompiled) ]
# Failures in secure networking while NSS is replaced with BoringSSL
io/https_client_certificate_test: RuntimeError # Issue 24070
io/secure_socket_renegotiate_test: RuntimeError
io/secure_socket_bad_data_test: RuntimeError # An error in a secure connection just puts a READ_CLOSED on the stream, rather than signaling an error on the stream.
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
map_literal_oom_test: Pass, Crash # Issue 24678
javascript*: SkipByDesign # JS overflow flag unsupported
io/web_socket_test: Pass, RuntimeError # Issue 24674
+
+[ $runtime == dart_precompiled ]
+debugger/*: Skip
+noopt_test: Skip
+precompilation_dart2js_test: Skip
+
+full_coverage_test: RuntimeError # Platform.executable
+http_launch_test: RuntimeError # Platform.executable
+io/addlatexhash_test: RuntimeError # Platform.executable
+io/compile_all_test: Crash # Incompatible flag --compile_all
+io/file_read_special_device_test: RuntimeError # Platform.executable
+io/file_stream_test: RuntimeError # Platform.executable
+io/file_test: RuntimeError # Platform.executable
+io/http_cross_process_test: RuntimeError # Platform.executable
+io/https_unauthorized_test: RuntimeError # Platform.executable
+io/platform_resolved_executable_test: RuntimeError # Platform.resolvedExecutable
+io/skipping_dart2js_compilations_test: RuntimeError # Platform.executable
+io/snapshot_fail_test: RuntimeError # Platform.executable
+io/stdin_sync_test: RuntimeError # Platform.executable
+io/test_extension_fail_test: RuntimeError # Platform.executable
+precompilation_test: RuntimeError # Platform.executable
+standalone/io/file_read_special_device_test: RuntimeError # Platform.executable
+verbose_gc_to_bmu_test: RuntimeError # Platform.executable
+io/http_server_close_response_after_error_test: RuntimeError # Platform.executable
+io/http_client_stays_alive_test: RuntimeError # Platform.executable
+io/print_sync_test: RuntimeError # Platform.executable
+io/signals_test: RuntimeError # Platform.executable
+io/stdio_nonblocking_test: RuntimeError # Platform.executable
+io/regress_7191_test: RuntimeError # Platform.executable
+io/secure_unauthorized_test: RuntimeError # Platform.executable
+io/dart_std_io_pipe_test: RuntimeError # Platform.executable
+io/platform_test: RuntimeError # Platform.executable
+io/socket_cross_process_test: RuntimeError # Platform.executable
+io/test_runner_test: RuntimeError # Platform.executable
+io/file_lock_test: RuntimeError # Platform.executable
+io/code_collection_test: RuntimeError # Platform.executable
+io/file_lock_test: RuntimeError # Platform.executable
+io/code_collection_test: RuntimeError # Platform.executable
+io/raw_socket_cross_process_test: RuntimeError # Platform.executable
+io/test_extension_test: RuntimeError # Platform.executable
+io/regress_7679_test: RuntimeError # Platform.executable
+
+io/process_*: Skip # Most use Platform.executable
\ No newline at end of file
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index 1f6c520..bf69360 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -13,14 +13,14 @@
[ $compiler == dart2js && $browser ]
*: Skip
-[ $compiler == none && $runtime != vm ]
+[ ($compiler == none || $compiler == precompiler) && $runtime != vm ]
dart2js_test: SkipByDesign # Uses dart:io.
[ $compiler == dart2js && $mode == debug ]
dummy_compiler_test: Slow, Pass
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
+[ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
dummy_compiler_test: Pass, RuntimeError # Issue 17662
recursive_import_test: Pass, RuntimeError # Issue 17662
source_mirrors_test: Pass, RuntimeError # Issue 17662
@@ -30,5 +30,5 @@
recursive_import_test: Crash # (switch (function.na... continue to a labeled switch case
source_mirrors_test: Crash, Slow # (switch (function.na... continue to a labeled switch case
-[ $noopt ]
+[ ($noopt || $compiler == precompiler) ]
source_mirrors_test: SkipByDesign # Imports dart:mirrors
diff --git a/third_party/.gitignore b/third_party/.gitignore
index a55ad28..3f481f1 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -6,4 +6,9 @@
!pkg
!pkg_tested
!boringssl
+!drt_resources
!d8
+!7zip.tar.gz.sha1
+!firefox_jsshell
+!gsutil.tar.gz.sha1
+!clang.tar.gz.sha1
\ No newline at end of file
diff --git a/third_party/7zip.tar.gz.sha1 b/third_party/7zip.tar.gz.sha1
new file mode 100644
index 0000000..83e790b
--- /dev/null
+++ b/third_party/7zip.tar.gz.sha1
@@ -0,0 +1 @@
+22fe352b3c39c4281a599cf8576abef80ec44cc9
\ No newline at end of file
diff --git a/third_party/clang.tar.gz.sha1 b/third_party/clang.tar.gz.sha1
new file mode 100644
index 0000000..027ff64
--- /dev/null
+++ b/third_party/clang.tar.gz.sha1
@@ -0,0 +1 @@
+9eec86b20d62ad8d5bc6af617e91f01ae4354166
\ No newline at end of file
diff --git a/third_party/drt_resources/.gitignore b/third_party/drt_resources/.gitignore
new file mode 100644
index 0000000..7912236
--- /dev/null
+++ b/third_party/drt_resources/.gitignore
@@ -0,0 +1 @@
+AHEM____.TTF
diff --git a/third_party/drt_resources/AHEM____.TTF.sha1 b/third_party/drt_resources/AHEM____.TTF.sha1
new file mode 100644
index 0000000..bba0dbc
--- /dev/null
+++ b/third_party/drt_resources/AHEM____.TTF.sha1
@@ -0,0 +1 @@
+8cdc9e68594fbb6db8c7b4bff643ab2432b51db6
\ No newline at end of file
diff --git a/third_party/drt_resources/README.md b/third_party/drt_resources/README.md
new file mode 100644
index 0000000..c981e5b
--- /dev/null
+++ b/third_party/drt_resources/README.md
@@ -0,0 +1,6 @@
+# Content-shell resources
+
+The layout tests of content_shell (formerly called DumpRenderTree, drt)
+require a font called AHEM____.TTF on Windows. This resource is downloaded
+from cloud storage, using the hash in AHEM____.TTF.sha1, by a hook
+in the DEPS file, that is run by gclient sync or gclient runhooks.
diff --git a/third_party/firefox_jsshell/README.google b/third_party/firefox_jsshell/README.google
new file mode 100644
index 0000000..08b90f8
--- /dev/null
+++ b/third_party/firefox_jsshell/README.google
@@ -0,0 +1,12 @@
+Name: Firefox command line javascript shell.
+Short Name: js-shell
+URL: http://ftp.mozilla.org/pub/mozilla.org/firefox/candidates/38-candidates/build2/
+Version: JavaScript-C38
+Date: May 05 2015
+License: MPL, http://www.mozilla.org/MPL
+
+Description:
+This directory contains the firefox js-shell binaries for Windows, Mac and
+Linux.
+The binaries are used for testing dart code compiled to javascript.
+
diff --git a/third_party/firefox_jsshell/linux/jsshell.tar.gz.sha1 b/third_party/firefox_jsshell/linux/jsshell.tar.gz.sha1
new file mode 100644
index 0000000..8f8d719
--- /dev/null
+++ b/third_party/firefox_jsshell/linux/jsshell.tar.gz.sha1
@@ -0,0 +1 @@
+624241d790b53c24ea67997ed658f31f1ed9292d
\ No newline at end of file
diff --git a/third_party/firefox_jsshell/mac/jsshell.tar.gz.sha1 b/third_party/firefox_jsshell/mac/jsshell.tar.gz.sha1
new file mode 100644
index 0000000..a5c645a
--- /dev/null
+++ b/third_party/firefox_jsshell/mac/jsshell.tar.gz.sha1
@@ -0,0 +1 @@
+16c59a086b713720df0154cd4ceaed2ee8cf0d33
\ No newline at end of file
diff --git a/third_party/firefox_jsshell/win/jsshell.tar.gz.sha1 b/third_party/firefox_jsshell/win/jsshell.tar.gz.sha1
new file mode 100644
index 0000000..d43fcd1
--- /dev/null
+++ b/third_party/firefox_jsshell/win/jsshell.tar.gz.sha1
@@ -0,0 +1 @@
+a7ed194f518813a9915f67026ef138dd96adfec1
\ No newline at end of file
diff --git a/third_party/gsutil.tar.gz.sha1 b/third_party/gsutil.tar.gz.sha1
new file mode 100644
index 0000000..cfc510a
--- /dev/null
+++ b/third_party/gsutil.tar.gz.sha1
@@ -0,0 +1 @@
+99b82a42b98b78fc2a3f155995a16d8d7517b657
\ No newline at end of file
diff --git a/third_party/pkg/petitparser.tar.gz.sha1 b/third_party/pkg/petitparser.tar.gz.sha1
new file mode 100644
index 0000000..20b3196
--- /dev/null
+++ b/third_party/pkg/petitparser.tar.gz.sha1
@@ -0,0 +1 @@
+9626eed1ad9963e782f55a943ee8a1f82ff251a1
\ No newline at end of file
diff --git a/tools/FAKE_COMMITS b/tools/FAKE_COMMITS
index 709ba90..4a2c46d 100644
--- a/tools/FAKE_COMMITS
+++ b/tools/FAKE_COMMITS
@@ -15,3 +15,4 @@
Trigger bots
Purple is the new green.
googlecode back up
+CIT outage - all slaves rebooted
diff --git a/tools/VERSION b/tools/VERSION
index 083073e..d53b55e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 1
MINOR 14
PATCH 0
-PRERELEASE 5
+PRERELEASE 6
PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/bin/ssh_with_key b/tools/apps/update_homebrew/bin/ssh_with_key
index 210ad1c..6df4a04 100755
--- a/tools/apps/update_homebrew/bin/ssh_with_key
+++ b/tools/apps/update_homebrew/bin/ssh_with_key
@@ -1,2 +1,2 @@
-#!/bin/bash
+#!/usr/bin/env bash
ssh -i $SSH_KEY_PATH $@
diff --git a/tools/apps/update_homebrew/bin/update_homebrew.dart b/tools/apps/update_homebrew/bin/update_homebrew.dart
index 50474c93..4623e9a 100644
--- a/tools/apps/update_homebrew/bin/update_homebrew.dart
+++ b/tools/apps/update_homebrew/bin/update_homebrew.dart
@@ -186,7 +186,7 @@
def shim_script target
<<-EOS.undent
- #!/bin/bash
+ #!/usr/bin/env bash
exec "#{prefix}/#{target}" "\$@"
EOS
end
diff --git a/tools/bots/run_android_tests.sh b/tools/bots/run_android_tests.sh
index 6bd2034..4b05094 100755
--- a/tools/bots/run_android_tests.sh
+++ b/tools/bots/run_android_tests.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
diff --git a/tools/create_debian_chroot.sh b/tools/create_debian_chroot.sh
index fdb1cf2..0f42c3e3 100755
--- a/tools/create_debian_chroot.sh
+++ b/tools/create_debian_chroot.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
diff --git a/tools/dartium/download_shellscript_template.sh b/tools/dartium/download_shellscript_template.sh
index 3399945..5e44053 100644
--- a/tools/dartium/download_shellscript_template.sh
+++ b/tools/dartium/download_shellscript_template.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2013, 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.
diff --git a/tools/dartium/start_dartium_roll.sh b/tools/dartium/start_dartium_roll.sh
index 41aebbf..d908620 100755
--- a/tools/dartium/start_dartium_roll.sh
+++ b/tools/dartium/start_dartium_roll.sh
@@ -1,4 +1,6 @@
-#!/bin/bash -e
+#!/usr/bin/env bash
+
+set -e
# Requirements:
# sudo apt-get install xclip
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 08529ef..135dd34 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -69,6 +69,7 @@
"yaml_rev": "@563a5ffd4a800a2897b8f4dd6b19f2a370df2f2b",
"zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
"web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
+ "WebCore_rev": "@4f90b41b0165f23f412cecdba07b7d81d3fbb5b5",
"co19_rev": "@3ed795ea02e022ef19c77cf1b6095b7c8f5584d0",
})
@@ -186,7 +187,7 @@
(Var("github_mirror") % "test") + Var("unittest_tag"),
"src/dart/third_party/WebCore":
- "http://dart.googlecode.com/svn/third_party/WebCore",
+ "https://github.com/dart-lang/webcore.git" + Var("WebCore_rev"),
"src/dart/tests/co19/src":
(Var("github_mirror") % "co19") + Var("co19_rev"),
diff --git a/tools/dom/scripts/go.sh b/tools/dom/scripts/go.sh
index 946bdb9..c17719f 100755
--- a/tools/dom/scripts/go.sh
+++ b/tools/dom/scripts/go.sh
@@ -1,5 +1,8 @@
-#!/bin/bash -x
+#!/usr/bin/env bash
#
+
+set -x
+
# go.sh [systems]
#
# Convenience script to generate systems. Do not call from build steps or tests
diff --git a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
index 1b4b7e6..191d2db 100644
--- a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
@@ -295,16 +295,9 @@
createdParametersValid = createdParametersValid && parameter.isOptional;
});
}
-
- // Get the created constructor source and look at the initializer;
- // Must call super.created() if not its as an error.
- var createdSource = methodMirror.source;
- superCreatedCalled = createdSource.contains("super.created(");
}
- if (!superCreatedCalled) {
- throw new DomException.jsInterop('created constructor initializer must call super.created()');
- } else if (!createdParametersValid) {
+ if (!createdParametersValid) {
throw new DomException.jsInterop('created constructor must have no parameters');
}
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 896e204..d891762 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -47,10 +47,11 @@
*/
Document get document => JS('Document', '#.document', this);
- WindowBase _open2(url, name) => JS('Window', '#.open(#,#)', this, url, name);
+ WindowBase _open2(url, name) =>
+ JS('Window|Null', '#.open(#,#)', this, url, name);
WindowBase _open3(url, name, options) =>
- JS('Window', '#.open(#,#,#)', this, url, name, options);
+ JS('Window|Null', '#.open(#,#,#)', this, url, name, options);
/**
* Opens a new window.
diff --git a/tools/precompilation/precompiler.dart b/tools/precompilation/precompiler.dart
new file mode 100755
index 0000000..419875a
--- /dev/null
+++ b/tools/precompilation/precompiler.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library precompiler;
+
+import 'dart:io';
+
+void run(String executable, String arguments, [String workingDirectory]) {
+ print("+ $executable ${arguments.join(' ')}");
+ var result = Process.runSync(executable, arguments,
+ workingDirectory: workingDirectory);
+ stdout.write(result.stdout);
+ stderr.write(result.stderr);
+ if (result.exitCode != 0) {
+ exit(result.exitCode);
+ }
+}
+
+void main(List<String> args) {
+ var configuration = Platform.environment["DART_CONFIGURATION"];
+
+ var cc, cc_flags, shared, libname;
+ if (Platform.isLinux) {
+ cc = 'gcc';
+ shared = '-shared';
+ libname = 'libprecompiled.so';
+ } else if (Platform.isMacOS) {
+ cc = 'clang';
+ shared = '-dynamiclib';
+ libname = 'libprecompiled.dylib';
+ } else {
+ print("Test only supports Linux and Mac");
+ return;
+ }
+
+ if (configuration.endsWith("X64")) {
+ cc_flags = "-m64";
+ } else if (configuration.endsWith("SIMARM64")) {
+ cc_flags = "-m64";
+ } else if (configuration.endsWith("SIMARM")) {
+ cc_flags = "-m32";
+ } else if (configuration.endsWith("SIMMIPS")) {
+ cc_flags = "-m32";
+ } else if (configuration.endsWith("ARM")) {
+ cc_flags = "";
+ } else if (configuration.endsWith("MIPS")) {
+ cc_flags = "-EL";
+ } else {
+ print("Architecture not supported: $configuration");
+ return;
+ }
+
+ var tmpDir;
+ for (var arg in args) {
+ if (arg.startsWith("--gen-precompiled-snapshot")) {
+ tmpDir = arg.substring("--gen-precompiled-snapshot".length + 1);
+ }
+ }
+ print("Using directory $tmpDir");
+
+ run(args[0], args.sublist(1));
+ run(cc, [shared, cc_flags, "-o", libname, "precompiled.S"], tmpDir);
+}
diff --git a/tools/precompilation/test_linux.sh b/tools/precompilation/test_linux.sh
index f5b1865..553dc18b 100755
--- a/tools/precompilation/test_linux.sh
+++ b/tools/precompilation/test_linux.sh
@@ -1,4 +1,6 @@
-#!/bin/bash -ex
+#!/usr/bin/env bash
+
+set -ex
# Usage:
# cd sdk
diff --git a/tools/precompilation/test_linux_simarm.sh b/tools/precompilation/test_linux_simarm.sh
index f87c6a5..e61b58b 100755
--- a/tools/precompilation/test_linux_simarm.sh
+++ b/tools/precompilation/test_linux_simarm.sh
@@ -1,4 +1,6 @@
-#!/bin/bash -ex
+#!/usr/bin/env bash
+
+set -ex
# Usage:
# cd sdk
diff --git a/tools/precompilation/test_macos.sh b/tools/precompilation/test_macos.sh
index 510478f..57e02dc 100755
--- a/tools/precompilation/test_macos.sh
+++ b/tools/precompilation/test_macos.sh
@@ -1,4 +1,6 @@
-#!/bin/bash -ex
+#!/usr/bin/env bash
+
+set -ex
# Usage:
# cd sdk
diff --git a/tools/presubmit.sh b/tools/presubmit.sh
index a3e6f8a..bedee8b 100755
--- a/tools/presubmit.sh
+++ b/tools/presubmit.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
diff --git a/tools/testing/bin/jsshell b/tools/testing/bin/jsshell
index 359950d..c9dc261 100755
--- a/tools/testing/bin/jsshell
+++ b/tools/testing/bin/jsshell
@@ -1,16 +1,17 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright (c) 2012, 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.
+JSDIR=${0%/*}/../../../third_party/firefox_jsshell
case $OSTYPE in
*[Dd]arwin*)
- exec ${0%/*}/../../../third_party/firefox_jsshell/macos/js "$@"
+ exec $JSDIR/mac/jsshell/js "$@"
;;
*[Ll]inux*)
- LD_LIBRARY_PATH=${0%/*}/../../../third_party/firefox_jsshell/linux/ \
- exec ${0%/*}/../../../third_party/firefox_jsshell/linux/js "$@"
+ LD_LIBRARY_PATH=$JSDIR/linux/jsshell/ \
+ exec $JSDIR/linux/jsshell/js "$@"
;;
*)
echo No jsshell binary for $(uname) >2
diff --git a/tools/testing/bin/jsshell.bat b/tools/testing/bin/jsshell.bat
index e99335f..0666885 100644
--- a/tools/testing/bin/jsshell.bat
+++ b/tools/testing/bin/jsshell.bat
@@ -10,4 +10,4 @@
set arguments=%*
-"%SCRIPTPATH%..\..\..\third_party\firefox_jsshell\windows\js.exe" %arguments%
+"%SCRIPTPATH%..\..\..\third_party\firefox_jsshell\win\jsshell\js.exe" %arguments%
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index e901344..a89aad5 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -74,6 +74,9 @@
isHostChecked: isHostChecked, useCps: useCps, useSdk: useSdk,
isCsp: isCsp, extraDart2jsOptions:
TestUtils.getExtraOptions(configuration, 'dart2js_options'));
+ case 'precompiler':
+ return new PrecompilerCompilerConfiguration(
+ isDebug: isDebug, isChecked: isChecked);
case 'none':
return new NoneCompilerConfiguration(
isDebug: isDebug, isChecked: isChecked,
@@ -119,6 +122,12 @@
return new CommandArtifact([], null, null);
}
+ List<String> computeCompilerArguments(vmOptions, sharedOptions, args) {
+ return new List<String>()
+ ..addAll(sharedOptions)
+ ..addAll(args);
+ }
+
List<String> computeRuntimeArguments(
RuntimeConfiguration runtimeConfiguration,
String buildDir,
@@ -294,6 +303,92 @@
}
}
+
+class PrecompilerCompilerConfiguration extends CompilerConfiguration {
+ PrecompilerCompilerConfiguration({
+ bool isDebug,
+ bool isChecked})
+ : super._subclass(isDebug: isDebug, isChecked: isChecked);
+
+ int computeTimeoutMultiplier() {
+ int multiplier = 2;
+ if (isDebug) multiplier *= 4;
+ if (isChecked) multiplier *= 2;
+ return multiplier;
+ }
+
+ CommandArtifact computeCompilationArtifact(
+ String buildDir,
+ String tempDir,
+ CommandBuilder commandBuilder,
+ List arguments,
+ Map<String, String> environmentOverrides) {
+ return new CommandArtifact(
+ <Command>[
+ this.computeCompilationCommand(
+ tempDir,
+ buildDir,
+ CommandBuilder.instance,
+ arguments,
+ environmentOverrides)],
+ '$tempDir',
+ 'application/dart-precompiled');
+ }
+
+ CompilationCommand computeCompilationCommand(
+ String tempDir,
+ String buildDir,
+ CommandBuilder commandBuilder,
+ List arguments,
+ Map<String, String> environmentOverrides) {
+ var exec = "$buildDir/dart";
+ var args = new List();
+ args.add("tools/precompilation/precompiler.dart");
+ args.add("$buildDir/dart_no_snapshot");
+ args.add("--gen-precompiled-snapshot=$tempDir");
+ args.addAll(arguments);
+
+ return commandBuilder.getCompilationCommand(
+ 'precompiler.dart', tempDir, !useSdk,
+ bootstrapDependencies(buildDir),
+ exec, args, environmentOverrides);
+ }
+
+ List<String> computeCompilerArguments(vmOptions,
+ sharedOptions,
+ originalArguments) {
+ List<String> args = [];
+ if (isChecked) {
+ args.add('--enable_asserts');
+ args.add('--enable_type_checks');
+ }
+ return args
+ ..addAll(vmOptions)
+ ..addAll(sharedOptions)
+ ..addAll(originalArguments);
+ }
+
+ List<String> computeRuntimeArguments(
+ RuntimeConfiguration runtimeConfiguration,
+ String buildDir,
+ TestInformation info,
+ List<String> vmOptions,
+ List<String> sharedOptions,
+ List<String> originalArguments,
+ CommandArtifact artifact) {
+ List<String> args = [];
+ if (isChecked) {
+ args.add('--enable_asserts');
+ args.add('--enable_type_checks');
+ }
+ return args
+ ..addAll(vmOptions)
+ ..addAll(sharedOptions)
+ ..addAll(originalArguments);
+ }
+}
+
+
class AnalyzerCompilerConfiguration extends CompilerConfiguration {
AnalyzerCompilerConfiguration(
{bool isDebug,
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 1fbf54d..55810eb 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -52,6 +52,9 @@
case 'vm':
return new StandaloneDartRuntimeConfiguration();
+ case 'dart_precompiled':
+ return new DartPrecompiledRuntimeConfiguration();
+
case 'drt':
return new DrtRuntimeConfiguration();
@@ -218,6 +221,32 @@
}
}
+
+class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration {
+ List<Command> computeRuntimeCommands(
+ TestSuite suite,
+ CommandBuilder commandBuilder,
+ CommandArtifact artifact,
+ List<String> arguments,
+ Map<String, String> environmentOverrides) {
+ String script = artifact.filename;
+ String type = artifact.mimeType;
+ if (script != null && type != 'application/dart-precompiled') {
+ throw "dart_precompiled cannot run files of type '$type'.";
+ }
+
+ var augmentedArgs = new List();
+ augmentedArgs.add("--run-precompiled-snapshot=${artifact.filename}");
+ augmentedArgs.addAll(arguments);
+
+ var augmentedEnv = new Map.from(environmentOverrides);
+ augmentedEnv['LD_LIBRARY_PATH'] = artifact.filename;
+
+ return <Command>[commandBuilder.getVmCommand(
+ suite.dartPrecompiledBinaryFileName, augmentedArgs, augmentedEnv)];
+ }
+}
+
/// Temporary runtime configuration for browser runtimes that haven't been
/// migrated yet.
// TODO(ahe): Remove this class.
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index a376f28..92514fe 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -67,7 +67,7 @@
dart2analyzer: Perform static analysis on Dart code by running the analyzer
(only valid with the following runtimes: none)''',
['-c', '--compiler'],
- ['none', 'dart2js', 'dart2analyzer'],
+ ['none', 'precompiler', 'dart2js', 'dart2analyzer'],
'none'),
// TODO(antonm): fix the option drt.
new _TestOptionSpecification(
@@ -75,6 +75,9 @@
'''Where the tests should be run.
vm: Run Dart code on the standalone dart vm.
+ dart_precompiled: Run a precompiled snapshot on a variant of the standalone
+ dart vm lacking a JIT.
+
d8: Run JavaScript from the command line using v8.
jsshell: Run JavaScript from the command line using firefox js-shell.
@@ -95,7 +98,8 @@
none: No runtime, compile only (for example, used for dart2analyzer static
analysis tests).''',
['-r', '--runtime'],
- ['vm', 'd8', 'jsshell', 'drt', 'dartium', 'ff', 'firefox',
+ ['vm', 'dart_precompiled', 'd8', 'jsshell', 'drt', 'dartium',
+ 'ff', 'firefox',
'chrome', 'safari', 'ie9', 'ie10', 'ie11', 'opera',
'chromeOnAndroid', 'safarimobilesim',
'ContentShellOnAndroid', 'DartiumOnAndroid', 'none'],
@@ -644,6 +648,9 @@
case 'dart2analyzer':
validRuntimes = const ['none'];
break;
+ case 'precompiler':
+ validRuntimes = const ['dart_precompiled'];
+ break;
case 'none':
validRuntimes = const ['vm', 'drt', 'dartium',
'ContentShellOnAndroid', 'DartiumOnAndroid'];
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index eeb1d69..ffd9921 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -1679,6 +1679,10 @@
return new VmCommandOutputImpl(
command, exitCode, timedOut, stdout, stderr, time, pid);
} else if (command is CompilationCommand) {
+ if (command.displayName == 'precompiler.dart') {
+ return new VmCommandOutputImpl(
+ command, exitCode, timedOut, stdout, stderr, time, pid);
+ }
return new CompilationCommandOutputImpl(
command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
} else if (command is JSCommandlineCommand) {
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index bec08a8..533c01c 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -212,6 +212,19 @@
return dartExecutable;
}
+ String get dartPrecompiledBinaryFileName {
+ // Controlled by user with the option "--dart_precompiled".
+ String dartExecutable = configuration['dart_precompiled'];
+
+ if (dartExecutable == null || dartExecutable == '') {
+ String suffix = executableBinarySuffix;
+ dartExecutable = '$buildDir/dart_precompiled$suffix';
+ }
+
+ TestUtils.ensureExists(dartExecutable, configuration);
+ return dartExecutable;
+ }
+
String get d8FileName {
var suffix = getExecutableSuffix('d8');
var d8Dir = TestUtils.dartDir.append('third_party/d8');
@@ -882,6 +895,12 @@
var packageDirectories = {};
if (configuration['use_repository_packages']) {
packageDirectories = new Map.from(localPackageDirectories);
+
+ // Don't create a dependency override for pub, since it's an application
+ // package and it has a dependency on compiler_unsupported which isn't
+ // in the repo.
+ packageDirectories.remove('pub');
+
// Do not create an dependency override for the package itself.
if (packageDirectories.containsKey(packageName)) {
packageDirectories.remove(packageName);
@@ -1009,9 +1028,10 @@
List<String> compileTimeArguments = <String>[];
String tempDir;
if (compilerConfiguration.hasCompiler) {
- compileTimeArguments
- ..addAll(sharedOptions)
- ..addAll(args);
+ compileTimeArguments =
+ compilerConfiguration.computeCompilerArguments(vmOptions,
+ sharedOptions,
+ args);
// Avoid doing this for analyzer.
tempDir = createCompilationOutputDirectory(info.filePath);
}
@@ -1772,8 +1792,8 @@
}
List<List<String>> getVmOptions(Map optionsFromFile) {
- var COMPILERS = const ['none'];
- var RUNTIMES = const ['none', 'vm', 'drt', 'dartium',
+ var COMPILERS = const ['none', 'precompiler'];
+ var RUNTIMES = const ['none', 'dart_precompiled', 'vm', 'drt', 'dartium',
'ContentShellOnAndroid', 'DartiumOnAndroid'];
var needsVmOptions = COMPILERS.contains(configuration['compiler']) &&
RUNTIMES.contains(configuration['runtime']);
@@ -1974,6 +1994,12 @@
var packageDirectories = {};
if (!configuration['use_public_packages']) {
packageDirectories = new Map.from(localPackageDirectories);
+
+ // Don't create a dependency override for pub, since it's an
+ // application package and it has a dependency on compiler_unsupported
+ // which isn't in the repo.
+ packageDirectories.remove('pub');
+
if (packageDirectories.containsKey(packageName)) {
packageDirectories.remove(packageName);
}