Version 1.15.0-dev.3.0
Merge commit '1c698c183be2d74bfb1576cffb4476e6d77317e6' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6a62b7f..55db4b3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,14 @@
`SecurityContext.setTrustedCertificates` is no longer supported.
The method now only supports one argument for the PEM file name containing
the trusted certificates.
+ * Added support to SecurityContext for PKCS12 certificate and key containers.
+* `dart:async`
+ * Made `StreamView` class a `const` class.
+
+## 1.14.2 - 2016-02-09
+
+* Fixes a bug where pub would download packages from pub.dartlang.org even when
+ a different hosted URL was specified.
## 1.14.1 - 2016-02-04
diff --git a/DEPS b/DEPS
index d605a86..702e439 100644
--- a/DEPS
+++ b/DEPS
@@ -52,7 +52,7 @@
"intl_rev": "@a8b480b9c436f6c0ec16730804c914bdb4e30d53",
"jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_tag": "@1.1.1",
- "linter_rev": "@5a599fd32d3b6ef00ffa7c330d1f32bbad287228",
+ "linter_rev": "@87f066f9243b36540c33186e742a798b87e76f8e",
"logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
"markdown_rev": "@4aaadf3d940bb172e1f6285af4d2b1710d309982",
"matcher_tag": "@0.12.0",
@@ -91,7 +91,7 @@
"when_tag": "@0.2.0+2",
"which_tag": "@0.1.3+1",
"web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
- "WebCore_rev": "@4f90b41b0165f23f412cecdba07b7d81d3fbb5b5",
+ "WebCore_rev": "@5ecb723fd9ffcc0d108f5e0e24d12b8b3df7b200",
"yaml_tag": "@2.1.5",
"zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
"barback-0.13.0_rev": "@34853",
@@ -293,20 +293,6 @@
"action": ["python", Var("dart_root") + "/tools/gyp_dart.py"],
},
{
- 'name': 'checked_in_dart_binaries',
- 'pattern': '.',
- 'action': [
- 'download_from_google_storage',
- '--no_auth',
- '--no_resume',
- '--bucket',
- 'dart-dependencies',
- '--recursive',
- '--directory',
- Var('dart_root') + '/tools/testing/bin',
- ],
- },
- {
'name': 'd8_testing_binaries',
'pattern': '.',
'action': [
diff --git a/WATCHLISTS b/WATCHLISTS
index 9b4f4dc..a6f72e3 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -10,9 +10,6 @@
'runtime': {
'filepath': '^runtime/',
},
- 'tools': {
- 'filepath': 'tools/',
- },
'observatory': {
'filepath': 'runtime/bin/vmservice/' \
'|runtime/bin/vmservice*' \
@@ -24,7 +21,6 @@
'WATCHLISTS': {
'runtime': ['vm-dev@dartlang.org'],
- 'tools': ['ricow@google.com'],
'observatory': ['johnmccutchan@google.com', 'turnidge@google.com', 'rmacnak@google.com'],
},
}
diff --git a/dart.gyp b/dart.gyp
index a7d4f95..918e5d6 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -27,6 +27,7 @@
'runtime/dart-runtime.gyp:dart',
'runtime/dart-runtime.gyp:dart_noopt',
'runtime/dart-runtime.gyp:dart_precompiled_runtime',
+ 'runtime/dart-runtime.gyp:dart_product',
'runtime/dart-runtime.gyp:dart_no_snapshot',
'runtime/dart-runtime.gyp:run_vm_tests',
'runtime/dart-runtime.gyp:process_test',
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 430a2e6..df9075e 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -9,7 +9,8 @@
import 'dart:core' hide Resource;
import 'dart:math' show max;
-import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element;
+import 'package:analysis_server/plugin/protocol/protocol.dart'
+ hide AnalysisOptions, Element;
import 'package:analysis_server/src/analysis_logger.dart';
import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/context_manager.dart';
@@ -140,9 +141,14 @@
List<RequestHandler> handlers;
/**
- * The current default [DartSdk].
+ * The function used to create a new SDK using the default SDK.
*/
- final DartSdk defaultSdk;
+ final SdkCreator defaultSdkCreator;
+
+ /**
+ * The object used to manage the SDK's known to this server.
+ */
+ DartSdkManager sdkManager;
/**
* The instrumentation service that is to be used by this analysis server.
@@ -300,7 +306,7 @@
Index _index,
this.serverPlugin,
this.options,
- this.defaultSdk,
+ this.defaultSdkCreator,
this.instrumentationService,
{ResolverProvider packageResolverProvider: null,
EmbeddedResolverProvider embeddedResolverProvider: null,
@@ -342,6 +348,7 @@
channel.sendNotification(notification);
channel.listen(handleRequest, onDone: done, onError: error);
handlers = serverPlugin.createDomains(this);
+ sdkManager = new DartSdkManager(defaultSdkCreator);
}
/**
@@ -427,6 +434,19 @@
}
/**
+ * Return one of the SDKs that has been created, or `null` if no SDKs have
+ * been created yet.
+ */
+ DartSdk findSdk() {
+ DartSdk sdk = sdkManager.anySdk;
+ if (sdk != null) {
+ return sdk;
+ }
+ // TODO(brianwilkerson) Should we create an SDK using the default options?
+ return null;
+ }
+
+ /**
* Return the preferred [AnalysisContext] for analyzing the given [path].
* This will be the context that explicitly contains the path, if any such
* context exists, otherwise it will be the first analysis context that
@@ -510,11 +530,13 @@
ContextSourcePair getContextSourcePair(String path) {
// try SDK
{
- Uri uri = resourceProvider.pathContext.toUri(path);
- Source sdkSource = defaultSdk.fromFileUri(uri);
- if (sdkSource != null) {
- AnalysisContext sdkContext = defaultSdk.context;
- return new ContextSourcePair(sdkContext, sdkSource);
+ DartSdk sdk = findSdk();
+ if (sdk != null) {
+ Uri uri = resourceProvider.pathContext.toUri(path);
+ Source sdkSource = sdk.fromFileUri(uri);
+ if (sdkSource != null) {
+ return new ContextSourcePair(sdk.context, sdkSource);
+ }
}
}
// try to find the deep-most containing context
@@ -1459,15 +1481,20 @@
}
@override
- AnalysisContext addContext(Folder folder, FolderDisposition disposition) {
+ AnalysisOptions get defaultAnalysisOptions =>
+ analysisServer.defaultContextOptions;
+
+ @override
+ AnalysisContext addContext(
+ Folder folder, AnalysisOptions options, FolderDisposition disposition) {
InternalAnalysisContext context =
AnalysisEngine.instance.createAnalysisContext();
context.contentCache = analysisServer.overlayState;
analysisServer.folderMap[folder] = context;
_locateEmbedderYamls(context, disposition);
- context.sourceFactory = _createSourceFactory(context, disposition, folder);
- context.analysisOptions =
- new AnalysisOptionsImpl.from(analysisServer.defaultContextOptions);
+ context.sourceFactory =
+ _createSourceFactory(context, options, disposition, folder);
+ context.analysisOptions = options;
analysisServer._onContextsChangedController
.add(new ContextsChangedEvent(added: [context]));
analysisServer.schedulePerformAnalysisOperation(context);
@@ -1536,8 +1563,8 @@
void updateContextPackageUriResolver(
Folder contextFolder, FolderDisposition disposition) {
AnalysisContext context = analysisServer.folderMap[contextFolder];
- context.sourceFactory =
- _createSourceFactory(context, disposition, contextFolder);
+ context.sourceFactory = _createSourceFactory(
+ context, context.analysisOptions, disposition, contextFolder);
analysisServer._onContextsChangedController
.add(new ContextsChangedEvent(changed: [context]));
analysisServer.schedulePerformAnalysisOperation(context);
@@ -1556,7 +1583,7 @@
* given [disposition].
*/
SourceFactory _createSourceFactory(InternalAnalysisContext context,
- FolderDisposition disposition, Folder folder) {
+ AnalysisOptions options, FolderDisposition disposition, Folder folder) {
List<UriResolver> resolvers = [];
List<UriResolver> packageUriResolvers =
disposition.createPackageUriResolvers(resourceProvider);
@@ -1579,7 +1606,8 @@
if (embedderUriResolver.length == 0) {
// The embedder uri resolver has no mappings. Use the default Dart SDK
// uri resolver.
- resolvers.add(new DartUriResolver(analysisServer.defaultSdk));
+ resolvers.add(new DartUriResolver(
+ analysisServer.sdkManager.getSdkForOptions(options)));
} else {
// The embedder uri resolver has mappings, use it instead of the default
// Dart SDK uri resolver.
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index a91e47d..ed5e8e9 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -5,10 +5,10 @@
library computer.highlights;
import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element;
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
/**
* A computer for [HighlightRegion]s in a Dart [CompilationUnit].
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
index fc0d77e..5665d49 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
@@ -5,10 +5,10 @@
library computer.highlights2;
import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element;
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
/**
* A computer for [HighlightRegion]s in a Dart [CompilationUnit].
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 92efe4d..992cf55 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -307,10 +307,18 @@
*/
abstract class ContextManagerCallbacks {
/**
- * Create and return a new analysis context, allowing [disposition] to govern
- * details of how the context is to be created.
+ * Return the default analysis options to be used when creating an analysis
+ * context.
*/
- AnalysisContext addContext(Folder folder, FolderDisposition disposition);
+ AnalysisOptions get defaultAnalysisOptions;
+
+ /**
+ * Create and return a new analysis context rooted at the given [folder], with
+ * the given analysis [options], allowing [disposition] to govern details of
+ * how the context is to be created.
+ */
+ AnalysisContext addContext(
+ Folder folder, AnalysisOptions options, FolderDisposition disposition);
/**
* Called when the set of files associated with a context have changed (or
@@ -550,15 +558,8 @@
/**
* Process [options] for the given context [info].
*/
- void processOptionsForContext(ContextInfo info, Folder folder,
+ void processOptionsForContext(ContextInfo info, Map<String, Object> options,
{bool optionsRemoved: false}) {
- Map<String, Object> options;
- try {
- options = analysisOptionsProvider.getOptions(folder);
- } catch (_) {
- // Parse errors are reported by GenerateOptionsErrorsTask.
- }
-
if (options == null && !optionsRemoved) {
return;
}
@@ -613,6 +614,20 @@
}
}
+ /**
+ * Return the options from the analysis options file in the given [folder], or
+ * `null` if there is no file in the folder or if the contents of the file are
+ * not valid YAML.
+ */
+ Map<String, Object> readOptions(Folder folder) {
+ try {
+ return analysisOptionsProvider.getOptions(folder);
+ } catch (_) {
+ // Parse errors are reported by GenerateOptionsErrorsTask.
+ }
+ return null;
+ }
+
@override
void refresh(List<Resource> roots) {
// Destroy old contexts
@@ -835,7 +850,11 @@
if (AnalysisEngine.isAnalysisOptionsFileName(path, pathContext)) {
var analysisContext = info.context;
if (analysisContext is context.AnalysisContextImpl) {
- processOptionsForContext(info, info.folder,
+ // TODO(brianwilkerson) This doesn't correctly update the source factory
+ // if the changes necessitate it (such as by changing the setting of the
+ // strong-mode option).
+ Map<String, Object> options = readOptions(info.folder);
+ processOptionsForContext(info, options,
optionsRemoved: changeType == ChangeType.REMOVE);
analysisContext.invalidateCachedResults();
callbacks.applyChangesToContext(info.folder, new ChangeSet());
@@ -1019,11 +1038,16 @@
_computeFolderDisposition(folder, dependencies.add, packagespecFile);
}
+ Map<String, Object> optionMap = readOptions(info.folder);
+ AnalysisOptions options =
+ new AnalysisOptionsImpl.from(callbacks.defaultAnalysisOptions);
+ applyToAnalysisOptions(options, optionMap);
+
info.setDependencies(dependencies);
- info.context = callbacks.addContext(folder, disposition);
+ info.context = callbacks.addContext(folder, options, disposition);
info.context.name = folder.path;
- processOptionsForContext(info, folder);
+ processOptionsForContext(info, optionMap);
return info;
}
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 8810ff6..f9ea745 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -53,12 +53,17 @@
CompletionPerformance computeCachePerformance;
/**
+ * The current request being processed or `null` if none.
+ */
+ CompletionRequestImpl _currentRequest;
+
+ /**
* Initialize a new request handler for the given [server].
*/
CompletionDomainHandler(this.server);
/**
- * Compute completion results for the given reqeust and append them to the stream.
+ * Compute completion results for the given request 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
@@ -76,7 +81,12 @@
for (CompletionContributor contributor in newContributors) {
String contributorTag = 'computeSuggestions - ${contributor.runtimeType}';
performance.logStartTime(contributorTag);
- suggestions.addAll(await contributor.computeSuggestions(request));
+ try {
+ suggestions.addAll(await contributor.computeSuggestions(request));
+ } on AbortCompletion {
+ suggestions.clear();
+ break;
+ }
performance.logElapseTime(contributorTag);
}
@@ -139,7 +149,7 @@
recordRequest(performance, context, source, params.offset);
- CompletionRequest completionRequest = new CompletionRequestImpl(
+ CompletionRequestImpl completionRequest = new CompletionRequestImpl(
context,
server.resourceProvider,
server.searchEngine,
@@ -148,6 +158,9 @@
performance);
String completionId = (_nextCompletionId++).toString();
+ _abortCurrentRequest();
+ _currentRequest = completionRequest;
+
// Compute suggestions in the background
computeSuggestions(completionRequest).then((CompletionResult result) {
const SEND_NOTIFICATION_TAG = 'send notification';
@@ -161,6 +174,10 @@
performance.suggestionCountFirst = result.suggestions.length;
performance.suggestionCountLast = result.suggestions.length;
performance.complete();
+ }).whenComplete(() {
+ if (_currentRequest == completionRequest) {
+ _currentRequest = null;
+ }
});
// initial response without results
@@ -198,6 +215,16 @@
completionId, replacementOffset, replacementLength, results, true)
.toNotification());
}
+
+ /**
+ * Abort the current completion request, if any.
+ */
+ void _abortCurrentRequest() {
+ if (_currentRequest != null) {
+ _currentRequest.abort();
+ _currentRequest = null;
+ }
+ }
}
/**
diff --git a/pkg/analysis_server/lib/src/domain_diagnostic.dart b/pkg/analysis_server/lib/src/domain_diagnostic.dart
index e9bd0c3..94b1c3a 100644
--- a/pkg/analysis_server/lib/src/domain_diagnostic.dart
+++ b/pkg/analysis_server/lib/src/domain_diagnostic.dart
@@ -63,6 +63,10 @@
AnalysisTarget target = iterator.key;
if (countedTargets.add(target)) {
CacheEntry cacheEntry = iterator.value;
+ if (cacheEntry == null) {
+ throw new StateError(
+ "mutated cache key detected: $target (${target.runtimeType})");
+ }
if (target is Source) {
if (cacheEntry.explicitlyAdded) {
explicitFiles++;
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
index 931d87f..20ddb4f 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
@@ -6,11 +6,11 @@
import 'package:analysis_server/plugin/analysis/navigation/navigation_core.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
/**
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index ce2b38c..4197555 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -20,11 +20,11 @@
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart' as engine;
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart' as engine;
import 'package:analyzer/src/generated/error.dart' as engine;
import 'package:analyzer/src/generated/parser.dart' as engine;
-import 'package:analyzer/src/generated/scanner.dart' as engine;
import 'package:analyzer/src/generated/source.dart';
import 'package:dart_style/dart_style.dart';
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 9a585dd..1aa1c9f 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
@@ -26,6 +26,14 @@
typedef CompletionContributor CompletionContributorFactory();
/**
+ * [AbortCompletion] is thrown when the current completion request
+ * should be aborted because either
+ * the source changed since the request was made, or
+ * a new completion request was received.
+ */
+class AbortCompletion {}
+
+/**
* An object used to produce completions at a specific location within a file.
*
* Clients may implement this class when implementing plugins.
@@ -33,7 +41,8 @@
abstract class CompletionContributor {
/**
* Return a [Future] that completes with a list of suggestions
- * for the given completion [request].
+ * for the given completion [request]. This will
+ * throw [AbortCompletion] if the completion request has been aborted.
*/
Future<List<CompletionSuggestion>> computeSuggestions(
CompletionRequest request);
@@ -70,4 +79,9 @@
* Return the source in which the completion is being requested.
*/
Source get source;
+
+ /**
+ * Throw [AbortCompletion] if the completion request has been aborted.
+ */
+ void checkAborted();
}
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index c6a9a74..434ae63 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -107,16 +107,6 @@
CompletionTarget get target;
/**
- * Return a [Future] that completes with a list of directives for the library
- * in which in which the completion is occurring.
- * The [Future] may return `null` if the library unit cannot be determined
- * (e.g. unlinked part file).
- * Any information obtained from [target] prior to calling this method
- * should be discarded as it may have changed.
- */
- Future<List<Directive>> resolveDirectives();
-
- /**
* Return a [Future] that completes when the element associated with
* the given [expression] in the target compilation unit is available.
* It may also complete if the expression cannot be resolved
@@ -125,4 +115,24 @@
* should be discarded as it may have changed.
*/
Future resolveExpression(Expression expression);
+
+ /**
+ * Return a [Future] that completes with a list of [ImportElement]s
+ * for the library in which in which the completion is occurring.
+ * The [Future] may return `null` if the library unit cannot be determined
+ * (e.g. unlinked part file).
+ * Any information obtained from [target] prior to calling this method
+ * should be discarded as it may have changed.
+ */
+ Future<List<ImportElement>> resolveImports();
+
+ /**
+ * Return a [Future] that completes with a list of [CompilationUnitElement]s
+ * comprising the library in which in which the completion is occurring.
+ * The [Future] may return `null` if the library unit cannot be determined
+ * (e.g. unlinked part file).
+ * Any information obtained from [target] prior to calling this method
+ * should be discarded as it may have changed.
+ */
+ Future<List<CompilationUnitElement>> resolveUnits();
}
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
index c04ce43..9a03a1e 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
@@ -4,10 +4,10 @@
library analysis_server.src.provisional.completion.dart.completion_target;
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
int _computeArgIndex(AstNode containingNode, Object entity) {
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 2cdb251..4f9e472 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -375,14 +375,20 @@
_initIncrementalLogger(results[INCREMENTAL_RESOLUTION_LOG]);
- DartSdk defaultSdk;
+ JavaFile defaultSdkDirectory;
if (results[SDK_OPTION] != null) {
- defaultSdk = new DirectoryBasedDartSdk(new JavaFile(results[SDK_OPTION]));
+ defaultSdkDirectory = new JavaFile(results[SDK_OPTION]);
} else {
- // No path to the SDK provided; use DirectoryBasedDartSdk.defaultSdk,
- // which will make a guess.
- defaultSdk = DirectoryBasedDartSdk.defaultSdk;
+ // No path to the SDK was provided.
+ // Use DirectoryBasedDartSdk.defaultSdkDirectory, which will make a guess.
+ defaultSdkDirectory = DirectoryBasedDartSdk.defaultSdkDirectory;
}
+ SdkCreator defaultSdkCreator =
+ () => new DirectoryBasedDartSdk(defaultSdkDirectory);
+ // TODO(brianwilkerson) It would be nice to avoid creating an SDK that
+ // cannot be re-used, but the SDK is needed to create a package map provider
+ // in the case where we need to run `pub` in order to get the package map.
+ DirectoryBasedDartSdk defaultSdk = defaultSdkCreator();
//
// Initialize the instrumentation service.
//
@@ -420,8 +426,14 @@
//
// Create the sockets and start listening for requests.
//
- socketServer = new SocketServer(analysisServerOptions, defaultSdk, service,
- serverPlugin, packageResolverProvider, embeddedUriResolverProvider);
+ socketServer = new SocketServer(
+ analysisServerOptions,
+ defaultSdkCreator,
+ defaultSdk,
+ service,
+ serverPlugin,
+ packageResolverProvider,
+ embeddedUriResolverProvider);
httpServer = new HttpAnalysisServer(socketServer);
stdioServer = new StdioAnalysisServer(socketServer);
socketServer.userDefinedPlugins = _userDefinedPlugins;
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 e0635aa..b79a9d8 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -21,6 +21,14 @@
@override
final Source source;
+ /**
+ * The content cache modification stamp of the associated [source],
+ * or `null` if the content cache does not override the [source] content.
+ * This is used to determine if the [source] contents have been modified
+ * after the completion request was made.
+ */
+ final int sourceModificationStamp;
+
@override
final int offset;
@@ -48,16 +56,21 @@
@override
final SearchEngine searchEngine;
+ bool _aborted = false;
+
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.performance) {
- replacementOffset = offset;
- replacementLength = 0;
- }
+ CompletionRequestImpl(AnalysisContext context, this.resourceProvider,
+ this.searchEngine, Source source, int offset, this.performance)
+ : this.context = context,
+ this.source = source,
+ this.offset = offset,
+ replacementOffset = offset,
+ replacementLength = 0,
+ sourceModificationStamp = context.getModificationStamp(source);
/**
* Return the original text from the [replacementOffset] to the [offset]
@@ -69,4 +82,22 @@
.data
.substring(replacementOffset, offset);
}
+
+ /**
+ * Abort the current completion request.
+ */
+ void abort() {
+ _aborted = true;
+ }
+
+ @override
+ void checkAborted() {
+ if (_aborted) {
+ throw new AbortCompletion();
+ }
+ if (sourceModificationStamp != context.getModificationStamp(source)) {
+ _aborted = true;
+ throw new AbortCompletion();
+ }
+ }
}
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 602503e..b56bd9f 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
@@ -18,17 +18,20 @@
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/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/context.dart'
show AnalysisFutureHelper, AnalysisContextImpl;
+import 'package:analyzer/src/dart/ast/token.dart';
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/java_engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/model.dart';
/**
* [DartCompletionManager] determines if a completion request is Dart specific
@@ -44,17 +47,15 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
CompletionRequest request) async {
+ request.checkAborted();
if (!AnalysisEngine.isDartFileName(request.source.shortName)) {
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);
- performance.logElapseTime(BUILD_REQUEST_TAG);
// Don't suggest in comments.
if (dartRequest.target.isCommentText) {
@@ -78,6 +79,7 @@
List<CompletionSuggestion> contributorSuggestions =
await contributor.computeSuggestions(dartRequest);
performance.logElapseTime(contributorTag);
+ request.checkAborted();
for (CompletionSuggestion newSuggestion in contributorSuggestions) {
var oldSuggestion = suggestionMap.putIfAbsent(
@@ -95,6 +97,7 @@
performance.logStartTime(SORT_TAG);
await contributionSorter.sort(dartRequest, suggestions);
performance.logElapseTime(SORT_TAG);
+ request.checkAborted();
return suggestions;
}
}
@@ -137,8 +140,22 @@
*/
InterfaceType _objectType;
+ /**
+ * A list of resolved [ImportElement]s for the imported libraries
+ * or `null` if not computed.
+ */
+ List<ImportElement> _resolvedImports;
+
+ /**
+ * The resolved [CompilationUnitElement]s comprising the library
+ * or `null` if not computed.
+ */
+ List<CompilationUnitElement> _resolvedUnits;
+
OpType _opType;
+ final CompletionRequest _originalRequest;
+
final CompletionPerformance performance;
DartCompletionRequestImpl._(
@@ -149,6 +166,7 @@
this.source,
this.offset,
CompilationUnit unit,
+ this._originalRequest,
this.performance) {
_updateTargets(unit);
}
@@ -200,26 +218,17 @@
return _opType;
}
- // For internal use only
- @override
- Future<List<Directive>> resolveDirectives() async {
- CompilationUnit libUnit;
- 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;
+ /**
+ * Throw [AbortCompletion] if the completion request has been aborted.
+ */
+ void checkAborted() {
+ _originalRequest.checkAborted();
}
@override
Future resolveExpression(Expression expression) async {
+ checkAborted();
+
// Return immediately if the expression has already been resolved
if (expression.propagatedType != null) {
return;
@@ -233,13 +242,12 @@
// 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);
+ CompilationUnit resolvedUnit = await _computeAsync(
+ this,
+ new LibrarySpecificUnit(librarySource, source),
+ RESOLVED_UNIT,
+ performance,
+ 'resolve expression');
// TODO(danrubel) determine if the underlying source has been modified
// in a way that invalidates the completion request
@@ -254,6 +262,55 @@
_updateTargets(resolvedUnit);
}
+ @override
+ Future<List<ImportElement>> resolveImports() async {
+ checkAborted();
+ if (_resolvedImports != null) {
+ return _resolvedImports;
+ }
+ LibraryElement libElem = libraryElement;
+ if (libElem == null) {
+ return null;
+ }
+ _resolvedImports = <ImportElement>[];
+ for (ImportElement importElem in libElem.imports) {
+ if (importElem.importedLibrary.exportNamespace == null) {
+ await _computeAsync(this, importElem.importedLibrary.source,
+ LIBRARY_ELEMENT4, performance, 'resolve imported library');
+ checkAborted();
+ }
+ _resolvedImports.add(importElem);
+ }
+ return _resolvedImports;
+ }
+
+ @override
+ Future<List<CompilationUnitElement>> resolveUnits() async {
+ checkAborted();
+ if (_resolvedUnits != null) {
+ return _resolvedUnits;
+ }
+ LibraryElement libElem = libraryElement;
+ if (libElem == null) {
+ return null;
+ }
+ _resolvedUnits = <CompilationUnitElement>[];
+ for (CompilationUnitElement unresolvedUnit in libElem.units) {
+ CompilationUnit unit = await _computeAsync(
+ this,
+ new LibrarySpecificUnit(libElem.source, unresolvedUnit.source),
+ RESOLVED_UNIT3,
+ performance,
+ 'resolve library unit');
+ checkAborted();
+ CompilationUnitElement resolvedUnit = unit?.element;
+ if (resolvedUnit != null) {
+ _resolvedUnits.add(resolvedUnit);
+ }
+ }
+ return _resolvedUnits;
+ }
+
/**
* Update the completion [target] and [dotTarget] based on the given [unit].
*/
@@ -285,9 +342,12 @@
/**
* Return a [Future] that completes with a newly created completion request
- * based on the given [request].
+ * based on the given [request]. This method will throw [AbortCompletion]
+ * if the completion request has been aborted.
*/
- static Future<DartCompletionRequest> from(CompletionRequest request) async {
+ static Future<DartCompletionRequest> from(CompletionRequest request,
+ {ResultDescriptor resultDescriptor}) async {
+ request.checkAborted();
CompletionPerformance performance =
(request as CompletionRequestImpl).performance;
const BUILD_REQUEST_TAG = 'build DartCompletionRequest';
@@ -313,12 +373,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);
+ unit = await _computeAsync(
+ request,
+ new LibrarySpecificUnit(libSource, source),
+ resultDescriptor ?? RESOLVED_UNIT3,
+ performance,
+ 'resolve declarations');
}
DartCompletionRequestImpl dartRequest = new DartCompletionRequestImpl._(
@@ -329,6 +389,7 @@
request.source,
request.offset,
unit,
+ request,
performance);
// Resolve the expression in which the completion occurs
@@ -341,12 +402,37 @@
performance.logStartTime(FUNCTIONAL_ARG_TAG);
await dartRequest.resolveExpression(node);
performance.logElapseTime(FUNCTIONAL_ARG_TAG);
+ dartRequest.checkAborted();
}
}
performance.logElapseTime(BUILD_REQUEST_TAG);
return dartRequest;
}
+
+ static Future _computeAsync(
+ CompletionRequest request,
+ AnalysisTarget target,
+ ResultDescriptor descriptor,
+ CompletionPerformance performance,
+ String perfTag) async {
+ request.checkAborted();
+ performance.logStartTime(perfTag);
+ var result;
+ try {
+ result =
+ await new AnalysisFutureHelper(request.context, target, descriptor)
+ .computeAsync();
+ } catch (e, s) {
+ if (e is AnalysisNotScheduledError) {
+ request.checkAborted();
+ }
+ throw new AnalysisException(
+ 'failed to $perfTag', new CaughtException(e, s));
+ }
+ request.checkAborted();
+ return result;
+ }
}
/**
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 736f2a0..abed735 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
@@ -10,12 +10,11 @@
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/dart/optype.dart';
-import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/resolver.dart';
import '../../../protocol_server.dart'
show CompletionSuggestion, CompletionSuggestionKind;
-import 'package:analyzer/src/generated/resolver.dart';
/**
* A contributor for calculating suggestions for imported top level members.
@@ -31,29 +30,23 @@
return EMPTY_LIST;
}
- List<Directive> directives = await request.resolveDirectives();
- if (directives == null) {
+ List<ImportElement> imports = await request.resolveImports();
+ if (imports == null) {
return EMPTY_LIST;
}
this.request = request;
this.optype = (request as DartCompletionRequestImpl).opType;
+ List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
- // Traverse dart:core
- List<CompletionSuggestion> suggestions =
- _buildSuggestions(request.coreLib.exportNamespace);
-
- // Traverse imports
- for (Directive directive in directives) {
- if (directive is ImportDirective) {
- ImportElement importElem = directive.element;
- LibraryElement libElem = importElem?.importedLibrary;
- if (libElem != null) {
- suggestions.addAll(_buildSuggestions(libElem.exportNamespace,
- prefix: importElem.prefix?.name,
- showNames: showNamesIn(importElem),
- hiddenNames: hiddenNamesIn(importElem)));
- }
+ // Traverse imports including dart:core
+ for (ImportElement importElem in imports) {
+ LibraryElement libElem = importElem?.importedLibrary;
+ if (libElem != null) {
+ suggestions.addAll(_buildSuggestions(libElem.exportNamespace,
+ prefix: importElem.prefix?.name,
+ showNames: showNamesIn(importElem),
+ hiddenNames: hiddenNamesIn(importElem)));
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index 9892a10..6008fe7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -9,8 +9,9 @@
import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
const ASYNC = 'async';
const ASYNC_STAR = 'async*';
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 014d4ee..b5bae6c 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
@@ -14,8 +14,9 @@
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:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import '../../../protocol_server.dart'
@@ -27,6 +28,127 @@
new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), null);
/**
+* Create a new protocol Element for inclusion in a completion suggestion.
+*/
+protocol.Element createLocalElement(
+ Source source, protocol.ElementKind kind, SimpleIdentifier id,
+ {String parameters,
+ TypeName returnType,
+ bool isAbstract: false,
+ bool isDeprecated: false}) {
+ String name;
+ Location location;
+ if (id != null) {
+ name = id.name;
+ // TODO(danrubel) use lineInfo to determine startLine and startColumn
+ location = new Location(source.fullName, id.offset, id.length, 0, 0);
+ } else {
+ name = '';
+ location = new Location(source.fullName, -1, 0, 1, 0);
+ }
+ int flags = protocol.Element.makeFlags(
+ isAbstract: isAbstract,
+ isDeprecated: isDeprecated,
+ isPrivate: Identifier.isPrivateName(name));
+ return new protocol.Element(kind, name, flags,
+ location: location,
+ parameters: parameters,
+ returnType: nameForType(returnType));
+}
+
+/**
+* Create a new suggestion for the given field.
+* Return the new suggestion or `null` if it could not be created.
+*/
+CompletionSuggestion createLocalFieldSuggestion(
+ Source source, FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
+ bool deprecated = isDeprecated(fieldDecl) || isDeprecated(varDecl);
+ TypeName type = fieldDecl.fields.type;
+ return createLocalSuggestion(
+ varDecl.name, deprecated, DART_RELEVANCE_LOCAL_FIELD, type,
+ classDecl: fieldDecl.parent,
+ element: createLocalElement(
+ source, protocol.ElementKind.FIELD, varDecl.name,
+ returnType: type, isDeprecated: deprecated));
+}
+
+/**
+* Create a new suggestion based upon the given information.
+* Return the new suggestion or `null` if it could not be created.
+*/
+CompletionSuggestion createLocalSuggestion(SimpleIdentifier id,
+ bool isDeprecated, int defaultRelevance, TypeName returnType,
+ {ClassDeclaration classDecl, protocol.Element element}) {
+ if (id == null) {
+ return null;
+ }
+ String completion = id.name;
+ if (completion == null || completion.length <= 0 || completion == '_') {
+ return null;
+ }
+ CompletionSuggestion suggestion = new CompletionSuggestion(
+ CompletionSuggestionKind.INVOCATION,
+ isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
+ completion,
+ completion.length,
+ 0,
+ isDeprecated,
+ false,
+ returnType: nameForType(returnType),
+ element: element);
+ if (classDecl != null) {
+ SimpleIdentifier classId = classDecl.name;
+ if (classId != null) {
+ String className = classId.name;
+ if (className != null && className.length > 0) {
+ suggestion.declaringType = className;
+ }
+ }
+ }
+ return suggestion;
+}
+
+/**
+* Return `true` if the @deprecated annotation is present
+*/
+bool isDeprecated(AnnotatedNode node) {
+ if (node != null) {
+ NodeList<Annotation> metadata = node.metadata;
+ if (metadata != null) {
+ return metadata.any((Annotation a) {
+ return a.name is SimpleIdentifier && a.name.name == 'deprecated';
+ });
+ }
+ }
+ return false;
+}
+
+/**
+* Return the name for the given type.
+*/
+String nameForType(TypeName type) {
+ if (type == NO_RETURN_TYPE) {
+ return null;
+ }
+ if (type == null) {
+ return DYNAMIC;
+ }
+ Identifier id = type.name;
+ if (id == null) {
+ return DYNAMIC;
+ }
+ String name = id.name;
+ if (name == null || name.length <= 0) {
+ return DYNAMIC;
+ }
+ TypeArgumentList typeArgs = type.typeArguments;
+ if (typeArgs != null) {
+ //TODO (danrubel) include type arguments
+ }
+ return name;
+}
+
+/**
* A contributor for calculating label suggestions.
*/
class LabelContributor extends DartCompletionContributor {
@@ -163,124 +285,3 @@
return null;
}
}
-
-/**
-* Create a new protocol Element for inclusion in a completion suggestion.
-*/
-protocol.Element createLocalElement(
- Source source, protocol.ElementKind kind, SimpleIdentifier id,
- {String parameters,
- TypeName returnType,
- bool isAbstract: false,
- bool isDeprecated: false}) {
- String name;
- Location location;
- if (id != null) {
- name = id.name;
- // TODO(danrubel) use lineInfo to determine startLine and startColumn
- location = new Location(source.fullName, id.offset, id.length, 0, 0);
- } else {
- name = '';
- location = new Location(source.fullName, -1, 0, 1, 0);
- }
- int flags = protocol.Element.makeFlags(
- isAbstract: isAbstract,
- isDeprecated: isDeprecated,
- isPrivate: Identifier.isPrivateName(name));
- return new protocol.Element(kind, name, flags,
- location: location,
- parameters: parameters,
- returnType: nameForType(returnType));
-}
-
-/**
-* Create a new suggestion for the given field.
-* Return the new suggestion or `null` if it could not be created.
-*/
-CompletionSuggestion createLocalFieldSuggestion(
- Source source, FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
- bool deprecated = isDeprecated(fieldDecl) || isDeprecated(varDecl);
- TypeName type = fieldDecl.fields.type;
- return createLocalSuggestion(
- varDecl.name, deprecated, DART_RELEVANCE_LOCAL_FIELD, type,
- classDecl: fieldDecl.parent,
- element: createLocalElement(
- source, protocol.ElementKind.FIELD, varDecl.name,
- returnType: type, isDeprecated: deprecated));
-}
-
-/**
-* Create a new suggestion based upon the given information.
-* Return the new suggestion or `null` if it could not be created.
-*/
-CompletionSuggestion createLocalSuggestion(SimpleIdentifier id,
- bool isDeprecated, int defaultRelevance, TypeName returnType,
- {ClassDeclaration classDecl, protocol.Element element}) {
- if (id == null) {
- return null;
- }
- String completion = id.name;
- if (completion == null || completion.length <= 0 || completion == '_') {
- return null;
- }
- CompletionSuggestion suggestion = new CompletionSuggestion(
- CompletionSuggestionKind.INVOCATION,
- isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
- completion,
- completion.length,
- 0,
- isDeprecated,
- false,
- returnType: nameForType(returnType),
- element: element);
- if (classDecl != null) {
- SimpleIdentifier classId = classDecl.name;
- if (classId != null) {
- String className = classId.name;
- if (className != null && className.length > 0) {
- suggestion.declaringType = className;
- }
- }
- }
- return suggestion;
-}
-
-/**
-* Return `true` if the @deprecated annotation is present
-*/
-bool isDeprecated(AnnotatedNode node) {
- if (node != null) {
- NodeList<Annotation> metadata = node.metadata;
- if (metadata != null) {
- return metadata.any((Annotation a) {
- return a.name is SimpleIdentifier && a.name.name == 'deprecated';
- });
- }
- }
- return false;
-}
-
-/**
-* Return the name for the given type.
-*/
-String nameForType(TypeName type) {
- if (type == NO_RETURN_TYPE) {
- return null;
- }
- if (type == null) {
- return DYNAMIC;
- }
- Identifier id = type.name;
- if (id == null) {
- return DYNAMIC;
- }
- String name = id.name;
- if (name == null || name.length <= 0) {
- return DYNAMIC;
- }
- TypeArgumentList typeArgs = type.typeArguments;
- if (typeArgs != null) {
- //TODO (danrubel) include type arguments
- }
- return name;
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
index c7b9590..118103f 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
@@ -34,14 +34,13 @@
Expression targetId = request.dotTarget;
if (targetId is SimpleIdentifier && !request.target.isCascade) {
Element elem = targetId.bestElement;
- if (elem is PrefixElement) {
- List<Directive> directives = await request.resolveDirectives();
+ if (elem is PrefixElement && !elem.isSynthetic) {
+ List<ImportElement> imports = await request.resolveImports();
LibraryElement containingLibrary = request.libraryElement;
// Gracefully degrade if the library or directives
// could not be determined (e.g. detached part file or source change)
- if (containingLibrary != null && directives != null) {
- return _buildSuggestions(
- request, elem, containingLibrary, directives);
+ if (containingLibrary != null && imports != null) {
+ return _buildSuggestions(request, elem, containingLibrary, imports);
}
}
}
@@ -52,36 +51,27 @@
DartCompletionRequest request,
PrefixElement elem,
LibraryElement containingLibrary,
- List<Directive> directives) {
+ List<ImportElement> imports) {
List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
- for (Directive directive in directives) {
- if (directive is ImportDirective) {
- if (directive.prefix != null) {
- if (directive.prefix.name == elem.name) {
- LibraryElement library = directive.uriElement;
+ for (ImportElement importElem in imports) {
+ if (importElem.prefix?.name == elem.name) {
+ LibraryElement library = importElem.importedLibrary;
- // Suggest elements from the imported library
- if (library != null) {
- AstNode parent = request.target.containingNode.parent;
- bool isConstructor = parent.parent is ConstructorName;
- bool typesOnly = parent is TypeName;
- bool instCreation = typesOnly && isConstructor;
- LibraryElementSuggestionBuilder builder =
- new LibraryElementSuggestionBuilder(
- containingLibrary,
- CompletionSuggestionKind.INVOCATION,
- typesOnly,
- instCreation);
- library.visitChildren(builder);
- suggestions.addAll(builder.suggestions);
+ // Suggest elements from the imported library
+ AstNode parent = request.target.containingNode.parent;
+ bool isConstructor = parent.parent is ConstructorName;
+ bool typesOnly = parent is TypeName;
+ bool instCreation = typesOnly && isConstructor;
+ LibraryElementSuggestionBuilder builder =
+ new LibraryElementSuggestionBuilder(containingLibrary,
+ CompletionSuggestionKind.INVOCATION, typesOnly, instCreation);
+ library.visitChildren(builder);
+ suggestions.addAll(builder.suggestions);
- // If the import is 'deferred' then suggest 'loadLibrary'
- if (directive.deferredKeyword != null) {
- FunctionElement loadLibFunct = library.loadLibraryFunction;
- suggestions.add(createSuggestion(loadLibFunct));
- }
- }
- }
+ // If the import is 'deferred' then suggest 'loadLibrary'
+ if (importElem.isDeferred) {
+ FunctionElement loadLibFunct = library.loadLibraryFunction;
+ suggestions.add(createSuggestion(loadLibFunct));
}
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
index 194e741..a216606 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
@@ -9,7 +9,6 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
import '../../../protocol_server.dart'
show CompletionSuggestion, CompletionSuggestionKind;
@@ -26,26 +25,22 @@
return EMPTY_LIST;
}
- List<Directive> directives = await request.resolveDirectives();
- if (directives == null) {
+ List<ImportElement> imports = await request.resolveImports();
+ if (imports == null) {
return EMPTY_LIST;
}
List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
- for (Directive directive in directives) {
- if (directive is ImportDirective) {
- SimpleIdentifier prefix = directive.prefix;
- ImportElement element = directive.element;
- if (prefix != null && element != null) {
- String completion = prefix.name;
- LibraryElement libElem = element.importedLibrary;
- if (completion != null && completion.length > 0 && libElem != null) {
- CompletionSuggestion suggestion = createSuggestion(libElem,
- completion: completion,
- kind: CompletionSuggestionKind.IDENTIFIER);
- if (suggestion != null) {
- suggestions.add(suggestion);
- }
+ for (ImportElement element in imports) {
+ String completion = element.prefix?.name;
+ if (completion != null && completion.length > 0) {
+ LibraryElement libElem = element.importedLibrary;
+ if (libElem != null) {
+ CompletionSuggestion suggestion = createSuggestion(libElem,
+ completion: completion,
+ kind: CompletionSuggestionKind.IDENTIFIER);
+ if (suggestion != null) {
+ suggestions.add(suggestion);
}
}
}
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 d8d4e36..c05a215 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
@@ -15,9 +15,10 @@
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:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import '../../../protocol_server.dart'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_declaration_visitor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_declaration_visitor.dart
index 964c6b4..586eac2 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_declaration_visitor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_declaration_visitor.dart
@@ -4,8 +4,9 @@
library services.completion.dart.local.declaration.visitor;
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
/**
* `LocalDeclarationCollector` visits an [AstNode] and its parent recursively
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 9469154..9b36935 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
@@ -11,7 +11,6 @@
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:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import '../../../protocol_server.dart'
@@ -30,23 +29,17 @@
return EMPTY_LIST;
}
- List<Directive> directives = await request.resolveDirectives();
- if (directives == null) {
+ List<CompilationUnitElement> libraryUnits = await request.resolveUnits();
+ if (libraryUnits == null) {
return EMPTY_LIST;
}
OpType optype = (request as DartCompletionRequestImpl).opType;
LibraryElementSuggestionBuilder visitor =
new LibraryElementSuggestionBuilder(request, optype);
- if (request.librarySource != request.source) {
- request.libraryElement.definingCompilationUnit.accept(visitor);
- }
- for (Directive directive in directives) {
- if (directive is PartDirective) {
- CompilationUnitElement partElem = directive.element;
- if (partElem != null && partElem.source != request.source) {
- partElem.accept(visitor);
- }
+ for (CompilationUnitElement unit in libraryUnits) {
+ if (unit != null && unit.source != request.source) {
+ unit.accept(visitor);
}
}
return visitor.suggestions;
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 966f1d9..661f89a 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
@@ -15,8 +15,9 @@
show LocalDeclarationVisitor;
import 'package:analysis_server/src/services/completion/dart/optype.dart';
import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
@@ -29,6 +30,116 @@
new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), null);
/**
+* Create a new protocol Element for inclusion in a completion suggestion.
+*/
+protocol.Element _createLocalElement(
+ Source source, protocol.ElementKind kind, SimpleIdentifier id,
+ {String parameters,
+ TypeName returnType,
+ bool isAbstract: false,
+ bool isDeprecated: false}) {
+ String name;
+ Location location;
+ if (id != null) {
+ name = id.name;
+ // TODO(danrubel) use lineInfo to determine startLine and startColumn
+ location = new Location(source.fullName, id.offset, id.length, 0, 0);
+ } else {
+ name = '';
+ location = new Location(source.fullName, -1, 0, 1, 0);
+ }
+ int flags = protocol.Element.makeFlags(
+ isAbstract: isAbstract,
+ isDeprecated: isDeprecated,
+ isPrivate: Identifier.isPrivateName(name));
+ return new protocol.Element(kind, name, flags,
+ location: location,
+ parameters: parameters,
+ returnType: _nameForType(returnType));
+}
+
+/**
+* Create a new suggestion based upon the given information.
+* Return the new suggestion or `null` if it could not be created.
+*/
+CompletionSuggestion _createLocalSuggestion(
+ SimpleIdentifier id,
+ CompletionSuggestionKind kind,
+ bool isDeprecated,
+ int defaultRelevance,
+ TypeName returnType,
+ {ClassDeclaration classDecl,
+ protocol.Element element}) {
+ if (id == null) {
+ return null;
+ }
+ String completion = id.name;
+ if (completion == null || completion.length <= 0 || completion == '_') {
+ return null;
+ }
+ CompletionSuggestion suggestion = new CompletionSuggestion(
+ kind,
+ isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
+ completion,
+ completion.length,
+ 0,
+ isDeprecated,
+ false,
+ returnType: _nameForType(returnType),
+ element: element);
+ if (classDecl != null) {
+ SimpleIdentifier classId = classDecl.name;
+ if (classId != null) {
+ String className = classId.name;
+ if (className != null && className.length > 0) {
+ suggestion.declaringType = className;
+ }
+ }
+ }
+ return suggestion;
+}
+
+/**
+* Return `true` if the @deprecated annotation is present
+*/
+bool _isDeprecated(AnnotatedNode node) {
+ if (node != null) {
+ NodeList<Annotation> metadata = node.metadata;
+ if (metadata != null) {
+ return metadata.any((Annotation a) {
+ return a.name is SimpleIdentifier && a.name.name == 'deprecated';
+ });
+ }
+ }
+ return false;
+}
+
+/**
+* Return the name for the given type.
+*/
+String _nameForType(TypeName type) {
+ if (type == NO_RETURN_TYPE) {
+ return null;
+ }
+ if (type == null) {
+ return DYNAMIC;
+ }
+ Identifier id = type.name;
+ if (id == null) {
+ return DYNAMIC;
+ }
+ String name = id.name;
+ if (name == null || name.length <= 0) {
+ return DYNAMIC;
+ }
+ TypeArgumentList typeArgs = type.typeArguments;
+ if (typeArgs != null) {
+ //TODO (danrubel) include type arguments
+ }
+ return name;
+}
+
+/**
* A contributor for calculating suggestions for declarations in the local
* file and containing library.
*/
@@ -259,6 +370,38 @@
}
}
+ void _addLocalSuggestion(
+ SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
+ {bool isAbstract: false,
+ bool isDeprecated: false,
+ ClassDeclaration classDecl,
+ FormalParameterList param,
+ int relevance: DART_RELEVANCE_DEFAULT}) {
+ CompletionSuggestionKind kind = targetIsFunctionalArgument
+ ? CompletionSuggestionKind.IDENTIFIER
+ : optype.suggestKind;
+ CompletionSuggestion suggestion = _createLocalSuggestion(
+ id, kind, isDeprecated, relevance, typeName,
+ classDecl: classDecl);
+ if (suggestion != null) {
+ if (privateMemberRelevance != null &&
+ suggestion.completion.startsWith('_')) {
+ suggestion.relevance = privateMemberRelevance;
+ }
+ suggestionMap.putIfAbsent(suggestion.completion, () => suggestion);
+ suggestion.element = _createLocalElement(request.source, elemKind, id,
+ isAbstract: isAbstract,
+ isDeprecated: isDeprecated,
+ parameters: param != null ? param.toSource() : null,
+ returnType: typeName);
+ if ((elemKind == protocol.ElementKind.METHOD ||
+ elemKind == protocol.ElementKind.FUNCTION) &&
+ param != null) {
+ _addParameterInfo(suggestion, param);
+ }
+ }
+ }
+
void _addParameterInfo(
CompletionSuggestion suggestion, FormalParameterList parameters) {
var paramList = parameters.parameters;
@@ -296,38 +439,6 @@
.any((FormalParameter param) => param.kind == ParameterKind.NAMED);
}
- void _addLocalSuggestion(
- SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
- {bool isAbstract: false,
- bool isDeprecated: false,
- ClassDeclaration classDecl,
- FormalParameterList param,
- int relevance: DART_RELEVANCE_DEFAULT}) {
- CompletionSuggestionKind kind = targetIsFunctionalArgument
- ? CompletionSuggestionKind.IDENTIFIER
- : optype.suggestKind;
- CompletionSuggestion suggestion = _createLocalSuggestion(
- id, kind, isDeprecated, relevance, typeName,
- classDecl: classDecl);
- if (suggestion != null) {
- if (privateMemberRelevance != null &&
- suggestion.completion.startsWith('_')) {
- suggestion.relevance = privateMemberRelevance;
- }
- suggestionMap.putIfAbsent(suggestion.completion, () => suggestion);
- suggestion.element = _createLocalElement(request.source, elemKind, id,
- isAbstract: isAbstract,
- isDeprecated: isDeprecated,
- parameters: param != null ? param.toSource() : null,
- returnType: typeName);
- if ((elemKind == protocol.ElementKind.METHOD ||
- elemKind == protocol.ElementKind.FUNCTION) &&
- param != null) {
- _addParameterInfo(suggestion, param);
- }
- }
- }
-
bool _isVoid(TypeName returnType) {
if (returnType != null) {
Identifier id = returnType.name;
@@ -338,113 +449,3 @@
return false;
}
}
-
-/**
-* Create a new protocol Element for inclusion in a completion suggestion.
-*/
-protocol.Element _createLocalElement(
- Source source, protocol.ElementKind kind, SimpleIdentifier id,
- {String parameters,
- TypeName returnType,
- bool isAbstract: false,
- bool isDeprecated: false}) {
- String name;
- Location location;
- if (id != null) {
- name = id.name;
- // TODO(danrubel) use lineInfo to determine startLine and startColumn
- location = new Location(source.fullName, id.offset, id.length, 0, 0);
- } else {
- name = '';
- location = new Location(source.fullName, -1, 0, 1, 0);
- }
- int flags = protocol.Element.makeFlags(
- isAbstract: isAbstract,
- isDeprecated: isDeprecated,
- isPrivate: Identifier.isPrivateName(name));
- return new protocol.Element(kind, name, flags,
- location: location,
- parameters: parameters,
- returnType: _nameForType(returnType));
-}
-
-/**
-* Create a new suggestion based upon the given information.
-* Return the new suggestion or `null` if it could not be created.
-*/
-CompletionSuggestion _createLocalSuggestion(
- SimpleIdentifier id,
- CompletionSuggestionKind kind,
- bool isDeprecated,
- int defaultRelevance,
- TypeName returnType,
- {ClassDeclaration classDecl,
- protocol.Element element}) {
- if (id == null) {
- return null;
- }
- String completion = id.name;
- if (completion == null || completion.length <= 0 || completion == '_') {
- return null;
- }
- CompletionSuggestion suggestion = new CompletionSuggestion(
- kind,
- isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
- completion,
- completion.length,
- 0,
- isDeprecated,
- false,
- returnType: _nameForType(returnType),
- element: element);
- if (classDecl != null) {
- SimpleIdentifier classId = classDecl.name;
- if (classId != null) {
- String className = classId.name;
- if (className != null && className.length > 0) {
- suggestion.declaringType = className;
- }
- }
- }
- return suggestion;
-}
-
-/**
-* Return `true` if the @deprecated annotation is present
-*/
-bool _isDeprecated(AnnotatedNode node) {
- if (node != null) {
- NodeList<Annotation> metadata = node.metadata;
- if (metadata != null) {
- return metadata.any((Annotation a) {
- return a.name is SimpleIdentifier && a.name.name == 'deprecated';
- });
- }
- }
- return false;
-}
-
-/**
-* Return the name for the given type.
-*/
-String _nameForType(TypeName type) {
- if (type == NO_RETURN_TYPE) {
- return null;
- }
- if (type == null) {
- return DYNAMIC;
- }
- Identifier id = type.name;
- if (id == null) {
- return DYNAMIC;
- }
- String name = id.name;
- if (name == null || name.length <= 0) {
- return DYNAMIC;
- }
- TypeArgumentList typeArgs = type.typeArguments;
- if (typeArgs != null) {
- //TODO (danrubel) include type arguments
- }
- return name;
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/optype.dart b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
index 9acbf07..71c1bfd 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/optype.dart
@@ -4,10 +4,11 @@
library services.completion.dart.optype;
-import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/generated/ast.dart';
/**
* An [AstVisitor] for determining whether top level suggestions or invocation
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index 257527b..7a0f760 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -72,7 +72,8 @@
} else if (elem is LocalVariableElement) {
type = elem.type;
}
- if (type.isDynamic && expression is SimpleIdentifier) {
+ if ((type == null || type.isDynamic) &&
+ expression is SimpleIdentifier) {
// If the element does not provide a good type
// then attempt to get a better type from a local declaration
_LocalBestTypeVisitor visitor =
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 13714ae..be95ec1 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -17,12 +17,13 @@
import 'package:analysis_server/src/services/correction/statement_analyzer.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:path/path.dart';
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 ffdf72d..36eb5b9 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -24,9 +24,11 @@
import 'package:analysis_server/src/services/correction/strings.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
@@ -35,7 +37,6 @@
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
diff --git a/pkg/analysis_server/lib/src/services/correction/organize_directives.dart b/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
index a4adfac..9d9faa1 100644
--- a/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
+++ b/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
@@ -7,9 +7,9 @@
import 'package:analysis_server/plugin/protocol/protocol.dart'
hide AnalysisError, Element;
import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
/**
* Organizer of directives in the [unit].
diff --git a/pkg/analysis_server/lib/src/services/correction/sort_members.dart b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
index 1810cda..49f104b 100644
--- a/pkg/analysis_server/lib/src/services/correction/sort_members.dart
+++ b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
@@ -6,8 +6,8 @@
import 'package:analysis_server/plugin/protocol/protocol.dart' hide Element;
import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
/**
* Sorter for unit/class members.
diff --git a/pkg/analysis_server/lib/src/services/correction/source_range.dart b/pkg/analysis_server/lib/src/services/correction/source_range.dart
index bf52759..32c98b9 100644
--- a/pkg/analysis_server/lib/src/services/correction/source_range.dart
+++ b/pkg/analysis_server/lib/src/services/correction/source_range.dart
@@ -4,10 +4,10 @@
library services.src.correction.source_range_factory;
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
SourceRange rangeElementName(Element element) {
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
index c25f77a..2ec69eb 100644
--- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -9,9 +9,11 @@
import 'package:analysis_server/src/services/correction/source_range.dart';
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/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/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index c69bf69..65c12c6 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -12,12 +12,15 @@
show doSourceChange_addElementEdit;
import 'package:analysis_server/src/services/correction/source_range.dart';
import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:path/path.dart';
diff --git a/pkg/analysis_server/lib/src/services/index/index_contributor.dart b/pkg/analysis_server/lib/src/services/index/index_contributor.dart
index b5eee6b..ebac4d6 100644
--- a/pkg/analysis_server/lib/src/services/index/index_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/index/index_contributor.dart
@@ -12,12 +12,12 @@
import 'package:analysis_server/src/services/index/index_store.dart';
import 'package:analysis_server/src/services/index/indexable_element.dart';
import 'package:analysis_server/src/services/index/indexable_file.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
/**
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
index 51db1c2..d91306c 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
@@ -13,9 +13,9 @@
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/source.dart';
/**
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 a17bfda..bb513ba 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -17,10 +17,10 @@
import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
const String _TOKEN_SEPARATOR = "\uFFFF";
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index 7855298..1cb713a 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -20,13 +20,13 @@
import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart';
import 'package:analysis_server/src/services/search/element_visitors.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/resolver.dart' show ExitDetector;
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
const String _TOKEN_SEPARATOR = '\uFFFF';
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
index 1fe699a..d5c6894 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
@@ -13,10 +13,10 @@
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
/**
diff --git a/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart b/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
index aac5275..892da77 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
@@ -6,7 +6,7 @@
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/correction/strings.dart';
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/dart/ast/token.dart';
/**
* Returns the [RefactoringStatus] with severity:
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index 9fd17ca..ad1baaa 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -15,6 +15,7 @@
import 'package:analyzer/plugin/embedded_resolver_provider.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/pub_package_map_provider.dart';
+import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/sdk_io.dart';
import 'package:plugin/plugin.dart';
@@ -26,6 +27,12 @@
*/
class SocketServer {
final AnalysisServerOptions analysisServerOptions;
+
+ /**
+ * The function used to create a new SDK using the default SDK.
+ */
+ final SdkCreator defaultSdkCreator;
+
final DirectoryBasedDartSdk defaultSdk;
final InstrumentationService instrumentationService;
final ServerPlugin serverPlugin;
@@ -45,6 +52,7 @@
SocketServer(
this.analysisServerOptions,
+ this.defaultSdkCreator,
this.defaultSdk,
this.instrumentationService,
this.serverPlugin,
@@ -91,7 +99,7 @@
index,
serverPlugin,
analysisServerOptions,
- defaultSdk,
+ defaultSdkCreator,
instrumentationService,
packageResolverProvider: packageResolverProvider,
embeddedResolverProvider: embeddedResolverProvider,
diff --git a/pkg/analysis_server/lib/src/status/validator.dart b/pkg/analysis_server/lib/src/status/validator.dart
index b153c29..07f34b3 100644
--- a/pkg/analysis_server/lib/src/status/validator.dart
+++ b/pkg/analysis_server/lib/src/status/validator.dart
@@ -6,17 +6,17 @@
import 'dart:collection';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart'
show AnalysisEngine, AnalysisResult, CacheState, ChangeSet;
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_collection.dart';
import 'package:analyzer/src/task/dart.dart';
@@ -24,7 +24,6 @@
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/model.dart';
import 'package:html/dom.dart' as html;
-import 'package:analyzer/src/dart/element/element.dart';
/**
* A class used to compare two element models for equality.
@@ -757,8 +756,8 @@
* Write a simple message explaining that the [expected] and [actual] values
* were different, using the [describe] function to describe the values.
*/
- void _writeMismatch /*<E>*/ (Object /*=E*/ expected, Object /*=E*/ actual,
- String describe(Object /*=E*/ value)) {
+ void _writeMismatch/*<E>*/(Object/*=E*/ expected, Object/*=E*/ actual,
+ String describe(Object/*=E*/ value)) {
_write('Expected ');
_write(describe(expected));
_write('; found ');
@@ -1194,8 +1193,7 @@
//
// Handle special cases.
//
- if (first is ElementAnnotationImpl &&
- second is ElementAnnotationImpl) {
+ if (first is ElementAnnotationImpl && second is ElementAnnotationImpl) {
return _equal(first.source, second.source) &&
_equal(first.librarySource, second.librarySource) &&
_equal(first.annotationAst, second.annotationAst);
diff --git a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
index bac921d..51131dc 100644
--- a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
+++ b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
@@ -10,11 +10,11 @@
import 'package:analysis_server/src/services/correction/name_suggestion.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/utilities/change_builder_core.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
diff --git a/pkg/analysis_server/test/analysis/set_priority_files_test.dart b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
index f89ba30..9a1b5c9 100644
--- a/pkg/analysis_server/test/analysis/set_priority_files_test.dart
+++ b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
@@ -58,7 +58,7 @@
Response response = await _setPriorityFile(filePath);
expect(response, isResponseSuccess('0'));
// verify
- InternalAnalysisContext sdkContext = server.defaultSdk.context;
+ InternalAnalysisContext sdkContext = server.findSdk().context;
List<Source> prioritySources = sdkContext.prioritySources;
expect(prioritySources, hasLength(1));
expect(prioritySources.first.fullName, filePath);
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index 4faf108..3541d91 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -126,7 +126,7 @@
index,
serverPlugin,
new AnalysisServerOptions(),
- new MockSdk(),
+ () => new MockSdk(),
InstrumentationService.NULL_SERVICE);
}
@@ -171,7 +171,7 @@
*/
Response handleSuccessfulRequest(Request request) {
Response response = handler.handleRequest(request);
- expect(response, isResponseSuccess('0'));
+ expect(response, isResponseSuccess(request.id));
return response;
}
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 14d9fd6..e12a691 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -141,7 +141,7 @@
null,
new ServerPlugin(),
new AnalysisServerOptions(),
- new MockSdk(),
+ () => new MockSdk(),
InstrumentationService.NULL_SERVICE,
rethrowExceptions: true);
processRequiredPlugins();
@@ -152,12 +152,15 @@
resourceProvider.newFile('/foo/bar.dart', 'library lib;');
server.setAnalysisRoots('0', ['/foo'], [], {});
AnalysisContext context;
- return pumpEventQueue().then((_) {
- context = server.getAnalysisContext('/foo/bar.dart');
- server.setAnalysisRoots('1', [], [], {});
- }).then((_) => pumpEventQueue()).then((_) {
- expect(context.isDisposed, isTrue);
- });
+ return pumpEventQueue()
+ .then((_) {
+ context = server.getAnalysisContext('/foo/bar.dart');
+ server.setAnalysisRoots('1', [], [], {});
+ })
+ .then((_) => pumpEventQueue())
+ .then((_) {
+ expect(context.isDisposed, isTrue);
+ });
}
Future test_contextsChangedEvent() {
@@ -529,8 +532,9 @@
void _assertContextOfFolder(
AnalysisContext context, String expectedFolderPath) {
Folder expectedFolder = resourceProvider.newFolder(expectedFolderPath);
- ContextInfo expectedContextInfo = (server.contextManager
- as ContextManagerImpl).getContextInfoFor(expectedFolder);
+ ContextInfo expectedContextInfo =
+ (server.contextManager as ContextManagerImpl)
+ .getContextInfoFor(expectedFolder);
expect(expectedContextInfo, isNotNull);
expect(context, same(expectedContextInfo.context));
}
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index d225c90..a94314b 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -2363,7 +2363,11 @@
Iterable<String> get currentContextPaths => currentContextTimestamps.keys;
@override
- AnalysisContext addContext(Folder folder, FolderDisposition disposition) {
+ AnalysisOptions get defaultAnalysisOptions => new AnalysisOptionsImpl();
+
+ @override
+ AnalysisContext addContext(
+ Folder folder, AnalysisOptions options, FolderDisposition disposition) {
String path = folder.path;
expect(currentContextPaths, isNot(contains(path)));
currentContextTimestamps[path] = now;
@@ -2386,6 +2390,7 @@
}
resolvers.addAll(disposition.createPackageUriResolvers(resourceProvider));
resolvers.add(new FileUriResolver());
+ currentContext.analysisOptions = options;
currentContext.sourceFactory =
new SourceFactory(resolvers, disposition.packages);
return currentContext;
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index b7f4b34..f8c0afd 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -47,7 +47,7 @@
null,
serverPlugin,
new AnalysisServerOptions(),
- new MockSdk(),
+ () => new MockSdk(),
InstrumentationService.NULL_SERVICE);
handler = new AnalysisDomainHandler(server);
});
@@ -474,7 +474,7 @@
null,
serverPlugin,
new AnalysisServerOptions(),
- new MockSdk(),
+ () => new MockSdk(),
InstrumentationService.NULL_SERVICE);
handler = new AnalysisDomainHandler(server);
// listen for notifications
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index acff007..61734b6 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -17,6 +17,7 @@
import 'analysis_abstract.dart';
import 'domain_completion_util.dart';
+import 'mocks.dart' show pumpEventQueue;
import 'utils.dart';
main() {
@@ -53,6 +54,76 @@
});
}
+ test_imports_aborted_new_request() async {
+ addTestFile('''
+ class foo { }
+ c^''');
+
+ // Make a request for suggestions
+ Request request =
+ new CompletionGetSuggestionsParams(testFile, completionOffset)
+ .toRequest('7');
+ Response response = handleSuccessfulRequest(request);
+ var result1 = new CompletionGetSuggestionsResult.fromResponse(response);
+ var completionId1 = result1.id;
+ assertValidId(response.id);
+
+ // Perform some analysis but assert that no suggestions have yet been made
+ completionId = completionId1;
+ await pumpEventQueue(25);
+ expect(suggestionsDone, isFalse);
+ expect(suggestions, hasLength(0));
+
+ // Make another request before the first request completes
+ Request request2 =
+ new CompletionGetSuggestionsParams(testFile, completionOffset)
+ .toRequest('8');
+ Response response2 = handleSuccessfulRequest(request2);
+ var result2 = new CompletionGetSuggestionsResult.fromResponse(response2);
+ var completionId2 = result2.id;
+ assertValidId(completionId2);
+
+ // Wait for both sets of suggestions
+ completionId = completionId2;
+ await pumpEventQueue();
+ expect(allSuggestions[completionId1], hasLength(0));
+ expect(allSuggestions[completionId2], same(suggestions));
+ assertHasResult(CompletionSuggestionKind.KEYWORD, 'class',
+ relevance: DART_RELEVANCE_HIGH);
+ }
+
+ test_imports_aborted_source_changed() async {
+ addTestFile('''
+ class foo { }
+ c^''');
+
+ // Make a request for suggestions
+ Request request =
+ new CompletionGetSuggestionsParams(testFile, completionOffset)
+ .toRequest('0');
+ Response response = handleSuccessfulRequest(request);
+ completionId = response.id;
+ assertValidId(completionId);
+
+ // Perform some analysis but assert that no suggestions have yet been made
+ await pumpEventQueue(25);
+ expect(suggestionsDone, isFalse);
+ expect(suggestions, hasLength(0));
+
+ // Simulate user deleting text after request but before suggestions returned
+ server.updateContent('uc1', {testFile: new AddContentOverlay(testCode)});
+ server.updateContent('uc2', {
+ testFile: new ChangeContentOverlay(
+ [new SourceEdit(completionOffset - 1, 1, '')])
+ });
+
+ // Expect the completion domain to discard request because source changed
+ await pumpEventQueue().then((_) {
+ expect(suggestionsDone, isTrue);
+ });
+ expect(suggestions, hasLength(0));
+ }
+
test_imports_incremental() async {
addTestFile('''library foo;
e^
diff --git a/pkg/analysis_server/test/domain_completion_util.dart b/pkg/analysis_server/test/domain_completion_util.dart
index 29cff99..7c4ed6c 100644
--- a/pkg/analysis_server/test/domain_completion_util.dart
+++ b/pkg/analysis_server/test/domain_completion_util.dart
@@ -24,6 +24,7 @@
int replacementLength;
List<CompletionSuggestion> suggestions = [];
bool suggestionsDone = false;
+ Map<String,List<CompletionSuggestion>> allSuggestions = {};
String addTestFile(String content, {int offset}) {
completionOffset = content.indexOf('^');
@@ -109,6 +110,7 @@
expect(suggestionsDone, isNotNull);
suggestions = params.results;
}
+ allSuggestions[id] = params.results;
} else if (notification.event == SERVER_ERROR) {
fail('server error: ${notification.toJson()}');
}
diff --git a/pkg/analysis_server/test/domain_diagnostic_test.dart b/pkg/analysis_server/test/domain_diagnostic_test.dart
index e0a6867..277279a 100644
--- a/pkg/analysis_server/test/domain_diagnostic_test.dart
+++ b/pkg/analysis_server/test/domain_diagnostic_test.dart
@@ -53,7 +53,7 @@
null,
serverPlugin,
new AnalysisServerOptions(),
- new MockSdk(),
+ () => new MockSdk(),
InstrumentationService.NULL_SERVICE);
handler = new DiagnosticDomainHandler(server);
});
diff --git a/pkg/analysis_server/test/domain_execution_test.dart b/pkg/analysis_server/test/domain_execution_test.dart
index a142adb..1274eab 100644
--- a/pkg/analysis_server/test/domain_execution_test.dart
+++ b/pkg/analysis_server/test/domain_execution_test.dart
@@ -48,7 +48,7 @@
null,
serverPlugin,
new AnalysisServerOptions(),
- new MockSdk(),
+ () => new MockSdk(),
InstrumentationService.NULL_SERVICE);
handler = new ExecutionDomainHandler(server);
});
@@ -124,8 +124,9 @@
group('file to URI', () {
test('does not exist', () {
- Request request = new ExecutionMapUriParams(contextId,
- file: '/a/c.dart').toRequest('2');
+ Request request =
+ new ExecutionMapUriParams(contextId, file: '/a/c.dart')
+ .toRequest('2');
Response response = handler.handleRequest(request);
expect(response, isResponseFailure('2'));
});
@@ -141,8 +142,9 @@
group('URI to file', () {
test('invalid', () {
- Request request = new ExecutionMapUriParams(contextId,
- uri: 'foo:///a/b.dart').toRequest('2');
+ Request request =
+ new ExecutionMapUriParams(contextId, uri: 'foo:///a/b.dart')
+ .toRequest('2');
Response response = handler.handleRequest(request);
expect(response, isResponseFailure('2'));
});
@@ -299,7 +301,7 @@
}
void test_mapUri_file_dartUriKind() {
- String path = server.defaultSdk.mapDartUri('dart:async').fullName;
+ String path = server.findSdk().mapDartUri('dart:async').fullName;
// hack - pretend that the SDK file exists in the project FS
resourceProvider.newFile(path, '// hack');
// map file
diff --git a/pkg/analysis_server/test/domain_server_test.dart b/pkg/analysis_server/test/domain_server_test.dart
index 51237cd..6dc24d1 100644
--- a/pkg/analysis_server/test/domain_server_test.dart
+++ b/pkg/analysis_server/test/domain_server_test.dart
@@ -37,7 +37,7 @@
null,
serverPlugin,
new AnalysisServerOptions(),
- new MockSdk(),
+ () => new MockSdk(),
InstrumentationService.NULL_SERVICE);
handler = new ServerDomainHandler(server);
});
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 28c6a09..8ecfc8f 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
@@ -436,6 +436,7 @@
}
Future computeSuggestions([int times = 200]) async {
+ context.analysisPriorityOrder = [testSource];
CompletionRequestImpl baseRequest = new CompletionRequestImpl(
context,
provider,
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
new file mode 100644
index 0000000..fa43aa1
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -0,0 +1,106 @@
+// 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 test.services.completion.dart.manager;
+
+import 'dart:async';
+
+import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/completion_core.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/imported_reference_contributor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../utils.dart';
+import 'completion_contributor_util.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+main() {
+ initializeTestEnvironment();
+ defineReflectiveTests(CompletionManagerTest);
+}
+
+@reflectiveTest
+class CompletionManagerTest extends DartCompletionContributorTest {
+ @override
+ DartCompletionContributor createContributor() {
+ return new ImportedReferenceContributor();
+ }
+
+ test_resolveDirectives() async {
+ addSource(
+ '/libA.dart',
+ '''
+library libA;
+/// My class.
+/// Short description.
+///
+/// Longer description.
+class A {}
+''');
+ var libSource = addSource(
+ '/libB.dart',
+ '''
+library libB;
+import "/libA.dart" as foo;
+part '$testFile';
+''');
+ addTestSource('part of libB; main() {^}');
+
+ // Associate part with library
+ context.computeResult(
+ new LibrarySpecificUnit(libSource, testSource), LIBRARY_CYCLE_UNITS);
+
+ // Build the request
+ CompletionRequestImpl baseRequest = new CompletionRequestImpl(
+ context,
+ provider,
+ searchEngine,
+ testSource,
+ completionOffset,
+ new CompletionPerformance());
+ Completer<DartCompletionRequest> requestCompleter =
+ new Completer<DartCompletionRequest>();
+ DartCompletionRequestImpl
+ .from(baseRequest, resultDescriptor: RESOLVED_UNIT1)
+ .then((DartCompletionRequest request) {
+ requestCompleter.complete(request);
+ });
+ request = await performAnalysis(200, requestCompleter);
+
+ // Get the unresolved directives
+ var directives = request.target.unit.directives;
+
+ // Assert that the import does not have an export namespace
+ expect(directives[0].element?.library?.exportNamespace, isNull);
+
+ // Resolve directives
+ var importCompleter = new Completer<List<ImportElement>>();
+ request.resolveImports().then((List<ImportElement> elements) {
+ importCompleter.complete(elements);
+ });
+ List<ImportElement> imports = await performAnalysis(200, importCompleter);
+ expect(imports, hasLength(directives.length + 1));
+
+ ImportElement importNamed(String expectedUri) {
+ return imports.firstWhere((elem) => elem.uri == expectedUri, orElse: () {
+ var importedNames = imports.map((elem) => elem.uri);
+ fail('Failed to find $expectedUri in $importedNames');
+ });
+ }
+ void assertImportedLib(String expectedUri) {
+ ImportElement importElem = importNamed(expectedUri);
+ expect(importElem.importedLibrary.exportNamespace, isNotNull);
+ }
+
+ // Assert that the new imports each have an export namespace
+ assertImportedLib(null /* dart:core */);
+ assertImportedLib('/libA.dart');
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 167e3ab..73642ea 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -7,7 +7,7 @@
import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:unittest/unittest.dart';
@@ -269,6 +269,11 @@
}
}
+ @override
+ DartCompletionContributor createContributor() {
+ return new KeywordContributor();
+ }
+
fail_import_partial() async {
addTestSource('imp^ import "package:foo/foo.dart"; import "bar.dart";');
await computeSuggestions();
@@ -298,11 +303,6 @@
assertNotSuggested('class');
}
- @override
- DartCompletionContributor createContributor() {
- return new KeywordContributor();
- }
-
test_after_class() async {
addTestSource('class A {} ^');
await computeSuggestions();
@@ -1238,13 +1238,6 @@
assertSuggestKeywords(STMT_START_IN_CLASS, pseudoKeywords: ['await']);
}
- test_method_body_async_star() async {
- addTestSource('class A { foo() async* {^}}');
- await computeSuggestions();
- assertSuggestKeywords(STMT_START_IN_CLASS,
- pseudoKeywords: ['await', 'yield', 'yield*']);
- }
-
test_method_body_async2() async {
addTestSource('class A { foo() async => ^}');
await computeSuggestions();
@@ -1263,6 +1256,13 @@
assertSuggestKeywords(EXPRESSION_START_INSTANCE, pseudoKeywords: ['await']);
}
+ test_method_body_async_star() async {
+ addTestSource('class A { foo() async* {^}}');
+ await computeSuggestions();
+ assertSuggestKeywords(STMT_START_IN_CLASS,
+ pseudoKeywords: ['await', 'yield', 'yield*']);
+ }
+
test_method_body_expression1() async {
addTestSource('class A { foo() {return b == true ? ^}}');
await computeSuggestions();
diff --git a/pkg/analysis_server/test/services/completion/dart/local_declaration_visitor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_declaration_visitor_test.dart
index f70f720f..5765c68 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_declaration_visitor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_declaration_visitor_test.dart
@@ -5,10 +5,12 @@
library test.services.completion.local_declaration_visitor_test;
import 'package:analysis_server/src/services/completion/dart/local_declaration_visitor.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:unittest/unittest.dart';
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 c12f8de..b936392 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -9,6 +9,7 @@
import '../../../utils.dart';
import 'arglist_contributor_test.dart' as arglist_test;
import 'combinator_contributor_test.dart' as combinator_test;
+import 'completion_manager_test.dart' as completion_manager;
import 'common_usage_sorter_test.dart' as common_usage_test;
import 'field_formal_contributor_test.dart' as field_formal_contributor_test;
import 'imported_reference_contributor_test.dart' as imported_ref_test;
@@ -34,6 +35,7 @@
group('dart/completion', () {
arglist_test.main();
combinator_test.main();
+ completion_manager.main();
common_usage_test.main();
field_formal_contributor_test.main();
imported_ref_test.main();
diff --git a/pkg/analysis_server/test/socket_server_test.dart b/pkg/analysis_server/test/socket_server_test.dart
index b4e9f46..1175320 100644
--- a/pkg/analysis_server/test/socket_server_test.dart
+++ b/pkg/analysis_server/test/socket_server_test.dart
@@ -12,6 +12,7 @@
import 'package:analysis_server/src/plugin/server_plugin.dart';
import 'package:analysis_server/src/socket_server.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/sdk_io.dart';
import 'package:plugin/manager.dart';
import 'package:unittest/unittest.dart';
@@ -111,9 +112,12 @@
ServerPlugin serverPlugin = new ServerPlugin();
ExtensionManager manager = new ExtensionManager();
manager.processPlugins([serverPlugin]);
+ SdkCreator sdkCreator = () =>
+ new DirectoryBasedDartSdk(DirectoryBasedDartSdk.defaultSdkDirectory);
return new SocketServer(
new AnalysisServerOptions(),
- DirectoryBasedDartSdk.defaultSdk,
+ sdkCreator,
+ sdkCreator(),
InstrumentationService.NULL_SERVICE,
serverPlugin,
null,
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index 159944f..6c56047 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -11,9 +11,11 @@
import 'dart:io';
import 'package:analysis_server/plugin/protocol/protocol.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/error.dart' as error;
import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/util/glob.dart';
import 'package:args/args.dart';
diff --git a/pkg/analyzer/example/parser_driver.dart b/pkg/analyzer/example/parser_driver.dart
index 2e082b7..c302e41 100644
--- a/pkg/analyzer/example/parser_driver.dart
+++ b/pkg/analyzer/example/parser_driver.dart
@@ -7,9 +7,10 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
main(List<String> args) {
print('working dir ${new File('.').resolveSymbolicLinksSync()}');
diff --git a/pkg/analyzer/example/scanner_driver.dart b/pkg/analyzer/example/scanner_driver.dart
index d403fab..d867f19 100644
--- a/pkg/analyzer/example/scanner_driver.dart
+++ b/pkg/analyzer/example/scanner_driver.dart
@@ -5,7 +5,9 @@
import 'dart:io';
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
main(List<String> args) {
print('working dir ${new File('.').resolveSymbolicLinksSync()}');
diff --git a/pkg/analyzer/lib/analyzer.dart b/pkg/analyzer/lib/analyzer.dart
index 78de42e..0ac8cf4 100644
--- a/pkg/analyzer/lib/analyzer.dart
+++ b/pkg/analyzer/lib/analyzer.dart
@@ -7,10 +7,11 @@
import 'dart:io';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/error.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/string_source.dart';
import 'package:path/path.dart' as pathos;
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 31dd785..598d611 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -36,13 +36,12 @@
*/
library analyzer.dart.ast.ast;
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart' show AuxiliaryElements;
-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/source.dart' show LineInfo, Source;
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -537,7 +536,7 @@
* (either AST nodes or tokens) that make up the contents of this node,
* including doc comments but excluding other comments.
*/
- Iterable/*<AstNode | Token>*/ get childEntities;
+ Iterable /*<AstNode | Token>*/ get childEntities;
/**
* Return the offset of the character immediately following the last character
@@ -592,7 +591,7 @@
* Use the given [visitor] to visit this node. Return the value returned by
* the visitor as a result of visiting this node.
*/
- dynamic /* =E */ accept/*<E>*/(AstVisitor/*<E>*/ visitor);
+ dynamic /* =E */ accept /*<E>*/ (AstVisitor /*<E>*/ visitor);
/**
* Return the most immediate ancestor of this node for which the [predicate]
@@ -3781,6 +3780,32 @@
* is no star.
*/
Token get star;
+
+ /**
+ * If [variable] is a local variable or parameter declared anywhere within
+ * the top level function or method containing this [FunctionBody], return a
+ * boolean indicating whether [variable] is potentially mutated within a
+ * local function other than the function in which it is declared.
+ *
+ * If [variable] is not a local variable or parameter declared within the top
+ * level function or method containing this [FunctionBody], return `false`.
+ *
+ * Throws an exception if resolution has not yet been performed.
+ */
+ bool isPotentiallyMutatedInClosure(VariableElement variable);
+
+ /**
+ * If [variable] is a local variable or parameter declared anywhere within
+ * the top level function or method containing this [FunctionBody], return a
+ * boolean indicating whether [variable] is potentially mutated within the
+ * scope of its declaration.
+ *
+ * If [variable] is not a local variable or parameter declared within the top
+ * level function or method containing this [FunctionBody], return `false`.
+ *
+ * Throws an exception if resolution has not yet been performed.
+ */
+ bool isPotentiallyMutatedInScope(VariableElement variable);
}
/**
@@ -4500,10 +4525,10 @@
return allShows1.length - allShows2.length;
}
// next ensure that the lists are equivalent
- if (!javaCollectionContainsAll(allHides1, allHides2)) {
+ if (!allHides1.toSet().containsAll(allHides2)) {
return -1;
}
- if (!javaCollectionContainsAll(allShows1, allShows2)) {
+ if (!allShows1.toSet().containsAll(allShows2)) {
return -1;
}
return 0;
diff --git a/pkg/analyzer/lib/dart/ast/token.dart b/pkg/analyzer/lib/dart/ast/token.dart
new file mode 100644
index 0000000..6560a8e
--- /dev/null
+++ b/pkg/analyzer/lib/dart/ast/token.dart
@@ -0,0 +1,738 @@
+// 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.
+
+/**
+ * Defines the tokens that are produced by the scanner, used by the parser, and
+ * referenced from the [AST structure](ast.dart).
+ */
+library analyzer.dart.ast.token;
+
+import 'dart:collection';
+
+import 'package:analyzer/src/dart/ast/token.dart' show SimpleToken, TokenClass;
+
+/**
+ * The keywords in the Dart programming language.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class Keyword {
+ static const Keyword ABSTRACT = const Keyword._('ABSTRACT', "abstract", true);
+
+ static const Keyword AS = const Keyword._('AS', "as", true);
+
+ static const Keyword ASSERT = const Keyword._('ASSERT', "assert");
+
+ static const Keyword BREAK = const Keyword._('BREAK', "break");
+
+ static const Keyword CASE = const Keyword._('CASE', "case");
+
+ static const Keyword CATCH = const Keyword._('CATCH', "catch");
+
+ static const Keyword CLASS = const Keyword._('CLASS', "class");
+
+ static const Keyword CONST = const Keyword._('CONST', "const");
+
+ static const Keyword CONTINUE = const Keyword._('CONTINUE', "continue");
+
+ static const Keyword DEFAULT = const Keyword._('DEFAULT', "default");
+
+ static const Keyword DEFERRED = const Keyword._('DEFERRED', "deferred", true);
+
+ static const Keyword DO = const Keyword._('DO', "do");
+
+ static const Keyword DYNAMIC = const Keyword._('DYNAMIC', "dynamic", true);
+
+ static const Keyword ELSE = const Keyword._('ELSE', "else");
+
+ static const Keyword ENUM = const Keyword._('ENUM', "enum");
+
+ static const Keyword EXPORT = const Keyword._('EXPORT', "export", true);
+
+ static const Keyword EXTENDS = const Keyword._('EXTENDS', "extends");
+
+ static const Keyword EXTERNAL = const Keyword._('EXTERNAL', "external", true);
+
+ static const Keyword FACTORY = const Keyword._('FACTORY', "factory", true);
+
+ static const Keyword FALSE = const Keyword._('FALSE', "false");
+
+ static const Keyword FINAL = const Keyword._('FINAL', "final");
+
+ static const Keyword FINALLY = const Keyword._('FINALLY', "finally");
+
+ static const Keyword FOR = const Keyword._('FOR', "for");
+
+ static const Keyword GET = const Keyword._('GET', "get", true);
+
+ static const Keyword IF = const Keyword._('IF', "if");
+
+ static const Keyword IMPLEMENTS =
+ const Keyword._('IMPLEMENTS', "implements", true);
+
+ static const Keyword IMPORT = const Keyword._('IMPORT', "import", true);
+
+ static const Keyword IN = const Keyword._('IN', "in");
+
+ static const Keyword IS = const Keyword._('IS', "is");
+
+ static const Keyword LIBRARY = const Keyword._('LIBRARY', "library", true);
+
+ static const Keyword NEW = const Keyword._('NEW', "new");
+
+ static const Keyword NULL = const Keyword._('NULL', "null");
+
+ static const Keyword OPERATOR = const Keyword._('OPERATOR', "operator", true);
+
+ static const Keyword PART = const Keyword._('PART', "part", true);
+
+ static const Keyword RETHROW = const Keyword._('RETHROW', "rethrow");
+
+ static const Keyword RETURN = const Keyword._('RETURN', "return");
+
+ static const Keyword SET = const Keyword._('SET', "set", true);
+
+ static const Keyword STATIC = const Keyword._('STATIC', "static", true);
+
+ static const Keyword SUPER = const Keyword._('SUPER', "super");
+
+ static const Keyword SWITCH = const Keyword._('SWITCH', "switch");
+
+ static const Keyword THIS = const Keyword._('THIS', "this");
+
+ static const Keyword THROW = const Keyword._('THROW', "throw");
+
+ static const Keyword TRUE = const Keyword._('TRUE', "true");
+
+ static const Keyword TRY = const Keyword._('TRY', "try");
+
+ static const Keyword TYPEDEF = const Keyword._('TYPEDEF', "typedef", true);
+
+ static const Keyword VAR = const Keyword._('VAR', "var");
+
+ static const Keyword VOID = const Keyword._('VOID', "void");
+
+ static const Keyword WHILE = const Keyword._('WHILE', "while");
+
+ static const Keyword WITH = const Keyword._('WITH', "with");
+
+ static const List<Keyword> values = const <Keyword>[
+ ABSTRACT,
+ AS,
+ ASSERT,
+ BREAK,
+ CASE,
+ CATCH,
+ CLASS,
+ CONST,
+ CONTINUE,
+ DEFAULT,
+ DEFERRED,
+ DO,
+ DYNAMIC,
+ ELSE,
+ ENUM,
+ EXPORT,
+ EXTENDS,
+ EXTERNAL,
+ FACTORY,
+ FALSE,
+ FINAL,
+ FINALLY,
+ FOR,
+ GET,
+ IF,
+ IMPLEMENTS,
+ IMPORT,
+ IN,
+ IS,
+ LIBRARY,
+ NEW,
+ NULL,
+ OPERATOR,
+ PART,
+ RETHROW,
+ RETURN,
+ SET,
+ STATIC,
+ SUPER,
+ SWITCH,
+ THIS,
+ THROW,
+ TRUE,
+ TRY,
+ TYPEDEF,
+ VAR,
+ VOID,
+ WHILE,
+ WITH,
+ ];
+
+ /**
+ * A table mapping the lexemes of keywords to the corresponding keyword.
+ */
+ static final Map<String, Keyword> keywords = _createKeywordMap();
+
+ /**
+ * The name of the keyword type.
+ */
+ final String name;
+
+ /**
+ * The lexeme for the keyword.
+ */
+ final String syntax;
+
+ /**
+ * A flag indicating whether the keyword is a pseudo-keyword. Pseudo keywords
+ * can be used as identifiers.
+ */
+ final bool isPseudoKeyword;
+
+ /**
+ * Initialize a newly created keyword to have the given [name] and [syntax].
+ * The keyword is a pseudo-keyword if the [isPseudoKeyword] flag is `true`.
+ */
+ const Keyword._(this.name, this.syntax, [this.isPseudoKeyword = false]);
+
+ @override
+ String toString() => name;
+
+ /**
+ * Create a table mapping the lexemes of keywords to the corresponding keyword
+ * and return the table that was created.
+ */
+ static Map<String, Keyword> _createKeywordMap() {
+ LinkedHashMap<String, Keyword> result =
+ new LinkedHashMap<String, Keyword>();
+ for (Keyword keyword in values) {
+ result[keyword.syntax] = keyword;
+ }
+ return result;
+ }
+}
+
+/**
+ * A token that was scanned from the input. Each token knows which tokens
+ * precede and follow it, acting as a link in a doubly linked list of tokens.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Token {
+ /**
+ * Initialize a newly created token to have the given [type] and [offset].
+ */
+ factory Token(TokenType type, int offset) = SimpleToken;
+
+ /**
+ * Return the offset from the beginning of the file to the character after the
+ * last character of the token.
+ */
+ int get end;
+
+ /**
+ * Return `true` if this token represents an operator.
+ */
+ bool get isOperator;
+
+ /**
+ * Return `true` if this token is a synthetic token. A synthetic token is a
+ * token that was introduced by the parser in order to recover from an error
+ * in the code.
+ */
+ bool get isSynthetic;
+
+ /**
+ * Return `true` if this token represents an operator that can be defined by
+ * users.
+ */
+ bool get isUserDefinableOperator;
+
+ /**
+ * Return the number of characters in the node's source range.
+ */
+ int get length;
+
+ /**
+ * Return the lexeme that represents this token.
+ */
+ String get lexeme;
+
+ /**
+ * Return the next token in the token stream.
+ */
+ Token get next;
+
+ /**
+ * Return the offset from the beginning of the file to the first character in
+ * the token.
+ */
+ int get offset;
+
+ /**
+ * Set the offset from the beginning of the file to the first character in
+ * the token to the given [offset].
+ */
+ void set offset(int offset);
+
+ /**
+ * Return the first comment in the list of comments that precede this token,
+ * or `null` if there are no comments preceding this token. Additional
+ * comments can be reached by following the token stream using [next] until
+ * `null` is returned.
+ *
+ * For example, if the original contents were `/* one */ /* two */ id`, then
+ * the first preceding comment token will have a lexeme of `/* one */` and
+ * the next comment token will have a lexeme of `/* two */`.
+ */
+ Token get precedingComments;
+
+ /**
+ * Return the previous token in the token stream.
+ */
+ Token get previous;
+
+ /**
+ * Set the previous token in the token stream to the given [token].
+ */
+ void set previous(Token token);
+
+ /**
+ * Return the type of the token.
+ */
+ TokenType get type;
+
+ /**
+ * Apply (add) the given [delta] to this token's offset.
+ */
+ void applyDelta(int delta);
+
+ /**
+ * Return a newly created token that is a copy of this token but that is not a
+ * part of any token stream.
+ */
+ Token copy();
+
+ /**
+ * Copy a linked list of comment tokens identical to the given comment tokens.
+ */
+ Token copyComments(Token token);
+
+ /**
+ * Return `true` if this token has any one of the given [types].
+ */
+ bool matchesAny(List<TokenType> types);
+
+ /**
+ * Set the next token in the token stream to the given [token]. This has the
+ * side-effect of setting this token to be the previous token for the given
+ * token. Return the token that was passed in.
+ */
+ Token setNext(Token token);
+
+ /**
+ * Set the next token in the token stream to the given token without changing
+ * which token is the previous token for the given token. Return the token
+ * that was passed in.
+ */
+ Token setNextWithoutSettingPrevious(Token token);
+
+ /**
+ * Return the value of this token. For keyword tokens, this is the keyword
+ * associated with the token, for other tokens it is the lexeme associated
+ * with the token.
+ */
+ Object value();
+
+ /**
+ * Compare the given [tokens] to find the token that appears first in the
+ * source being parsed. That is, return the left-most of all of the tokens.
+ * The list must be non-`null`, but the elements of the list are allowed to be
+ * `null`. Return the token with the smallest offset, or `null` if the list is
+ * empty or if all of the elements of the list are `null`.
+ */
+ static Token lexicallyFirst(List<Token> tokens) {
+ Token first = null;
+ int offset = -1;
+ for (Token token in tokens) {
+ if (token != null && (offset < 0 || token.offset < offset)) {
+ first = token;
+ offset = token.offset;
+ }
+ }
+ return first;
+ }
+}
+
+/**
+ * The types of tokens that can be returned by the scanner.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class TokenType {
+ /**
+ * The type of the token that marks the start or end of the input.
+ */
+ static const TokenType EOF = const _EndOfFileTokenType();
+
+ static const TokenType DOUBLE = const TokenType._('DOUBLE');
+
+ static const TokenType HEXADECIMAL = const TokenType._('HEXADECIMAL');
+
+ static const TokenType IDENTIFIER = const TokenType._('IDENTIFIER');
+
+ static const TokenType INT = const TokenType._('INT');
+
+ static const TokenType KEYWORD = const TokenType._('KEYWORD');
+
+ static const TokenType MULTI_LINE_COMMENT =
+ const TokenType._('MULTI_LINE_COMMENT');
+
+ static const TokenType SCRIPT_TAG = const TokenType._('SCRIPT_TAG');
+
+ static const TokenType SINGLE_LINE_COMMENT =
+ const TokenType._('SINGLE_LINE_COMMENT');
+
+ static const TokenType STRING = const TokenType._('STRING');
+
+ static const TokenType AMPERSAND =
+ const TokenType._('AMPERSAND', TokenClass.BITWISE_AND_OPERATOR, '&');
+
+ static const TokenType AMPERSAND_AMPERSAND = const TokenType._(
+ 'AMPERSAND_AMPERSAND', TokenClass.LOGICAL_AND_OPERATOR, '&&');
+
+ static const TokenType AMPERSAND_EQ =
+ const TokenType._('AMPERSAND_EQ', TokenClass.ASSIGNMENT_OPERATOR, '&=');
+
+ static const TokenType AT = const TokenType._('AT', TokenClass.NO_CLASS, '@');
+
+ static const TokenType BANG =
+ const TokenType._('BANG', TokenClass.UNARY_PREFIX_OPERATOR, '!');
+
+ static const TokenType BANG_EQ =
+ const TokenType._('BANG_EQ', TokenClass.EQUALITY_OPERATOR, '!=');
+
+ static const TokenType BAR =
+ const TokenType._('BAR', TokenClass.BITWISE_OR_OPERATOR, '|');
+
+ static const TokenType BAR_BAR =
+ const TokenType._('BAR_BAR', TokenClass.LOGICAL_OR_OPERATOR, '||');
+
+ static const TokenType BAR_EQ =
+ const TokenType._('BAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, '|=');
+
+ static const TokenType COLON =
+ const TokenType._('COLON', TokenClass.NO_CLASS, ':');
+
+ static const TokenType COMMA =
+ const TokenType._('COMMA', TokenClass.NO_CLASS, ',');
+
+ static const TokenType CARET =
+ const TokenType._('CARET', TokenClass.BITWISE_XOR_OPERATOR, '^');
+
+ static const TokenType CARET_EQ =
+ const TokenType._('CARET_EQ', TokenClass.ASSIGNMENT_OPERATOR, '^=');
+
+ static const TokenType CLOSE_CURLY_BRACKET =
+ const TokenType._('CLOSE_CURLY_BRACKET', TokenClass.NO_CLASS, '}');
+
+ static const TokenType CLOSE_PAREN =
+ const TokenType._('CLOSE_PAREN', TokenClass.NO_CLASS, ')');
+
+ static const TokenType CLOSE_SQUARE_BRACKET =
+ const TokenType._('CLOSE_SQUARE_BRACKET', TokenClass.NO_CLASS, ']');
+
+ static const TokenType EQ =
+ const TokenType._('EQ', TokenClass.ASSIGNMENT_OPERATOR, '=');
+
+ static const TokenType EQ_EQ =
+ const TokenType._('EQ_EQ', TokenClass.EQUALITY_OPERATOR, '==');
+
+ static const TokenType FUNCTION =
+ const TokenType._('FUNCTION', TokenClass.NO_CLASS, '=>');
+
+ static const TokenType GT =
+ const TokenType._('GT', TokenClass.RELATIONAL_OPERATOR, '>');
+
+ static const TokenType GT_EQ =
+ const TokenType._('GT_EQ', TokenClass.RELATIONAL_OPERATOR, '>=');
+
+ static const TokenType GT_GT =
+ const TokenType._('GT_GT', TokenClass.SHIFT_OPERATOR, '>>');
+
+ static const TokenType GT_GT_EQ =
+ const TokenType._('GT_GT_EQ', TokenClass.ASSIGNMENT_OPERATOR, '>>=');
+
+ static const TokenType HASH =
+ const TokenType._('HASH', TokenClass.NO_CLASS, '#');
+
+ static const TokenType INDEX =
+ const TokenType._('INDEX', TokenClass.UNARY_POSTFIX_OPERATOR, '[]');
+
+ static const TokenType INDEX_EQ =
+ const TokenType._('INDEX_EQ', TokenClass.UNARY_POSTFIX_OPERATOR, '[]=');
+
+ static const TokenType IS =
+ const TokenType._('IS', TokenClass.RELATIONAL_OPERATOR, 'is');
+
+ static const TokenType LT =
+ const TokenType._('LT', TokenClass.RELATIONAL_OPERATOR, '<');
+
+ static const TokenType LT_EQ =
+ const TokenType._('LT_EQ', TokenClass.RELATIONAL_OPERATOR, '<=');
+
+ static const TokenType LT_LT =
+ const TokenType._('LT_LT', TokenClass.SHIFT_OPERATOR, '<<');
+
+ static const TokenType LT_LT_EQ =
+ const TokenType._('LT_LT_EQ', TokenClass.ASSIGNMENT_OPERATOR, '<<=');
+
+ static const TokenType MINUS =
+ const TokenType._('MINUS', TokenClass.ADDITIVE_OPERATOR, '-');
+
+ static const TokenType MINUS_EQ =
+ const TokenType._('MINUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, '-=');
+
+ static const TokenType MINUS_MINUS =
+ const TokenType._('MINUS_MINUS', TokenClass.UNARY_PREFIX_OPERATOR, '--');
+
+ static const TokenType OPEN_CURLY_BRACKET =
+ const TokenType._('OPEN_CURLY_BRACKET', TokenClass.NO_CLASS, '{');
+
+ static const TokenType OPEN_PAREN =
+ const TokenType._('OPEN_PAREN', TokenClass.UNARY_POSTFIX_OPERATOR, '(');
+
+ static const TokenType OPEN_SQUARE_BRACKET = const TokenType._(
+ 'OPEN_SQUARE_BRACKET', TokenClass.UNARY_POSTFIX_OPERATOR, '[');
+
+ static const TokenType PERCENT =
+ const TokenType._('PERCENT', TokenClass.MULTIPLICATIVE_OPERATOR, '%');
+
+ static const TokenType PERCENT_EQ =
+ const TokenType._('PERCENT_EQ', TokenClass.ASSIGNMENT_OPERATOR, '%=');
+
+ static const TokenType PERIOD =
+ const TokenType._('PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, '.');
+
+ static const TokenType PERIOD_PERIOD =
+ const TokenType._('PERIOD_PERIOD', TokenClass.CASCADE_OPERATOR, '..');
+
+ static const TokenType PLUS =
+ const TokenType._('PLUS', TokenClass.ADDITIVE_OPERATOR, '+');
+
+ static const TokenType PLUS_EQ =
+ const TokenType._('PLUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, '+=');
+
+ static const TokenType PLUS_PLUS =
+ const TokenType._('PLUS_PLUS', TokenClass.UNARY_PREFIX_OPERATOR, '++');
+
+ static const TokenType QUESTION =
+ const TokenType._('QUESTION', TokenClass.CONDITIONAL_OPERATOR, '?');
+
+ static const TokenType QUESTION_PERIOD = const TokenType._(
+ 'QUESTION_PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, '?.');
+
+ static const TokenType QUESTION_QUESTION =
+ const TokenType._('QUESTION_QUESTION', TokenClass.IF_NULL_OPERATOR, '??');
+
+ static const TokenType QUESTION_QUESTION_EQ = const TokenType._(
+ 'QUESTION_QUESTION_EQ', TokenClass.ASSIGNMENT_OPERATOR, '??=');
+
+ static const TokenType SEMICOLON =
+ const TokenType._('SEMICOLON', TokenClass.NO_CLASS, ';');
+
+ static const TokenType SLASH =
+ const TokenType._('SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, '/');
+
+ static const TokenType SLASH_EQ =
+ const TokenType._('SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, '/=');
+
+ static const TokenType STAR =
+ const TokenType._('STAR', TokenClass.MULTIPLICATIVE_OPERATOR, '*');
+
+ static const TokenType STAR_EQ =
+ const TokenType._('STAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, "*=");
+
+ static const TokenType STRING_INTERPOLATION_EXPRESSION = const TokenType._(
+ 'STRING_INTERPOLATION_EXPRESSION', TokenClass.NO_CLASS, '\${');
+
+ static const TokenType STRING_INTERPOLATION_IDENTIFIER = const TokenType._(
+ 'STRING_INTERPOLATION_IDENTIFIER', TokenClass.NO_CLASS, '\$');
+
+ static const TokenType TILDE =
+ const TokenType._('TILDE', TokenClass.UNARY_PREFIX_OPERATOR, '~');
+
+ static const TokenType TILDE_SLASH = const TokenType._(
+ 'TILDE_SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, '~/');
+
+ static const TokenType TILDE_SLASH_EQ = const TokenType._(
+ 'TILDE_SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, '~/=');
+
+ static const TokenType BACKPING =
+ const TokenType._('BACKPING', TokenClass.NO_CLASS, '`');
+
+ static const TokenType BACKSLASH =
+ const TokenType._('BACKSLASH', TokenClass.NO_CLASS, '\\');
+
+ static const TokenType PERIOD_PERIOD_PERIOD =
+ const TokenType._('PERIOD_PERIOD_PERIOD', TokenClass.NO_CLASS, '...');
+
+ static const TokenType GENERIC_METHOD_TYPE_LIST =
+ const TokenType._('GENERIC_METHOD_TYPE_LIST');
+
+ static const TokenType GENERIC_METHOD_TYPE_ASSIGN =
+ const TokenType._('GENERIC_METHOD_TYPE_ASSIGN');
+
+ /**
+ * The class of the token.
+ */
+ final TokenClass _tokenClass;
+
+ /**
+ * The name of the token type.
+ */
+ final String name;
+
+ /**
+ * The lexeme that defines this type of token, or `null` if there is more than
+ * one possible lexeme for this type of token.
+ */
+ final String lexeme;
+
+ /**
+ * Initialize a newly created token type to have the given [name],
+ * [_tokenClass] and [lexeme].
+ */
+ const TokenType._(this.name,
+ [this._tokenClass = TokenClass.NO_CLASS, this.lexeme = null]);
+
+ /**
+ * Return `true` if this type of token represents an additive operator.
+ */
+ bool get isAdditiveOperator => _tokenClass == TokenClass.ADDITIVE_OPERATOR;
+
+ /**
+ * Return `true` if this type of token represents an assignment operator.
+ */
+ bool get isAssignmentOperator =>
+ _tokenClass == TokenClass.ASSIGNMENT_OPERATOR;
+
+ /**
+ * Return `true` if this type of token represents an associative operator. An
+ * associative operator is an operator for which the following equality is
+ * true: `(a * b) * c == a * (b * c)`. In other words, if the result of
+ * applying the operator to multiple operands does not depend on the order in
+ * which those applications occur.
+ *
+ * Note: This method considers the logical-and and logical-or operators to be
+ * associative, even though the order in which the application of those
+ * operators can have an effect because evaluation of the right-hand operand
+ * is conditional.
+ */
+ bool get isAssociativeOperator =>
+ this == AMPERSAND ||
+ this == AMPERSAND_AMPERSAND ||
+ this == BAR ||
+ this == BAR_BAR ||
+ this == CARET ||
+ this == PLUS ||
+ this == STAR;
+
+ /**
+ * Return `true` if this type of token represents an equality operator.
+ */
+ bool get isEqualityOperator => _tokenClass == TokenClass.EQUALITY_OPERATOR;
+
+ /**
+ * Return `true` if this type of token represents an increment operator.
+ */
+ bool get isIncrementOperator =>
+ identical(lexeme, '++') || identical(lexeme, '--');
+
+ /**
+ * Return `true` if this type of token represents a multiplicative operator.
+ */
+ bool get isMultiplicativeOperator =>
+ _tokenClass == TokenClass.MULTIPLICATIVE_OPERATOR;
+
+ /**
+ * Return `true` if this token type represents an operator.
+ */
+ bool get isOperator =>
+ _tokenClass != TokenClass.NO_CLASS &&
+ this != OPEN_PAREN &&
+ this != OPEN_SQUARE_BRACKET &&
+ this != PERIOD;
+
+ /**
+ * Return `true` if this type of token represents a relational operator.
+ */
+ bool get isRelationalOperator =>
+ _tokenClass == TokenClass.RELATIONAL_OPERATOR;
+
+ /**
+ * Return `true` if this type of token represents a shift operator.
+ */
+ bool get isShiftOperator => _tokenClass == TokenClass.SHIFT_OPERATOR;
+
+ /**
+ * Return `true` if this type of token represents a unary postfix operator.
+ */
+ bool get isUnaryPostfixOperator =>
+ _tokenClass == TokenClass.UNARY_POSTFIX_OPERATOR;
+
+ /**
+ * Return `true` if this type of token represents a unary prefix operator.
+ */
+ bool get isUnaryPrefixOperator =>
+ _tokenClass == TokenClass.UNARY_PREFIX_OPERATOR;
+
+ /**
+ * Return `true` if this token type represents an operator that can be defined
+ * by users.
+ */
+ bool get isUserDefinableOperator =>
+ identical(lexeme, '==') ||
+ identical(lexeme, '~') ||
+ identical(lexeme, '[]') ||
+ identical(lexeme, '[]=') ||
+ identical(lexeme, '*') ||
+ identical(lexeme, '/') ||
+ identical(lexeme, '%') ||
+ identical(lexeme, '~/') ||
+ identical(lexeme, '+') ||
+ identical(lexeme, '-') ||
+ identical(lexeme, '<<') ||
+ identical(lexeme, '>>') ||
+ identical(lexeme, '>=') ||
+ identical(lexeme, '>') ||
+ identical(lexeme, '<=') ||
+ identical(lexeme, '<') ||
+ identical(lexeme, '&') ||
+ identical(lexeme, '^') ||
+ identical(lexeme, '|');
+
+ /**
+ * Return the precedence of the token, or `0` if the token does not represent
+ * an operator.
+ */
+ int get precedence => _tokenClass.precedence;
+
+ @override
+ String toString() => name;
+}
+
+/**
+ * A token representing the end (either the head or the tail) of a stream of
+ * tokens.
+ */
+class _EndOfFileTokenType extends TokenType {
+ /**
+ * Initialize a newly created token.
+ */
+ const _EndOfFileTokenType() : super._('EOF', TokenClass.NO_CLASS, '');
+
+ @override
+ String toString() => '-eof-';
+}
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index c7e971a..370f53e 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1464,14 +1464,12 @@
* which the name of this element is visible, or `null` if there is no single
* range of characters within which the element name is visible.
*
- * * For a local variable, this includes everything from the end of the
- * variable's initializer to the end of the block that encloses the variable
- * declaration.
+ * * For a local variable, this is the source range of the block that
+ * encloses the variable declaration.
* * For a parameter, this includes the body of the method or function that
* declares the parameter.
- * * For a local function, this includes everything from the beginning of the
- * function's body to the end of the block that encloses the function
- * declaration.
+ * * For a local function, this is the source range of the block that
+ * encloses the variable declaration.
* * For top-level functions, `null` will be returned because they are
* potentially visible in multiple sources.
*/
@@ -1621,9 +1619,13 @@
LibraryElement get enclosingElement;
/**
- * Return a list containing all of the libraries that are imported using this
- * prefix.
+ * Return the empty list.
+ *
+ * Deprecated: this getter was intended to return a list containing all of
+ * the libraries that are imported using this prefix, but it was never
+ * implemented. Due to lack of demand, it is being removed.
*/
+ @deprecated
List<LibraryElement> get importedLibraries;
}
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index f49c170..3ff2ce8 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -150,6 +150,15 @@
*/
DartType substitute2(
List<DartType> argumentTypes, List<DartType> parameterTypes);
+
+ /**
+ * If this type is a [TypeParameterType], returns its bound if it has one, or
+ * [objectType] otherwise.
+ *
+ * For any other type, returns `this`. Applies recursively -- if the bound is
+ * itself a type parameter, that is resolved too.
+ */
+ DartType resolveToBound(DartType objectType);
}
/**
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index d0d131d..e931197 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -1497,6 +1497,31 @@
}
/**
+ * Return a [CompilationUnit] for the given library and unit sources, which
+ * can be incrementally resolved.
+ */
+ CompilationUnit _getIncrementallyResolvableUnit(
+ Source librarySource, Source unitSource) {
+ LibrarySpecificUnit target =
+ new LibrarySpecificUnit(librarySource, unitSource);
+ for (ResultDescriptor result in [
+ RESOLVED_UNIT,
+ RESOLVED_UNIT11,
+ RESOLVED_UNIT10,
+ RESOLVED_UNIT9,
+ RESOLVED_UNIT8,
+ RESOLVED_UNIT7,
+ RESOLVED_UNIT6
+ ]) {
+ CompilationUnit unit = getResult(target, result);
+ if (unit != null) {
+ return unit;
+ }
+ }
+ return null;
+ }
+
+ /**
* Return a list containing all of the sources known to this context that have
* the given [kind].
*/
@@ -1843,7 +1868,7 @@
incrementalResolutionValidation_lastUnitSource = null;
incrementalResolutionValidation_lastLibrarySource = null;
incrementalResolutionValidation_lastUnit = null;
- // prepare the entry
+ // prepare the source entry
CacheEntry sourceEntry = _cache.get(unitSource);
if (sourceEntry == null) {
return false;
@@ -1854,19 +1879,15 @@
return false;
}
Source librarySource = librarySources[0];
+ // prepare the unit entry
CacheEntry unitEntry =
_cache.get(new LibrarySpecificUnit(librarySource, unitSource));
if (unitEntry == null) {
return false;
}
- // prepare the library element
- LibraryElement libraryElement = getLibraryElement(librarySource);
- if (libraryElement == null) {
- return false;
- }
// prepare the existing unit
CompilationUnit oldUnit =
- getResolvedCompilationUnit2(unitSource, librarySource);
+ _getIncrementallyResolvableUnit(librarySource, unitSource);
if (oldUnit == null) {
return false;
}
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 342d4a6..4a9826e 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -7,8 +7,10 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.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';
@@ -16,7 +18,6 @@
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/java_engine.dart';
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_dart.dart';
@@ -4721,6 +4722,13 @@
*/
abstract class FunctionBodyImpl extends AstNodeImpl implements FunctionBody {
/**
+ * Additional information about local variables and parameters that are
+ * declared within this function body or any enclosing function body. `null`
+ * if resolution has not yet been performed.
+ */
+ LocalVariableInfo localVariableInfo;
+
+ /**
* Return `true` if this function body is asynchronous.
*/
bool get isAsynchronous => false;
@@ -4746,6 +4754,22 @@
* is no star.
*/
Token get star => null;
+
+ @override
+ bool isPotentiallyMutatedInClosure(VariableElement variable) {
+ if (localVariableInfo == null) {
+ throw new StateError('Resolution has not yet been performed');
+ }
+ return localVariableInfo.potentiallyMutatedInClosure.contains(variable);
+ }
+
+ @override
+ bool isPotentiallyMutatedInScope(VariableElement variable) {
+ if (localVariableInfo == null) {
+ throw new StateError('Resolution has not yet been performed');
+ }
+ return localVariableInfo.potentiallyMutatedInScope.contains(variable);
+ }
}
/**
@@ -6556,6 +6580,26 @@
}
/**
+ * Additional information about local variables within a function or method
+ * produced at resolution time.
+ */
+class LocalVariableInfo {
+ /**
+ * The set of local variables and parameters that are potentially mutated
+ * within a local function other than the function in which they are declared.
+ */
+ final Set<VariableElement> potentiallyMutatedInClosure =
+ new Set<VariableElement>();
+
+ /**
+ * The set of local variables and parameters that are potentiall mutated
+ * within the scope of their declarations.
+ */
+ final Set<VariableElement> potentiallyMutatedInScope =
+ new Set<VariableElement>();
+}
+
+/**
* A single key/value pair in a map literal.
*
* > mapLiteralEntry ::=
diff --git a/pkg/analyzer/lib/src/dart/ast/token.dart b/pkg/analyzer/lib/src/dart/ast/token.dart
new file mode 100644
index 0000000..607df7b
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/ast/token.dart
@@ -0,0 +1,554 @@
+// 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.dart.ast.token;
+
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+
+/**
+ * The opening half of a grouping pair of tokens. This is used for curly
+ * brackets ('{'), parentheses ('('), and square brackets ('[').
+ */
+class BeginToken extends SimpleToken {
+ /**
+ * The token that corresponds to this token.
+ */
+ Token endToken;
+
+ /**
+ * Initialize a newly created token to have the given [type] at the given
+ * [offset].
+ */
+ BeginToken(TokenType type, int offset) : super(type, offset) {
+ assert(type == TokenType.OPEN_CURLY_BRACKET ||
+ type == TokenType.OPEN_PAREN ||
+ type == TokenType.OPEN_SQUARE_BRACKET ||
+ type == TokenType.STRING_INTERPOLATION_EXPRESSION);
+ }
+
+ @override
+ Token copy() => new BeginToken(type, offset);
+}
+
+/**
+ * A begin token that is preceded by comments.
+ */
+class BeginTokenWithComment extends BeginToken {
+ /**
+ * The first comment in the list of comments that precede this token.
+ */
+ CommentToken _precedingComment;
+
+ /**
+ * Initialize a newly created token to have the given [type] at the given
+ * [offset] and to be preceded by the comments reachable from the given
+ * [comment].
+ */
+ BeginTokenWithComment(TokenType type, int offset, this._precedingComment)
+ : super(type, offset) {
+ _setCommentParent(_precedingComment);
+ }
+
+ @override
+ CommentToken get precedingComments => _precedingComment;
+
+ void set precedingComments(CommentToken comment) {
+ _precedingComment = comment;
+ _setCommentParent(_precedingComment);
+ }
+
+ @override
+ void applyDelta(int delta) {
+ super.applyDelta(delta);
+ Token token = precedingComments;
+ while (token != null) {
+ token.applyDelta(delta);
+ token = token.next;
+ }
+ }
+
+ @override
+ Token copy() =>
+ new BeginTokenWithComment(type, offset, copyComments(precedingComments));
+}
+
+/**
+ * A token representing a comment.
+ */
+class CommentToken extends StringToken {
+ /**
+ * The [Token] that contains this comment.
+ */
+ Token parent;
+
+ /**
+ * Initialize a newly created token to represent a token of the given [type]
+ * with the given [value] at the given [offset].
+ */
+ CommentToken(TokenType type, String value, int offset)
+ : super(type, value, offset);
+
+ @override
+ CommentToken copy() => new CommentToken(type, _value, offset);
+}
+
+/**
+ * A documentation comment token.
+ */
+class DocumentationCommentToken extends CommentToken {
+ /**
+ * The references embedded within the documentation comment.
+ * This list will be empty unless this is a documentation comment that has
+ * references embedded within it.
+ */
+ final List<Token> references = <Token>[];
+
+ /**
+ * Initialize a newly created token to represent a token of the given [type]
+ * with the given [value] at the given [offset].
+ */
+ DocumentationCommentToken(TokenType type, String value, int offset)
+ : super(type, value, offset);
+
+ @override
+ CommentToken copy() {
+ DocumentationCommentToken copy =
+ new DocumentationCommentToken(type, _value, offset);
+ references.forEach((ref) => copy.references.add(ref.copy()));
+ return copy;
+ }
+}
+
+/**
+ * A token representing a keyword in the language.
+ */
+class KeywordToken extends SimpleToken {
+ /**
+ * The keyword being represented by this token.
+ */
+ final Keyword keyword;
+
+ /**
+ * Initialize a newly created token to represent the given [keyword] at the
+ * given [offset].
+ */
+ KeywordToken(this.keyword, int offset) : super(TokenType.KEYWORD, offset);
+
+ @override
+ String get lexeme => keyword.syntax;
+
+ @override
+ Token copy() => new KeywordToken(keyword, offset);
+
+ @override
+ Keyword value() => keyword;
+}
+
+/**
+ * A keyword token that is preceded by comments.
+ */
+class KeywordTokenWithComment extends KeywordToken {
+ /**
+ * The first comment in the list of comments that precede this token.
+ */
+ CommentToken _precedingComment;
+
+ /**
+ * Initialize a newly created token to to represent the given [keyword] at the
+ * given [offset] and to be preceded by the comments reachable from the given
+ * [comment].
+ */
+ KeywordTokenWithComment(Keyword keyword, int offset, this._precedingComment)
+ : super(keyword, offset) {
+ _setCommentParent(_precedingComment);
+ }
+
+ @override
+ CommentToken get precedingComments => _precedingComment;
+
+ void set precedingComments(CommentToken comment) {
+ _precedingComment = comment;
+ _setCommentParent(_precedingComment);
+ }
+
+ @override
+ void applyDelta(int delta) {
+ super.applyDelta(delta);
+ Token token = precedingComments;
+ while (token != null) {
+ token.applyDelta(delta);
+ token = token.next;
+ }
+ }
+
+ @override
+ Token copy() => new KeywordTokenWithComment(
+ keyword, offset, copyComments(precedingComments));
+}
+
+/**
+ * A token that was scanned from the input. Each token knows which tokens
+ * precede and follow it, acting as a link in a doubly linked list of tokens.
+ */
+class SimpleToken implements Token {
+ /**
+ * The type of the token.
+ */
+ @override
+ final TokenType type;
+
+ /**
+ * The offset from the beginning of the file to the first character in the
+ * token.
+ */
+ @override
+ int offset = 0;
+
+ /**
+ * The previous token in the token stream.
+ */
+ @override
+ Token previous;
+
+ /**
+ * The next token in the token stream.
+ */
+ Token _next;
+
+ /**
+ * Initialize a newly created token to have the given [type] and [offset].
+ */
+ SimpleToken(this.type, this.offset);
+
+ @override
+ int get end => offset + length;
+
+ @override
+ bool get isOperator => type.isOperator;
+
+ @override
+ bool get isSynthetic => length == 0;
+
+ @override
+ bool get isUserDefinableOperator => type.isUserDefinableOperator;
+
+ @override
+ int get length => lexeme.length;
+
+ @override
+ String get lexeme => type.lexeme;
+
+ @override
+ Token get next => _next;
+
+ @override
+ CommentToken get precedingComments => null;
+
+ @override
+ void applyDelta(int delta) {
+ offset += delta;
+ }
+
+ @override
+ Token copy() => new Token(type, offset);
+
+ @override
+ Token copyComments(Token token) {
+ if (token == null) {
+ return null;
+ }
+ Token head = token.copy();
+ Token tail = head;
+ token = token.next;
+ while (token != null) {
+ tail = tail.setNext(token.copy());
+ token = token.next;
+ }
+ return head;
+ }
+
+ @override
+ bool matchesAny(List<TokenType> types) {
+ for (TokenType type in types) {
+ if (this.type == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ Token setNext(Token token) {
+ _next = token;
+ token.previous = this;
+ return token;
+ }
+
+ @override
+ Token setNextWithoutSettingPrevious(Token token) {
+ _next = token;
+ return token;
+ }
+
+ @override
+ String toString() => lexeme;
+
+ @override
+ Object value() => type.lexeme;
+
+ /**
+ * Sets the `parent` property to `this` for the given [comment] and all the
+ * next tokens.
+ */
+ void _setCommentParent(CommentToken comment) {
+ while (comment != null) {
+ comment.parent = this;
+ comment = comment.next;
+ }
+ }
+}
+
+/**
+ * A token whose value is independent of it's type.
+ */
+class StringToken extends SimpleToken {
+ /**
+ * The lexeme represented by this token.
+ */
+ String _value;
+
+ /**
+ * Initialize a newly created token to represent a token of the given [type]
+ * with the given [value] at the given [offset].
+ */
+ StringToken(TokenType type, String value, int offset) : super(type, offset) {
+ this._value = StringUtilities.intern(value);
+ }
+
+ @override
+ String get lexeme => _value;
+
+ @override
+ Token copy() => new StringToken(type, _value, offset);
+
+ @override
+ String value() => _value;
+}
+
+/**
+ * A string token that is preceded by comments.
+ */
+class StringTokenWithComment extends StringToken {
+ /**
+ * The first comment in the list of comments that precede this token.
+ */
+ CommentToken _precedingComment;
+
+ /**
+ * Initialize a newly created token to have the given [type] at the given
+ * [offset] and to be preceded by the comments reachable from the given
+ * [comment].
+ */
+ StringTokenWithComment(
+ TokenType type, String value, int offset, this._precedingComment)
+ : super(type, value, offset) {
+ _setCommentParent(_precedingComment);
+ }
+
+ @override
+ CommentToken get precedingComments => _precedingComment;
+
+ void set precedingComments(CommentToken comment) {
+ _precedingComment = comment;
+ _setCommentParent(_precedingComment);
+ }
+
+ @override
+ void applyDelta(int delta) {
+ super.applyDelta(delta);
+ Token token = precedingComments;
+ while (token != null) {
+ token.applyDelta(delta);
+ token = token.next;
+ }
+ }
+
+ @override
+ Token copy() => new StringTokenWithComment(
+ type, lexeme, offset, copyComments(precedingComments));
+}
+
+/**
+ * A token whose value is independent of it's type.
+ */
+class SyntheticStringToken extends StringToken {
+ /**
+ * Initialize a newly created token to represent a token of the given [type]
+ * with the given [value] at the given [offset].
+ */
+ SyntheticStringToken(TokenType type, String value, int offset)
+ : super(type, value, offset);
+
+ @override
+ bool get isSynthetic => true;
+}
+
+/**
+ * The classes (or groups) of tokens with a similar use.
+ */
+class TokenClass {
+ /**
+ * A value used to indicate that the token type is not part of any specific
+ * class of token.
+ */
+ static const TokenClass NO_CLASS = const TokenClass('NO_CLASS');
+
+ /**
+ * A value used to indicate that the token type is an additive operator.
+ */
+ static const TokenClass ADDITIVE_OPERATOR =
+ const TokenClass('ADDITIVE_OPERATOR', 13);
+
+ /**
+ * A value used to indicate that the token type is an assignment operator.
+ */
+ static const TokenClass ASSIGNMENT_OPERATOR =
+ const TokenClass('ASSIGNMENT_OPERATOR', 1);
+
+ /**
+ * A value used to indicate that the token type is a bitwise-and operator.
+ */
+ static const TokenClass BITWISE_AND_OPERATOR =
+ const TokenClass('BITWISE_AND_OPERATOR', 11);
+
+ /**
+ * A value used to indicate that the token type is a bitwise-or operator.
+ */
+ static const TokenClass BITWISE_OR_OPERATOR =
+ const TokenClass('BITWISE_OR_OPERATOR', 9);
+
+ /**
+ * A value used to indicate that the token type is a bitwise-xor operator.
+ */
+ static const TokenClass BITWISE_XOR_OPERATOR =
+ const TokenClass('BITWISE_XOR_OPERATOR', 10);
+
+ /**
+ * A value used to indicate that the token type is a cascade operator.
+ */
+ static const TokenClass CASCADE_OPERATOR =
+ const TokenClass('CASCADE_OPERATOR', 2);
+
+ /**
+ * A value used to indicate that the token type is a conditional operator.
+ */
+ static const TokenClass CONDITIONAL_OPERATOR =
+ const TokenClass('CONDITIONAL_OPERATOR', 3);
+
+ /**
+ * A value used to indicate that the token type is an equality operator.
+ */
+ static const TokenClass EQUALITY_OPERATOR =
+ const TokenClass('EQUALITY_OPERATOR', 7);
+
+ /**
+ * A value used to indicate that the token type is an if-null operator.
+ */
+ static const TokenClass IF_NULL_OPERATOR =
+ const TokenClass('IF_NULL_OPERATOR', 4);
+
+ /**
+ * A value used to indicate that the token type is a logical-and operator.
+ */
+ static const TokenClass LOGICAL_AND_OPERATOR =
+ const TokenClass('LOGICAL_AND_OPERATOR', 6);
+
+ /**
+ * A value used to indicate that the token type is a logical-or operator.
+ */
+ static const TokenClass LOGICAL_OR_OPERATOR =
+ const TokenClass('LOGICAL_OR_OPERATOR', 5);
+
+ /**
+ * A value used to indicate that the token type is a multiplicative operator.
+ */
+ static const TokenClass MULTIPLICATIVE_OPERATOR =
+ const TokenClass('MULTIPLICATIVE_OPERATOR', 14);
+
+ /**
+ * A value used to indicate that the token type is a relational operator.
+ */
+ static const TokenClass RELATIONAL_OPERATOR =
+ const TokenClass('RELATIONAL_OPERATOR', 8);
+
+ /**
+ * A value used to indicate that the token type is a shift operator.
+ */
+ static const TokenClass SHIFT_OPERATOR =
+ const TokenClass('SHIFT_OPERATOR', 12);
+
+ /**
+ * A value used to indicate that the token type is a unary operator.
+ */
+ static const TokenClass UNARY_POSTFIX_OPERATOR =
+ const TokenClass('UNARY_POSTFIX_OPERATOR', 16);
+
+ /**
+ * A value used to indicate that the token type is a unary operator.
+ */
+ static const TokenClass UNARY_PREFIX_OPERATOR =
+ const TokenClass('UNARY_PREFIX_OPERATOR', 15);
+
+ /**
+ * The name of the token class.
+ */
+ final String name;
+
+ /**
+ * The precedence of tokens of this class, or `0` if the such tokens do not
+ * represent an operator.
+ */
+ final int precedence;
+
+ /**
+ * Initialize a newly created class of tokens to have the given [name] and
+ * [precedence].
+ */
+ const TokenClass(this.name, [this.precedence = 0]);
+
+ @override
+ String toString() => name;
+}
+
+/**
+ * A normal token that is preceded by comments.
+ */
+class TokenWithComment extends SimpleToken {
+ /**
+ * The first comment in the list of comments that precede this token.
+ */
+ CommentToken _precedingComment;
+
+ /**
+ * Initialize a newly created token to have the given [type] at the given
+ * [offset] and to be preceded by the comments reachable from the given
+ * [comment].
+ */
+ TokenWithComment(TokenType type, int offset, this._precedingComment)
+ : super(type, offset) {
+ _setCommentParent(_precedingComment);
+ }
+
+ @override
+ CommentToken get precedingComments => _precedingComment;
+
+ void set precedingComments(CommentToken comment) {
+ _precedingComment = comment;
+ _setCommentParent(_precedingComment);
+ }
+
+ @override
+ Token copy() => new TokenWithComment(type, offset, precedingComments);
+}
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 33bc821..05ff07f 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -7,12 +7,13 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/token.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';
@@ -216,17 +217,17 @@
ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) {
cloneToken(node.abstractKeyword);
return 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));
+ 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
@@ -247,16 +248,12 @@
@override
CompilationUnit visitCompilationUnit(CompilationUnit node) {
- ScriptTag scriptTag = cloneNode(node.scriptTag);
- List<Directive> directives = cloneNodeList(node.directives);
- List<CompilationUnitMember> declarations = cloneNodeList(node.declarations);
- Token endToken = cloneToken(node.endToken);
- Token beginToken = scriptTag?.beginToken ??
- (directives.isEmpty ? null : directives.first.beginToken) ??
- (declarations.isEmpty ? null : declarations.first.beginToken) ??
- endToken;
CompilationUnit clone = new CompilationUnit(
- beginToken, scriptTag, directives, declarations, endToken);
+ cloneToken(node.beginToken),
+ cloneNode(node.scriptTag),
+ cloneNodeList(node.directives),
+ cloneNodeList(node.declarations),
+ cloneToken(node.endToken));
clone.lineInfo = node.lineInfo;
return clone;
}
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 7422233..ef51b61 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -7,6 +7,7 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -16,7 +17,6 @@
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -176,7 +176,7 @@
exportElement.uri = node.uriContent;
exportElement.combinators = _buildCombinators(node);
exportElement.exportedLibrary = exportedLibrary;
- _setDoc(exportElement, node);
+ setElementDocumentationComment(exportElement, node);
node.element = exportElement;
exports.add(exportElement);
if (exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
@@ -218,7 +218,7 @@
importElement.deferred = node.deferredKeyword != null;
importElement.combinators = _buildCombinators(node);
importElement.importedLibrary = importedLibrary;
- _setDoc(importElement, node);
+ setElementDocumentationComment(importElement, node);
SimpleIdentifier prefixNode = node.prefix;
if (prefixNode != null) {
importElement.prefixOffset = prefixNode.offset;
@@ -272,19 +272,6 @@
}
/**
- * If the given [node] has a documentation comment, remember its content
- * and range into the given [element].
- */
- void _setDoc(ElementImpl element, AnnotatedNode node) {
- Comment comment = node.documentationComment;
- if (comment != null && comment.isDocumentation) {
- element.documentationComment =
- comment.tokens.map((Token t) => t.lexeme).join('\n');
- element.setDocRange(comment.offset, comment.length);
- }
- }
-
- /**
* Build the element model representing the combinators declared by
* the given [directive].
*/
@@ -316,11 +303,6 @@
ElementHolder _currentHolder;
/**
- * A flag indicating whether a variable declaration is in the context of a field declaration.
- */
- bool _inFieldContext = false;
-
- /**
* A flag indicating whether a variable declaration is within the body of a method or function.
*/
bool _inFunction = false;
@@ -349,18 +331,6 @@
}
@override
- Object visitBlock(Block node) {
- bool wasInField = _inFieldContext;
- _inFieldContext = false;
- try {
- node.visitChildren(this);
- } finally {
- _inFieldContext = wasInField;
- }
- return null;
- }
-
- @override
Object visitCatchClause(CatchClause node) {
SimpleIdentifier exceptionParameter = node.exceptionParameter;
if (exceptionParameter != null) {
@@ -415,7 +385,7 @@
interfaceType.typeArguments = typeArguments;
element.type = interfaceType;
element.typeParameters = typeParameters;
- _setDoc(element, node);
+ setElementDocumentationComment(element, node);
element.abstract = node.isAbstract;
element.accessors = holder.accessors;
List<ConstructorElement> constructors = holder.constructors;
@@ -466,7 +436,7 @@
InterfaceTypeImpl interfaceType = new InterfaceTypeImpl(element);
interfaceType.typeArguments = typeArguments;
element.type = interfaceType;
- _setDoc(element, node);
+ setElementDocumentationComment(element, node);
_currentHolder.addType(element);
className.staticElement = element;
holder.validate();
@@ -488,7 +458,7 @@
ConstructorElementImpl element =
new ConstructorElementImpl.forNode(constructorName);
element.metadata = _createElementAnnotations(node.metadata);
- _setDoc(element, node);
+ setElementDocumentationComment(element, node);
if (node.externalKeyword != null) {
element.external = true;
}
@@ -596,7 +566,7 @@
ClassElementImpl enumElement = new ClassElementImpl.forNode(enumName);
enumElement.metadata = _createElementAnnotations(node.metadata);
enumElement.enum2 = true;
- _setDoc(enumElement, node);
+ setElementDocumentationComment(enumElement, node);
InterfaceTypeImpl enumType = new InterfaceTypeImpl(enumElement);
enumElement.type = enumType;
// The equivalent code for enums in the spec shows a single constructor,
@@ -616,18 +586,6 @@
}
@override
- Object visitFieldDeclaration(FieldDeclaration node) {
- bool wasInField = _inFieldContext;
- _inFieldContext = true;
- try {
- node.visitChildren(this);
- } finally {
- _inFieldContext = wasInField;
- }
- return null;
- }
-
- @override
Object visitFieldFormalParameter(FieldFormalParameter node) {
if (node.parent is! DefaultFormalParameter) {
SimpleIdentifier parameterName = node.identifier;
@@ -677,7 +635,7 @@
FunctionElementImpl element =
new FunctionElementImpl.forNode(functionName);
element.metadata = _createElementAnnotations(node.metadata);
- _setDoc(element, node);
+ setElementDocumentationComment(element, node);
if (node.externalKeyword != null) {
element.external = true;
}
@@ -695,9 +653,8 @@
if (_inFunction) {
Block enclosingBlock = node.getAncestor((node) => node is Block);
if (enclosingBlock != null) {
- int functionEnd = node.offset + node.length;
- int blockEnd = enclosingBlock.offset + enclosingBlock.length;
- element.setVisibleRange(functionEnd, blockEnd - functionEnd - 1);
+ element.setVisibleRange(
+ enclosingBlock.offset, enclosingBlock.length);
}
}
if (node.returnType == null) {
@@ -725,7 +682,7 @@
PropertyAccessorElementImpl getter =
new PropertyAccessorElementImpl.forNode(propertyNameNode);
getter.metadata = _createElementAnnotations(node.metadata);
- _setDoc(getter, node);
+ setElementDocumentationComment(getter, node);
if (node.externalKeyword != null) {
getter.external = true;
}
@@ -752,7 +709,7 @@
PropertyAccessorElementImpl setter =
new PropertyAccessorElementImpl.forNode(propertyNameNode);
setter.metadata = _createElementAnnotations(node.metadata);
- _setDoc(setter, node);
+ setElementDocumentationComment(setter, node);
if (node.externalKeyword != null) {
setter.external = true;
}
@@ -816,9 +773,7 @@
if (_inFunction) {
Block enclosingBlock = node.getAncestor((node) => node is Block);
if (enclosingBlock != null) {
- int functionEnd = node.offset + node.length;
- int blockEnd = enclosingBlock.offset + enclosingBlock.length;
- element.setVisibleRange(functionEnd, blockEnd - functionEnd - 1);
+ element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
}
}
if (_functionTypesToFix != null) {
@@ -843,7 +798,7 @@
FunctionTypeAliasElementImpl element =
new FunctionTypeAliasElementImpl.forNode(aliasName);
element.metadata = _createElementAnnotations(node.metadata);
- _setDoc(element, node);
+ setElementDocumentationComment(element, node);
element.parameters = parameters;
element.typeParameters = typeParameters;
_createTypeParameterTypes(typeParameters);
@@ -928,7 +883,7 @@
MethodElementImpl element =
new MethodElementImpl(nameOfMethod, methodName.offset);
element.metadata = _createElementAnnotations(node.metadata);
- _setDoc(element, node);
+ setElementDocumentationComment(element, node);
element.abstract = node.isAbstract;
if (node.externalKeyword != null) {
element.external = true;
@@ -966,7 +921,7 @@
PropertyAccessorElementImpl getter =
new PropertyAccessorElementImpl.forNode(propertyNameNode);
getter.metadata = _createElementAnnotations(node.metadata);
- _setDoc(getter, node);
+ setElementDocumentationComment(getter, node);
if (node.externalKeyword != null) {
getter.external = true;
}
@@ -993,7 +948,7 @@
PropertyAccessorElementImpl setter =
new PropertyAccessorElementImpl.forNode(propertyNameNode);
setter.metadata = _createElementAnnotations(node.metadata);
- _setDoc(setter, node);
+ setElementDocumentationComment(setter, node);
if (node.externalKeyword != null) {
setter.external = true;
}
@@ -1127,22 +1082,22 @@
bool isConst = node.isConst;
bool isFinal = node.isFinal;
bool hasInitializer = node.initializer != null;
+ VariableDeclarationList varList = node.parent;
+ FieldDeclaration fieldNode =
+ varList.parent is FieldDeclaration ? varList.parent : null;
VariableElementImpl element;
- if (_inFieldContext) {
+ if (fieldNode != null) {
SimpleIdentifier fieldName = node.name;
FieldElementImpl field;
- if ((isConst || isFinal) && hasInitializer) {
+ if ((isConst || isFinal && !fieldNode.isStatic) && hasInitializer) {
field = new ConstFieldElementImpl.forNode(fieldName);
} else {
field = new FieldElementImpl.forNode(fieldName);
}
element = field;
- if (node.parent.parent is FieldDeclaration) {
- _setDoc(element, node.parent.parent);
- }
- if ((node.parent as VariableDeclarationList).type == null) {
- field.hasImplicitType = true;
- }
+ field.static = fieldNode.isStatic;
+ setElementDocumentationComment(element, fieldNode);
+ field.hasImplicitType = varList.type == null;
_currentHolder.addField(field);
fieldName.staticElement = field;
} else if (_inFunction) {
@@ -1158,9 +1113,7 @@
// TODO(brianwilkerson) This isn't right for variables declared in a for
// loop.
variable.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
- if ((node.parent as VariableDeclarationList).type == null) {
- variable.hasImplicitType = true;
- }
+ variable.hasImplicitType = varList.type == null;
_currentHolder.addLocalVariable(variable);
variableName.staticElement = element;
} else {
@@ -1172,12 +1125,10 @@
variable = new TopLevelVariableElementImpl.forNode(variableName);
}
element = variable;
- if (node.parent.parent is TopLevelVariableDeclaration) {
- _setDoc(element, node.parent.parent);
+ if (varList.parent is TopLevelVariableDeclaration) {
+ setElementDocumentationComment(element, varList.parent);
}
- if ((node.parent as VariableDeclarationList).type == null) {
- variable.hasImplicitType = true;
- }
+ variable.hasImplicitType = varList.type == null;
_currentHolder.addTopLevelVariable(variable);
variableName.staticElement = element;
}
@@ -1185,13 +1136,7 @@
element.final2 = isFinal;
if (hasInitializer) {
ElementHolder holder = new ElementHolder();
- bool wasInFieldContext = _inFieldContext;
- _inFieldContext = false;
- try {
- _visit(holder, node.initializer);
- } finally {
- _inFieldContext = wasInFieldContext;
- }
+ _visit(holder, node.initializer);
FunctionElementImpl initializer =
new FunctionElementImpl.forOffset(node.initializer.beginToken.offset);
initializer.functions = holder.functions;
@@ -1202,10 +1147,6 @@
holder.validate();
}
if (element is PropertyInducingElementImpl) {
- if (_inFieldContext) {
- (element as FieldElementImpl).static =
- (node.parent.parent as FieldDeclaration).isStatic;
- }
PropertyAccessorElementImpl getter =
new PropertyAccessorElementImpl.forVariable(element);
getter.getter = true;
@@ -1322,47 +1263,28 @@
}
/**
- * Return the body of the function that contains the given parameter, or `null` if no
- * function body could be found.
- *
- * @param node the parameter contained in the function whose body is to be returned
- * @return the body of the function that contains the given parameter
+ * Return the body of the function that contains the given [parameter], or
+ * `null` if no function body could be found.
*/
- FunctionBody _getFunctionBody(FormalParameter node) {
- AstNode parent = node.parent;
- while (parent != null) {
- if (parent is ConstructorDeclaration) {
- return parent.body;
- } else if (parent is FunctionExpression) {
- return parent.body;
- } else if (parent is MethodDeclaration) {
- return parent.body;
- }
- parent = parent.parent;
+ FunctionBody _getFunctionBody(FormalParameter parameter) {
+ AstNode parent = parameter?.parent?.parent;
+ if (parent is ConstructorDeclaration) {
+ return parent.body;
+ } else if (parent is FunctionExpression) {
+ return parent.body;
+ } else if (parent is MethodDeclaration) {
+ return parent.body;
}
return null;
}
/**
- * If the given [node] has a documentation comment, remember its content
- * and range into the given [element].
- */
- void _setDoc(ElementImpl element, AnnotatedNode node) {
- Comment comment = node.documentationComment;
- if (comment != null && comment.isDocumentation) {
- element.documentationComment =
- comment.tokens.map((Token t) => t.lexeme).join('\n');
- element.setDocRange(comment.offset, comment.length);
- }
- }
-
- /**
* Sets the visible source range for formal parameter.
*/
void _setParameterVisibleRange(
FormalParameter node, ParameterElementImpl element) {
FunctionBody body = _getFunctionBody(node);
- if (body != null) {
+ if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
element.setVisibleRange(body.offset, body.length);
}
}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 74c0bba..9677e89 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -8,6 +8,7 @@
import 'dart:math' show min;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/visitor.dart';
@@ -20,7 +21,6 @@
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart' show Keyword;
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_collection.dart';
@@ -1221,7 +1221,7 @@
ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name);
@override
- DartObject get constantValue => _result.value;
+ DartObject get constantValue => _result?.value;
@override
EvaluationResultImpl get evaluationResult => _result;
@@ -1255,7 +1255,7 @@
ConstLocalVariableElementImpl.forNode(Identifier name) : super.forNode(name);
@override
- DartObject get constantValue => _result.value;
+ DartObject get constantValue => _result?.value;
@override
EvaluationResultImpl get evaluationResult => _result;
@@ -1414,7 +1414,7 @@
: super.forNode(name);
@override
- DartObject get constantValue => _result.value;
+ DartObject get constantValue => _result?.value;
@override
EvaluationResultImpl get evaluationResult => _result;
@@ -1473,7 +1473,7 @@
: super.forNode(name);
@override
- DartObject get constantValue => _result.value;
+ DartObject get constantValue => _result?.value;
@override
EvaluationResultImpl get evaluationResult => _result;
@@ -1507,7 +1507,7 @@
DefaultParameterElementImpl.forNode(Identifier name) : super.forNode(name);
@override
- DartObject get constantValue => _result.value;
+ DartObject get constantValue => _result?.value;
@override
EvaluationResultImpl get evaluationResult => _result;
@@ -1610,7 +1610,7 @@
ElementAnnotationImpl(this.compilationUnit);
@override
- DartObject get constantValue => evaluationResult.value;
+ DartObject get constantValue => evaluationResult?.value;
@override
AnalysisContext get context => compilationUnit.library.context;
@@ -4300,11 +4300,6 @@
*/
class PrefixElementImpl extends ElementImpl implements PrefixElement {
/**
- * A list containing all of the libraries that are imported using this prefix.
- */
- List<LibraryElement> _importedLibraries = LibraryElement.EMPTY_LIST;
-
- /**
* Initialize a newly created method element to have the given [name] and
* [offset].
*/
@@ -4323,18 +4318,7 @@
String get identifier => "_${super.identifier}";
@override
- List<LibraryElement> get importedLibraries => _importedLibraries;
-
- /**
- * Set the libraries that are imported using this prefix to the given
- * [libraries].
- */
- void set importedLibraries(List<LibraryElement> libraries) {
- for (LibraryElement library in libraries) {
- (library as LibraryElementImpl).enclosingElement = this;
- }
- _importedLibraries = libraries;
- }
+ List<LibraryElement> get importedLibraries => LibraryElement.EMPTY_LIST;
@override
ElementKind get kind => ElementKind.PREFIX;
@@ -4616,6 +4600,14 @@
TypeParameterElementImpl(String name, int offset) : super(name, offset);
/**
+ * Initialize a newly created synthetic type parameter element to have the
+ * given [name], and with [synthetic] set to true.
+ */
+ TypeParameterElementImpl.synthetic(String name) : super(name, -1) {
+ synthetic = true;
+ }
+
+ /**
* Initialize a newly created type parameter element to have the given [name].
*/
TypeParameterElementImpl.forNode(Identifier name) : super.forNode(name);
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 57cbcb9..558b5ec 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -128,8 +128,7 @@
* type parameters are known.
*/
abstract class ExecutableMember extends Member implements ExecutableElement {
- @override
- final FunctionType type;
+ FunctionType _type;
/**
* Initialize a newly created element to represent a callable element (like a
@@ -139,9 +138,7 @@
*/
ExecutableMember(ExecutableElement baseElement, InterfaceType definingType,
[FunctionType type])
- : type = type ??
- baseElement.type.substitute2(definingType.typeArguments,
- TypeParameterTypeImpl.getTypes(definingType.typeParameters)),
+ : _type = type,
super(baseElement, definingType);
@override
@@ -201,6 +198,12 @@
DartType get returnType => type.returnType;
@override
+ FunctionType get type {
+ return _type ??= baseElement.type.substitute2(definingType.typeArguments,
+ TypeParameterTypeImpl.getTypes(definingType.typeParameters));
+ }
+
+ @override
List<TypeParameterElement> get typeParameters => baseElement.typeParameters;
@override
@@ -898,6 +901,68 @@
}
/**
+ * A type parameter defined inside of another parameterized type, where the
+ * values of the enclosing type parameters are known.
+ *
+ * For example:
+ *
+ * class C<T> {
+ * S m<S extends T>(S s);
+ * }
+ *
+ * If we have `C<num>.m` and we ask for the type parameter "S", we should get
+ * `<S extends num>` instead of `<S extends T>`. This is how the parameter
+ * and return types work, see: [FunctionType.parameters],
+ * [FunctionType.returnType], and [ParameterMember].
+ */
+class TypeParameterMember extends Member implements TypeParameterElement {
+ @override
+ final DartType bound;
+
+ TypeParameterMember(
+ TypeParameterElement baseElement, DartType definingType, this.bound)
+ : super(baseElement, definingType);
+
+ @override
+ TypeParameterElement get baseElement =>
+ super.baseElement as TypeParameterElement;
+
+ @override
+ Element get enclosingElement => baseElement.enclosingElement;
+
+ @override
+ TypeParameterType get type => baseElement.type;
+
+ @override
+ accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this);
+
+ /**
+ * If the given [parameter]'s type is different when any type parameters from
+ * the defining type's declaration are replaced with the actual type
+ * arguments from the [definingType], create a parameter member representing
+ * the given parameter. Return the member that was created, or the base
+ * parameter if no member was created.
+ */
+ static TypeParameterElement from(
+ TypeParameterElement parameter, ParameterizedType definingType) {
+ if (parameter?.bound == null || definingType.typeArguments.isEmpty) {
+ return parameter;
+ }
+
+ DartType bound = parameter.bound;
+ List<DartType> argumentTypes = definingType.typeArguments;
+ List<DartType> parameterTypes =
+ TypeParameterTypeImpl.getTypes(definingType.typeParameters);
+ DartType substitutedBound =
+ bound.substitute2(argumentTypes, parameterTypes);
+ if (bound == substitutedBound) {
+ return parameter;
+ }
+ return new TypeParameterMember(parameter, definingType, substitutedBound);
+ }
+}
+
+/**
* A variable element defined in a parameterized type where the values of the
* type parameters are known.
*/
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 1b9c290..cfc076ff 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -6,6 +6,7 @@
import 'dart:collection';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
@@ -13,8 +14,8 @@
import 'package:analyzer/src/generated/engine.dart'
show AnalysisContext, AnalysisEngine;
import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart' show Keyword;
import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
/**
@@ -144,8 +145,7 @@
/**
* Constructor used by [CircularTypeImpl].
*/
- DynamicTypeImpl._circular()
- : super(instance.element, Keyword.DYNAMIC.syntax);
+ DynamicTypeImpl._circular() : super(instance.element, Keyword.DYNAMIC.syntax);
@override
int get hashCode => 1;
@@ -397,15 +397,6 @@
}
@override
- List<DartType> get normalParameterTypes {
- List<DartType> types = <DartType>[];
- _forEachParameterType(ParameterKind.REQUIRED, (name, type) {
- types.add(type);
- });
- return types;
- }
-
- @override
List<String> get normalParameterNames {
return baseParameters
.where((parameter) => parameter.parameterKind == ParameterKind.REQUIRED)
@@ -414,9 +405,9 @@
}
@override
- List<DartType> get optionalParameterTypes {
+ List<DartType> get normalParameterTypes {
List<DartType> types = <DartType>[];
- _forEachParameterType(ParameterKind.POSITIONAL, (name, type) {
+ _forEachParameterType(ParameterKind.REQUIRED, (name, type) {
types.add(type);
});
return types;
@@ -432,6 +423,15 @@
}
@override
+ List<DartType> get optionalParameterTypes {
+ List<DartType> types = <DartType>[];
+ _forEachParameterType(ParameterKind.POSITIONAL, (name, type) {
+ types.add(type);
+ });
+ return types;
+ }
+
+ @override
List<ParameterElement> get parameters {
List<ParameterElement> baseParameters = this.baseParameters;
// no parameters, quick return
@@ -487,11 +487,24 @@
@override
List<TypeParameterElement> get typeFormals {
- if (_isInstantiated) {
+ if (_isInstantiated || element == null) {
return TypeParameterElement.EMPTY_LIST;
- } else {
- return element?.typeParameters ?? TypeParameterElement.EMPTY_LIST;
}
+ List<TypeParameterElement> baseTypeFormals = element.typeParameters;
+ int formalCount = baseTypeFormals.length;
+ if (formalCount == 0) {
+ return TypeParameterElement.EMPTY_LIST;
+ }
+
+ // Create type formals with specialized bounds.
+ // For example `<U extends T>` where T comes from an outer scope.
+ List<TypeParameterElement> result =
+ new List<TypeParameterElement>(formalCount);
+
+ for (int i = 0; i < formalCount; i++) {
+ result[i] = TypeParameterMember.from(baseTypeFormals[i], this);
+ }
+ return result;
}
@override
@@ -501,13 +514,19 @@
// for this generic function's type variables. Those variables are
// tracked in [boundTypeParameters].
_typeParameters = <TypeParameterElement>[];
- Element e = element?.enclosingElement;
+
+ Element e = element;
while (e != null) {
+ // If a static method, skip the enclosing class type parameters.
+ if (e is MethodElement && e.isStatic) {
+ e = e.enclosingElement;
+ }
+ e = e.enclosingElement;
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
@@ -534,28 +553,13 @@
// To test this, we instantiate both types with the same (unique) type
// variables, and see if the result is equal.
if (typeFormals.isNotEmpty) {
- List<DartType> instantiateTypeArgs = new List<DartType>();
- List<DartType> variablesThis = new List<DartType>();
- List<DartType> variablesOther = new List<DartType>();
- for (int i = 0; i < typeFormals.length; i++) {
- TypeParameterElement pThis = typeFormals[i];
- TypeParameterElement pOther = otherType.typeFormals[i];
- TypeParameterTypeImpl pFresh = new TypeParameterTypeImpl(
- new TypeParameterElementImpl(pThis.name, -1));
- instantiateTypeArgs.add(pFresh);
- variablesThis.add(pThis.type);
- variablesOther.add(pOther.type);
- // Check that the bounds are equal after equating the previous
- // bound variables.
- if (pThis.bound?.substitute2(instantiateTypeArgs, variablesThis) !=
- pOther.bound?.substitute2(instantiateTypeArgs, variablesOther)) {
- return false;
- }
+ List<DartType> freshVariables =
+ relateTypeFormals(this, otherType, (t, s) => t == s);
+ if (freshVariables == null) {
+ return false;
}
- // After instantiation, they will no longer have typeFormals,
- // so we will continue below.
- return this.instantiate(instantiateTypeArgs) ==
- otherType.instantiate(instantiateTypeArgs);
+ return instantiate(freshVariables) ==
+ otherType.instantiate(freshVariables);
}
return returnType == otherType.returnType &&
@@ -581,8 +585,8 @@
}
}
- List<DartType> instantiateTypeArgs = new List<DartType>();
- List<DartType> variables = new List<DartType>();
+ List<DartType> instantiateTypeArgs = <DartType>[];
+ List<DartType> variables = <DartType>[];
buffer.write("<");
for (TypeParameterElement e in typeFormals) {
if (e != typeFormals[0]) {
@@ -717,49 +721,186 @@
[bool withDynamic = false, Set<Element> visitedElements]) {
// Note: visitedElements is only used for breaking recursion in the type
// hierarchy; we don't use it when recursing into the function type.
- bool relation = _trivialFunctionRelation(type);
- if (relation != null) {
- return relation;
- }
-
- return structuralCompare(this, type,
- (TypeImpl t, TypeImpl s) => t.isMoreSpecificThan(s, withDynamic));
+ return relate(
+ this,
+ type,
+ (DartType t, DartType s) =>
+ (t as TypeImpl).isMoreSpecificThan(s, withDynamic),
+ new TypeSystemImpl().instantiateToBounds);
}
@override
bool isSubtypeOf(DartType type) {
- bool relation = _trivialFunctionRelation(type);
- if (relation != null) {
- return relation;
+ return relate(
+ this,
+ type,
+ (DartType t, DartType s) => t.isAssignableTo(s),
+ new TypeSystemImpl().instantiateToBounds);
+ }
+
+ @override
+ TypeImpl pruned(List<FunctionTypeAliasElement> prune) {
+ if (prune == null) {
+ return this;
+ } else if (prune.contains(element)) {
+ // Circularity found. Prune the type declaration.
+ return new CircularTypeImpl();
+ } else {
+ // There should never be a reason to prune a type that has already been
+ // pruned, since pruning is only done when expanding a function type
+ // alias, and function type aliases are always expanded by starting with
+ // base types.
+ assert(this.prunedTypedefs == null);
+ List<DartType> typeArgs = typeArguments
+ .map((TypeImpl t) => t.pruned(prune))
+ .toList(growable: false);
+ return new FunctionTypeImpl._(
+ element, name, prune, typeArgs, _isInstantiated);
+ }
+ }
+
+ @override
+ DartType substitute2(
+ List<DartType> argumentTypes, List<DartType> parameterTypes,
+ [List<FunctionTypeAliasElement> prune]) {
+ // Pruned types should only ever result from performing type variable
+ // substitution, and it doesn't make sense to substitute again after
+ // substituting once.
+ assert(this.prunedTypedefs == null);
+ if (argumentTypes.length != parameterTypes.length) {
+ throw new IllegalArgumentException(
+ "argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
+ }
+ Element element = this.element;
+ if (prune != null && prune.contains(element)) {
+ // Circularity found. Prune the type declaration.
+ return new CircularTypeImpl();
+ }
+ if (argumentTypes.length == 0) {
+ return this.pruned(prune);
+ }
+ List<DartType> typeArgs =
+ TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
+ return new FunctionTypeImpl._(
+ element, name, prune, typeArgs, _isInstantiated);
+ }
+
+ @override
+ FunctionTypeImpl substitute3(List<DartType> argumentTypes) =>
+ substitute2(argumentTypes, typeArguments);
+
+ /**
+ * Invokes [callback] for each parameter of [kind] with the parameter's [name]
+ * and [type] after any type parameters have been applied.
+ */
+ void _forEachParameterType(
+ ParameterKind kind, callback(String name, DartType type)) {
+ if (baseParameters.isEmpty) {
+ return;
}
- return structuralCompare(
- this, type, (TypeImpl t, TypeImpl s) => t.isAssignableTo(s));
+ List<DartType> typeParameters =
+ TypeParameterTypeImpl.getTypes(this.typeParameters);
+ for (ParameterElement parameter in baseParameters) {
+ if (parameter.parameterKind == kind) {
+ TypeImpl type = parameter.type;
+ if (typeArguments.length != 0 &&
+ typeArguments.length == typeParameters.length) {
+ type = type.substitute2(typeArguments, typeParameters, newPrune);
+ } else {
+ type = type.pruned(newPrune);
+ }
+
+ callback(parameter.name, type);
+ }
+ }
+ }
+
+ void _freeVariablesInFunctionType(
+ FunctionType type, Set<TypeParameterType> free) {
+ // Make some fresh variables to avoid capture.
+ List<DartType> typeArgs = DartType.EMPTY_LIST;
+ if (type.typeFormals.isNotEmpty) {
+ typeArgs = new List<DartType>.from(type.typeFormals.map((e) =>
+ new TypeParameterTypeImpl(new TypeParameterElementImpl(e.name, -1))));
+
+ type = type.instantiate(typeArgs);
+ }
+
+ for (ParameterElement p in type.parameters) {
+ _freeVariablesInType(p.type, free);
+ }
+ _freeVariablesInType(type.returnType, free);
+
+ // Remove all of our bound variables.
+ free.removeAll(typeArgs);
+ }
+
+ void _freeVariablesInInterfaceType(
+ InterfaceType type, Set<TypeParameterType> free) {
+ for (DartType typeArg in type.typeArguments) {
+ _freeVariablesInType(typeArg, free);
+ }
+ }
+
+ void _freeVariablesInType(DartType type, Set<TypeParameterType> free) {
+ if (type is TypeParameterType) {
+ free.add(type);
+ } else if (type is FunctionType) {
+ _freeVariablesInFunctionType(type, free);
+ } else if (type is InterfaceType) {
+ _freeVariablesInInterfaceType(type, free);
+ }
}
/**
- * Tests if [other] meets any of the easy relation cases for [isSubtypeOf]
- * and [isMoreSpecificThan].
+ * Given two functions [f1] and [f2] where f1 and f2 are known to be
+ * generic function types (both have type formals), this checks that they
+ * have the same number of formals, and that those formals have bounds
+ * (e.g. `<T extends LowerBound>`) that satisfy [relation].
*
- * Returns `true` if the relation is known to hold, `false` if it isn't, or
- * `null` if it's unknown and a deeper structural comparison is needed.
+ * The return value will be a new list of fresh type variables, that can be
+ * used to instantiate both function types, allowing further comparison.
+ * For example, given `<T>T -> T` and `<U>U -> U` we can instantiate them with
+ * `F` to get `F -> F` and `F -> F`, which we can see are equal.
*/
- bool _trivialFunctionRelation(DartType other) {
- // Trivial base cases.
- if (other == null) {
- return false;
- } else if (identical(this, other) ||
- other.isDynamic ||
- other.isDartCoreFunction ||
- other.isObject) {
- return true;
- } else if (other is! FunctionType) {
- return false;
- } else if (this == other) {
- return true;
+ static List<DartType> relateTypeFormals(
+ FunctionType f1, FunctionType f2, bool relation(DartType t, DartType s)) {
+ List<TypeParameterElement> params1 = f1.typeFormals;
+ List<TypeParameterElement> params2 = f2.typeFormals;
+ int count = params1.length;
+ if (params2.length != count) {
+ return null;
}
+ // We build up a substitution matching up the type parameters
+ // from the two types, {variablesFresh/variables1} and
+ // {variablesFresh/variables2}
+ List<DartType> variables1 = <DartType>[];
+ List<DartType> variables2 = <DartType>[];
+ List<DartType> variablesFresh = <DartType>[];
+ for (int i = 0; i < count; i++) {
+ TypeParameterElement p1 = params1[i];
+ TypeParameterElement p2 = params2[i];
+ TypeParameterElementImpl pFresh =
+ new TypeParameterElementImpl.synthetic(p2.name);
- return null;
+ DartType variable1 = p1.type;
+ DartType variable2 = p2.type;
+ DartType variableFresh = new TypeParameterTypeImpl(pFresh);
+
+ variables1.add(variable1);
+ variables2.add(variable2);
+ variablesFresh.add(variableFresh);
+ DartType bound1 = p1.bound ?? DynamicTypeImpl.instance;
+ DartType bound2 = p2.bound ?? DynamicTypeImpl.instance;
+ bound1 = bound1.substitute2(variablesFresh, variables1);
+ bound2 = bound2.substitute2(variablesFresh, variables2);
+ pFresh.bound = bound2;
+ if (!relation(bound2, bound1)) {
+ return null;
+ }
+ }
+ return variablesFresh;
}
/**
@@ -773,11 +914,45 @@
*
* If [returnRelation] is omitted, uses [parameterRelation] for both.
*/
- static bool structuralCompare(FunctionType t, FunctionType s,
+ static bool relate(
+ FunctionType t,
+ DartType other,
bool parameterRelation(DartType t, DartType s),
- [bool returnRelation(DartType t, DartType s)]) {
- // Test the return types.
+ FunctionType instantiateToBounds(FunctionType t),
+ {bool returnRelation(DartType t, DartType s)}) {
+
returnRelation ??= parameterRelation;
+
+ // Trivial base cases.
+ if (other == null) {
+ return false;
+ } else if (identical(t, other) ||
+ other.isDynamic ||
+ other.isDartCoreFunction ||
+ other.isObject) {
+ return true;
+ } else if (other is! FunctionType) {
+ return false;
+ }
+
+ // This type cast is safe, because we checked it above.
+ FunctionType s = other as FunctionType;
+ if (t.typeFormals.isNotEmpty) {
+ if (s.typeFormals.isEmpty) {
+ t = instantiateToBounds(t);
+ } else {
+ List<DartType> freshVariables = relateTypeFormals(t, s, returnRelation);
+ if (freshVariables == null) {
+ return false;
+ }
+ t = t.instantiate(freshVariables);
+ s = s.instantiate(freshVariables);
+ }
+ } else if (s.typeFormals.isNotEmpty) {
+ return false;
+ }
+
+ // Test the return types.
DartType sRetType = s.returnType;
if (!sRetType.isVoid && !returnRelation(t.returnType, sRetType)) {
return false;
@@ -848,94 +1023,6 @@
return true;
}
- @override
- TypeImpl pruned(List<FunctionTypeAliasElement> prune) {
- if (prune == null) {
- return this;
- } else if (prune.contains(element)) {
- // Circularity found. Prune the type declaration.
- return new CircularTypeImpl();
- } else {
- // There should never be a reason to prune a type that has already been
- // pruned, since pruning is only done when expanding a function type
- // alias, and function type aliases are always expanded by starting with
- // base types.
- assert(this.prunedTypedefs == null);
- List<DartType> typeArgs = typeArguments
- .map((TypeImpl t) => t.pruned(prune))
- .toList(growable: false);
- return new FunctionTypeImpl._(
- element, name, prune, typeArgs, _isInstantiated);
- }
- }
-
- @override
- DartType substitute2(
- List<DartType> argumentTypes, List<DartType> parameterTypes,
- [List<FunctionTypeAliasElement> prune]) {
- // Pruned types should only ever result from performing type variable
- // substitution, and it doesn't make sense to substitute again after
- // substituting once.
- assert(this.prunedTypedefs == null);
- if (argumentTypes.length != parameterTypes.length) {
- throw new IllegalArgumentException(
- "argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
- }
- Element element = this.element;
- if (prune != null && prune.contains(element)) {
- // Circularity found. Prune the type declaration.
- return new CircularTypeImpl();
- }
- if (argumentTypes.length == 0) {
- return this.pruned(prune);
- }
- List<DartType> typeArgs =
- TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
- return new FunctionTypeImpl._(
- element, name, prune, typeArgs, _isInstantiated);
- }
-
- @override
- FunctionTypeImpl substitute3(List<DartType> argumentTypes) =>
- substitute2(argumentTypes, typeArguments);
-
- void _freeVariablesInFunctionType(
- FunctionType type, Set<TypeParameterType> free) {
- // Make some fresh variables to avoid capture.
- List<DartType> typeArgs = DartType.EMPTY_LIST;
- if (type.typeFormals.isNotEmpty) {
- typeArgs = new List<DartType>.from(type.typeFormals.map((e) =>
- new TypeParameterTypeImpl(new TypeParameterElementImpl(e.name, -1))));
-
- type = type.instantiate(typeArgs);
- }
-
- for (ParameterElement p in type.parameters) {
- _freeVariablesInType(p.type, free);
- }
- _freeVariablesInType(type.returnType, free);
-
- // Remove all of our bound variables.
- free.removeAll(typeArgs);
- }
-
- void _freeVariablesInInterfaceType(
- InterfaceType type, Set<TypeParameterType> free) {
- for (DartType typeArg in type.typeArguments) {
- _freeVariablesInType(typeArg, free);
- }
- }
-
- void _freeVariablesInType(DartType type, Set<TypeParameterType> free) {
- if (type is TypeParameterType) {
- free.add(type);
- } else if (type is FunctionType) {
- _freeVariablesInFunctionType(type, free);
- } else if (type is InterfaceType) {
- _freeVariablesInInterfaceType(type, free);
- }
- }
-
/**
* Return `true` if all of the name/type pairs in the first map ([firstTypes])
* are equal to the corresponding name/type pairs in the second map
@@ -960,33 +1047,6 @@
}
return true;
}
-
- /**
- * Invokes [callback] for each parameter of [kind] with the parameter's [name]
- * and [type] after any type parameters have been applied.
- */
- void _forEachParameterType(
- ParameterKind kind, callback(String name, DartType type)) {
- if (baseParameters.isEmpty) {
- return;
- }
-
- List<DartType> typeParameters =
- TypeParameterTypeImpl.getTypes(this.typeParameters);
- for (ParameterElement parameter in baseParameters) {
- if (parameter.parameterKind == kind) {
- TypeImpl type = parameter.type;
- if (typeArguments.length != 0 &&
- typeArguments.length == typeParameters.length) {
- type = type.substitute2(typeArguments, typeParameters, newPrune);
- } else {
- type = type.pruned(newPrune);
- }
-
- callback(parameter.name, type);
- }
- }
- }
}
/**
@@ -1636,7 +1696,7 @@
}
List<DartType> newTypeArguments = TypeImpl.substitute(
typeArguments, argumentTypes, parameterTypes, prune);
- if (JavaArrays.equals(newTypeArguments, typeArguments)) {
+ if (listsEqual(newTypeArguments, typeArguments)) {
return this;
}
@@ -2172,6 +2232,9 @@
[List<FunctionTypeAliasElement> prune]);
@override
+ DartType resolveToBound(DartType objectType) => this;
+
+ @override
String toString() {
StringBuffer buffer = new StringBuffer();
appendTo(buffer);
@@ -2337,6 +2400,15 @@
}
return types;
}
+
+ @override
+ DartType resolveToBound(DartType objectType) {
+ if (element.bound == null) {
+ return objectType;
+ }
+
+ return element.bound.resolveToBound(objectType);
+ }
}
/**
diff --git a/pkg/analyzer/lib/src/dart/scanner/reader.dart b/pkg/analyzer/lib/src/dart/scanner/reader.dart
new file mode 100644
index 0000000..1f5d87d
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/scanner/reader.dart
@@ -0,0 +1,187 @@
+// 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.dart.scanner.reader;
+
+/**
+ * A [CharacterReader] that reads a range of characters from another character
+ * reader.
+ */
+class CharacterRangeReader extends CharacterReader {
+ /**
+ * The reader from which the characters are actually being read.
+ */
+ final CharacterReader baseReader;
+
+ /**
+ * The last character to be read.
+ */
+ final int endIndex;
+
+ /**
+ * Initialize a newly created reader to read the characters from the given
+ * [baseReader] between the [startIndex] inclusive to [endIndex] exclusive.
+ */
+ CharacterRangeReader(this.baseReader, int startIndex, this.endIndex) {
+ baseReader.offset = startIndex - 1;
+ }
+
+ @override
+ int get offset => baseReader.offset;
+
+ @override
+ void set offset(int offset) {
+ baseReader.offset = offset;
+ }
+
+ @override
+ int advance() {
+ if (baseReader.offset + 1 >= endIndex) {
+ return -1;
+ }
+ return baseReader.advance();
+ }
+
+ @override
+ String getString(int start, int endDelta) =>
+ baseReader.getString(start, endDelta);
+
+ @override
+ int peek() {
+ if (baseReader.offset + 1 >= endIndex) {
+ return -1;
+ }
+ return baseReader.peek();
+ }
+}
+
+/**
+ * An object used by the scanner to read the characters to be scanned.
+ */
+abstract class CharacterReader {
+ /**
+ * The current offset relative to the beginning of the source. Return the
+ * initial offset if the scanner has not yet scanned the source code, and one
+ * (1) past the end of the source code if the entire source code has been
+ * scanned.
+ */
+ int get offset;
+
+ /**
+ * Set the current offset relative to the beginning of the source to the given
+ * [offset]. The new offset must be between the initial offset and one (1)
+ * past the end of the source code.
+ */
+ void set offset(int offset);
+
+ /**
+ * Advance the current position and return the character at the new current
+ * position.
+ */
+ int advance();
+
+ /**
+ * Return the substring of the source code between the [start] offset and the
+ * modified current position. The current position is modified by adding the
+ * [endDelta], which is the number of characters after the current location to
+ * be included in the string, or the number of characters before the current
+ * location to be excluded if the offset is negative.
+ */
+ String getString(int start, int endDelta);
+
+ /**
+ * Return the character at the current position without changing the current
+ * position.
+ */
+ int peek();
+}
+
+/**
+ * A [CharacterReader] that reads characters from a character sequence.
+ */
+class CharSequenceReader implements CharacterReader {
+ /**
+ * The sequence from which characters will be read.
+ */
+ final String _sequence;
+
+ /**
+ * The number of characters in the string.
+ */
+ int _stringLength = 0;
+
+ /**
+ * The index, relative to the string, of the last character that was read.
+ */
+ int _charOffset = 0;
+
+ /**
+ * Initialize a newly created reader to read the characters in the given
+ * [_sequence].
+ */
+ CharSequenceReader(this._sequence) {
+ this._stringLength = _sequence.length;
+ this._charOffset = -1;
+ }
+
+ @override
+ int get offset => _charOffset;
+
+ @override
+ void set offset(int offset) {
+ _charOffset = offset;
+ }
+
+ @override
+ int advance() {
+ if (_charOffset + 1 >= _stringLength) {
+ return -1;
+ }
+ return _sequence.codeUnitAt(++_charOffset);
+ }
+
+ @override
+ String getString(int start, int endDelta) =>
+ _sequence.substring(start, _charOffset + 1 + endDelta).toString();
+
+ @override
+ int peek() {
+ if (_charOffset + 1 >= _stringLength) {
+ return -1;
+ }
+ return _sequence.codeUnitAt(_charOffset + 1);
+ }
+}
+
+/**
+ * A [CharacterReader] that reads characters from a character sequence, but adds
+ * a delta when reporting the current character offset so that the character
+ * sequence can be a subsequence from a larger sequence.
+ */
+class SubSequenceReader extends CharSequenceReader {
+ /**
+ * The offset from the beginning of the file to the beginning of the source
+ * being scanned.
+ */
+ final int _offsetDelta;
+
+ /**
+ * Initialize a newly created reader to read the characters in the given
+ * [sequence]. The [_offsetDelta] is the offset from the beginning of the file
+ * to the beginning of the source being scanned
+ */
+ SubSequenceReader(String sequence, this._offsetDelta) : super(sequence);
+
+ @override
+ int get offset => _offsetDelta + super.offset;
+
+ @override
+ void set offset(int offset) {
+ super.offset = offset - _offsetDelta;
+ }
+
+ @override
+ String getString(int start, int endDelta) =>
+ super.getString(start - _offsetDelta, endDelta);
+}
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
new file mode 100644
index 0000000..7814eb7
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -0,0 +1,1375 @@
+// 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.dart.scanner.scanner;
+
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+/**
+ * A state in a state machine used to scan keywords.
+ */
+class KeywordState {
+ /**
+ * An empty transition table used by leaf states.
+ */
+ static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);
+
+ /**
+ * The initial state in the state machine.
+ */
+ static final KeywordState KEYWORD_STATE = _createKeywordStateTable();
+
+ /**
+ * A table mapping characters to the states to which those characters will
+ * transition. (The index into the array is the offset from the character
+ * `'a'` to the transitioning character.)
+ */
+ final List<KeywordState> _table;
+
+ /**
+ * The keyword that is recognized by this state, or `null` if this state is
+ * not a terminal state.
+ */
+ Keyword _keyword;
+
+ /**
+ * Initialize a newly created state to have the given transitions and to
+ * recognize the keyword with the given [syntax].
+ */
+ KeywordState(this._table, String syntax) {
+ this._keyword = (syntax == null) ? null : Keyword.keywords[syntax];
+ }
+
+ /**
+ * Return the keyword that was recognized by this state, or `null` if this
+ * state does not recognized a keyword.
+ */
+ Keyword keyword() => _keyword;
+
+ /**
+ * Return the state that follows this state on a transition of the given
+ * [character], or `null` if there is no valid state reachable from this state
+ * with such a transition.
+ */
+ KeywordState next(int character) => _table[character - 0x61];
+
+ /**
+ * Create the next state in the state machine where we have already recognized
+ * the subset of strings in the given array of [strings] starting at the given
+ * [offset] and having the given [length]. All of these strings have a common
+ * prefix and the next character is at the given [start] index.
+ */
+ static KeywordState _computeKeywordStateTable(
+ int start, List<String> strings, int offset, int length) {
+ List<KeywordState> result = new List<KeywordState>(26);
+ assert(length != 0);
+ int chunk = 0x0;
+ int chunkStart = -1;
+ bool isLeaf = false;
+ for (int i = offset; i < offset + length; i++) {
+ if (strings[i].length == start) {
+ isLeaf = true;
+ }
+ if (strings[i].length > start) {
+ int c = strings[i].codeUnitAt(start);
+ if (chunk != c) {
+ if (chunkStart != -1) {
+ result[chunk - 0x61] = _computeKeywordStateTable(
+ start + 1, strings, chunkStart, i - chunkStart);
+ }
+ chunkStart = i;
+ chunk = c;
+ }
+ }
+ }
+ if (chunkStart != -1) {
+ assert(result[chunk - 0x61] == null);
+ result[chunk - 0x61] = _computeKeywordStateTable(
+ start + 1, strings, chunkStart, offset + length - chunkStart);
+ } else {
+ assert(length == 1);
+ return new KeywordState(_EMPTY_TABLE, strings[offset]);
+ }
+ if (isLeaf) {
+ return new KeywordState(result, strings[offset]);
+ } else {
+ return new KeywordState(result, null);
+ }
+ }
+
+ /**
+ * Create and return the initial state in the state machine.
+ */
+ static KeywordState _createKeywordStateTable() {
+ List<Keyword> values = Keyword.values;
+ List<String> strings = new List<String>(values.length);
+ for (int i = 0; i < values.length; i++) {
+ strings[i] = values[i].syntax;
+ }
+ strings.sort();
+ return _computeKeywordStateTable(0, strings, 0, strings.length);
+ }
+}
+
+/**
+ * The class `Scanner` implements a scanner for Dart code.
+ *
+ * The lexical structure of Dart is ambiguous without knowledge of the context
+ * in which a token is being scanned. For example, without context we cannot
+ * determine whether source of the form "<<" should be scanned as a single
+ * left-shift operator or as two left angle brackets. This scanner does not have
+ * any context, so it always resolves such conflicts by scanning the longest
+ * possible token.
+ */
+class Scanner {
+ /**
+ * The source being scanned.
+ */
+ final Source source;
+
+ /**
+ * The reader used to access the characters in the source.
+ */
+ final CharacterReader _reader;
+
+ /**
+ * The error listener that will be informed of any errors that are found
+ * during the scan.
+ */
+ final AnalysisErrorListener _errorListener;
+
+ /**
+ * The flag specifying whether documentation comments should be parsed.
+ */
+ bool _preserveComments = true;
+
+ /**
+ * The token pointing to the head of the linked list of tokens.
+ */
+ Token _tokens;
+
+ /**
+ * The last token that was scanned.
+ */
+ Token _tail;
+
+ /**
+ * The first token in the list of comment tokens found since the last
+ * non-comment token.
+ */
+ Token _firstComment;
+
+ /**
+ * The last token in the list of comment tokens found since the last
+ * non-comment token.
+ */
+ Token _lastComment;
+
+ /**
+ * The index of the first character of the current token.
+ */
+ int _tokenStart = 0;
+
+ /**
+ * A list containing the offsets of the first character of each line in the
+ * source code.
+ */
+ List<int> _lineStarts = new List<int>();
+
+ /**
+ * A list, treated something like a stack, of tokens representing the
+ * beginning of a matched pair. It is used to pair the end tokens with the
+ * begin tokens.
+ */
+ List<BeginToken> _groupingStack = new List<BeginToken>();
+
+ /**
+ * The index of the last item in the [_groupingStack], or `-1` if the stack is
+ * empty.
+ */
+ int _stackEnd = -1;
+
+ /**
+ * A flag indicating whether any unmatched groups were found during the parse.
+ */
+ bool _hasUnmatchedGroups = false;
+
+ /**
+ * A flag indicating whether to parse generic method comments, of the form
+ * `/*=T*/` and `/*<T>*/`.
+ */
+ bool scanGenericMethodComments = false;
+
+ /**
+ * Initialize a newly created scanner to scan characters from the given
+ * [source]. The given character [_reader] will be used to read the characters
+ * in the source. The given [_errorListener] will be informed of any errors
+ * that are found.
+ */
+ Scanner(this.source, this._reader, this._errorListener) {
+ _tokens = new Token(TokenType.EOF, -1);
+ _tokens.setNext(_tokens);
+ _tail = _tokens;
+ _tokenStart = -1;
+ _lineStarts.add(0);
+ }
+
+ /**
+ * Return the first token in the token stream that was scanned.
+ */
+ Token get firstToken => _tokens.next;
+
+ /**
+ * Return `true` if any unmatched groups were found during the parse.
+ */
+ bool get hasUnmatchedGroups => _hasUnmatchedGroups;
+
+ /**
+ * Return an array containing the offsets of the first character of each line
+ * in the source code.
+ */
+ List<int> get lineStarts => _lineStarts;
+
+ /**
+ * Set whether documentation tokens should be preserved.
+ */
+ void set preserveComments(bool preserveComments) {
+ this._preserveComments = preserveComments;
+ }
+
+ /**
+ * Return the last token that was scanned.
+ */
+ Token get tail => _tail;
+
+ /**
+ * Append the given [token] to the end of the token stream being scanned. This
+ * method is intended to be used by subclasses that copy existing tokens and
+ * should not normally be used because it will fail to correctly associate any
+ * comments with the token being passed in.
+ */
+ void appendToken(Token token) {
+ _tail = _tail.setNext(token);
+ }
+
+ int bigSwitch(int next) {
+ _beginToken();
+ if (next == 0xD) {
+ // '\r'
+ next = _reader.advance();
+ if (next == 0xA) {
+ // '\n'
+ next = _reader.advance();
+ }
+ recordStartOfLine();
+ return next;
+ } else if (next == 0xA) {
+ // '\n'
+ next = _reader.advance();
+ recordStartOfLine();
+ return next;
+ } else if (next == 0x9 || next == 0x20) {
+ // '\t' || ' '
+ return _reader.advance();
+ }
+ if (next == 0x72) {
+ // 'r'
+ int peek = _reader.peek();
+ if (peek == 0x22 || peek == 0x27) {
+ // '"' || "'"
+ int start = _reader.offset;
+ return _tokenizeString(_reader.advance(), start, true);
+ }
+ }
+ if (0x61 <= next && next <= 0x7A) {
+ // 'a'-'z'
+ return _tokenizeKeywordOrIdentifier(next, true);
+ }
+ if ((0x41 <= next && next <= 0x5A) || next == 0x5F || next == 0x24) {
+ // 'A'-'Z' || '_' || '$'
+ return _tokenizeIdentifier(next, _reader.offset, true);
+ }
+ if (next == 0x3C) {
+ // '<'
+ return _tokenizeLessThan(next);
+ }
+ if (next == 0x3E) {
+ // '>'
+ return _tokenizeGreaterThan(next);
+ }
+ if (next == 0x3D) {
+ // '='
+ return _tokenizeEquals(next);
+ }
+ if (next == 0x21) {
+ // '!'
+ return _tokenizeExclamation(next);
+ }
+ if (next == 0x2B) {
+ // '+'
+ return _tokenizePlus(next);
+ }
+ if (next == 0x2D) {
+ // '-'
+ return _tokenizeMinus(next);
+ }
+ if (next == 0x2A) {
+ // '*'
+ return _tokenizeMultiply(next);
+ }
+ if (next == 0x25) {
+ // '%'
+ return _tokenizePercent(next);
+ }
+ if (next == 0x26) {
+ // '&'
+ return _tokenizeAmpersand(next);
+ }
+ if (next == 0x7C) {
+ // '|'
+ return _tokenizeBar(next);
+ }
+ if (next == 0x5E) {
+ // '^'
+ return _tokenizeCaret(next);
+ }
+ if (next == 0x5B) {
+ // '['
+ return _tokenizeOpenSquareBracket(next);
+ }
+ if (next == 0x7E) {
+ // '~'
+ return _tokenizeTilde(next);
+ }
+ if (next == 0x5C) {
+ // '\\'
+ _appendTokenOfType(TokenType.BACKSLASH);
+ return _reader.advance();
+ }
+ if (next == 0x23) {
+ // '#'
+ return _tokenizeTag(next);
+ }
+ if (next == 0x28) {
+ // '('
+ _appendBeginToken(TokenType.OPEN_PAREN);
+ return _reader.advance();
+ }
+ if (next == 0x29) {
+ // ')'
+ _appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN);
+ return _reader.advance();
+ }
+ if (next == 0x2C) {
+ // ','
+ _appendTokenOfType(TokenType.COMMA);
+ return _reader.advance();
+ }
+ if (next == 0x3A) {
+ // ':'
+ _appendTokenOfType(TokenType.COLON);
+ return _reader.advance();
+ }
+ if (next == 0x3B) {
+ // ';'
+ _appendTokenOfType(TokenType.SEMICOLON);
+ return _reader.advance();
+ }
+ if (next == 0x3F) {
+ // '?'
+ return _tokenizeQuestion();
+ }
+ if (next == 0x5D) {
+ // ']'
+ _appendEndToken(
+ TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACKET);
+ return _reader.advance();
+ }
+ if (next == 0x60) {
+ // '`'
+ _appendTokenOfType(TokenType.BACKPING);
+ return _reader.advance();
+ }
+ if (next == 0x7B) {
+ // '{'
+ _appendBeginToken(TokenType.OPEN_CURLY_BRACKET);
+ return _reader.advance();
+ }
+ if (next == 0x7D) {
+ // '}'
+ _appendEndToken(
+ TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
+ return _reader.advance();
+ }
+ if (next == 0x2F) {
+ // '/'
+ return _tokenizeSlashOrComment(next);
+ }
+ if (next == 0x40) {
+ // '@'
+ _appendTokenOfType(TokenType.AT);
+ return _reader.advance();
+ }
+ if (next == 0x22 || next == 0x27) {
+ // '"' || "'"
+ return _tokenizeString(next, _reader.offset, false);
+ }
+ if (next == 0x2E) {
+ // '.'
+ return _tokenizeDotOrNumber(next);
+ }
+ if (next == 0x30) {
+ // '0'
+ return _tokenizeHexOrNumber(next);
+ }
+ if (0x31 <= next && next <= 0x39) {
+ // '1'-'9'
+ return _tokenizeNumber(next);
+ }
+ if (next == -1) {
+ // EOF
+ return -1;
+ }
+ _reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]);
+ return _reader.advance();
+ }
+
+ /**
+ * Record the fact that we are at the beginning of a new line in the source.
+ */
+ void recordStartOfLine() {
+ _lineStarts.add(_reader.offset);
+ }
+
+ /**
+ * Record that the source begins on the given [line] and [column] at the
+ * current offset as given by the reader. Both the line and the column are
+ * one-based indexes. The line starts for lines before the given line will not
+ * be correct.
+ *
+ * This method must be invoked at most one time and must be invoked before
+ * scanning begins. The values provided must be sensible. The results are
+ * undefined if these conditions are violated.
+ */
+ void setSourceStart(int line, int column) {
+ int offset = _reader.offset;
+ if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
+ return;
+ }
+ for (int i = 2; i < line; i++) {
+ _lineStarts.add(1);
+ }
+ _lineStarts.add(offset - column + 1);
+ }
+
+ /**
+ * Scan the source code to produce a list of tokens representing the source,
+ * and return the first token in the list of tokens that were produced.
+ */
+ Token tokenize() {
+ int next = _reader.advance();
+ while (next != -1) {
+ next = bigSwitch(next);
+ }
+ _appendEofToken();
+ return firstToken;
+ }
+
+ void _appendBeginToken(TokenType type) {
+ BeginToken token;
+ if (_firstComment == null) {
+ token = new BeginToken(type, _tokenStart);
+ } else {
+ token = new BeginTokenWithComment(type, _tokenStart, _firstComment);
+ _firstComment = null;
+ _lastComment = null;
+ }
+ _tail = _tail.setNext(token);
+ _groupingStack.add(token);
+ _stackEnd++;
+ }
+
+ void _appendCommentToken(TokenType type, String value) {
+ CommentToken token = null;
+ TokenType genericComment = _matchGenericMethodCommentType(value);
+ if (genericComment != null) {
+ token = new CommentToken(genericComment, value, _tokenStart);
+ } else if (!_preserveComments) {
+ // Ignore comment tokens if client specified that it doesn't need them.
+ return;
+ } else {
+ // OK, remember comment tokens.
+ if (_isDocumentationComment(value)) {
+ token = new DocumentationCommentToken(type, value, _tokenStart);
+ } else {
+ token = new CommentToken(type, value, _tokenStart);
+ }
+ }
+ if (_firstComment == null) {
+ _firstComment = token;
+ _lastComment = _firstComment;
+ } else {
+ _lastComment = _lastComment.setNext(token);
+ }
+ }
+
+ void _appendEndToken(TokenType type, TokenType beginType) {
+ Token token;
+ if (_firstComment == null) {
+ token = new Token(type, _tokenStart);
+ } else {
+ token = new TokenWithComment(type, _tokenStart, _firstComment);
+ _firstComment = null;
+ _lastComment = null;
+ }
+ _tail = _tail.setNext(token);
+ if (_stackEnd >= 0) {
+ BeginToken begin = _groupingStack[_stackEnd];
+ if (begin.type == beginType) {
+ begin.endToken = token;
+ _groupingStack.removeAt(_stackEnd--);
+ }
+ }
+ }
+
+ void _appendEofToken() {
+ Token eofToken;
+ if (_firstComment == null) {
+ eofToken = new Token(TokenType.EOF, _reader.offset + 1);
+ } else {
+ eofToken = new TokenWithComment(
+ TokenType.EOF, _reader.offset + 1, _firstComment);
+ _firstComment = null;
+ _lastComment = null;
+ }
+ // The EOF token points to itself so that there is always infinite
+ // look-ahead.
+ eofToken.setNext(eofToken);
+ _tail = _tail.setNext(eofToken);
+ if (_stackEnd >= 0) {
+ _hasUnmatchedGroups = true;
+ // TODO(brianwilkerson) Fix the ungrouped tokens?
+ }
+ }
+
+ void _appendKeywordToken(Keyword keyword) {
+ if (_firstComment == null) {
+ _tail = _tail.setNext(new KeywordToken(keyword, _tokenStart));
+ } else {
+ _tail = _tail.setNext(
+ new KeywordTokenWithComment(keyword, _tokenStart, _firstComment));
+ _firstComment = null;
+ _lastComment = null;
+ }
+ }
+
+ void _appendStringToken(TokenType type, String value) {
+ if (_firstComment == null) {
+ _tail = _tail.setNext(new StringToken(type, value, _tokenStart));
+ } else {
+ _tail = _tail.setNext(
+ new StringTokenWithComment(type, value, _tokenStart, _firstComment));
+ _firstComment = null;
+ _lastComment = null;
+ }
+ }
+
+ void _appendStringTokenWithOffset(TokenType type, String value, int offset) {
+ if (_firstComment == null) {
+ _tail = _tail.setNext(new StringToken(type, value, _tokenStart + offset));
+ } else {
+ _tail = _tail.setNext(new StringTokenWithComment(
+ type, value, _tokenStart + offset, _firstComment));
+ _firstComment = null;
+ _lastComment = null;
+ }
+ }
+
+ void _appendTokenOfType(TokenType type) {
+ if (_firstComment == null) {
+ _tail = _tail.setNext(new Token(type, _tokenStart));
+ } else {
+ _tail =
+ _tail.setNext(new TokenWithComment(type, _tokenStart, _firstComment));
+ _firstComment = null;
+ _lastComment = null;
+ }
+ }
+
+ void _appendTokenOfTypeWithOffset(TokenType type, int offset) {
+ if (_firstComment == null) {
+ _tail = _tail.setNext(new Token(type, offset));
+ } else {
+ _tail = _tail.setNext(new TokenWithComment(type, offset, _firstComment));
+ _firstComment = null;
+ _lastComment = null;
+ }
+ }
+
+ void _beginToken() {
+ _tokenStart = _reader.offset;
+ }
+
+ /**
+ * Return the beginning token corresponding to a closing brace that was found
+ * while scanning inside a string interpolation expression. Tokens that cannot
+ * be matched with the closing brace will be dropped from the stack.
+ */
+ BeginToken _findTokenMatchingClosingBraceInInterpolationExpression() {
+ while (_stackEnd >= 0) {
+ BeginToken begin = _groupingStack[_stackEnd];
+ if (begin.type == TokenType.OPEN_CURLY_BRACKET ||
+ begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
+ return begin;
+ }
+ _hasUnmatchedGroups = true;
+ _groupingStack.removeAt(_stackEnd--);
+ }
+ //
+ // We should never get to this point because we wouldn't be inside a string
+ // interpolation expression unless we had previously found the start of the
+ // expression.
+ //
+ return null;
+ }
+
+ /**
+ * Checks if [value] is the start of a generic method type annotation comment.
+ *
+ * This can either be of the form `/*<T>*/` or `/*=T*/`. The token type is
+ * returned, or null if it was not a generic method comment.
+ */
+ TokenType _matchGenericMethodCommentType(String value) {
+ if (scanGenericMethodComments) {
+ // Match /*< and >*/
+ if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3C) &&
+ StringUtilities.endsWith3(value, 0x3E, 0x2A, 0x2F)) {
+ return TokenType.GENERIC_METHOD_TYPE_LIST;
+ }
+ // Match /*=
+ if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3D)) {
+ return TokenType.GENERIC_METHOD_TYPE_ASSIGN;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Report an error at the current offset. The [errorCode] is the error code
+ * indicating the nature of the error. The [arguments] are any arguments
+ * needed to complete the error message
+ */
+ void _reportError(ScannerErrorCode errorCode, [List<Object> arguments]) {
+ _errorListener.onError(
+ new AnalysisError(source, _reader.offset, 1, errorCode, arguments));
+ }
+
+ int _select(int choice, TokenType yesType, TokenType noType) {
+ int next = _reader.advance();
+ if (next == choice) {
+ _appendTokenOfType(yesType);
+ return _reader.advance();
+ } else {
+ _appendTokenOfType(noType);
+ return next;
+ }
+ }
+
+ int _selectWithOffset(
+ int choice, TokenType yesType, TokenType noType, int offset) {
+ int next = _reader.advance();
+ if (next == choice) {
+ _appendTokenOfTypeWithOffset(yesType, offset);
+ return _reader.advance();
+ } else {
+ _appendTokenOfTypeWithOffset(noType, offset);
+ return next;
+ }
+ }
+
+ int _tokenizeAmpersand(int next) {
+ // && &= &
+ next = _reader.advance();
+ if (next == 0x26) {
+ _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND);
+ return _reader.advance();
+ } else if (next == 0x3D) {
+ _appendTokenOfType(TokenType.AMPERSAND_EQ);
+ return _reader.advance();
+ } else {
+ _appendTokenOfType(TokenType.AMPERSAND);
+ return next;
+ }
+ }
+
+ int _tokenizeBar(int next) {
+ // | || |=
+ next = _reader.advance();
+ if (next == 0x7C) {
+ _appendTokenOfType(TokenType.BAR_BAR);
+ return _reader.advance();
+ } else if (next == 0x3D) {
+ _appendTokenOfType(TokenType.BAR_EQ);
+ return _reader.advance();
+ } else {
+ _appendTokenOfType(TokenType.BAR);
+ return next;
+ }
+ }
+
+ int _tokenizeCaret(int next) =>
+ _select(0x3D, TokenType.CARET_EQ, TokenType.CARET);
+
+ int _tokenizeDotOrNumber(int next) {
+ int start = _reader.offset;
+ next = _reader.advance();
+ if (0x30 <= next && next <= 0x39) {
+ return _tokenizeFractionPart(next, start);
+ } else if (0x2E == next) {
+ return _select(
+ 0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD);
+ } else {
+ _appendTokenOfType(TokenType.PERIOD);
+ return next;
+ }
+ }
+
+ int _tokenizeEquals(int next) {
+ // = == =>
+ next = _reader.advance();
+ if (next == 0x3D) {
+ _appendTokenOfType(TokenType.EQ_EQ);
+ return _reader.advance();
+ } else if (next == 0x3E) {
+ _appendTokenOfType(TokenType.FUNCTION);
+ return _reader.advance();
+ }
+ _appendTokenOfType(TokenType.EQ);
+ return next;
+ }
+
+ int _tokenizeExclamation(int next) {
+ // ! !=
+ next = _reader.advance();
+ if (next == 0x3D) {
+ _appendTokenOfType(TokenType.BANG_EQ);
+ return _reader.advance();
+ }
+ _appendTokenOfType(TokenType.BANG);
+ return next;
+ }
+
+ int _tokenizeExponent(int next) {
+ if (next == 0x2B || next == 0x2D) {
+ next = _reader.advance();
+ }
+ bool hasDigits = false;
+ while (true) {
+ if (0x30 <= next && next <= 0x39) {
+ hasDigits = true;
+ } else {
+ if (!hasDigits) {
+ _reportError(ScannerErrorCode.MISSING_DIGIT);
+ }
+ return next;
+ }
+ next = _reader.advance();
+ }
+ }
+
+ int _tokenizeFractionPart(int next, int start) {
+ bool done = false;
+ bool hasDigit = false;
+ LOOP: while (!done) {
+ if (0x30 <= next && next <= 0x39) {
+ hasDigit = true;
+ } else if (0x65 == next || 0x45 == next) {
+ hasDigit = true;
+ next = _tokenizeExponent(_reader.advance());
+ done = true;
+ continue LOOP;
+ } else {
+ done = true;
+ continue LOOP;
+ }
+ next = _reader.advance();
+ }
+ if (!hasDigit) {
+ _appendStringToken(TokenType.INT, _reader.getString(start, -2));
+ if (0x2E == next) {
+ return _selectWithOffset(0x2E, TokenType.PERIOD_PERIOD_PERIOD,
+ TokenType.PERIOD_PERIOD, _reader.offset - 1);
+ }
+ _appendTokenOfTypeWithOffset(TokenType.PERIOD, _reader.offset - 1);
+ return bigSwitch(next);
+ }
+ _appendStringToken(
+ TokenType.DOUBLE, _reader.getString(start, next < 0 ? 0 : -1));
+ return next;
+ }
+
+ int _tokenizeGreaterThan(int next) {
+ // > >= >> >>=
+ next = _reader.advance();
+ if (0x3D == next) {
+ _appendTokenOfType(TokenType.GT_EQ);
+ return _reader.advance();
+ } else if (0x3E == next) {
+ next = _reader.advance();
+ if (0x3D == next) {
+ _appendTokenOfType(TokenType.GT_GT_EQ);
+ return _reader.advance();
+ } else {
+ _appendTokenOfType(TokenType.GT_GT);
+ return next;
+ }
+ } else {
+ _appendTokenOfType(TokenType.GT);
+ return next;
+ }
+ }
+
+ int _tokenizeHex(int next) {
+ int start = _reader.offset - 1;
+ bool hasDigits = false;
+ while (true) {
+ next = _reader.advance();
+ if ((0x30 <= next && next <= 0x39) ||
+ (0x41 <= next && next <= 0x46) ||
+ (0x61 <= next && next <= 0x66)) {
+ hasDigits = true;
+ } else {
+ if (!hasDigits) {
+ _reportError(ScannerErrorCode.MISSING_HEX_DIGIT);
+ }
+ _appendStringToken(
+ TokenType.HEXADECIMAL, _reader.getString(start, next < 0 ? 0 : -1));
+ return next;
+ }
+ }
+ }
+
+ int _tokenizeHexOrNumber(int next) {
+ int x = _reader.peek();
+ if (x == 0x78 || x == 0x58) {
+ _reader.advance();
+ return _tokenizeHex(x);
+ }
+ return _tokenizeNumber(next);
+ }
+
+ int _tokenizeIdentifier(int next, int start, bool allowDollar) {
+ while ((0x61 <= next && next <= 0x7A) ||
+ (0x41 <= next && next <= 0x5A) ||
+ (0x30 <= next && next <= 0x39) ||
+ next == 0x5F ||
+ (next == 0x24 && allowDollar)) {
+ next = _reader.advance();
+ }
+ _appendStringToken(
+ TokenType.IDENTIFIER, _reader.getString(start, next < 0 ? 0 : -1));
+ return next;
+ }
+
+ int _tokenizeInterpolatedExpression(int next, int start) {
+ _appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION);
+ next = _reader.advance();
+ while (next != -1) {
+ if (next == 0x7D) {
+ BeginToken begin =
+ _findTokenMatchingClosingBraceInInterpolationExpression();
+ if (begin == null) {
+ _beginToken();
+ _appendTokenOfType(TokenType.CLOSE_CURLY_BRACKET);
+ next = _reader.advance();
+ _beginToken();
+ return next;
+ } else if (begin.type == TokenType.OPEN_CURLY_BRACKET) {
+ _beginToken();
+ _appendEndToken(
+ TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
+ next = _reader.advance();
+ _beginToken();
+ } else if (begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
+ _beginToken();
+ _appendEndToken(TokenType.CLOSE_CURLY_BRACKET,
+ TokenType.STRING_INTERPOLATION_EXPRESSION);
+ next = _reader.advance();
+ _beginToken();
+ return next;
+ }
+ } else {
+ next = bigSwitch(next);
+ }
+ }
+ return next;
+ }
+
+ int _tokenizeInterpolatedIdentifier(int next, int start) {
+ _appendStringTokenWithOffset(
+ TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0);
+ if ((0x41 <= next && next <= 0x5A) ||
+ (0x61 <= next && next <= 0x7A) ||
+ next == 0x5F) {
+ _beginToken();
+ next = _tokenizeKeywordOrIdentifier(next, false);
+ }
+ _beginToken();
+ return next;
+ }
+
+ int _tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
+ KeywordState state = KeywordState.KEYWORD_STATE;
+ int start = _reader.offset;
+ while (state != null && 0x61 <= next && next <= 0x7A) {
+ state = state.next(next);
+ next = _reader.advance();
+ }
+ if (state == null || state.keyword() == null) {
+ return _tokenizeIdentifier(next, start, allowDollar);
+ }
+ if ((0x41 <= next && next <= 0x5A) ||
+ (0x30 <= next && next <= 0x39) ||
+ next == 0x5F ||
+ next == 0x24) {
+ return _tokenizeIdentifier(next, start, allowDollar);
+ } else if (next < 128) {
+ _appendKeywordToken(state.keyword());
+ return next;
+ } else {
+ return _tokenizeIdentifier(next, start, allowDollar);
+ }
+ }
+
+ int _tokenizeLessThan(int next) {
+ // < <= << <<=
+ next = _reader.advance();
+ if (0x3D == next) {
+ _appendTokenOfType(TokenType.LT_EQ);
+ return _reader.advance();
+ } else if (0x3C == next) {
+ return _select(0x3D, TokenType.LT_LT_EQ, TokenType.LT_LT);
+ } else {
+ _appendTokenOfType(TokenType.LT);
+ return next;
+ }
+ }
+
+ int _tokenizeMinus(int next) {
+ // - -- -=
+ next = _reader.advance();
+ if (next == 0x2D) {
+ _appendTokenOfType(TokenType.MINUS_MINUS);
+ return _reader.advance();
+ } else if (next == 0x3D) {
+ _appendTokenOfType(TokenType.MINUS_EQ);
+ return _reader.advance();
+ } else {
+ _appendTokenOfType(TokenType.MINUS);
+ return next;
+ }
+ }
+
+ int _tokenizeMultiLineComment(int next) {
+ int nesting = 1;
+ next = _reader.advance();
+ while (true) {
+ if (-1 == next) {
+ _reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT);
+ _appendCommentToken(
+ TokenType.MULTI_LINE_COMMENT, _reader.getString(_tokenStart, 0));
+ return next;
+ } else if (0x2A == next) {
+ next = _reader.advance();
+ if (0x2F == next) {
+ --nesting;
+ if (0 == nesting) {
+ _appendCommentToken(TokenType.MULTI_LINE_COMMENT,
+ _reader.getString(_tokenStart, 0));
+ return _reader.advance();
+ } else {
+ next = _reader.advance();
+ }
+ }
+ } else if (0x2F == next) {
+ next = _reader.advance();
+ if (0x2A == next) {
+ next = _reader.advance();
+ ++nesting;
+ }
+ } else if (next == 0xD) {
+ next = _reader.advance();
+ if (next == 0xA) {
+ next = _reader.advance();
+ }
+ recordStartOfLine();
+ } else if (next == 0xA) {
+ next = _reader.advance();
+ recordStartOfLine();
+ } else {
+ next = _reader.advance();
+ }
+ }
+ }
+
+ int _tokenizeMultiLineRawString(int quoteChar, int start) {
+ int next = _reader.advance();
+ outer: while (next != -1) {
+ while (next != quoteChar) {
+ if (next == -1) {
+ break outer;
+ } else if (next == 0xD) {
+ next = _reader.advance();
+ if (next == 0xA) {
+ next = _reader.advance();
+ }
+ recordStartOfLine();
+ } else if (next == 0xA) {
+ next = _reader.advance();
+ recordStartOfLine();
+ } else {
+ next = _reader.advance();
+ }
+ }
+ next = _reader.advance();
+ if (next == quoteChar) {
+ next = _reader.advance();
+ if (next == quoteChar) {
+ _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+ return _reader.advance();
+ }
+ }
+ }
+ _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
+ _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+ return _reader.advance();
+ }
+
+ int _tokenizeMultiLineString(int quoteChar, int start, bool raw) {
+ if (raw) {
+ return _tokenizeMultiLineRawString(quoteChar, start);
+ }
+ int next = _reader.advance();
+ while (next != -1) {
+ if (next == 0x24) {
+ _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
+ next = _tokenizeStringInterpolation(start);
+ _beginToken();
+ start = _reader.offset;
+ continue;
+ }
+ if (next == quoteChar) {
+ next = _reader.advance();
+ if (next == quoteChar) {
+ next = _reader.advance();
+ if (next == quoteChar) {
+ _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+ return _reader.advance();
+ }
+ }
+ continue;
+ }
+ if (next == 0x5C) {
+ next = _reader.advance();
+ if (next == -1) {
+ break;
+ }
+ if (next == 0xD) {
+ next = _reader.advance();
+ if (next == 0xA) {
+ next = _reader.advance();
+ }
+ recordStartOfLine();
+ } else if (next == 0xA) {
+ recordStartOfLine();
+ next = _reader.advance();
+ } else {
+ next = _reader.advance();
+ }
+ } else if (next == 0xD) {
+ next = _reader.advance();
+ if (next == 0xA) {
+ next = _reader.advance();
+ }
+ recordStartOfLine();
+ } else if (next == 0xA) {
+ recordStartOfLine();
+ next = _reader.advance();
+ } else {
+ next = _reader.advance();
+ }
+ }
+ _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
+ if (start == _reader.offset) {
+ _appendStringTokenWithOffset(TokenType.STRING, "", 1);
+ } else {
+ _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+ }
+ return _reader.advance();
+ }
+
+ int _tokenizeMultiply(int next) =>
+ _select(0x3D, TokenType.STAR_EQ, TokenType.STAR);
+
+ int _tokenizeNumber(int next) {
+ int start = _reader.offset;
+ while (true) {
+ next = _reader.advance();
+ if (0x30 <= next && next <= 0x39) {
+ continue;
+ } else if (next == 0x2E) {
+ return _tokenizeFractionPart(_reader.advance(), start);
+ } else if (next == 0x65 || next == 0x45) {
+ return _tokenizeFractionPart(next, start);
+ } else {
+ _appendStringToken(
+ TokenType.INT, _reader.getString(start, next < 0 ? 0 : -1));
+ return next;
+ }
+ }
+ }
+
+ int _tokenizeOpenSquareBracket(int next) {
+ // [ [] []=
+ next = _reader.advance();
+ if (next == 0x5D) {
+ return _select(0x3D, TokenType.INDEX_EQ, TokenType.INDEX);
+ } else {
+ _appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
+ return next;
+ }
+ }
+
+ int _tokenizePercent(int next) =>
+ _select(0x3D, TokenType.PERCENT_EQ, TokenType.PERCENT);
+
+ int _tokenizePlus(int next) {
+ // + ++ +=
+ next = _reader.advance();
+ if (0x2B == next) {
+ _appendTokenOfType(TokenType.PLUS_PLUS);
+ return _reader.advance();
+ } else if (0x3D == next) {
+ _appendTokenOfType(TokenType.PLUS_EQ);
+ return _reader.advance();
+ } else {
+ _appendTokenOfType(TokenType.PLUS);
+ return next;
+ }
+ }
+
+ int _tokenizeQuestion() {
+ // ? ?. ?? ??=
+ int next = _reader.advance();
+ if (next == 0x2E) {
+ // '.'
+ _appendTokenOfType(TokenType.QUESTION_PERIOD);
+ return _reader.advance();
+ } else if (next == 0x3F) {
+ // '?'
+ next = _reader.advance();
+ if (next == 0x3D) {
+ // '='
+ _appendTokenOfType(TokenType.QUESTION_QUESTION_EQ);
+ return _reader.advance();
+ } else {
+ _appendTokenOfType(TokenType.QUESTION_QUESTION);
+ return next;
+ }
+ } else {
+ _appendTokenOfType(TokenType.QUESTION);
+ return next;
+ }
+ }
+
+ int _tokenizeSingleLineComment(int next) {
+ while (true) {
+ next = _reader.advance();
+ if (-1 == next) {
+ _appendCommentToken(
+ TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, 0));
+ return next;
+ } else if (0xA == next || 0xD == next) {
+ _appendCommentToken(
+ TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, -1));
+ return next;
+ }
+ }
+ }
+
+ int _tokenizeSingleLineRawString(int next, int quoteChar, int start) {
+ next = _reader.advance();
+ while (next != -1) {
+ if (next == quoteChar) {
+ _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+ return _reader.advance();
+ } else if (next == 0xD || next == 0xA) {
+ _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
+ _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
+ return _reader.advance();
+ }
+ next = _reader.advance();
+ }
+ _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
+ _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+ return _reader.advance();
+ }
+
+ int _tokenizeSingleLineString(int next, int quoteChar, int start) {
+ while (next != quoteChar) {
+ if (next == 0x5C) {
+ next = _reader.advance();
+ } else if (next == 0x24) {
+ _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
+ next = _tokenizeStringInterpolation(start);
+ _beginToken();
+ start = _reader.offset;
+ continue;
+ }
+ if (next <= 0xD && (next == 0xA || next == 0xD || next == -1)) {
+ _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
+ if (start == _reader.offset) {
+ _appendStringTokenWithOffset(TokenType.STRING, "", 1);
+ } else if (next == -1) {
+ _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+ } else {
+ _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
+ }
+ return _reader.advance();
+ }
+ next = _reader.advance();
+ }
+ _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
+ return _reader.advance();
+ }
+
+ int _tokenizeSlashOrComment(int next) {
+ next = _reader.advance();
+ if (0x2A == next) {
+ return _tokenizeMultiLineComment(next);
+ } else if (0x2F == next) {
+ return _tokenizeSingleLineComment(next);
+ } else if (0x3D == next) {
+ _appendTokenOfType(TokenType.SLASH_EQ);
+ return _reader.advance();
+ } else {
+ _appendTokenOfType(TokenType.SLASH);
+ return next;
+ }
+ }
+
+ int _tokenizeString(int next, int start, bool raw) {
+ int quoteChar = next;
+ next = _reader.advance();
+ if (quoteChar == next) {
+ next = _reader.advance();
+ if (quoteChar == next) {
+ // Multiline string.
+ return _tokenizeMultiLineString(quoteChar, start, raw);
+ } else {
+ // Empty string.
+ _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
+ return next;
+ }
+ }
+ if (raw) {
+ return _tokenizeSingleLineRawString(next, quoteChar, start);
+ } else {
+ return _tokenizeSingleLineString(next, quoteChar, start);
+ }
+ }
+
+ int _tokenizeStringInterpolation(int start) {
+ _beginToken();
+ int next = _reader.advance();
+ if (next == 0x7B) {
+ return _tokenizeInterpolatedExpression(next, start);
+ } else {
+ return _tokenizeInterpolatedIdentifier(next, start);
+ }
+ }
+
+ int _tokenizeTag(int next) {
+ // # or #!.*[\n\r]
+ if (_reader.offset == 0) {
+ if (_reader.peek() == 0x21) {
+ do {
+ next = _reader.advance();
+ } while (next != 0xA && next != 0xD && next > 0);
+ _appendStringToken(
+ TokenType.SCRIPT_TAG, _reader.getString(_tokenStart, 0));
+ return next;
+ }
+ }
+ _appendTokenOfType(TokenType.HASH);
+ return _reader.advance();
+ }
+
+ int _tokenizeTilde(int next) {
+ // ~ ~/ ~/=
+ next = _reader.advance();
+ if (next == 0x2F) {
+ return _select(0x3D, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
+ } else {
+ _appendTokenOfType(TokenType.TILDE);
+ return next;
+ }
+ }
+
+ /**
+ * Checks if [value] is a single-line or multi-line comment.
+ */
+ static bool _isDocumentationComment(String value) {
+ return StringUtilities.startsWith3(value, 0, 0x2F, 0x2F, 0x2F) ||
+ StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x2A);
+ }
+}
+
+/**
+ * The error codes used for errors detected by the scanner.
+ */
+class ScannerErrorCode extends ErrorCode {
+ static const ScannerErrorCode ILLEGAL_CHARACTER =
+ const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character {0}");
+
+ static const ScannerErrorCode MISSING_DIGIT =
+ const ScannerErrorCode('MISSING_DIGIT', "Decimal digit expected");
+
+ static const ScannerErrorCode MISSING_HEX_DIGIT =
+ const ScannerErrorCode('MISSING_HEX_DIGIT', "Hexidecimal digit expected");
+
+ static const ScannerErrorCode MISSING_QUOTE =
+ const ScannerErrorCode('MISSING_QUOTE', "Expected quote (' or \")");
+
+ static const ScannerErrorCode UNABLE_GET_CONTENT = const ScannerErrorCode(
+ 'UNABLE_GET_CONTENT', "Unable to get content: {0}");
+
+ static const ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT =
+ const ScannerErrorCode(
+ 'UNTERMINATED_MULTI_LINE_COMMENT', "Unterminated multi-line comment");
+
+ static const ScannerErrorCode UNTERMINATED_STRING_LITERAL =
+ const ScannerErrorCode(
+ 'UNTERMINATED_STRING_LITERAL', "Unterminated string literal");
+
+ /**
+ * Initialize a newly created error code to have the given [name]. The message
+ * associated with the error will be created from the given [message]
+ * template. The correction associated with the error will be created from the
+ * given [correction] template.
+ */
+ const ScannerErrorCode(String name, String message, [String correction])
+ : super(name, message, correction);
+
+ @override
+ ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
+
+ @override
+ ErrorType get type => ErrorType.SYNTACTIC_ERROR;
+}
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 7123029..b2d1e0d 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -7,6 +7,7 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -21,7 +22,6 @@
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType;
import 'package:analyzer/src/generated/source.dart' show Source;
import 'package:analyzer/src/generated/type_system.dart'
show TypeSystem, TypeSystemImpl;
@@ -31,12 +31,12 @@
import 'package:analyzer/src/task/dart.dart';
ConstructorElementImpl _getConstructorImpl(ConstructorElement constructor) {
- if (constructor is ConstructorElementHandle) {
- constructor = (constructor as ConstructorElementHandle).actualElement;
- }
while (constructor is ConstructorMember) {
constructor = (constructor as ConstructorMember).baseElement;
}
+ if (constructor is ConstructorElementHandle) {
+ constructor = (constructor as ConstructorElementHandle).actualElement;
+ }
return constructor;
}
@@ -1248,8 +1248,8 @@
/**
* The elements and AST nodes whose constant values need to be computed.
*/
- HashSet<ConstantEvaluationTarget> constantsToCompute =
- new HashSet<ConstantEvaluationTarget>();
+ List<ConstantEvaluationTarget> constantsToCompute =
+ <ConstantEvaluationTarget>[];
/**
* True if instance variables marked as "final" should be treated as "const".
diff --git a/pkg/analyzer/lib/src/generated/element_handle.dart b/pkg/analyzer/lib/src/generated/element_handle.dart
index 03f9137..84b4bdc 100644
--- a/pkg/analyzer/lib/src/generated/element_handle.dart
+++ b/pkg/analyzer/lib/src/generated/element_handle.dart
@@ -915,7 +915,7 @@
super.enclosingElement as LibraryElement;
@override
- List<LibraryElement> get importedLibraries => actualElement.importedLibraries;
+ List<LibraryElement> get importedLibraries => LibraryElement.EMPTY_LIST;
@override
ElementKind get kind => ElementKind.PREFIX;
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index b5cddef..c3c343b 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -7,6 +7,7 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -17,7 +18,6 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart' as sc;
/**
* An object used by instances of [ResolverVisitor] to resolve references within
@@ -149,10 +149,10 @@
@override
Object visitAssignmentExpression(AssignmentExpression node) {
- sc.Token operator = node.operator;
- sc.TokenType operatorType = operator.type;
- if (operatorType != sc.TokenType.EQ &&
- operatorType != sc.TokenType.QUESTION_QUESTION_EQ) {
+ Token operator = node.operator;
+ TokenType operatorType = operator.type;
+ if (operatorType != TokenType.EQ &&
+ operatorType != TokenType.QUESTION_QUESTION_EQ) {
operatorType = _operatorFromCompoundAssignment(operatorType);
Expression leftHandSide = node.leftHandSide;
if (leftHandSide != null) {
@@ -188,11 +188,11 @@
@override
Object visitBinaryExpression(BinaryExpression node) {
- sc.Token operator = node.operator;
+ Token operator = node.operator;
if (operator.isUserDefinableOperator) {
_resolveBinaryExpression(node, operator.lexeme);
- } else if (operator.type == sc.TokenType.BANG_EQ) {
- _resolveBinaryExpression(node, sc.TokenType.EQ_EQ.lexeme);
+ } else if (operator.type == TokenType.BANG_EQ) {
+ _resolveBinaryExpression(node, TokenType.EQ_EQ.lexeme);
}
return null;
}
@@ -494,8 +494,8 @@
Expression target = node.realTarget;
DartType staticType = _getStaticType(target);
DartType propagatedType = _getPropagatedType(target);
- String getterMethodName = sc.TokenType.INDEX.lexeme;
- String setterMethodName = sc.TokenType.INDEX_EQ.lexeme;
+ String getterMethodName = TokenType.INDEX.lexeme;
+ String setterMethodName = TokenType.INDEX_EQ.lexeme;
bool isInGetterContext = node.inGetterContext();
bool isInSetterContext = node.inSetterContext();
if (isInGetterContext && isInSetterContext) {
@@ -612,7 +612,7 @@
propagatedElement = null;
} else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME &&
_isDeferredPrefix(target)) {
- if (node.operator.type == sc.TokenType.QUESTION_PERIOD) {
+ if (node.operator.type == TokenType.QUESTION_PERIOD) {
_resolver.reportErrorForNode(
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
target,
@@ -630,7 +630,7 @@
// hierarchy, instead we just look for the member in the type only. This
// does not apply to conditional method invocation (i.e. 'C?.m(...)').
//
- bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD;
+ bool isConditional = node.operator.type == TokenType.QUESTION_PERIOD;
ClassElementImpl typeReference = getTypeReference(target);
if (typeReference != null) {
if (node.isCascaded) {
@@ -934,11 +934,11 @@
@override
Object visitPrefixExpression(PrefixExpression node) {
- sc.Token operator = node.operator;
- sc.TokenType operatorType = operator.type;
+ Token operator = node.operator;
+ TokenType operatorType = operator.type;
if (operatorType.isUserDefinableOperator ||
- operatorType == sc.TokenType.PLUS_PLUS ||
- operatorType == sc.TokenType.MINUS_MINUS) {
+ operatorType == TokenType.PLUS_PLUS ||
+ operatorType == TokenType.MINUS_MINUS) {
Expression operand = node.operand;
String methodName = _getPrefixOperator(node);
DartType staticType = _getStaticType(operand);
@@ -1300,8 +1300,8 @@
propagatedType.element, methodName, true, false);
if (shouldReportMissingMember_static ||
shouldReportMissingMember_propagated) {
- sc.Token leftBracket = expression.leftBracket;
- sc.Token rightBracket = expression.rightBracket;
+ Token leftBracket = expression.leftBracket;
+ Token rightBracket = expression.rightBracket;
ErrorCode errorCode;
if (shouldReportMissingMember_static) {
if (target is SuperExpression) {
@@ -1451,21 +1451,21 @@
* Return the name of the method invoked by the given postfix [expression].
*/
String _getPostfixOperator(PostfixExpression expression) =>
- (expression.operator.type == sc.TokenType.PLUS_PLUS)
- ? sc.TokenType.PLUS.lexeme
- : sc.TokenType.MINUS.lexeme;
+ (expression.operator.type == TokenType.PLUS_PLUS)
+ ? TokenType.PLUS.lexeme
+ : TokenType.MINUS.lexeme;
/**
* Return the name of the method invoked by the given postfix [expression].
*/
String _getPrefixOperator(PrefixExpression expression) {
- sc.Token operator = expression.operator;
- sc.TokenType operatorType = operator.type;
- if (operatorType == sc.TokenType.PLUS_PLUS) {
- return sc.TokenType.PLUS.lexeme;
- } else if (operatorType == sc.TokenType.MINUS_MINUS) {
- return sc.TokenType.MINUS.lexeme;
- } else if (operatorType == sc.TokenType.MINUS) {
+ Token operator = expression.operator;
+ TokenType operatorType = operator.type;
+ if (operatorType == TokenType.PLUS_PLUS) {
+ return TokenType.PLUS.lexeme;
+ } else if (operatorType == TokenType.MINUS_MINUS) {
+ return TokenType.MINUS.lexeme;
+ } else if (operatorType == TokenType.MINUS) {
return "unary-";
} else {
return operator.lexeme;
@@ -1519,12 +1519,13 @@
NodeList<TypeName> arguments = typeArguments?.arguments;
if (arguments != null && arguments.length != parameters.length) {
- // Wrong number of type arguments. Ignore them
- arguments = null;
_resolver.reportErrorForNode(
StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
node,
[type, parameters.length, arguments?.length ?? 0]);
+
+ // Wrong number of type arguments. Ignore them.
+ arguments = null;
}
if (parameters.isNotEmpty) {
if (arguments == null) {
@@ -1746,30 +1747,30 @@
* Return the binary operator that is invoked by the given compound assignment
* [operator].
*/
- sc.TokenType _operatorFromCompoundAssignment(sc.TokenType operator) {
+ TokenType _operatorFromCompoundAssignment(TokenType operator) {
while (true) {
- if (operator == sc.TokenType.AMPERSAND_EQ) {
- return sc.TokenType.AMPERSAND;
- } else if (operator == sc.TokenType.BAR_EQ) {
- return sc.TokenType.BAR;
- } else if (operator == sc.TokenType.CARET_EQ) {
- return sc.TokenType.CARET;
- } else if (operator == sc.TokenType.GT_GT_EQ) {
- return sc.TokenType.GT_GT;
- } else if (operator == sc.TokenType.LT_LT_EQ) {
- return sc.TokenType.LT_LT;
- } else if (operator == sc.TokenType.MINUS_EQ) {
- return sc.TokenType.MINUS;
- } else if (operator == sc.TokenType.PERCENT_EQ) {
- return sc.TokenType.PERCENT;
- } else if (operator == sc.TokenType.PLUS_EQ) {
- return sc.TokenType.PLUS;
- } else if (operator == sc.TokenType.SLASH_EQ) {
- return sc.TokenType.SLASH;
- } else if (operator == sc.TokenType.STAR_EQ) {
- return sc.TokenType.STAR;
- } else if (operator == sc.TokenType.TILDE_SLASH_EQ) {
- return sc.TokenType.TILDE_SLASH;
+ if (operator == TokenType.AMPERSAND_EQ) {
+ return TokenType.AMPERSAND;
+ } else if (operator == TokenType.BAR_EQ) {
+ return TokenType.BAR;
+ } else if (operator == TokenType.CARET_EQ) {
+ return TokenType.CARET;
+ } else if (operator == TokenType.GT_GT_EQ) {
+ return TokenType.GT_GT;
+ } else if (operator == TokenType.LT_LT_EQ) {
+ return TokenType.LT_LT;
+ } else if (operator == TokenType.MINUS_EQ) {
+ return TokenType.MINUS;
+ } else if (operator == TokenType.PERCENT_EQ) {
+ return TokenType.PERCENT;
+ } else if (operator == TokenType.PLUS_EQ) {
+ return TokenType.PLUS;
+ } else if (operator == TokenType.SLASH_EQ) {
+ return TokenType.SLASH;
+ } else if (operator == TokenType.STAR_EQ) {
+ return TokenType.STAR;
+ } else if (operator == TokenType.TILDE_SLASH_EQ) {
+ return TokenType.TILDE_SLASH;
} else {
// Internal error: Unmapped assignment operator.
AnalysisEngine.instance.logger.logError(
@@ -1837,7 +1838,7 @@
* message.
*/
void _recordUndefinedToken(Element declaringElement, ErrorCode errorCode,
- sc.Token token, List<Object> arguments) {
+ Token token, List<Object> arguments) {
if (_doesntHaveProxy(declaringElement)) {
_resolver.reportErrorForToken(errorCode, token, arguments);
}
@@ -2424,26 +2425,15 @@
* If the given [type] is a type parameter, resolve it to the type that should
* be used when looking up members. Otherwise, return the original type.
*/
- DartType _resolveTypeParameter(DartType type) {
- if (type is TypeParameterType) {
- DartType bound = type.element.bound;
- if (bound == null) {
- return _resolver.typeProvider.objectType;
- }
- return bound;
- }
- return type;
- }
+ DartType _resolveTypeParameter(DartType type) =>
+ type?.resolveToBound(_resolver.typeProvider.objectType);
/**
* Return `true` if we should report an error as a result of looking up a
* [member] in the given [type] and not finding any member.
*/
bool _shouldReportMissingMember(DartType type, Element member) {
- if (member != null || type == null || type.isDynamic || type.isBottom) {
- return false;
- }
- return true;
+ return member == null && type != null && !type.isDynamic && !type.isBottom;
}
/**
@@ -2563,7 +2553,7 @@
SyntheticIdentifier(this.name, this.targetIdentifier);
@override
- sc.Token get beginToken => null;
+ Token get beginToken => null;
@override
Element get bestElement => null;
@@ -2577,7 +2567,7 @@
}
@override
- sc.Token get endToken => null;
+ Token get endToken => null;
@override
int get length => targetIdentifier.length;
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index b27c42e..c3aa019 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -881,8 +881,8 @@
if (fileName == null) {
return false;
}
- return javaStringEqualsIgnoreCase(
- FileNameUtilities.getExtension(fileName), SUFFIX_DART);
+ String extension = FileNameUtilities.getExtension(fileName).toLowerCase();
+ return extension == SUFFIX_DART;
}
/**
@@ -892,9 +892,8 @@
if (fileName == null) {
return false;
}
- String extension = FileNameUtilities.getExtension(fileName);
- return javaStringEqualsIgnoreCase(extension, SUFFIX_HTML) ||
- javaStringEqualsIgnoreCase(extension, SUFFIX_HTM);
+ String extension = FileNameUtilities.getExtension(fileName).toLowerCase();
+ return extension == SUFFIX_HTML || extension == SUFFIX_HTM;
}
}
@@ -1123,6 +1122,19 @@
* Return `true` if strong mode analysis should be used.
*/
bool get strongMode;
+
+ /**
+ * Return an integer encoding of the values of the options that need to be the
+ * same across all of the contexts associated with partitions that are to be
+ * shared by a single analysis context.
+ */
+ int encodeCrossContextOptions();
+
+ /**
+ * Set the values of the cross-context options to match those in the given set
+ * of [options].
+ */
+ void setCrossContextOptionsFrom(AnalysisOptions options);
}
/**
@@ -1135,6 +1147,14 @@
*/
static const int DEFAULT_CACHE_SIZE = 64;
+ static const int ENABLE_ASSERT_FLAG = 0x01;
+ static const int ENABLE_ASYNC_FLAG = 0x02;
+ static const int ENABLE_GENERIC_METHODS_FLAG = 0x04;
+ static const int ENABLE_STRICT_CALL_CHECKS_FLAG = 0x08;
+ static const int ENABLE_STRONG_MODE_FLAG = 0x10;
+ static const int ENABLE_STRONG_MODE_HINTS_FLAG = 0x20;
+ static const int ENABLE_SUPER_MIXINS_FLAG = 0x40;
+
/**
* A predicate indicating whether analysis is to parse and analyze function
* bodies.
@@ -1308,6 +1328,29 @@
_analyzeFunctionBodiesPredicate = value;
}
+ @override
+ int encodeCrossContextOptions() =>
+ (enableAssertMessage ? ENABLE_ASSERT_FLAG : 0) |
+ (enableAsync ? ENABLE_ASYNC_FLAG : 0) |
+ (enableGenericMethods ? ENABLE_GENERIC_METHODS_FLAG : 0) |
+ (enableStrictCallChecks ? ENABLE_STRICT_CALL_CHECKS_FLAG : 0) |
+ (strongMode ? ENABLE_STRONG_MODE_FLAG : 0) |
+ (strongModeHints ? ENABLE_STRONG_MODE_HINTS_FLAG : 0) |
+ (enableSuperMixins ? ENABLE_SUPER_MIXINS_FLAG : 0);
+
+ @override
+ void setCrossContextOptionsFrom(AnalysisOptions options) {
+ enableAssertMessage = options.enableAssertMessage;
+ enableAsync = options.enableAsync;
+ enableGenericMethods = options.enableGenericMethods;
+ enableStrictCallChecks = options.enableStrictCallChecks;
+ enableSuperMixins = options.enableSuperMixins;
+ strongMode = options.strongMode;
+ if (options is AnalysisOptionsImpl) {
+ strongModeHints = options.strongModeHints;
+ }
+ }
+
/**
* Predicate used for [analyzeFunctionBodiesPredicate] when
* [analyzeFunctionBodies] is set to `true`.
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index fe21b9d..938aa23 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -7,13 +7,13 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart' show AstNode;
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/source/error_processor.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart' show ScannerErrorCode;
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
-import 'package:analyzer/src/generated/scanner.dart'
- show ScannerErrorCode, Token;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/task/model.dart';
import 'package:analyzer/task/model.dart';
@@ -5640,7 +5640,8 @@
* 0: the name of the constant that is missing
*/
static const StaticWarningCode MISSING_ENUM_CONSTANT_IN_SWITCH =
- const StaticWarningCode('MISSING_ENUM_CONSTANT_IN_SWITCH',
+ const StaticWarningCode(
+ 'MISSING_ENUM_CONSTANT_IN_SWITCH',
"Missing case clause for '{0}'",
"Add a case clause for the missing constant or add a default clause.");
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 4cb96b4..5de25974 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -8,6 +8,8 @@
import "dart:math" as math;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -22,7 +24,6 @@
import 'package:analyzer/src/generated/parser.dart'
show Parser, ParserErrorCode;
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart' as sc;
import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -328,11 +329,11 @@
@override
Object visitAssignmentExpression(AssignmentExpression node) {
- sc.TokenType operatorType = node.operator.type;
+ TokenType operatorType = node.operator.type;
Expression lhs = node.leftHandSide;
Expression rhs = node.rightHandSide;
- if (operatorType == sc.TokenType.EQ ||
- operatorType == sc.TokenType.QUESTION_QUESTION_EQ) {
+ if (operatorType == TokenType.EQ ||
+ operatorType == TokenType.QUESTION_QUESTION_EQ) {
_checkForInvalidAssignment(lhs, rhs);
} else {
_checkForInvalidCompoundAssignment(node, lhs, rhs);
@@ -353,10 +354,10 @@
@override
Object visitBinaryExpression(BinaryExpression node) {
- sc.Token operator = node.operator;
- sc.TokenType type = operator.type;
- if (type == sc.TokenType.AMPERSAND_AMPERSAND ||
- type == sc.TokenType.BAR_BAR) {
+ Token operator = node.operator;
+ TokenType type = operator.type;
+ if (type == TokenType.AMPERSAND_AMPERSAND ||
+ type == TokenType.BAR_BAR) {
String lexeme = operator.lexeme;
_checkForAssignability(node.leftOperand, _boolType,
StaticTypeWarningCode.NON_BOOL_OPERAND, [lexeme]);
@@ -947,9 +948,9 @@
@override
Object visitPrefixExpression(PrefixExpression node) {
- sc.TokenType operatorType = node.operator.type;
+ TokenType operatorType = node.operator.type;
Expression operand = node.operand;
- if (operatorType == sc.TokenType.BANG) {
+ if (operatorType == TokenType.BANG) {
_checkForNonBoolNegationExpression(operand);
} else if (operatorType.isIncrementOperator) {
_checkForAssignmentToFinal(operand);
@@ -2169,8 +2170,8 @@
*/
bool _checkForBuiltInIdentifierAsName(
SimpleIdentifier identifier, ErrorCode errorCode) {
- sc.Token token = identifier.token;
- if (token.type == sc.TokenType.KEYWORD) {
+ Token token = identifier.token;
+ if (token.type == TokenType.KEYWORD) {
_errorReporter
.reportErrorForNode(errorCode, identifier, [identifier.name]);
return true;
@@ -2831,8 +2832,8 @@
if (type.element.isAbstract) {
ConstructorElement element = expression.staticElement;
if (element != null && !element.isFactory) {
- if ((expression.keyword as sc.KeywordToken).keyword ==
- sc.Keyword.CONST) {
+ if ((expression.keyword as KeywordToken).keyword ==
+ Keyword.CONST) {
_errorReporter.reportErrorForNode(
StaticWarningCode.CONST_WITH_ABSTRACT_CLASS, typeName);
} else {
@@ -3981,7 +3982,7 @@
*/
bool _checkForInvalidModifierOnBody(
FunctionBody body, CompileTimeErrorCode errorCode) {
- sc.Token keyword = body.keyword;
+ Token keyword = body.keyword;
if (keyword != null) {
_errorReporter.reportErrorForToken(errorCode, keyword, [keyword.lexeme]);
return true;
@@ -5852,7 +5853,7 @@
int count = directives.length;
if (count > 1) {
for (int i = 0; i < count; i++) {
- sc.Token deferredToken = directives[i].deferredKeyword;
+ Token deferredToken = directives[i].deferredKeyword;
if (deferredToken != null) {
_errorReporter.reportErrorForToken(
CompileTimeErrorCode.SHARED_DEFERRED_PREFIX, deferredToken);
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index b19b4b1..f102201 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -8,14 +8,18 @@
import 'dart:math' as math;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
@@ -25,7 +29,6 @@
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/task/dart.dart';
@@ -2049,9 +2052,9 @@
/**
* Adjusts the location of each Element that moved.
*
- * Since operator== and hashCode of an Element are based
- * on the element location, we also need to remove each
- * moved element from the cache to avoid a memory leak.
+ * Since `==` and `hashCode` of a local variable or function Element are based
+ * on the element name offsets, we also need to remove these elements from the
+ * cache to avoid a memory leak. TODO(scheglov) fix and remove this
*/
class _ElementOffsetUpdater extends GeneralizingElementVisitor {
final int updateOffset;
@@ -2065,7 +2068,13 @@
// name offset
int nameOffset = element.nameOffset;
if (nameOffset > updateOffset) {
- cache.remove(element);
+ // TODO(scheglov) make sure that we don't put local variables
+ // and functions into the cache at all.
+ if (element is LocalVariableElement ||
+ element is FunctionElement &&
+ element.enclosingElement is ExecutableElement) {
+ cache.remove(element);
+ }
(element as ElementImpl).nameOffset = nameOffset + updateDelta;
if (element is ConstVariableElement) {
ConstVariableElement constVariable = element as ConstVariableElement;
diff --git a/pkg/analyzer/lib/src/generated/incremental_scanner.dart b/pkg/analyzer/lib/src/generated/incremental_scanner.dart
index 6f4abee..ae34471 100644
--- a/pkg/analyzer/lib/src/generated/incremental_scanner.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_scanner.dart
@@ -6,9 +6,11 @@
import "dart:math" as math;
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap;
@@ -203,8 +205,8 @@
*/
bool _equalTokens(Token oldToken, Token newToken) =>
oldToken.type == newToken.type &&
- oldToken.length == newToken.length &&
- oldToken.lexeme == newToken.lexeme;
+ oldToken.length == newToken.length &&
+ oldToken.lexeme == newToken.lexeme;
/**
* Given a [token], return the EOF token that follows the token.
diff --git a/pkg/analyzer/lib/src/generated/java_core.dart b/pkg/analyzer/lib/src/generated/java_core.dart
index fd684ed..d28dd98 100644
--- a/pkg/analyzer/lib/src/generated/java_core.dart
+++ b/pkg/analyzer/lib/src/generated/java_core.dart
@@ -4,8 +4,6 @@
library analyzer.src.generated.java_core;
-const int LONG_MAX_VALUE = 0x7fffffffffffffff;
-
final Stopwatch nanoTimeStopwatch = new Stopwatch();
/**
@@ -17,6 +15,8 @@
*/
String format(String pattern,
[arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7]) {
+ // TODO(rnystrom): This is not used by analyzer, but is called by
+ // analysis_server. Move this code there and remove it from here.
return formatList(pattern, [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7]);
}
@@ -41,35 +41,6 @@
});
}
-bool javaCollectionContainsAll(Iterable list, Iterable c) {
- return c.fold(true, (bool prev, e) => prev && list.contains(e));
-}
-
-javaListSet(List list, int index, newValue) {
- var oldValue = list[index];
- list[index] = newValue;
- return oldValue;
-}
-
-bool javaSetEquals(Set a, Set b) {
- return a.containsAll(b) && b.containsAll(a);
-}
-
-bool javaStringEqualsIgnoreCase(String a, String b) {
- return a.toLowerCase() == b.toLowerCase();
-}
-
-bool javaStringRegionMatches(
- String t, int toffset, String o, int ooffset, int len) {
- if (toffset < 0) return false;
- if (ooffset < 0) return false;
- var tend = toffset + len;
- var oend = ooffset + len;
- if (tend > t.length) return false;
- if (oend > o.length) return false;
- return t.substring(toffset, tend) == o.substring(ooffset, oend);
-}
-
/// Parses given string to [Uri], throws [URISyntaxException] if invalid.
Uri parseUriWithException(String str) {
Uri uri;
@@ -130,6 +101,7 @@
static const int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000;
static const int MIN_LOW_SURROGATE = 0xDC00;
static const int MIN_HIGH_SURROGATE = 0xD800;
+
static int digit(int codePoint, int radix) {
if (radix != 16) {
throw new ArgumentError("only radix == 16 is supported");
@@ -146,29 +118,15 @@
return -1;
}
- static bool isDigit(int c) {
- return c >= 0x30 && c <= 0x39;
- }
+ static bool isDigit(int c) => c >= 0x30 && c <= 0x39;
- static bool isLetter(int c) {
- return c >= 0x41 && c <= 0x5A || c >= 0x61 && c <= 0x7A;
- }
+ static bool isLetter(int c) =>
+ c >= 0x41 && c <= 0x5A || c >= 0x61 && c <= 0x7A;
- static bool isLetterOrDigit(int c) {
- return isLetter(c) || isDigit(c);
- }
+ static bool isLetterOrDigit(int c) => isLetter(c) || isDigit(c);
- static bool isLowerCase(int c) {
- return c >= 0x61 && c <= 0x7A;
- }
-
- static bool isUpperCase(int c) {
- return c >= 0x41 && c <= 0x5A;
- }
-
- static bool isWhitespace(int c) {
- return c == 0x09 || c == 0x20 || c == 0x0A || c == 0x0D;
- }
+ static bool isWhitespace(int c) =>
+ c == 0x09 || c == 0x20 || c == 0x0A || c == 0x0D;
static String toChars(int codePoint) {
if (codePoint < 0 || codePoint > MAX_CODE_POINT) {
@@ -182,20 +140,6 @@
int c1 = (offset & 0x3ff) + MIN_LOW_SURROGATE;
return new String.fromCharCodes([c0, c1]);
}
-
- static int toLowerCase(int c) {
- if (c >= 0x41 && c <= 0x5A) {
- return 0x61 + (c - 0x41);
- }
- return c;
- }
-
- static int toUpperCase(int c) {
- if (c >= 0x61 && c <= 0x7A) {
- return 0x41 + (c - 0x61);
- }
- return c;
- }
}
abstract class Enum<E extends Enum> implements Comparable<E> {
@@ -220,23 +164,9 @@
}
class JavaArrays {
- static bool equals(List a, List b) {
- if (identical(a, b)) {
- return true;
- }
- if (a.length != b.length) {
- return false;
- }
- var len = a.length;
- for (int i = 0; i < len; i++) {
- if (a[i] != b[i]) {
- return false;
- }
- }
- return true;
- }
-
static int makeHashCode(List a) {
+ // TODO(rnystrom): This is not used by analyzer, but is called by
+ // analysis_server. Move this code there and remove it from here.
if (a == null) {
return 0;
}
@@ -292,10 +222,6 @@
if (fromIndex < 0) fromIndex = 0;
return target.lastIndexOf(str, fromIndex);
}
-
- static bool startsWithBefore(String s, String other, int start) {
- return s.indexOf(other, start) != -1;
- }
}
class JavaSystem {
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 7a39b04..ad18d2c 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -8,9 +8,13 @@
import "dart:math" as math;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart'
show AnalysisEngine, AnalysisOptionsImpl;
import 'package:analyzer/src/generated/error.dart';
@@ -18,7 +22,6 @@
as shared_messages;
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/source.dart';
import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap;
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -7049,7 +7052,8 @@
_peek().matchesAny([
TokenType.OPEN_PAREN,
TokenType.OPEN_CURLY_BRACKET,
- TokenType.FUNCTION
+ TokenType.FUNCTION,
+ TokenType.LT
])) {
return _parseFunctionDeclarationStatementAfterReturnType(
commentAndMetadata, returnType);
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index ecfe204..fab4ed1 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -7,10 +7,13 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
@@ -23,7 +26,6 @@
import 'package:analyzer/src/generated/error_verifier.dart';
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/source.dart';
import 'package:analyzer/src/generated/static_type_analyzer.dart';
import 'package:analyzer/src/generated/type_system.dart';
@@ -2302,6 +2304,7 @@
if (node.parent is! FunctionDeclaration) {
FunctionElement element = _findAtOffset(
_enclosingExecutable.functions, node, node.beginToken.offset);
+ _expectedElements.remove(element);
node.element = element;
}
ExecutableElement outerExecutable = _enclosingExecutable;
@@ -3270,12 +3273,14 @@
List<DartObjectImpl> constantValues = new List<DartObjectImpl>();
int constantCount = constants.length;
for (int i = 0; i < constantCount; i++) {
- SimpleIdentifier constantName = constants[i].name;
+ EnumConstantDeclaration constant = constants[i];
+ SimpleIdentifier constantName = constant.name;
FieldElementImpl constantField =
new ConstFieldElementImpl.forNode(constantName);
constantField.static = true;
constantField.const3 = true;
constantField.type = enumType;
+ setElementDocumentationComment(constantField, constant);
//
// Create a value for the constant.
//
@@ -4001,6 +4006,7 @@
* An [AstVisitor] that fills [UsedLocalElements].
*/
class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor {
+ final List<Element> definedElements = <Element>[];
final UsedLocalElements usedElements = new UsedLocalElements();
final LibraryElement _enclosingLibrary;
@@ -4070,10 +4076,13 @@
@override
visitSimpleIdentifier(SimpleIdentifier node) {
+ Element element = node.staticElement;
if (node.inDeclarationContext()) {
+ if (element != null) {
+ definedElements.add(element);
+ }
return;
}
- Element element = node.staticElement;
bool isIdentifierRead = _isReadIdentifier(node);
if (element is LocalVariableElement) {
if (isIdentifierRead) {
@@ -7293,6 +7302,48 @@
}
/**
+ * Given a downward inference type [fnType], and the declared
+ * [typeParameterList] for a function expression, determines if we can enable
+ * downward inference and if so, returns the function type to use for
+ * inference.
+ *
+ * This will return null if inference is not possible. This happens when
+ * there is no way we can find a subtype of the function type, given the
+ * provided type parameter list.
+ */
+ FunctionType matchFunctionTypeParameters(
+ TypeParameterList typeParameterList, FunctionType fnType) {
+ if (typeParameterList == null) {
+ if (fnType.typeFormals.isEmpty) {
+ return fnType;
+ }
+
+ // A non-generic function cannot be a subtype of a generic one.
+ return null;
+ }
+
+ NodeList<TypeParameter> typeParameters = typeParameterList.typeParameters;
+ if (fnType.typeFormals.isEmpty) {
+ // TODO(jmesserly): this is a legal subtype. We don't currently infer
+ // here, but we could. This is similar to
+ // StrongTypeSystemImpl.inferFunctionTypeInstantiation, but we don't
+ // have the FunctionType yet for the current node, so it's not quite
+ // straightforward to apply.
+ return null;
+ }
+
+ if (fnType.typeFormals.length != typeParameters.length) {
+ // A subtype cannot have different number of type formals.
+ return null;
+ }
+
+ // Same number of type formals. Instantiate the function type so its
+ // parameter and return type are in terms of the surrounding context.
+ return fnType.instantiate(
+ typeParameters.map((t) => t.name.staticElement.type).toList());
+ }
+
+ /**
* If it is appropriate to do so, override the current type of the static and propagated elements
* associated with the given expression with the given type. Generally speaking, it is appropriate
* if the given type is more specific than the current type.
@@ -8076,12 +8127,16 @@
try {
DartType functionType = InferenceContext.getType(node);
if (functionType is FunctionType) {
- _inferFormalParameterList(node.parameters, functionType);
- DartType returnType = _computeReturnOrYieldType(
- functionType.returnType,
- _enclosingFunction.isGenerator,
- _enclosingFunction.isAsynchronous);
- InferenceContext.setType(node.body, returnType);
+ functionType =
+ matchFunctionTypeParameters(node.typeParameters, functionType);
+ if (functionType is FunctionType) {
+ _inferFormalParameterList(node.parameters, functionType);
+ DartType returnType = _computeReturnOrYieldType(
+ functionType.returnType,
+ _enclosingFunction.isGenerator,
+ _enclosingFunction.isAsynchronous);
+ InferenceContext.setType(node.body, returnType);
+ }
}
super.visitFunctionExpression(node);
} finally {
@@ -11513,7 +11568,7 @@
if (element is MultiplyDefinedElement) {
_setElement(typeName, element);
} else {
- _setElement(typeName, _dynamicType.element);
+ _setElement(typeName, null);
}
typeName.staticType = _undefinedType;
node.type = _undefinedType;
@@ -11578,7 +11633,7 @@
StaticWarningCode.NOT_A_TYPE, typeName, [typeName.name]);
}
}
- _setElement(typeName, _dynamicType.element);
+ _setElement(typeName, null);
typeName.staticType = _dynamicType;
node.type = _dynamicType;
return null;
@@ -12080,18 +12135,25 @@
return types;
}
+ /**
+ * If the given [element] is not `null`, set `staticElement` of the
+ * [typeName] to it. If the [typeName] is a prefixed identifier, and the
+ * prefix can be resolved to a not `null` element, set also the
+ * `staticElement` of the prefix.
+ */
void _setElement(Identifier typeName, Element element) {
- if (element != null) {
- if (typeName is SimpleIdentifier) {
+ if (typeName is SimpleIdentifier) {
+ if (element != null) {
typeName.staticElement = element;
- } else if (typeName is PrefixedIdentifier) {
- PrefixedIdentifier identifier = typeName;
- identifier.identifier.staticElement = element;
- SimpleIdentifier prefix = identifier.prefix;
- Element prefixElement = nameScope.lookup(prefix, definingLibrary);
- if (prefixElement != null) {
- prefix.staticElement = prefixElement;
- }
+ }
+ } else if (typeName is PrefixedIdentifier) {
+ if (element != null) {
+ typeName.identifier.staticElement = element;
+ }
+ SimpleIdentifier prefix = typeName.prefix;
+ Element prefixElement = nameScope.lookup(prefix, definingLibrary);
+ if (prefixElement != null) {
+ prefix.staticElement = prefixElement;
}
}
}
@@ -12148,7 +12210,7 @@
* structure looking for cases of [HintCode.UNUSED_ELEMENT],
* [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc.
*/
-class UnusedLocalElementsVerifier extends RecursiveElementVisitor {
+class UnusedLocalElementsVerifier extends SimpleElementVisitor {
/**
* The error listener to which errors will be reported.
*/
@@ -12398,6 +12460,11 @@
ExecutableElement _enclosingFunction;
/**
+ * Information about local variables in the enclosing function or method.
+ */
+ LocalVariableInfo _localVariableInfo;
+
+ /**
* Initialize a newly created visitor to resolve the nodes in an AST node.
*
* [definingLibrary] is the element for the library containing the node being
@@ -12419,15 +12486,35 @@
nameScope: nameScope);
@override
+ Object visitConstructorDeclaration(ConstructorDeclaration node) {
+ ExecutableElement outerFunction = _enclosingFunction;
+ LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
+ try {
+ _localVariableInfo ??= new LocalVariableInfo();
+ (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+ _enclosingFunction = node.element;
+ return super.visitConstructorDeclaration(node);
+ } finally {
+ _localVariableInfo = outerLocalVariableInfo;
+ _enclosingFunction = outerFunction;
+ }
+ }
+
+ @override
Object visitExportDirective(ExportDirective node) => null;
@override
Object visitFunctionDeclaration(FunctionDeclaration node) {
ExecutableElement outerFunction = _enclosingFunction;
+ LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
try {
+ _localVariableInfo ??= new LocalVariableInfo();
+ (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
+ _localVariableInfo;
_enclosingFunction = node.element;
return super.visitFunctionDeclaration(node);
} finally {
+ _localVariableInfo = outerLocalVariableInfo;
_enclosingFunction = outerFunction;
}
}
@@ -12436,10 +12523,14 @@
Object visitFunctionExpression(FunctionExpression node) {
if (node.parent is! FunctionDeclaration) {
ExecutableElement outerFunction = _enclosingFunction;
+ LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
try {
+ _localVariableInfo ??= new LocalVariableInfo();
+ (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
_enclosingFunction = node.element;
return super.visitFunctionExpression(node);
} finally {
+ _localVariableInfo = outerLocalVariableInfo;
_enclosingFunction = outerFunction;
}
} else {
@@ -12453,10 +12544,14 @@
@override
Object visitMethodDeclaration(MethodDeclaration node) {
ExecutableElement outerFunction = _enclosingFunction;
+ LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
try {
+ _localVariableInfo ??= new LocalVariableInfo();
+ (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
_enclosingFunction = node.element;
return super.visitMethodDeclaration(node);
} finally {
+ _localVariableInfo = outerLocalVariableInfo;
_enclosingFunction = outerFunction;
}
}
@@ -12508,8 +12603,10 @@
element as LocalVariableElementImpl;
if (node.inSetterContext()) {
variableImpl.markPotentiallyMutatedInScope();
+ _localVariableInfo.potentiallyMutatedInScope.add(element);
if (element.enclosingElement != _enclosingFunction) {
variableImpl.markPotentiallyMutatedInClosure();
+ _localVariableInfo.potentiallyMutatedInClosure.add(element);
}
}
} else if (kind == ElementKind.PARAMETER) {
@@ -12517,11 +12614,13 @@
if (node.inSetterContext()) {
ParameterElementImpl parameterImpl = element as ParameterElementImpl;
parameterImpl.markPotentiallyMutatedInScope();
+ _localVariableInfo.potentiallyMutatedInScope.add(element);
// If we are in some closure, check if it is not the same as where
// variable is declared.
if (_enclosingFunction != null &&
(element.enclosingElement != _enclosingFunction)) {
parameterImpl.markPotentiallyMutatedInClosure();
+ _localVariableInfo.potentiallyMutatedInClosure.add(element);
}
}
}
diff --git a/pkg/analyzer/lib/src/generated/scanner.dart b/pkg/analyzer/lib/src/generated/scanner.dart
index 3fc2113..5a2e2c0 100644
--- a/pkg/analyzer/lib/src/generated/scanner.dart
+++ b/pkg/analyzer/lib/src/generated/scanner.dart
@@ -2,2715 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+@deprecated
library analyzer.src.generated.scanner;
-import 'dart:collection';
-
-import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-/**
- * The opening half of a grouping pair of tokens. This is used for curly
- * brackets ('{'), parentheses ('('), and square brackets ('[').
- */
-class BeginToken extends Token {
- /**
- * The token that corresponds to this token.
- */
- Token endToken;
-
- /**
- * Initialize a newly created token to have the given [type] at the given
- * [offset].
- */
- BeginToken(TokenType type, int offset) : super(type, offset) {
- assert(type == TokenType.OPEN_CURLY_BRACKET ||
- type == TokenType.OPEN_PAREN ||
- type == TokenType.OPEN_SQUARE_BRACKET ||
- type == TokenType.STRING_INTERPOLATION_EXPRESSION);
- }
-
- @override
- Token copy() => new BeginToken(type, offset);
-}
-
-/**
- * A begin token that is preceded by comments.
- */
-class BeginTokenWithComment extends BeginToken {
- /**
- * The first comment in the list of comments that precede this token.
- */
- CommentToken _precedingComment;
-
- /**
- * Initialize a newly created token to have the given [type] at the given
- * [offset] and to be preceded by the comments reachable from the given
- * [comment].
- */
- BeginTokenWithComment(TokenType type, int offset, this._precedingComment)
- : super(type, offset) {
- _setCommentParent(_precedingComment);
- }
-
- CommentToken get precedingComments => _precedingComment;
-
- void set precedingComments(CommentToken comment) {
- _precedingComment = comment;
- _setCommentParent(_precedingComment);
- }
-
- @override
- void applyDelta(int delta) {
- super.applyDelta(delta);
- Token token = precedingComments;
- while (token != null) {
- token.applyDelta(delta);
- token = token.next;
- }
- }
-
- @override
- Token copy() =>
- new BeginTokenWithComment(type, offset, copyComments(precedingComments));
-}
-
-/**
- * A [CharacterReader] that reads a range of characters from another character
- * reader.
- */
-class CharacterRangeReader extends CharacterReader {
- /**
- * The reader from which the characters are actually being read.
- */
- final CharacterReader baseReader;
-
- /**
- * The last character to be read.
- */
- final int endIndex;
-
- /**
- * Initialize a newly created reader to read the characters from the given
- * [baseReader] between the [startIndex] inclusive to [endIndex] exclusive.
- */
- CharacterRangeReader(this.baseReader, int startIndex, this.endIndex) {
- baseReader.offset = startIndex - 1;
- }
-
- @override
- int get offset => baseReader.offset;
-
- @override
- void set offset(int offset) {
- baseReader.offset = offset;
- }
-
- @override
- int advance() {
- if (baseReader.offset + 1 >= endIndex) {
- return -1;
- }
- return baseReader.advance();
- }
-
- @override
- String getString(int start, int endDelta) =>
- baseReader.getString(start, endDelta);
-
- @override
- int peek() {
- if (baseReader.offset + 1 >= endIndex) {
- return -1;
- }
- return baseReader.peek();
- }
-}
-
-/**
- * An object used by the scanner to read the characters to be scanned.
- */
-abstract class CharacterReader {
- /**
- * The current offset relative to the beginning of the source. Return the
- * initial offset if the scanner has not yet scanned the source code, and one
- * (1) past the end of the source code if the entire source code has been
- * scanned.
- */
- int get offset;
-
- /**
- * Set the current offset relative to the beginning of the source to the given
- * [offset]. The new offset must be between the initial offset and one (1)
- * past the end of the source code.
- */
- void set offset(int offset);
-
- /**
- * Advance the current position and return the character at the new current
- * position.
- */
- int advance();
-
- /**
- * Return the substring of the source code between the [start] offset and the
- * modified current position. The current position is modified by adding the
- * [endDelta], which is the number of characters after the current location to
- * be included in the string, or the number of characters before the current
- * location to be excluded if the offset is negative.
- */
- String getString(int start, int endDelta);
-
- /**
- * Return the character at the current position without changing the current
- * position.
- */
- int peek();
-}
-
-/**
- * A [CharacterReader] that reads characters from a character sequence.
- */
-class CharSequenceReader implements CharacterReader {
- /**
- * The sequence from which characters will be read.
- */
- final String _sequence;
-
- /**
- * The number of characters in the string.
- */
- int _stringLength = 0;
-
- /**
- * The index, relative to the string, of the last character that was read.
- */
- int _charOffset = 0;
-
- /**
- * Initialize a newly created reader to read the characters in the given
- * [_sequence].
- */
- CharSequenceReader(this._sequence) {
- this._stringLength = _sequence.length;
- this._charOffset = -1;
- }
-
- @override
- int get offset => _charOffset;
-
- @override
- void set offset(int offset) {
- _charOffset = offset;
- }
-
- @override
- int advance() {
- if (_charOffset + 1 >= _stringLength) {
- return -1;
- }
- return _sequence.codeUnitAt(++_charOffset);
- }
-
- @override
- String getString(int start, int endDelta) =>
- _sequence.substring(start, _charOffset + 1 + endDelta).toString();
-
- @override
- int peek() {
- if (_charOffset + 1 >= _stringLength) {
- return -1;
- }
- return _sequence.codeUnitAt(_charOffset + 1);
- }
-}
-
-/**
- * A token representing a comment.
- */
-class CommentToken extends StringToken {
- /**
- * The [Token] that contains this comment.
- */
- Token parent;
-
- /**
- * Initialize a newly created token to represent a token of the given [type]
- * with the given [value] at the given [offset].
- */
- CommentToken(TokenType type, String value, int offset)
- : super(type, value, offset);
-
- @override
- CommentToken copy() => new CommentToken(type, _value, offset);
-}
-
-/**
- * A documentation comment token.
- */
-class DocumentationCommentToken extends CommentToken {
- /**
- * The references embedded within the documentation comment.
- * This list will be empty unless this is a documentation comment that has
- * references embedded within it.
- */
- final List<Token> references = <Token>[];
-
- /**
- * Initialize a newly created token to represent a token of the given [type]
- * with the given [value] at the given [offset].
- */
- DocumentationCommentToken(TokenType type, String value, int offset)
- : super(type, value, offset);
-
- @override
- CommentToken copy() {
- DocumentationCommentToken copy =
- new DocumentationCommentToken(type, _value, offset);
- references.forEach((ref) => copy.references.add(ref.copy()));
- return copy;
- }
-}
-
-/**
- * The keywords in the Dart programming language.
- */
-class Keyword {
- static const Keyword ASSERT = const Keyword('ASSERT', "assert");
-
- static const Keyword BREAK = const Keyword('BREAK', "break");
-
- static const Keyword CASE = const Keyword('CASE', "case");
-
- static const Keyword CATCH = const Keyword('CATCH', "catch");
-
- static const Keyword CLASS = const Keyword('CLASS', "class");
-
- static const Keyword CONST = const Keyword('CONST', "const");
-
- static const Keyword CONTINUE = const Keyword('CONTINUE', "continue");
-
- static const Keyword DEFAULT = const Keyword('DEFAULT', "default");
-
- static const Keyword DO = const Keyword('DO', "do");
-
- static const Keyword ELSE = const Keyword('ELSE', "else");
-
- static const Keyword ENUM = const Keyword('ENUM', "enum");
-
- static const Keyword EXTENDS = const Keyword('EXTENDS', "extends");
-
- static const Keyword FALSE = const Keyword('FALSE', "false");
-
- static const Keyword FINAL = const Keyword('FINAL', "final");
-
- static const Keyword FINALLY = const Keyword('FINALLY', "finally");
-
- static const Keyword FOR = const Keyword('FOR', "for");
-
- static const Keyword IF = const Keyword('IF', "if");
-
- static const Keyword IN = const Keyword('IN', "in");
-
- static const Keyword IS = const Keyword('IS', "is");
-
- static const Keyword NEW = const Keyword('NEW', "new");
-
- static const Keyword NULL = const Keyword('NULL', "null");
-
- static const Keyword RETHROW = const Keyword('RETHROW', "rethrow");
-
- static const Keyword RETURN = const Keyword('RETURN', "return");
-
- static const Keyword SUPER = const Keyword('SUPER', "super");
-
- static const Keyword SWITCH = const Keyword('SWITCH', "switch");
-
- static const Keyword THIS = const Keyword('THIS', "this");
-
- static const Keyword THROW = const Keyword('THROW', "throw");
-
- static const Keyword TRUE = const Keyword('TRUE', "true");
-
- static const Keyword TRY = const Keyword('TRY', "try");
-
- static const Keyword VAR = const Keyword('VAR', "var");
-
- static const Keyword VOID = const Keyword('VOID', "void");
-
- static const Keyword WHILE = const Keyword('WHILE', "while");
-
- static const Keyword WITH = const Keyword('WITH', "with");
-
- static const Keyword ABSTRACT = const Keyword('ABSTRACT', "abstract", true);
-
- static const Keyword AS = const Keyword('AS', "as", true);
-
- static const Keyword DEFERRED = const Keyword('DEFERRED', "deferred", true);
-
- static const Keyword DYNAMIC = const Keyword('DYNAMIC', "dynamic", true);
-
- static const Keyword EXPORT = const Keyword('EXPORT', "export", true);
-
- static const Keyword EXTERNAL = const Keyword('EXTERNAL', "external", true);
-
- static const Keyword FACTORY = const Keyword('FACTORY', "factory", true);
-
- static const Keyword GET = const Keyword('GET', "get", true);
-
- static const Keyword IMPLEMENTS =
- const Keyword('IMPLEMENTS', "implements", true);
-
- static const Keyword IMPORT = const Keyword('IMPORT', "import", true);
-
- static const Keyword LIBRARY = const Keyword('LIBRARY', "library", true);
-
- static const Keyword OPERATOR = const Keyword('OPERATOR', "operator", true);
-
- static const Keyword PART = const Keyword('PART', "part", true);
-
- static const Keyword SET = const Keyword('SET', "set", true);
-
- static const Keyword STATIC = const Keyword('STATIC', "static", true);
-
- static const Keyword TYPEDEF = const Keyword('TYPEDEF', "typedef", true);
-
- static const List<Keyword> values = const [
- ASSERT,
- BREAK,
- CASE,
- CATCH,
- CLASS,
- CONST,
- CONTINUE,
- DEFAULT,
- DO,
- ELSE,
- ENUM,
- EXTENDS,
- FALSE,
- FINAL,
- FINALLY,
- FOR,
- IF,
- IN,
- IS,
- NEW,
- NULL,
- RETHROW,
- RETURN,
- SUPER,
- SWITCH,
- THIS,
- THROW,
- TRUE,
- TRY,
- VAR,
- VOID,
- WHILE,
- WITH,
- ABSTRACT,
- AS,
- DEFERRED,
- DYNAMIC,
- EXPORT,
- EXTERNAL,
- FACTORY,
- GET,
- IMPLEMENTS,
- IMPORT,
- LIBRARY,
- OPERATOR,
- PART,
- SET,
- STATIC,
- TYPEDEF
- ];
-
- /**
- * A table mapping the lexemes of keywords to the corresponding keyword.
- */
- static final Map<String, Keyword> keywords = _createKeywordMap();
-
- /**
- * The name of the keyword type.
- */
- final String name;
-
- /**
- * The lexeme for the keyword.
- */
- final String syntax;
-
- /**
- * A flag indicating whether the keyword is a pseudo-keyword. Pseudo keywords
- * can be used as identifiers.
- */
- final bool isPseudoKeyword;
-
- /**
- * Initialize a newly created keyword to have the given [name] and [syntax].
- * The keyword is a pseudo-keyword if the [isPseudoKeyword] flag is `true`.
- */
- const Keyword(this.name, this.syntax, [this.isPseudoKeyword = false]);
-
- @override
- String toString() => name;
-
- /**
- * Create a table mapping the lexemes of keywords to the corresponding keyword
- * and return the table that was created.
- */
- static Map<String, Keyword> _createKeywordMap() {
- LinkedHashMap<String, Keyword> result =
- new LinkedHashMap<String, Keyword>();
- for (Keyword keyword in values) {
- result[keyword.syntax] = keyword;
- }
- return result;
- }
-}
-
-/**
- * A state in a state machine used to scan keywords.
- */
-class KeywordState {
- /**
- * An empty transition table used by leaf states.
- */
- static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);
-
- /**
- * The initial state in the state machine.
- */
- static final KeywordState KEYWORD_STATE = _createKeywordStateTable();
-
- /**
- * A table mapping characters to the states to which those characters will
- * transition. (The index into the array is the offset from the character
- * `'a'` to the transitioning character.)
- */
- final List<KeywordState> _table;
-
- /**
- * The keyword that is recognized by this state, or `null` if this state is
- * not a terminal state.
- */
- Keyword _keyword;
-
- /**
- * Initialize a newly created state to have the given transitions and to
- * recognize the keyword with the given [syntax].
- */
- KeywordState(this._table, String syntax) {
- this._keyword = (syntax == null) ? null : Keyword.keywords[syntax];
- }
-
- /**
- * Return the keyword that was recognized by this state, or `null` if this
- * state does not recognized a keyword.
- */
- Keyword keyword() => _keyword;
-
- /**
- * Return the state that follows this state on a transition of the given
- * [character], or `null` if there is no valid state reachable from this state
- * with such a transition.
- */
- KeywordState next(int character) => _table[character - 0x61];
-
- /**
- * Create the next state in the state machine where we have already recognized
- * the subset of strings in the given array of [strings] starting at the given
- * [offset] and having the given [length]. All of these strings have a common
- * prefix and the next character is at the given [start] index.
- */
- static KeywordState _computeKeywordStateTable(
- int start, List<String> strings, int offset, int length) {
- List<KeywordState> result = new List<KeywordState>(26);
- assert(length != 0);
- int chunk = 0x0;
- int chunkStart = -1;
- bool isLeaf = false;
- for (int i = offset; i < offset + length; i++) {
- if (strings[i].length == start) {
- isLeaf = true;
- }
- if (strings[i].length > start) {
- int c = strings[i].codeUnitAt(start);
- if (chunk != c) {
- if (chunkStart != -1) {
- result[chunk - 0x61] = _computeKeywordStateTable(
- start + 1, strings, chunkStart, i - chunkStart);
- }
- chunkStart = i;
- chunk = c;
- }
- }
- }
- if (chunkStart != -1) {
- assert(result[chunk - 0x61] == null);
- result[chunk - 0x61] = _computeKeywordStateTable(
- start + 1, strings, chunkStart, offset + length - chunkStart);
- } else {
- assert(length == 1);
- return new KeywordState(_EMPTY_TABLE, strings[offset]);
- }
- if (isLeaf) {
- return new KeywordState(result, strings[offset]);
- } else {
- return new KeywordState(result, null);
- }
- }
-
- /**
- * Create and return the initial state in the state machine.
- */
- static KeywordState _createKeywordStateTable() {
- List<Keyword> values = Keyword.values;
- List<String> strings = new List<String>(values.length);
- for (int i = 0; i < values.length; i++) {
- strings[i] = values[i].syntax;
- }
- strings.sort();
- return _computeKeywordStateTable(0, strings, 0, strings.length);
- }
-}
-
-/**
- * A token representing a keyword in the language.
- */
-class KeywordToken extends Token {
- /**
- * The keyword being represented by this token.
- */
- final Keyword keyword;
-
- /**
- * Initialize a newly created token to represent the given [keyword] at the
- * given [offset].
- */
- KeywordToken(this.keyword, int offset) : super(TokenType.KEYWORD, offset);
-
- @override
- String get lexeme => keyword.syntax;
-
- @override
- Token copy() => new KeywordToken(keyword, offset);
-
- @override
- Keyword value() => keyword;
-}
-
-/**
- * A keyword token that is preceded by comments.
- */
-class KeywordTokenWithComment extends KeywordToken {
- /**
- * The first comment in the list of comments that precede this token.
- */
- CommentToken _precedingComment;
-
- /**
- * Initialize a newly created token to to represent the given [keyword] at the
- * given [offset] and to be preceded by the comments reachable from the given
- * [comment].
- */
- KeywordTokenWithComment(Keyword keyword, int offset, this._precedingComment)
- : super(keyword, offset) {
- _setCommentParent(_precedingComment);
- }
-
- CommentToken get precedingComments => _precedingComment;
-
- void set precedingComments(CommentToken comment) {
- _precedingComment = comment;
- _setCommentParent(_precedingComment);
- }
-
- @override
- void applyDelta(int delta) {
- super.applyDelta(delta);
- Token token = precedingComments;
- while (token != null) {
- token.applyDelta(delta);
- token = token.next;
- }
- }
-
- @override
- Token copy() => new KeywordTokenWithComment(
- keyword, offset, copyComments(precedingComments));
-}
-
-/**
- * The class `Scanner` implements a scanner for Dart code.
- *
- * The lexical structure of Dart is ambiguous without knowledge of the context
- * in which a token is being scanned. For example, without context we cannot
- * determine whether source of the form "<<" should be scanned as a single
- * left-shift operator or as two left angle brackets. This scanner does not have
- * any context, so it always resolves such conflicts by scanning the longest
- * possible token.
- */
-class Scanner {
- /**
- * The source being scanned.
- */
- final Source source;
-
- /**
- * The reader used to access the characters in the source.
- */
- final CharacterReader _reader;
-
- /**
- * The error listener that will be informed of any errors that are found
- * during the scan.
- */
- final AnalysisErrorListener _errorListener;
-
- /**
- * The flag specifying whether documentation comments should be parsed.
- */
- bool _preserveComments = true;
-
- /**
- * The token pointing to the head of the linked list of tokens.
- */
- Token _tokens;
-
- /**
- * The last token that was scanned.
- */
- Token _tail;
-
- /**
- * The first token in the list of comment tokens found since the last
- * non-comment token.
- */
- Token _firstComment;
-
- /**
- * The last token in the list of comment tokens found since the last
- * non-comment token.
- */
- Token _lastComment;
-
- /**
- * The index of the first character of the current token.
- */
- int _tokenStart = 0;
-
- /**
- * A list containing the offsets of the first character of each line in the
- * source code.
- */
- List<int> _lineStarts = new List<int>();
-
- /**
- * A list, treated something like a stack, of tokens representing the
- * beginning of a matched pair. It is used to pair the end tokens with the
- * begin tokens.
- */
- List<BeginToken> _groupingStack = new List<BeginToken>();
-
- /**
- * The index of the last item in the [_groupingStack], or `-1` if the stack is
- * empty.
- */
- int _stackEnd = -1;
-
- /**
- * A flag indicating whether any unmatched groups were found during the parse.
- */
- bool _hasUnmatchedGroups = false;
-
- /**
- * A flag indicating whether to parse generic method comments, of the form
- * `/*=T*/` and `/*<T>*/`.
- */
- bool scanGenericMethodComments = false;
-
- /**
- * Initialize a newly created scanner to scan characters from the given
- * [source]. The given character [_reader] will be used to read the characters
- * in the source. The given [_errorListener] will be informed of any errors
- * that are found.
- */
- Scanner(this.source, this._reader, this._errorListener) {
- _tokens = new Token(TokenType.EOF, -1);
- _tokens.setNext(_tokens);
- _tail = _tokens;
- _tokenStart = -1;
- _lineStarts.add(0);
- }
-
- /**
- * Return the first token in the token stream that was scanned.
- */
- Token get firstToken => _tokens.next;
-
- /**
- * Return `true` if any unmatched groups were found during the parse.
- */
- bool get hasUnmatchedGroups => _hasUnmatchedGroups;
-
- /**
- * Return an array containing the offsets of the first character of each line
- * in the source code.
- */
- List<int> get lineStarts => _lineStarts;
-
- /**
- * Set whether documentation tokens should be preserved.
- */
- void set preserveComments(bool preserveComments) {
- this._preserveComments = preserveComments;
- }
-
- /**
- * Return the last token that was scanned.
- */
- Token get tail => _tail;
-
- /**
- * Append the given [token] to the end of the token stream being scanned. This
- * method is intended to be used by subclasses that copy existing tokens and
- * should not normally be used because it will fail to correctly associate any
- * comments with the token being passed in.
- */
- void appendToken(Token token) {
- _tail = _tail.setNext(token);
- }
-
- int bigSwitch(int next) {
- _beginToken();
- if (next == 0xD) {
- // '\r'
- next = _reader.advance();
- if (next == 0xA) {
- // '\n'
- next = _reader.advance();
- }
- recordStartOfLine();
- return next;
- } else if (next == 0xA) {
- // '\n'
- next = _reader.advance();
- recordStartOfLine();
- return next;
- } else if (next == 0x9 || next == 0x20) {
- // '\t' || ' '
- return _reader.advance();
- }
- if (next == 0x72) {
- // 'r'
- int peek = _reader.peek();
- if (peek == 0x22 || peek == 0x27) {
- // '"' || "'"
- int start = _reader.offset;
- return _tokenizeString(_reader.advance(), start, true);
- }
- }
- if (0x61 <= next && next <= 0x7A) {
- // 'a'-'z'
- return _tokenizeKeywordOrIdentifier(next, true);
- }
- if ((0x41 <= next && next <= 0x5A) || next == 0x5F || next == 0x24) {
- // 'A'-'Z' || '_' || '$'
- return _tokenizeIdentifier(next, _reader.offset, true);
- }
- if (next == 0x3C) {
- // '<'
- return _tokenizeLessThan(next);
- }
- if (next == 0x3E) {
- // '>'
- return _tokenizeGreaterThan(next);
- }
- if (next == 0x3D) {
- // '='
- return _tokenizeEquals(next);
- }
- if (next == 0x21) {
- // '!'
- return _tokenizeExclamation(next);
- }
- if (next == 0x2B) {
- // '+'
- return _tokenizePlus(next);
- }
- if (next == 0x2D) {
- // '-'
- return _tokenizeMinus(next);
- }
- if (next == 0x2A) {
- // '*'
- return _tokenizeMultiply(next);
- }
- if (next == 0x25) {
- // '%'
- return _tokenizePercent(next);
- }
- if (next == 0x26) {
- // '&'
- return _tokenizeAmpersand(next);
- }
- if (next == 0x7C) {
- // '|'
- return _tokenizeBar(next);
- }
- if (next == 0x5E) {
- // '^'
- return _tokenizeCaret(next);
- }
- if (next == 0x5B) {
- // '['
- return _tokenizeOpenSquareBracket(next);
- }
- if (next == 0x7E) {
- // '~'
- return _tokenizeTilde(next);
- }
- if (next == 0x5C) {
- // '\\'
- _appendTokenOfType(TokenType.BACKSLASH);
- return _reader.advance();
- }
- if (next == 0x23) {
- // '#'
- return _tokenizeTag(next);
- }
- if (next == 0x28) {
- // '('
- _appendBeginToken(TokenType.OPEN_PAREN);
- return _reader.advance();
- }
- if (next == 0x29) {
- // ')'
- _appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN);
- return _reader.advance();
- }
- if (next == 0x2C) {
- // ','
- _appendTokenOfType(TokenType.COMMA);
- return _reader.advance();
- }
- if (next == 0x3A) {
- // ':'
- _appendTokenOfType(TokenType.COLON);
- return _reader.advance();
- }
- if (next == 0x3B) {
- // ';'
- _appendTokenOfType(TokenType.SEMICOLON);
- return _reader.advance();
- }
- if (next == 0x3F) {
- // '?'
- return _tokenizeQuestion();
- }
- if (next == 0x5D) {
- // ']'
- _appendEndToken(
- TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACKET);
- return _reader.advance();
- }
- if (next == 0x60) {
- // '`'
- _appendTokenOfType(TokenType.BACKPING);
- return _reader.advance();
- }
- if (next == 0x7B) {
- // '{'
- _appendBeginToken(TokenType.OPEN_CURLY_BRACKET);
- return _reader.advance();
- }
- if (next == 0x7D) {
- // '}'
- _appendEndToken(
- TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
- return _reader.advance();
- }
- if (next == 0x2F) {
- // '/'
- return _tokenizeSlashOrComment(next);
- }
- if (next == 0x40) {
- // '@'
- _appendTokenOfType(TokenType.AT);
- return _reader.advance();
- }
- if (next == 0x22 || next == 0x27) {
- // '"' || "'"
- return _tokenizeString(next, _reader.offset, false);
- }
- if (next == 0x2E) {
- // '.'
- return _tokenizeDotOrNumber(next);
- }
- if (next == 0x30) {
- // '0'
- return _tokenizeHexOrNumber(next);
- }
- if (0x31 <= next && next <= 0x39) {
- // '1'-'9'
- return _tokenizeNumber(next);
- }
- if (next == -1) {
- // EOF
- return -1;
- }
- _reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]);
- return _reader.advance();
- }
-
- /**
- * Record the fact that we are at the beginning of a new line in the source.
- */
- void recordStartOfLine() {
- _lineStarts.add(_reader.offset);
- }
-
- /**
- * Record that the source begins on the given [line] and [column] at the
- * current offset as given by the reader. Both the line and the column are
- * one-based indexes. The line starts for lines before the given line will not
- * be correct.
- *
- * This method must be invoked at most one time and must be invoked before
- * scanning begins. The values provided must be sensible. The results are
- * undefined if these conditions are violated.
- */
- void setSourceStart(int line, int column) {
- int offset = _reader.offset;
- if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
- return;
- }
- for (int i = 2; i < line; i++) {
- _lineStarts.add(1);
- }
- _lineStarts.add(offset - column + 1);
- }
-
- /**
- * Scan the source code to produce a list of tokens representing the source,
- * and return the first token in the list of tokens that were produced.
- */
- Token tokenize() {
- int next = _reader.advance();
- while (next != -1) {
- next = bigSwitch(next);
- }
- _appendEofToken();
- return firstToken;
- }
-
- void _appendBeginToken(TokenType type) {
- BeginToken token;
- if (_firstComment == null) {
- token = new BeginToken(type, _tokenStart);
- } else {
- token = new BeginTokenWithComment(type, _tokenStart, _firstComment);
- _firstComment = null;
- _lastComment = null;
- }
- _tail = _tail.setNext(token);
- _groupingStack.add(token);
- _stackEnd++;
- }
-
- void _appendCommentToken(TokenType type, String value) {
- CommentToken token = null;
- TokenType genericComment = _matchGenericMethodCommentType(value);
- if (genericComment != null) {
- token = new CommentToken(genericComment, value, _tokenStart);
- } else if (!_preserveComments) {
- // Ignore comment tokens if client specified that it doesn't need them.
- return;
- } else {
- // OK, remember comment tokens.
- if (_isDocumentationComment(value)) {
- token = new DocumentationCommentToken(type, value, _tokenStart);
- } else {
- token = new CommentToken(type, value, _tokenStart);
- }
- }
- if (_firstComment == null) {
- _firstComment = token;
- _lastComment = _firstComment;
- } else {
- _lastComment = _lastComment.setNext(token);
- }
- }
-
- void _appendEndToken(TokenType type, TokenType beginType) {
- Token token;
- if (_firstComment == null) {
- token = new Token(type, _tokenStart);
- } else {
- token = new TokenWithComment(type, _tokenStart, _firstComment);
- _firstComment = null;
- _lastComment = null;
- }
- _tail = _tail.setNext(token);
- if (_stackEnd >= 0) {
- BeginToken begin = _groupingStack[_stackEnd];
- if (begin.type == beginType) {
- begin.endToken = token;
- _groupingStack.removeAt(_stackEnd--);
- }
- }
- }
-
- void _appendEofToken() {
- Token eofToken;
- if (_firstComment == null) {
- eofToken = new Token(TokenType.EOF, _reader.offset + 1);
- } else {
- eofToken = new TokenWithComment(
- TokenType.EOF, _reader.offset + 1, _firstComment);
- _firstComment = null;
- _lastComment = null;
- }
- // The EOF token points to itself so that there is always infinite
- // look-ahead.
- eofToken.setNext(eofToken);
- _tail = _tail.setNext(eofToken);
- if (_stackEnd >= 0) {
- _hasUnmatchedGroups = true;
- // TODO(brianwilkerson) Fix the ungrouped tokens?
- }
- }
-
- void _appendKeywordToken(Keyword keyword) {
- if (_firstComment == null) {
- _tail = _tail.setNext(new KeywordToken(keyword, _tokenStart));
- } else {
- _tail = _tail.setNext(
- new KeywordTokenWithComment(keyword, _tokenStart, _firstComment));
- _firstComment = null;
- _lastComment = null;
- }
- }
-
- void _appendStringToken(TokenType type, String value) {
- if (_firstComment == null) {
- _tail = _tail.setNext(new StringToken(type, value, _tokenStart));
- } else {
- _tail = _tail.setNext(
- new StringTokenWithComment(type, value, _tokenStart, _firstComment));
- _firstComment = null;
- _lastComment = null;
- }
- }
-
- void _appendStringTokenWithOffset(TokenType type, String value, int offset) {
- if (_firstComment == null) {
- _tail = _tail.setNext(new StringToken(type, value, _tokenStart + offset));
- } else {
- _tail = _tail.setNext(new StringTokenWithComment(
- type, value, _tokenStart + offset, _firstComment));
- _firstComment = null;
- _lastComment = null;
- }
- }
-
- void _appendTokenOfType(TokenType type) {
- if (_firstComment == null) {
- _tail = _tail.setNext(new Token(type, _tokenStart));
- } else {
- _tail =
- _tail.setNext(new TokenWithComment(type, _tokenStart, _firstComment));
- _firstComment = null;
- _lastComment = null;
- }
- }
-
- void _appendTokenOfTypeWithOffset(TokenType type, int offset) {
- if (_firstComment == null) {
- _tail = _tail.setNext(new Token(type, offset));
- } else {
- _tail = _tail.setNext(new TokenWithComment(type, offset, _firstComment));
- _firstComment = null;
- _lastComment = null;
- }
- }
-
- void _beginToken() {
- _tokenStart = _reader.offset;
- }
-
- /**
- * Return the beginning token corresponding to a closing brace that was found
- * while scanning inside a string interpolation expression. Tokens that cannot
- * be matched with the closing brace will be dropped from the stack.
- */
- BeginToken _findTokenMatchingClosingBraceInInterpolationExpression() {
- while (_stackEnd >= 0) {
- BeginToken begin = _groupingStack[_stackEnd];
- if (begin.type == TokenType.OPEN_CURLY_BRACKET ||
- begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
- return begin;
- }
- _hasUnmatchedGroups = true;
- _groupingStack.removeAt(_stackEnd--);
- }
- //
- // We should never get to this point because we wouldn't be inside a string
- // interpolation expression unless we had previously found the start of the
- // expression.
- //
- return null;
- }
-
- /**
- * Checks if [value] is the start of a generic method type annotation comment.
- *
- * This can either be of the form `/*<T>*/` or `/*=T*/`. The token type is
- * returned, or null if it was not a generic method comment.
- */
- TokenType _matchGenericMethodCommentType(String value) {
- if (scanGenericMethodComments) {
- // Match /*< and >*/
- if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3C) &&
- StringUtilities.endsWith3(value, 0x3E, 0x2A, 0x2F)) {
- return TokenType.GENERIC_METHOD_TYPE_LIST;
- }
- // Match /*=
- if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3D)) {
- return TokenType.GENERIC_METHOD_TYPE_ASSIGN;
- }
- }
- return null;
- }
-
- /**
- * Report an error at the current offset. The [errorCode] is the error code
- * indicating the nature of the error. The [arguments] are any arguments
- * needed to complete the error message
- */
- void _reportError(ScannerErrorCode errorCode, [List<Object> arguments]) {
- _errorListener.onError(
- new AnalysisError(source, _reader.offset, 1, errorCode, arguments));
- }
-
- int _select(int choice, TokenType yesType, TokenType noType) {
- int next = _reader.advance();
- if (next == choice) {
- _appendTokenOfType(yesType);
- return _reader.advance();
- } else {
- _appendTokenOfType(noType);
- return next;
- }
- }
-
- int _selectWithOffset(
- int choice, TokenType yesType, TokenType noType, int offset) {
- int next = _reader.advance();
- if (next == choice) {
- _appendTokenOfTypeWithOffset(yesType, offset);
- return _reader.advance();
- } else {
- _appendTokenOfTypeWithOffset(noType, offset);
- return next;
- }
- }
-
- int _tokenizeAmpersand(int next) {
- // && &= &
- next = _reader.advance();
- if (next == 0x26) {
- _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND);
- return _reader.advance();
- } else if (next == 0x3D) {
- _appendTokenOfType(TokenType.AMPERSAND_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.AMPERSAND);
- return next;
- }
- }
-
- int _tokenizeBar(int next) {
- // | || |=
- next = _reader.advance();
- if (next == 0x7C) {
- _appendTokenOfType(TokenType.BAR_BAR);
- return _reader.advance();
- } else if (next == 0x3D) {
- _appendTokenOfType(TokenType.BAR_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.BAR);
- return next;
- }
- }
-
- int _tokenizeCaret(int next) =>
- _select(0x3D, TokenType.CARET_EQ, TokenType.CARET);
-
- int _tokenizeDotOrNumber(int next) {
- int start = _reader.offset;
- next = _reader.advance();
- if (0x30 <= next && next <= 0x39) {
- return _tokenizeFractionPart(next, start);
- } else if (0x2E == next) {
- return _select(
- 0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD);
- } else {
- _appendTokenOfType(TokenType.PERIOD);
- return next;
- }
- }
-
- int _tokenizeEquals(int next) {
- // = == =>
- next = _reader.advance();
- if (next == 0x3D) {
- _appendTokenOfType(TokenType.EQ_EQ);
- return _reader.advance();
- } else if (next == 0x3E) {
- _appendTokenOfType(TokenType.FUNCTION);
- return _reader.advance();
- }
- _appendTokenOfType(TokenType.EQ);
- return next;
- }
-
- int _tokenizeExclamation(int next) {
- // ! !=
- next = _reader.advance();
- if (next == 0x3D) {
- _appendTokenOfType(TokenType.BANG_EQ);
- return _reader.advance();
- }
- _appendTokenOfType(TokenType.BANG);
- return next;
- }
-
- int _tokenizeExponent(int next) {
- if (next == 0x2B || next == 0x2D) {
- next = _reader.advance();
- }
- bool hasDigits = false;
- while (true) {
- if (0x30 <= next && next <= 0x39) {
- hasDigits = true;
- } else {
- if (!hasDigits) {
- _reportError(ScannerErrorCode.MISSING_DIGIT);
- }
- return next;
- }
- next = _reader.advance();
- }
- }
-
- int _tokenizeFractionPart(int next, int start) {
- bool done = false;
- bool hasDigit = false;
- LOOP: while (!done) {
- if (0x30 <= next && next <= 0x39) {
- hasDigit = true;
- } else if (0x65 == next || 0x45 == next) {
- hasDigit = true;
- next = _tokenizeExponent(_reader.advance());
- done = true;
- continue LOOP;
- } else {
- done = true;
- continue LOOP;
- }
- next = _reader.advance();
- }
- if (!hasDigit) {
- _appendStringToken(TokenType.INT, _reader.getString(start, -2));
- if (0x2E == next) {
- return _selectWithOffset(0x2E, TokenType.PERIOD_PERIOD_PERIOD,
- TokenType.PERIOD_PERIOD, _reader.offset - 1);
- }
- _appendTokenOfTypeWithOffset(TokenType.PERIOD, _reader.offset - 1);
- return bigSwitch(next);
- }
- _appendStringToken(
- TokenType.DOUBLE, _reader.getString(start, next < 0 ? 0 : -1));
- return next;
- }
-
- int _tokenizeGreaterThan(int next) {
- // > >= >> >>=
- next = _reader.advance();
- if (0x3D == next) {
- _appendTokenOfType(TokenType.GT_EQ);
- return _reader.advance();
- } else if (0x3E == next) {
- next = _reader.advance();
- if (0x3D == next) {
- _appendTokenOfType(TokenType.GT_GT_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.GT_GT);
- return next;
- }
- } else {
- _appendTokenOfType(TokenType.GT);
- return next;
- }
- }
-
- int _tokenizeHex(int next) {
- int start = _reader.offset - 1;
- bool hasDigits = false;
- while (true) {
- next = _reader.advance();
- if ((0x30 <= next && next <= 0x39) ||
- (0x41 <= next && next <= 0x46) ||
- (0x61 <= next && next <= 0x66)) {
- hasDigits = true;
- } else {
- if (!hasDigits) {
- _reportError(ScannerErrorCode.MISSING_HEX_DIGIT);
- }
- _appendStringToken(
- TokenType.HEXADECIMAL, _reader.getString(start, next < 0 ? 0 : -1));
- return next;
- }
- }
- }
-
- int _tokenizeHexOrNumber(int next) {
- int x = _reader.peek();
- if (x == 0x78 || x == 0x58) {
- _reader.advance();
- return _tokenizeHex(x);
- }
- return _tokenizeNumber(next);
- }
-
- int _tokenizeIdentifier(int next, int start, bool allowDollar) {
- while ((0x61 <= next && next <= 0x7A) ||
- (0x41 <= next && next <= 0x5A) ||
- (0x30 <= next && next <= 0x39) ||
- next == 0x5F ||
- (next == 0x24 && allowDollar)) {
- next = _reader.advance();
- }
- _appendStringToken(
- TokenType.IDENTIFIER, _reader.getString(start, next < 0 ? 0 : -1));
- return next;
- }
-
- int _tokenizeInterpolatedExpression(int next, int start) {
- _appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION);
- next = _reader.advance();
- while (next != -1) {
- if (next == 0x7D) {
- BeginToken begin =
- _findTokenMatchingClosingBraceInInterpolationExpression();
- if (begin == null) {
- _beginToken();
- _appendTokenOfType(TokenType.CLOSE_CURLY_BRACKET);
- next = _reader.advance();
- _beginToken();
- return next;
- } else if (begin.type == TokenType.OPEN_CURLY_BRACKET) {
- _beginToken();
- _appendEndToken(
- TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
- next = _reader.advance();
- _beginToken();
- } else if (begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
- _beginToken();
- _appendEndToken(TokenType.CLOSE_CURLY_BRACKET,
- TokenType.STRING_INTERPOLATION_EXPRESSION);
- next = _reader.advance();
- _beginToken();
- return next;
- }
- } else {
- next = bigSwitch(next);
- }
- }
- return next;
- }
-
- int _tokenizeInterpolatedIdentifier(int next, int start) {
- _appendStringTokenWithOffset(
- TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0);
- if ((0x41 <= next && next <= 0x5A) ||
- (0x61 <= next && next <= 0x7A) ||
- next == 0x5F) {
- _beginToken();
- next = _tokenizeKeywordOrIdentifier(next, false);
- }
- _beginToken();
- return next;
- }
-
- int _tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
- KeywordState state = KeywordState.KEYWORD_STATE;
- int start = _reader.offset;
- while (state != null && 0x61 <= next && next <= 0x7A) {
- state = state.next(next);
- next = _reader.advance();
- }
- if (state == null || state.keyword() == null) {
- return _tokenizeIdentifier(next, start, allowDollar);
- }
- if ((0x41 <= next && next <= 0x5A) ||
- (0x30 <= next && next <= 0x39) ||
- next == 0x5F ||
- next == 0x24) {
- return _tokenizeIdentifier(next, start, allowDollar);
- } else if (next < 128) {
- _appendKeywordToken(state.keyword());
- return next;
- } else {
- return _tokenizeIdentifier(next, start, allowDollar);
- }
- }
-
- int _tokenizeLessThan(int next) {
- // < <= << <<=
- next = _reader.advance();
- if (0x3D == next) {
- _appendTokenOfType(TokenType.LT_EQ);
- return _reader.advance();
- } else if (0x3C == next) {
- return _select(0x3D, TokenType.LT_LT_EQ, TokenType.LT_LT);
- } else {
- _appendTokenOfType(TokenType.LT);
- return next;
- }
- }
-
- int _tokenizeMinus(int next) {
- // - -- -=
- next = _reader.advance();
- if (next == 0x2D) {
- _appendTokenOfType(TokenType.MINUS_MINUS);
- return _reader.advance();
- } else if (next == 0x3D) {
- _appendTokenOfType(TokenType.MINUS_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.MINUS);
- return next;
- }
- }
-
- int _tokenizeMultiLineComment(int next) {
- int nesting = 1;
- next = _reader.advance();
- while (true) {
- if (-1 == next) {
- _reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT);
- _appendCommentToken(
- TokenType.MULTI_LINE_COMMENT, _reader.getString(_tokenStart, 0));
- return next;
- } else if (0x2A == next) {
- next = _reader.advance();
- if (0x2F == next) {
- --nesting;
- if (0 == nesting) {
- _appendCommentToken(TokenType.MULTI_LINE_COMMENT,
- _reader.getString(_tokenStart, 0));
- return _reader.advance();
- } else {
- next = _reader.advance();
- }
- }
- } else if (0x2F == next) {
- next = _reader.advance();
- if (0x2A == next) {
- next = _reader.advance();
- ++nesting;
- }
- } else if (next == 0xD) {
- next = _reader.advance();
- if (next == 0xA) {
- next = _reader.advance();
- }
- recordStartOfLine();
- } else if (next == 0xA) {
- next = _reader.advance();
- recordStartOfLine();
- } else {
- next = _reader.advance();
- }
- }
- }
-
- int _tokenizeMultiLineRawString(int quoteChar, int start) {
- int next = _reader.advance();
- outer: while (next != -1) {
- while (next != quoteChar) {
- if (next == -1) {
- break outer;
- } else if (next == 0xD) {
- next = _reader.advance();
- if (next == 0xA) {
- next = _reader.advance();
- }
- recordStartOfLine();
- } else if (next == 0xA) {
- next = _reader.advance();
- recordStartOfLine();
- } else {
- next = _reader.advance();
- }
- }
- next = _reader.advance();
- if (next == quoteChar) {
- next = _reader.advance();
- if (next == quoteChar) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- }
- }
- }
- _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- }
-
- int _tokenizeMultiLineString(int quoteChar, int start, bool raw) {
- if (raw) {
- return _tokenizeMultiLineRawString(quoteChar, start);
- }
- int next = _reader.advance();
- while (next != -1) {
- if (next == 0x24) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
- next = _tokenizeStringInterpolation(start);
- _beginToken();
- start = _reader.offset;
- continue;
- }
- if (next == quoteChar) {
- next = _reader.advance();
- if (next == quoteChar) {
- next = _reader.advance();
- if (next == quoteChar) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- }
- }
- continue;
- }
- if (next == 0x5C) {
- next = _reader.advance();
- if (next == -1) {
- break;
- }
- if (next == 0xD) {
- next = _reader.advance();
- if (next == 0xA) {
- next = _reader.advance();
- }
- recordStartOfLine();
- } else if (next == 0xA) {
- recordStartOfLine();
- next = _reader.advance();
- } else {
- next = _reader.advance();
- }
- } else if (next == 0xD) {
- next = _reader.advance();
- if (next == 0xA) {
- next = _reader.advance();
- }
- recordStartOfLine();
- } else if (next == 0xA) {
- recordStartOfLine();
- next = _reader.advance();
- } else {
- next = _reader.advance();
- }
- }
- _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
- if (start == _reader.offset) {
- _appendStringTokenWithOffset(TokenType.STRING, "", 1);
- } else {
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- }
- return _reader.advance();
- }
-
- int _tokenizeMultiply(int next) =>
- _select(0x3D, TokenType.STAR_EQ, TokenType.STAR);
-
- int _tokenizeNumber(int next) {
- int start = _reader.offset;
- while (true) {
- next = _reader.advance();
- if (0x30 <= next && next <= 0x39) {
- continue;
- } else if (next == 0x2E) {
- return _tokenizeFractionPart(_reader.advance(), start);
- } else if (next == 0x65 || next == 0x45) {
- return _tokenizeFractionPart(next, start);
- } else {
- _appendStringToken(
- TokenType.INT, _reader.getString(start, next < 0 ? 0 : -1));
- return next;
- }
- }
- }
-
- int _tokenizeOpenSquareBracket(int next) {
- // [ [] []=
- next = _reader.advance();
- if (next == 0x5D) {
- return _select(0x3D, TokenType.INDEX_EQ, TokenType.INDEX);
- } else {
- _appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
- return next;
- }
- }
-
- int _tokenizePercent(int next) =>
- _select(0x3D, TokenType.PERCENT_EQ, TokenType.PERCENT);
-
- int _tokenizePlus(int next) {
- // + ++ +=
- next = _reader.advance();
- if (0x2B == next) {
- _appendTokenOfType(TokenType.PLUS_PLUS);
- return _reader.advance();
- } else if (0x3D == next) {
- _appendTokenOfType(TokenType.PLUS_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.PLUS);
- return next;
- }
- }
-
- int _tokenizeQuestion() {
- // ? ?. ?? ??=
- int next = _reader.advance();
- if (next == 0x2E) {
- // '.'
- _appendTokenOfType(TokenType.QUESTION_PERIOD);
- return _reader.advance();
- } else if (next == 0x3F) {
- // '?'
- next = _reader.advance();
- if (next == 0x3D) {
- // '='
- _appendTokenOfType(TokenType.QUESTION_QUESTION_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.QUESTION_QUESTION);
- return next;
- }
- } else {
- _appendTokenOfType(TokenType.QUESTION);
- return next;
- }
- }
-
- int _tokenizeSingleLineComment(int next) {
- while (true) {
- next = _reader.advance();
- if (-1 == next) {
- _appendCommentToken(
- TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, 0));
- return next;
- } else if (0xA == next || 0xD == next) {
- _appendCommentToken(
- TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, -1));
- return next;
- }
- }
- }
-
- int _tokenizeSingleLineRawString(int next, int quoteChar, int start) {
- next = _reader.advance();
- while (next != -1) {
- if (next == quoteChar) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- } else if (next == 0xD || next == 0xA) {
- _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
- _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
- return _reader.advance();
- }
- next = _reader.advance();
- }
- _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- }
-
- int _tokenizeSingleLineString(int next, int quoteChar, int start) {
- while (next != quoteChar) {
- if (next == 0x5C) {
- next = _reader.advance();
- } else if (next == 0x24) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
- next = _tokenizeStringInterpolation(start);
- _beginToken();
- start = _reader.offset;
- continue;
- }
- if (next <= 0xD && (next == 0xA || next == 0xD || next == -1)) {
- _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
- if (start == _reader.offset) {
- _appendStringTokenWithOffset(TokenType.STRING, "", 1);
- } else if (next == -1) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- } else {
- _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
- }
- return _reader.advance();
- }
- next = _reader.advance();
- }
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- }
-
- int _tokenizeSlashOrComment(int next) {
- next = _reader.advance();
- if (0x2A == next) {
- return _tokenizeMultiLineComment(next);
- } else if (0x2F == next) {
- return _tokenizeSingleLineComment(next);
- } else if (0x3D == next) {
- _appendTokenOfType(TokenType.SLASH_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.SLASH);
- return next;
- }
- }
-
- int _tokenizeString(int next, int start, bool raw) {
- int quoteChar = next;
- next = _reader.advance();
- if (quoteChar == next) {
- next = _reader.advance();
- if (quoteChar == next) {
- // Multiline string.
- return _tokenizeMultiLineString(quoteChar, start, raw);
- } else {
- // Empty string.
- _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
- return next;
- }
- }
- if (raw) {
- return _tokenizeSingleLineRawString(next, quoteChar, start);
- } else {
- return _tokenizeSingleLineString(next, quoteChar, start);
- }
- }
-
- int _tokenizeStringInterpolation(int start) {
- _beginToken();
- int next = _reader.advance();
- if (next == 0x7B) {
- return _tokenizeInterpolatedExpression(next, start);
- } else {
- return _tokenizeInterpolatedIdentifier(next, start);
- }
- }
-
- int _tokenizeTag(int next) {
- // # or #!.*[\n\r]
- if (_reader.offset == 0) {
- if (_reader.peek() == 0x21) {
- do {
- next = _reader.advance();
- } while (next != 0xA && next != 0xD && next > 0);
- _appendStringToken(
- TokenType.SCRIPT_TAG, _reader.getString(_tokenStart, 0));
- return next;
- }
- }
- _appendTokenOfType(TokenType.HASH);
- return _reader.advance();
- }
-
- int _tokenizeTilde(int next) {
- // ~ ~/ ~/=
- next = _reader.advance();
- if (next == 0x2F) {
- return _select(0x3D, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
- } else {
- _appendTokenOfType(TokenType.TILDE);
- return next;
- }
- }
-
- /**
- * Checks if [value] is a single-line or multi-line comment.
- */
- static bool _isDocumentationComment(String value) {
- return StringUtilities.startsWith3(value, 0, 0x2F, 0x2F, 0x2F) ||
- StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x2A);
- }
-}
-
-/**
- * The error codes used for errors detected by the scanner.
- */
-class ScannerErrorCode extends ErrorCode {
- static const ScannerErrorCode ILLEGAL_CHARACTER =
- const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character {0}");
-
- static const ScannerErrorCode MISSING_DIGIT =
- const ScannerErrorCode('MISSING_DIGIT', "Decimal digit expected");
-
- static const ScannerErrorCode MISSING_HEX_DIGIT =
- const ScannerErrorCode('MISSING_HEX_DIGIT', "Hexidecimal digit expected");
-
- static const ScannerErrorCode MISSING_QUOTE =
- const ScannerErrorCode('MISSING_QUOTE', "Expected quote (' or \")");
-
- static const ScannerErrorCode UNABLE_GET_CONTENT = const ScannerErrorCode(
- 'UNABLE_GET_CONTENT', "Unable to get content: {0}");
-
- static const ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT =
- const ScannerErrorCode(
- 'UNTERMINATED_MULTI_LINE_COMMENT', "Unterminated multi-line comment");
-
- static const ScannerErrorCode UNTERMINATED_STRING_LITERAL =
- const ScannerErrorCode(
- 'UNTERMINATED_STRING_LITERAL', "Unterminated string literal");
-
- /**
- * Initialize a newly created error code to have the given [name]. The message
- * associated with the error will be created from the given [message]
- * template. The correction associated with the error will be created from the
- * given [correction] template.
- */
- const ScannerErrorCode(String name, String message, [String correction])
- : super(name, message, correction);
-
- @override
- ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
-
- @override
- ErrorType get type => ErrorType.SYNTACTIC_ERROR;
-}
-
-/**
- * A token whose value is independent of it's type.
- */
-class StringToken extends Token {
- /**
- * The lexeme represented by this token.
- */
- String _value;
-
- /**
- * Initialize a newly created token to represent a token of the given [type]
- * with the given [value] at the given [offset].
- */
- StringToken(TokenType type, String value, int offset) : super(type, offset) {
- this._value = StringUtilities.intern(value);
- }
-
- @override
- String get lexeme => _value;
-
- @override
- Token copy() => new StringToken(type, _value, offset);
-
- @override
- String value() => _value;
-}
-
-/**
- * A string token that is preceded by comments.
- */
-class StringTokenWithComment extends StringToken {
- /**
- * The first comment in the list of comments that precede this token.
- */
- CommentToken _precedingComment;
-
- /**
- * Initialize a newly created token to have the given [type] at the given
- * [offset] and to be preceded by the comments reachable from the given
- * [comment].
- */
- StringTokenWithComment(
- TokenType type, String value, int offset, this._precedingComment)
- : super(type, value, offset) {
- _setCommentParent(_precedingComment);
- }
-
- CommentToken get precedingComments => _precedingComment;
-
- void set precedingComments(CommentToken comment) {
- _precedingComment = comment;
- _setCommentParent(_precedingComment);
- }
-
- @override
- void applyDelta(int delta) {
- super.applyDelta(delta);
- Token token = precedingComments;
- while (token != null) {
- token.applyDelta(delta);
- token = token.next;
- }
- }
-
- @override
- Token copy() => new StringTokenWithComment(
- type, lexeme, offset, copyComments(precedingComments));
-}
-
-/**
- * A [CharacterReader] that reads characters from a character sequence, but adds
- * a delta when reporting the current character offset so that the character
- * sequence can be a subsequence from a larger sequence.
- */
-class SubSequenceReader extends CharSequenceReader {
- /**
- * The offset from the beginning of the file to the beginning of the source
- * being scanned.
- */
- final int _offsetDelta;
-
- /**
- * Initialize a newly created reader to read the characters in the given
- * [sequence]. The [_offsetDelta] is the offset from the beginning of the file
- * to the beginning of the source being scanned
- */
- SubSequenceReader(String sequence, this._offsetDelta) : super(sequence);
-
- @override
- int get offset => _offsetDelta + super.offset;
-
- @override
- void set offset(int offset) {
- super.offset = offset - _offsetDelta;
- }
-
- @override
- String getString(int start, int endDelta) =>
- super.getString(start - _offsetDelta, endDelta);
-}
-
-/**
- * A token whose value is independent of it's type.
- */
-class SyntheticStringToken extends StringToken {
- /**
- * Initialize a newly created token to represent a token of the given [type]
- * with the given [value] at the given [offset].
- */
- SyntheticStringToken(TokenType type, String value, int offset)
- : super(type, value, offset);
-
- @override
- bool get isSynthetic => true;
-}
-
-/**
- * A token that was scanned from the input. Each token knows which tokens
- * precede and follow it, acting as a link in a doubly linked list of tokens.
- */
-class Token {
- /**
- * The type of the token.
- */
- final TokenType type;
-
- /**
- * The offset from the beginning of the file to the first character in the
- * token.
- */
- int offset = 0;
-
- /**
- * The previous token in the token stream.
- */
- Token previous;
-
- /**
- * The next token in the token stream.
- */
- Token _next;
-
- /**
- * Initialize a newly created token to have the given [type] and [offset].
- */
- Token(this.type, this.offset);
-
- /**
- * Return the offset from the beginning of the file to the character after the
- * last character of the token.
- */
- int get end => offset + length;
-
- /**
- * Return `true` if this token represents an operator.
- */
- bool get isOperator => type.isOperator;
-
- /**
- * Return `true` if this token is a synthetic token. A synthetic token is a
- * token that was introduced by the parser in order to recover from an error
- * in the code.
- */
- bool get isSynthetic => length == 0;
-
- /**
- * Return `true` if this token represents an operator that can be defined by
- * users.
- */
- bool get isUserDefinableOperator => type.isUserDefinableOperator;
-
- /**
- * Return the number of characters in the node's source range.
- */
- int get length => lexeme.length;
-
- /**
- * Return the lexeme that represents this token.
- */
- String get lexeme => type.lexeme;
-
- /**
- * Return the next token in the token stream.
- */
- Token get next => _next;
-
- /**
- * Return the first comment in the list of comments that precede this token,
- * or `null` if there are no comments preceding this token. Additional
- * comments can be reached by following the token stream using [next] until
- * `null` is returned.
- *
- * For example, if the original contents were `/* one */ /* two */ id`, then
- * the first preceding comment token will have a lexeme of `/* one */` and
- * the next comment token will have a lexeme of `/* two */`.
- */
- CommentToken get precedingComments => null;
-
- /**
- * Apply (add) the given [delta] to this token's offset.
- */
- void applyDelta(int delta) {
- offset += delta;
- }
-
- /**
- * Return a newly created token that is a copy of this token but that is not a
- * part of any token stream.
- */
- Token copy() => new Token(type, offset);
-
- /**
- * Copy a linked list of comment tokens identical to the given comment tokens.
- */
- Token copyComments(Token token) {
- if (token == null) {
- return null;
- }
- Token head = token.copy();
- Token tail = head;
- token = token.next;
- while (token != null) {
- tail = tail.setNext(token.copy());
- token = token.next;
- }
- return head;
- }
-
- /**
- * Return `true` if this token has any one of the given [types].
- */
- bool matchesAny(List<TokenType> types) {
- for (TokenType type in types) {
- if (this.type == type) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Set the next token in the token stream to the given [token]. This has the
- * side-effect of setting this token to be the previous token for the given
- * token. Return the token that was passed in.
- */
- Token setNext(Token token) {
- _next = token;
- token.previous = this;
- return token;
- }
-
- /**
- * Set the next token in the token stream to the given token without changing
- * which token is the previous token for the given token. Return the token
- * that was passed in.
- */
- Token setNextWithoutSettingPrevious(Token token) {
- _next = token;
- return token;
- }
-
- @override
- String toString() => lexeme;
-
- /**
- * Return the value of this token. For keyword tokens, this is the keyword
- * associated with the token, for other tokens it is the lexeme associated
- * with the token.
- */
- Object value() => type.lexeme;
-
- /**
- * Sets the `parent` property to `this` for the given [comment] and all the
- * next tokens.
- */
- void _setCommentParent(CommentToken comment) {
- while (comment != null) {
- comment.parent = this;
- comment = comment.next;
- }
- }
-
- /**
- * Compare the given [tokens] to find the token that appears first in the
- * source being parsed. That is, return the left-most of all of the tokens.
- * The list must be non-`null`, but the elements of the list are allowed to be
- * `null`. Return the token with the smallest offset, or `null` if the list is
- * empty or if all of the elements of the list are `null`.
- */
- static Token lexicallyFirst(List<Token> tokens) {
- Token first = null;
- int offset = -1;
- for (Token token in tokens) {
- if (token != null && (offset < 0 || token.offset < offset)) {
- first = token;
- offset = token.offset;
- }
- }
- return first;
- }
-}
-
-/**
- * The classes (or groups) of tokens with a similar use.
- */
-class TokenClass {
- /**
- * A value used to indicate that the token type is not part of any specific
- * class of token.
- */
- static const TokenClass NO_CLASS = const TokenClass('NO_CLASS');
-
- /**
- * A value used to indicate that the token type is an additive operator.
- */
- static const TokenClass ADDITIVE_OPERATOR =
- const TokenClass('ADDITIVE_OPERATOR', 13);
-
- /**
- * A value used to indicate that the token type is an assignment operator.
- */
- static const TokenClass ASSIGNMENT_OPERATOR =
- const TokenClass('ASSIGNMENT_OPERATOR', 1);
-
- /**
- * A value used to indicate that the token type is a bitwise-and operator.
- */
- static const TokenClass BITWISE_AND_OPERATOR =
- const TokenClass('BITWISE_AND_OPERATOR', 11);
-
- /**
- * A value used to indicate that the token type is a bitwise-or operator.
- */
- static const TokenClass BITWISE_OR_OPERATOR =
- const TokenClass('BITWISE_OR_OPERATOR', 9);
-
- /**
- * A value used to indicate that the token type is a bitwise-xor operator.
- */
- static const TokenClass BITWISE_XOR_OPERATOR =
- const TokenClass('BITWISE_XOR_OPERATOR', 10);
-
- /**
- * A value used to indicate that the token type is a cascade operator.
- */
- static const TokenClass CASCADE_OPERATOR =
- const TokenClass('CASCADE_OPERATOR', 2);
-
- /**
- * A value used to indicate that the token type is a conditional operator.
- */
- static const TokenClass CONDITIONAL_OPERATOR =
- const TokenClass('CONDITIONAL_OPERATOR', 3);
-
- /**
- * A value used to indicate that the token type is an equality operator.
- */
- static const TokenClass EQUALITY_OPERATOR =
- const TokenClass('EQUALITY_OPERATOR', 7);
-
- /**
- * A value used to indicate that the token type is an if-null operator.
- */
- static const TokenClass IF_NULL_OPERATOR =
- const TokenClass('IF_NULL_OPERATOR', 4);
-
- /**
- * A value used to indicate that the token type is a logical-and operator.
- */
- static const TokenClass LOGICAL_AND_OPERATOR =
- const TokenClass('LOGICAL_AND_OPERATOR', 6);
-
- /**
- * A value used to indicate that the token type is a logical-or operator.
- */
- static const TokenClass LOGICAL_OR_OPERATOR =
- const TokenClass('LOGICAL_OR_OPERATOR', 5);
-
- /**
- * A value used to indicate that the token type is a multiplicative operator.
- */
- static const TokenClass MULTIPLICATIVE_OPERATOR =
- const TokenClass('MULTIPLICATIVE_OPERATOR', 14);
-
- /**
- * A value used to indicate that the token type is a relational operator.
- */
- static const TokenClass RELATIONAL_OPERATOR =
- const TokenClass('RELATIONAL_OPERATOR', 8);
-
- /**
- * A value used to indicate that the token type is a shift operator.
- */
- static const TokenClass SHIFT_OPERATOR =
- const TokenClass('SHIFT_OPERATOR', 12);
-
- /**
- * A value used to indicate that the token type is a unary operator.
- */
- static const TokenClass UNARY_POSTFIX_OPERATOR =
- const TokenClass('UNARY_POSTFIX_OPERATOR', 16);
-
- /**
- * A value used to indicate that the token type is a unary operator.
- */
- static const TokenClass UNARY_PREFIX_OPERATOR =
- const TokenClass('UNARY_PREFIX_OPERATOR', 15);
-
- /**
- * The name of the token class.
- */
- final String name;
-
- /**
- * The precedence of tokens of this class, or `0` if the such tokens do not
- * represent an operator.
- */
- final int precedence;
-
- const TokenClass(this.name, [this.precedence = 0]);
-
- @override
- String toString() => name;
-}
-
-/**
- * The types of tokens that can be returned by the scanner.
- */
-class TokenType {
- /**
- * The type of the token that marks the end of the input.
- */
- static const TokenType EOF = const TokenType_EOF('EOF');
-
- static const TokenType DOUBLE = const TokenType('DOUBLE');
-
- static const TokenType HEXADECIMAL = const TokenType('HEXADECIMAL');
-
- static const TokenType IDENTIFIER = const TokenType('IDENTIFIER');
-
- static const TokenType INT = const TokenType('INT');
-
- static const TokenType KEYWORD = const TokenType('KEYWORD');
-
- static const TokenType MULTI_LINE_COMMENT =
- const TokenType('MULTI_LINE_COMMENT');
-
- static const TokenType SCRIPT_TAG = const TokenType('SCRIPT_TAG');
-
- static const TokenType SINGLE_LINE_COMMENT =
- const TokenType('SINGLE_LINE_COMMENT');
-
- static const TokenType STRING = const TokenType('STRING');
-
- static const TokenType AMPERSAND =
- const TokenType('AMPERSAND', TokenClass.BITWISE_AND_OPERATOR, "&");
-
- static const TokenType AMPERSAND_AMPERSAND = const TokenType(
- 'AMPERSAND_AMPERSAND', TokenClass.LOGICAL_AND_OPERATOR, "&&");
-
- static const TokenType AMPERSAND_EQ =
- const TokenType('AMPERSAND_EQ', TokenClass.ASSIGNMENT_OPERATOR, "&=");
-
- static const TokenType AT = const TokenType('AT', TokenClass.NO_CLASS, "@");
-
- static const TokenType BANG =
- const TokenType('BANG', TokenClass.UNARY_PREFIX_OPERATOR, "!");
-
- static const TokenType BANG_EQ =
- const TokenType('BANG_EQ', TokenClass.EQUALITY_OPERATOR, "!=");
-
- static const TokenType BAR =
- const TokenType('BAR', TokenClass.BITWISE_OR_OPERATOR, "|");
-
- static const TokenType BAR_BAR =
- const TokenType('BAR_BAR', TokenClass.LOGICAL_OR_OPERATOR, "||");
-
- static const TokenType BAR_EQ =
- const TokenType('BAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, "|=");
-
- static const TokenType COLON =
- const TokenType('COLON', TokenClass.NO_CLASS, ":");
-
- static const TokenType COMMA =
- const TokenType('COMMA', TokenClass.NO_CLASS, ",");
-
- static const TokenType CARET =
- const TokenType('CARET', TokenClass.BITWISE_XOR_OPERATOR, "^");
-
- static const TokenType CARET_EQ =
- const TokenType('CARET_EQ', TokenClass.ASSIGNMENT_OPERATOR, "^=");
-
- static const TokenType CLOSE_CURLY_BRACKET =
- const TokenType('CLOSE_CURLY_BRACKET', TokenClass.NO_CLASS, "}");
-
- static const TokenType CLOSE_PAREN =
- const TokenType('CLOSE_PAREN', TokenClass.NO_CLASS, ")");
-
- static const TokenType CLOSE_SQUARE_BRACKET =
- const TokenType('CLOSE_SQUARE_BRACKET', TokenClass.NO_CLASS, "]");
-
- static const TokenType EQ =
- const TokenType('EQ', TokenClass.ASSIGNMENT_OPERATOR, "=");
-
- static const TokenType EQ_EQ =
- const TokenType('EQ_EQ', TokenClass.EQUALITY_OPERATOR, "==");
-
- static const TokenType FUNCTION =
- const TokenType('FUNCTION', TokenClass.NO_CLASS, "=>");
-
- static const TokenType GT =
- const TokenType('GT', TokenClass.RELATIONAL_OPERATOR, ">");
-
- static const TokenType GT_EQ =
- const TokenType('GT_EQ', TokenClass.RELATIONAL_OPERATOR, ">=");
-
- static const TokenType GT_GT =
- const TokenType('GT_GT', TokenClass.SHIFT_OPERATOR, ">>");
-
- static const TokenType GT_GT_EQ =
- const TokenType('GT_GT_EQ', TokenClass.ASSIGNMENT_OPERATOR, ">>=");
-
- static const TokenType HASH =
- const TokenType('HASH', TokenClass.NO_CLASS, "#");
-
- static const TokenType INDEX =
- const TokenType('INDEX', TokenClass.UNARY_POSTFIX_OPERATOR, "[]");
-
- static const TokenType INDEX_EQ =
- const TokenType('INDEX_EQ', TokenClass.UNARY_POSTFIX_OPERATOR, "[]=");
-
- static const TokenType IS =
- const TokenType('IS', TokenClass.RELATIONAL_OPERATOR, "is");
-
- static const TokenType LT =
- const TokenType('LT', TokenClass.RELATIONAL_OPERATOR, "<");
-
- static const TokenType LT_EQ =
- const TokenType('LT_EQ', TokenClass.RELATIONAL_OPERATOR, "<=");
-
- static const TokenType LT_LT =
- const TokenType('LT_LT', TokenClass.SHIFT_OPERATOR, "<<");
-
- static const TokenType LT_LT_EQ =
- const TokenType('LT_LT_EQ', TokenClass.ASSIGNMENT_OPERATOR, "<<=");
-
- static const TokenType MINUS =
- const TokenType('MINUS', TokenClass.ADDITIVE_OPERATOR, "-");
-
- static const TokenType MINUS_EQ =
- const TokenType('MINUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, "-=");
-
- static const TokenType MINUS_MINUS =
- const TokenType('MINUS_MINUS', TokenClass.UNARY_PREFIX_OPERATOR, "--");
-
- static const TokenType OPEN_CURLY_BRACKET =
- const TokenType('OPEN_CURLY_BRACKET', TokenClass.NO_CLASS, "{");
-
- static const TokenType OPEN_PAREN =
- const TokenType('OPEN_PAREN', TokenClass.UNARY_POSTFIX_OPERATOR, "(");
-
- static const TokenType OPEN_SQUARE_BRACKET = const TokenType(
- 'OPEN_SQUARE_BRACKET', TokenClass.UNARY_POSTFIX_OPERATOR, "[");
-
- static const TokenType PERCENT =
- const TokenType('PERCENT', TokenClass.MULTIPLICATIVE_OPERATOR, "%");
-
- static const TokenType PERCENT_EQ =
- const TokenType('PERCENT_EQ', TokenClass.ASSIGNMENT_OPERATOR, "%=");
-
- static const TokenType PERIOD =
- const TokenType('PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, ".");
-
- static const TokenType PERIOD_PERIOD =
- const TokenType('PERIOD_PERIOD', TokenClass.CASCADE_OPERATOR, "..");
-
- static const TokenType PLUS =
- const TokenType('PLUS', TokenClass.ADDITIVE_OPERATOR, "+");
-
- static const TokenType PLUS_EQ =
- const TokenType('PLUS_EQ', TokenClass.ASSIGNMENT_OPERATOR, "+=");
-
- static const TokenType PLUS_PLUS =
- const TokenType('PLUS_PLUS', TokenClass.UNARY_PREFIX_OPERATOR, "++");
-
- static const TokenType QUESTION =
- const TokenType('QUESTION', TokenClass.CONDITIONAL_OPERATOR, "?");
-
- static const TokenType QUESTION_PERIOD = const TokenType(
- 'QUESTION_PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, '?.');
-
- static const TokenType QUESTION_QUESTION =
- const TokenType('QUESTION_QUESTION', TokenClass.IF_NULL_OPERATOR, '??');
-
- static const TokenType QUESTION_QUESTION_EQ = const TokenType(
- 'QUESTION_QUESTION_EQ', TokenClass.ASSIGNMENT_OPERATOR, '??=');
-
- static const TokenType SEMICOLON =
- const TokenType('SEMICOLON', TokenClass.NO_CLASS, ";");
-
- static const TokenType SLASH =
- const TokenType('SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, "/");
-
- static const TokenType SLASH_EQ =
- const TokenType('SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, "/=");
-
- static const TokenType STAR =
- const TokenType('STAR', TokenClass.MULTIPLICATIVE_OPERATOR, "*");
-
- static const TokenType STAR_EQ =
- const TokenType('STAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, "*=");
-
- static const TokenType STRING_INTERPOLATION_EXPRESSION = const TokenType(
- 'STRING_INTERPOLATION_EXPRESSION', TokenClass.NO_CLASS, "\${");
-
- static const TokenType STRING_INTERPOLATION_IDENTIFIER = const TokenType(
- 'STRING_INTERPOLATION_IDENTIFIER', TokenClass.NO_CLASS, "\$");
-
- static const TokenType TILDE =
- const TokenType('TILDE', TokenClass.UNARY_PREFIX_OPERATOR, "~");
-
- static const TokenType TILDE_SLASH =
- const TokenType('TILDE_SLASH', TokenClass.MULTIPLICATIVE_OPERATOR, "~/");
-
- static const TokenType TILDE_SLASH_EQ =
- const TokenType('TILDE_SLASH_EQ', TokenClass.ASSIGNMENT_OPERATOR, "~/=");
-
- static const TokenType BACKPING =
- const TokenType('BACKPING', TokenClass.NO_CLASS, "`");
-
- static const TokenType BACKSLASH =
- const TokenType('BACKSLASH', TokenClass.NO_CLASS, "\\");
-
- static const TokenType PERIOD_PERIOD_PERIOD =
- const TokenType('PERIOD_PERIOD_PERIOD', TokenClass.NO_CLASS, "...");
-
- static const TokenType GENERIC_METHOD_TYPE_LIST =
- const TokenType('GENERIC_METHOD_TYPE_LIST');
-
- static const TokenType GENERIC_METHOD_TYPE_ASSIGN =
- const TokenType('GENERIC_METHOD_TYPE_ASSIGN');
-
- /**
- * The class of the token.
- */
- final TokenClass _tokenClass;
-
- /**
- * The name of the token type.
- */
- final String name;
-
- /**
- * The lexeme that defines this type of token, or `null` if there is more than
- * one possible lexeme for this type of token.
- */
- final String lexeme;
-
- const TokenType(this.name,
- [this._tokenClass = TokenClass.NO_CLASS, this.lexeme = null]);
-
- /**
- * Return `true` if this type of token represents an additive operator.
- */
- bool get isAdditiveOperator => _tokenClass == TokenClass.ADDITIVE_OPERATOR;
-
- /**
- * Return `true` if this type of token represents an assignment operator.
- */
- bool get isAssignmentOperator =>
- _tokenClass == TokenClass.ASSIGNMENT_OPERATOR;
-
- /**
- * Return `true` if this type of token represents an associative operator. An
- * associative operator is an operator for which the following equality is
- * true: `(a * b) * c == a * (b * c)`. In other words, if the result of
- * applying the operator to multiple operands does not depend on the order in
- * which those applications occur.
- *
- * Note: This method considers the logical-and and logical-or operators to be
- * associative, even though the order in which the application of those
- * operators can have an effect because evaluation of the right-hand operand
- * is conditional.
- */
- bool get isAssociativeOperator =>
- this == AMPERSAND ||
- this == AMPERSAND_AMPERSAND ||
- this == BAR ||
- this == BAR_BAR ||
- this == CARET ||
- this == PLUS ||
- this == STAR;
-
- /**
- * Return `true` if this type of token represents an equality operator.
- */
- bool get isEqualityOperator => _tokenClass == TokenClass.EQUALITY_OPERATOR;
-
- /**
- * Return `true` if this type of token represents an increment operator.
- */
- bool get isIncrementOperator =>
- identical(lexeme, "++") || identical(lexeme, "--");
-
- /**
- * Return `true` if this type of token represents a multiplicative operator.
- */
- bool get isMultiplicativeOperator =>
- _tokenClass == TokenClass.MULTIPLICATIVE_OPERATOR;
-
- /**
- * Return `true` if this token type represents an operator.
- */
- bool get isOperator =>
- _tokenClass != TokenClass.NO_CLASS &&
- this != OPEN_PAREN &&
- this != OPEN_SQUARE_BRACKET &&
- this != PERIOD;
-
- /**
- * Return `true` if this type of token represents a relational operator.
- */
- bool get isRelationalOperator =>
- _tokenClass == TokenClass.RELATIONAL_OPERATOR;
-
- /**
- * Return `true` if this type of token represents a shift operator.
- */
- bool get isShiftOperator => _tokenClass == TokenClass.SHIFT_OPERATOR;
-
- /**
- * Return `true` if this type of token represents a unary postfix operator.
- */
- bool get isUnaryPostfixOperator =>
- _tokenClass == TokenClass.UNARY_POSTFIX_OPERATOR;
-
- /**
- * Return `true` if this type of token represents a unary prefix operator.
- */
- bool get isUnaryPrefixOperator =>
- _tokenClass == TokenClass.UNARY_PREFIX_OPERATOR;
-
- /**
- * Return `true` if this token type represents an operator that can be defined
- * by users.
- */
- bool get isUserDefinableOperator =>
- identical(lexeme, "==") ||
- identical(lexeme, "~") ||
- identical(lexeme, "[]") ||
- identical(lexeme, "[]=") ||
- identical(lexeme, "*") ||
- identical(lexeme, "/") ||
- identical(lexeme, "%") ||
- identical(lexeme, "~/") ||
- identical(lexeme, "+") ||
- identical(lexeme, "-") ||
- identical(lexeme, "<<") ||
- identical(lexeme, ">>") ||
- identical(lexeme, ">=") ||
- identical(lexeme, ">") ||
- identical(lexeme, "<=") ||
- identical(lexeme, "<") ||
- identical(lexeme, "&") ||
- identical(lexeme, "^") ||
- identical(lexeme, "|");
-
- /**
- * Return the precedence of the token, or `0` if the token does not represent
- * an operator.
- */
- int get precedence => _tokenClass.precedence;
-
- @override
- String toString() => name;
-}
-
-class TokenType_EOF extends TokenType {
- const TokenType_EOF(String name) : super(name, TokenClass.NO_CLASS, "");
-
- @override
- String toString() => "-eof-";
-}
-
-/**
- * A normal token that is preceded by comments.
- */
-class TokenWithComment extends Token {
- /**
- * The first comment in the list of comments that precede this token.
- */
- CommentToken _precedingComment;
-
- /**
- * Initialize a newly created token to have the given [type] at the given
- * [offset] and to be preceded by the comments reachable from the given
- * [comment].
- */
- TokenWithComment(TokenType type, int offset, this._precedingComment)
- : super(type, offset) {
- _setCommentParent(_precedingComment);
- }
-
- CommentToken get precedingComments => _precedingComment;
-
- void set precedingComments(CommentToken comment) {
- _precedingComment = comment;
- _setCommentParent(_precedingComment);
- }
-
- @override
- Token copy() => new TokenWithComment(type, offset, precedingComments);
-}
+export 'package:analyzer/dart/ast/token.dart';
+export 'package:analyzer/src/dart/ast/token.dart' hide SimpleToken;
+export 'package:analyzer/src/dart/scanner/scanner.dart';
+export 'package:analyzer/src/dart/scanner/reader.dart';
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart
index a2b6325..51c6ccc 100644
--- a/pkg/analyzer/lib/src/generated/sdk.dart
+++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -8,34 +8,40 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/generated/engine.dart'
+ show AnalysisContext, AnalysisOptions;
import 'package:analyzer/src/generated/source.dart'
show ContentCache, Source, UriKind;
/**
+ * A function used to create a new DartSdk
+ */
+typedef DartSdk SdkCreator();
+
+/**
* A Dart SDK installed in a specified location.
*/
abstract class DartSdk {
/**
* The short name of the dart SDK 'async' library.
*/
- static final String DART_ASYNC = "dart:async";
+ static const String DART_ASYNC = "dart:async";
/**
* The short name of the dart SDK 'core' library.
*/
- static final String DART_CORE = "dart:core";
+ static const String DART_CORE = "dart:core";
/**
* The short name of the dart SDK 'html' library.
*/
- static final String DART_HTML = "dart:html";
+ static const String DART_HTML = "dart:html";
/**
* The version number that is returned when the real version number could not
* be determined.
*/
- static final String DEFAULT_VERSION = "0";
+ static const String DEFAULT_VERSION = "0";
/**
* Return the analysis context used for all of the sources in this [DartSdk].
@@ -79,6 +85,56 @@
}
/**
+ * Manages the DartSdk's that have been created. Clients need to create multiple
+ * SDKs when the analysis options associated with those SDK's contexts will
+ * produce different analysis results.
+ */
+class DartSdkManager {
+ /**
+ * The function used to create new SDK's.
+ */
+ final SdkCreator sdkCreator;
+
+ /**
+ * A table mapping (an encoding of) analysis options to the SDK that has been
+ * configured with those options.
+ */
+ Map<int, DartSdk> sdkMap = new HashMap<int, DartSdk>();
+
+ /**
+ * Initialize a newly created manager.
+ */
+ DartSdkManager(this.sdkCreator);
+
+ /**
+ * Return any SDK that has been created, or `null` if no SDKs have been
+ * created.
+ */
+ DartSdk get anySdk {
+ if (sdkMap.isEmpty) {
+ return null;
+ }
+ return sdkMap.values.first;
+ }
+
+ /**
+ * Return the Dart SDK that is appropriate for the given analysis [options].
+ * If such an SDK has not yet been created, then the [sdkCreator] will be
+ * invoked to create it.
+ */
+ DartSdk getSdkForOptions(AnalysisOptions options) {
+ int encoding = options.encodeCrossContextOptions();
+ DartSdk sdk = sdkMap[encoding];
+ if (sdk == null) {
+ sdk = sdkCreator();
+ sdkMap[encoding] = sdk;
+ sdk.context.analysisOptions.setCrossContextOptionsFrom(options);
+ }
+ return sdk;
+ }
+}
+
+/**
* A map from Dart library URI's to the [SdkLibraryImpl] representing that
* library.
*/
@@ -224,7 +280,7 @@
library.category =
convertCategories((expression as StringLiteral).stringValue);
} else if (name == _IMPLEMENTATION) {
- library.implementation = (expression as BooleanLiteral).value;
+ library._implementation = (expression as BooleanLiteral).value;
} else if (name == _DOCUMENTED) {
library.documented = (expression as BooleanLiteral).value;
} else if (name == _PLATFORMS) {
@@ -364,13 +420,6 @@
this._documented = documented;
}
- /**
- * Set whether the library is an implementation library.
- */
- void set implementation(bool implementation) {
- this._implementation = implementation;
- }
-
@override
bool get isDart2JsLibrary => (_platforms & DART2JS_PLATFORM) != 0;
@@ -381,7 +430,7 @@
bool get isImplementation => _implementation;
@override
- bool get isInternal => "Internal" == category;
+ bool get isInternal => category == "Internal";
@override
bool get isShared => category == "Shared";
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index 8cdb8f2..6a1e38d 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -9,6 +9,8 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_core.dart';
@@ -16,7 +18,6 @@
import 'package:analyzer/src/generated/java_engine_io.dart';
import 'package:analyzer/src/generated/java_io.dart';
import 'package:analyzer/src/generated/parser.dart';
-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/idl.dart' show SdkBundle;
@@ -207,6 +208,11 @@
JavaFile _libraryDirectory;
/**
+ * The flag that specifies whether SDK summary should be used.
+ */
+ bool _useSummary = false;
+
+ /**
* The revision number of this SDK, or `"0"` if the revision number cannot be
* discovered.
*/
@@ -259,10 +265,12 @@
SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
_analysisContext.sourceFactory = factory;
// Try to use summaries.
- SdkBundle sdkBundle = _getSummarySdkBundle();
- if (sdkBundle != null) {
- _analysisContext.resultProvider =
- new SdkSummaryResultProvider(_analysisContext, sdkBundle);
+ if (_useSummary) {
+ SdkBundle sdkBundle = _getSummarySdkBundle();
+ if (sdkBundle != null) {
+ _analysisContext.resultProvider =
+ new SdkSummaryResultProvider(_analysisContext, sdkBundle);
+ }
}
}
return _analysisContext;
@@ -390,6 +398,17 @@
List<String> get uris => _libraryMap.uris;
/**
+ * Specify whether SDK summary should be used. This property can only be set
+ * before [context] is invoked.
+ */
+ void set useSummary(bool use) {
+ if (_analysisContext != null) {
+ throw new StateError('SDK analysis context has been already created.');
+ }
+ _useSummary = use;
+ }
+
+ /**
* Return the name of the file containing the VM executable.
*/
String get vmBinaryName {
@@ -538,7 +557,7 @@
*/
SdkBundle _getSummarySdkBundle() {
String rootPath = directory.getAbsolutePath();
- String path = pathos.join(rootPath, 'lib', '_internal', 'analysis_summary');
+ String path = pathos.join(rootPath, 'lib', '_internal', 'spec.sum');
try {
File file = new File(path);
if (file.existsSync()) {
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index fa2bf1c..4a2362f 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -7,6 +7,7 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -14,8 +15,6 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-import 'package:analyzer/src/generated/scanner.dart' as sc;
import 'package:analyzer/src/generated/utilities_dart.dart';
/**
@@ -238,8 +237,8 @@
*/
@override
Object visitAssignmentExpression(AssignmentExpression node) {
- sc.TokenType operator = node.operator.type;
- if (operator == sc.TokenType.EQ) {
+ TokenType operator = node.operator.type;
+ if (operator == TokenType.EQ) {
Expression rightHandSide = node.rightHandSide;
DartType staticType = _getStaticType(rightHandSide);
_recordStaticType(node, staticType);
@@ -250,7 +249,7 @@
overrideType = propagatedType;
}
_resolver.overrideExpression(node.leftHandSide, overrideType, true, true);
- } else if (operator == sc.TokenType.QUESTION_QUESTION_EQ) {
+ } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
// The static type of a compound assignment using ??= is the least upper
// bound of the static types of the LHS and RHS.
_analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide);
@@ -477,11 +476,16 @@
DartType functionType = InferenceContext.getType(node);
if (functionType is FunctionType) {
- DartType returnType = functionType.returnType;
- if (computedType.isDynamic &&
- !(returnType.isDynamic || returnType.isBottom)) {
- computedType = returnType;
- _resolver.inferenceContext.recordInference(node, functionType);
+ functionType = _resolver.matchFunctionTypeParameters(
+ node.typeParameters, functionType);
+
+ if (functionType is FunctionType) {
+ DartType returnType = functionType.returnType;
+ if (computedType.isDynamic &&
+ !(returnType.isDynamic || returnType.isBottom)) {
+ computedType = returnType;
+ _resolver.inferenceContext.recordInference(node, functionType);
+ }
}
}
}
@@ -968,9 +972,8 @@
Object visitPostfixExpression(PostfixExpression node) {
Expression operand = node.operand;
DartType staticType = _getStaticType(operand);
- sc.TokenType operator = node.operator.type;
- if (operator == sc.TokenType.MINUS_MINUS ||
- operator == sc.TokenType.PLUS_PLUS) {
+ TokenType operator = node.operator.type;
+ if (operator == TokenType.MINUS_MINUS || operator == TokenType.PLUS_PLUS) {
DartType intType = _typeProvider.intType;
if (identical(_getStaticType(node.operand), intType)) {
staticType = intType;
@@ -1070,15 +1073,15 @@
*/
@override
Object visitPrefixExpression(PrefixExpression node) {
- sc.TokenType operator = node.operator.type;
- if (operator == sc.TokenType.BANG) {
+ TokenType operator = node.operator.type;
+ if (operator == TokenType.BANG) {
_recordStaticType(node, _typeProvider.boolType);
} else {
// The other cases are equivalent to invoking a method.
ExecutableElement staticMethodElement = node.staticElement;
DartType staticType = _computeStaticReturnType(staticMethodElement);
- if (operator == sc.TokenType.MINUS_MINUS ||
- operator == sc.TokenType.PLUS_PLUS) {
+ if (operator == TokenType.MINUS_MINUS ||
+ operator == TokenType.PLUS_PLUS) {
DartType intType = _typeProvider.intType;
if (identical(_getStaticType(node.operand), intType)) {
staticType = intType;
@@ -1535,14 +1538,11 @@
// TODO(vsm): Use leafp's matchType here?
DartType _findIteratedType(DartType type, DartType targetType) {
// Set by _find if match is found
- DartType result = null;
+ DartType result;
// Elements we've already visited on a given inheritance path.
- HashSet<ClassElement> visitedClasses = null;
+ HashSet<ClassElement> visitedClasses;
- while (type is TypeParameterType) {
- TypeParameterElement element = type.element;
- type = element.bound;
- }
+ type = type.resolveToBound(_typeProvider.objectType);
bool _find(InterfaceType type) {
ClassElement element = type.element;
@@ -1817,6 +1817,21 @@
return false;
}
+ /**
+ * Given an uninstantiated generic type, try to infer the instantiated generic
+ * type from the surrounding context.
+ */
+ DartType _inferGenericInstantiationFromContext(
+ DartType context, DartType type) {
+ TypeSystem ts = _typeSystem;
+ if (context is FunctionType &&
+ type is FunctionType &&
+ ts is StrongTypeSystemImpl) {
+ return ts.inferFunctionTypeInstantiation(_typeProvider, context, type);
+ }
+ return type;
+ }
+
FunctionType _inferGenericInvoke(FunctionType invokeType, FunctionType fnType,
TypeArgumentList typeArguments, ArgumentList argumentList) {
TypeSystem ts = _typeSystem;
@@ -1895,21 +1910,6 @@
}
/**
- * Given an uninstantiated generic type, try to infer the instantiated generic
- * type from the surrounding context.
- */
- DartType _inferGenericInstantiationFromContext(
- DartType context, DartType type) {
- TypeSystem ts = _typeSystem;
- if (context is FunctionType &&
- type is FunctionType &&
- ts is StrongTypeSystemImpl) {
- return ts.inferFunctionTypeInstantiation(_typeProvider, context, type);
- }
- return type;
- }
-
- /**
* Given a method invocation [node], attempt to infer a better
* type for the result if it is an inline JS invocation
*/
@@ -2119,32 +2119,32 @@
DartType _refineBinaryExpressionType(
BinaryExpression expression, DartType currentType,
[DartType typeAccessor(Expression node)]) {
- sc.TokenType operator = expression.operator.type;
+ TokenType operator = expression.operator.type;
// bool
- if (operator == sc.TokenType.AMPERSAND_AMPERSAND ||
- operator == sc.TokenType.BAR_BAR ||
- operator == sc.TokenType.EQ_EQ ||
- operator == sc.TokenType.BANG_EQ) {
+ if (operator == TokenType.AMPERSAND_AMPERSAND ||
+ operator == TokenType.BAR_BAR ||
+ operator == TokenType.EQ_EQ ||
+ operator == TokenType.BANG_EQ) {
return _typeProvider.boolType;
}
DartType intType = _typeProvider.intType;
if (typeAccessor(expression.leftOperand) == intType) {
// int op double
- if (operator == sc.TokenType.MINUS ||
- operator == sc.TokenType.PERCENT ||
- operator == sc.TokenType.PLUS ||
- operator == sc.TokenType.STAR) {
+ if (operator == TokenType.MINUS ||
+ operator == TokenType.PERCENT ||
+ operator == TokenType.PLUS ||
+ operator == TokenType.STAR) {
DartType doubleType = _typeProvider.doubleType;
if (typeAccessor(expression.rightOperand) == doubleType) {
return doubleType;
}
}
// int op int
- if (operator == sc.TokenType.MINUS ||
- operator == sc.TokenType.PERCENT ||
- operator == sc.TokenType.PLUS ||
- operator == sc.TokenType.STAR ||
- operator == sc.TokenType.TILDE_SLASH) {
+ if (operator == TokenType.MINUS ||
+ operator == TokenType.PERCENT ||
+ operator == TokenType.PLUS ||
+ operator == TokenType.STAR ||
+ operator == TokenType.TILDE_SLASH) {
if (typeAccessor(expression.rightOperand) == intType) {
return intType;
}
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
index 7e697eb..d8d44f4 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
@@ -5,9 +5,9 @@
library analyzer.src.generated.testing.ast_factory;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 72d8acf..b94cb64 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -7,6 +7,7 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
@@ -15,7 +16,6 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/testing/ast_factory.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -202,7 +202,8 @@
}
static FieldElementImpl fieldElement(
- String name, bool isStatic, bool isFinal, bool isConst, DartType type) {
+ String name, bool isStatic, bool isFinal, bool isConst, DartType type,
+ {Expression initializer}) {
FieldElementImpl field = isConst
? new ConstFieldElementImpl(name, 0)
: new FieldElementImpl(name, 0);
@@ -210,6 +211,9 @@
field.final2 = isFinal;
field.static = isStatic;
field.type = type;
+ if (isConst) {
+ (field as ConstFieldElementImpl).constantInitializer = initializer;
+ }
PropertyAccessorElementImpl getter =
new PropertyAccessorElementImpl.forVariable(field);
getter.getter = true;
@@ -496,6 +500,16 @@
return parameter;
}
+ static ParameterElementImpl namedParameter3(String name,
+ {DartType type, Expression initializer}) {
+ DefaultParameterElementImpl parameter =
+ new DefaultParameterElementImpl(name, 0);
+ parameter.parameterKind = ParameterKind.NAMED;
+ parameter.type = type;
+ parameter.constantInitializer = initializer;
+ return parameter;
+ }
+
static ParameterElementImpl positionalParameter(String name) {
ParameterElementImpl parameter = new ParameterElementImpl(name, 0);
parameter.parameterKind = ParameterKind.POSITIONAL;
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index b3aaea8..48c4f98 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -5,6 +5,7 @@
library analyzer.src.generated.testing.test_type_provider;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
@@ -12,7 +13,6 @@
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:analyzer/src/generated/source.dart' show Source;
import 'package:analyzer/src/generated/testing/ast_factory.dart';
@@ -170,7 +170,8 @@
.constructorElement(boolElement, "fromEnvironment", true);
fromEnvironment.parameters = <ParameterElement>[
ElementFactory.requiredParameter2("name", stringType),
- ElementFactory.namedParameter2("defaultValue", _boolType)
+ ElementFactory.namedParameter3("defaultValue",
+ type: _boolType, initializer: AstFactory.booleanLiteral(false))
];
fromEnvironment.factory = true;
fromEnvironment.isCycleFree = true;
@@ -195,7 +196,9 @@
FieldElementImpl expiresField = ElementFactory.fieldElement(
'expires', false, true, false, stringType);
deprecatedElement.fields = <FieldElement>[expiresField];
- deprecatedElement.accessors = <PropertyAccessorElement>[expiresField.getter];
+ deprecatedElement.accessors = <PropertyAccessorElement>[
+ expiresField.getter
+ ];
ConstructorElementImpl constructor = ElementFactory
.constructorElement(deprecatedElement, '', true, [stringType]);
(constructor.parameters[0] as ParameterElementImpl).name = 'expires';
@@ -492,7 +495,7 @@
.constructorElement(stringElement, "fromEnvironment", true);
fromEnvironment.parameters = <ParameterElement>[
ElementFactory.requiredParameter2("name", stringType),
- ElementFactory.namedParameter2("defaultValue", _stringType)
+ ElementFactory.namedParameter3("defaultValue", type: _stringType)
];
fromEnvironment.factory = true;
fromEnvironment.isCycleFree = true;
@@ -610,7 +613,7 @@
ElementFactory.constructorElement(intElement, "fromEnvironment", true);
fromEnvironment.parameters = <ParameterElement>[
ElementFactory.requiredParameter2("name", stringType),
- ElementFactory.namedParameter2("defaultValue", _intType)
+ ElementFactory.namedParameter3("defaultValue", type: _intType)
];
fromEnvironment.factory = true;
fromEnvironment.isCycleFree = true;
@@ -623,18 +626,23 @@
ElementFactory.constructorElement(doubleElement, null, false)
..synthetic = true
];
- ConstFieldElementImpl varINFINITY =
- ElementFactory.fieldElement("INFINITY", true, false, true, _doubleType);
+ ConstFieldElementImpl varINFINITY = ElementFactory.fieldElement(
+ "INFINITY", true, false, true, _doubleType,
+ initializer: AstFactory.doubleLiteral(double.INFINITY));
varINFINITY.constantInitializer = AstFactory.binaryExpression(
AstFactory.integer(1), TokenType.SLASH, AstFactory.integer(0));
List<FieldElement> fields = <FieldElement>[
- ElementFactory.fieldElement("NAN", true, false, true, _doubleType),
+ ElementFactory.fieldElement("NAN", true, false, true, _doubleType,
+ initializer: AstFactory.doubleLiteral(double.NAN)),
varINFINITY,
ElementFactory.fieldElement(
- "NEGATIVE_INFINITY", true, false, true, _doubleType),
+ "NEGATIVE_INFINITY", true, false, true, _doubleType,
+ initializer: AstFactory.doubleLiteral(double.NEGATIVE_INFINITY)),
ElementFactory.fieldElement(
- "MIN_POSITIVE", true, false, true, _doubleType),
- ElementFactory.fieldElement("MAX_FINITE", true, false, true, _doubleType)
+ "MIN_POSITIVE", true, false, true, _doubleType,
+ initializer: AstFactory.doubleLiteral(double.MIN_POSITIVE)),
+ ElementFactory.fieldElement("MAX_FINITE", true, false, true, _doubleType,
+ initializer: AstFactory.doubleLiteral(double.MAX_FINITE))
];
doubleElement.fields = fields;
int fieldCount = fields.length;
diff --git a/pkg/analyzer/lib/src/generated/testing/token_factory.dart b/pkg/analyzer/lib/src/generated/testing/token_factory.dart
index a293842..918b9a1 100644
--- a/pkg/analyzer/lib/src/generated/testing/token_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/token_factory.dart
@@ -4,7 +4,8 @@
library analyzer.src.generated.testing.token_factory;
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
/**
* A set of utility methods that can be used to create tokens.
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 16e0817..851a990 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -53,20 +53,20 @@
}
/// Given a function type with generic type parameters, infer the type
- /// parameters from the actual argument types, and return it. If we can't.
- /// returns the original function type.
+ /// parameters from the actual argument types, and return the instantiated
+ /// function type. If we can't, returns the original function type.
///
/// Concretely, given a function type with parameter types P0, P1, ... Pn,
/// result type R, and generic type parameters T0, T1, ... Tm, use the
/// argument types A0, A1, ... An to solve for the type parameters.
///
/// For each parameter Pi, we want to ensure that Ai <: Pi. We can do this by
- /// running the subtype algorithm, and when we reach a type parameter Pj,
+ /// running the subtype algorithm, and when we reach a type parameter Tj,
/// recording the lower or upper bound it must satisfy. At the end, all
/// constraints can be combined to determine the type.
///
/// As a simplification, we do not actually store all constraints on each type
- /// parameter Pj. Instead we track Uj and Lj where U is the upper bound and
+ /// parameter Tj. Instead we track Uj and Lj where U is the upper bound and
/// L is the lower bound of that type parameter.
FunctionType inferCallFromArguments(
TypeProvider typeProvider,
@@ -91,7 +91,14 @@
argumentTypes[i], correspondingParameterTypes[i]);
}
- return inferringTypeSystem._infer(fnType);
+ // We are okay inferring some type variables and not others.
+ //
+ // This lets our return type be as precise as possible, which will help
+ // make any type information resulting from it more precise.
+ //
+ // This is simply a heuristic: the code is incorrect, and we'll issue an
+ // error on this call, to indicate that types don't match.
+ return inferringTypeSystem._infer(fnType, allowPartialSolution: true);
}
/**
@@ -118,61 +125,25 @@
var inferringTypeSystem =
new _StrongInferenceTypeSystem(typeProvider, fnType.typeFormals);
- // Add constraints for each corresponding pair of parameters.
- var fRequired = fnType.normalParameterTypes;
- var cRequired = contextType.normalParameterTypes;
- if (cRequired.length != fRequired.length) {
- // If the number of required parameters differs, we can't infer from this
- // type (this will be a static type error).
+ // Since we're trying to infer the instantiation, we want to ignore type
+ // formals as we check the parameters and return type.
+ var inferFnType =
+ fnType.instantiate(TypeParameterTypeImpl.getTypes(fnType.typeFormals));
+ if (!inferringTypeSystem.isSubtypeOf(inferFnType, contextType)) {
return fnType;
}
- for (int i = 0; i < fRequired.length; i++) {
- inferringTypeSystem.isSubtypeOf(cRequired[i], fRequired[i]);
- }
- var fOptional = fnType.optionalParameterTypes;
- var cOptional = contextType.optionalParameterTypes;
- if (cOptional.length > fOptional.length) {
- // If we have more optional parameters that can be passed, we can't infer
- // from this type (this will be a static type error).
- return fnType;
- }
- // Ignore any extra optional arguments in F. We only need to pass arguments
- // that could be passed to C.
- for (int i = 0; i < cOptional.length; i++) {
- inferringTypeSystem.isSubtypeOf(cOptional[i], fOptional[i]);
- }
+ // Try to infer and instantiate the resulting type.
+ var resultType =
+ inferringTypeSystem._infer(fnType, allowPartialSolution: false);
- var fNamed = fnType.namedParameterTypes;
- var cNamed = contextType.namedParameterTypes;
- for (var name in cNamed.keys) {
- DartType fNamedType = fNamed[name];
- if (fNamedType == null) {
- // If F does not have a named parameter needed for C, then we can't
- // infer from this type (this will be a static type error).
- return fnType;
- }
- DartType cNamedType = cNamed[name];
- inferringTypeSystem.isSubtypeOf(cNamedType, fNamedType);
- }
-
- // Infer from the return type. F must return a subtype of what C returns.
- inferringTypeSystem.isSubtypeOf(fnType.returnType, contextType.returnType);
-
- // Instantiate the resulting type.
- var resultType = inferringTypeSystem._infer(fnType);
-
- // If the instantiation is not a subtype of our context (because some
- // constraints could not be solved), return the original type, so the error
- // is in terms of it.
+ // If the instantiation failed (because some type variable constraints
+ // could not be solved, in other words, we could not find a valid subtype),
+ // then return the original type, so the error is in terms of it.
//
- // TODO(jmesserly): for performance, we could refactor this so the _infer
- // call above bails out sooner, and then we can avoid this extra check.
- if (isSubtypeOf(resultType, contextType)) {
- return resultType;
- } else {
- return fnType;
- }
+ // It would be safe to return a partial solution here, but the user
+ // experience may be better if we simply do not infer in this case.
+ return resultType ?? fnType;
}
/**
@@ -319,69 +290,14 @@
*/
bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2,
{bool fuzzyArrows: true}) {
- if (!f1.typeFormals.isEmpty) {
- if (f2.typeFormals.isEmpty) {
- f1 = instantiateToBounds(f1);
- return _isFunctionSubtypeOf(f1, f2);
- } else {
- return _isGenericFunctionSubtypeOf(f1, f2, fuzzyArrows: fuzzyArrows);
- }
- }
- return FunctionTypeImpl.structuralCompare(
+ return FunctionTypeImpl.relate(
f1,
f2,
(DartType t1, DartType t2) =>
_isSubtypeOf(t2, t1, null, dynamicIsBottom: fuzzyArrows),
- isSubtypeOf);
- }
-
- /**
- * Check that [f1] is a subtype of [f2] where f1 and f2 are known
- * to be generic function types (both have type parameters)
- * [fuzzyArrows] indicates whether or not the f1 and f2 should be
- * treated as fuzzy arrow types (and hence dynamic parameters to f2 treated
- * as bottom).
- */
- bool _isGenericFunctionSubtypeOf(FunctionType f1, FunctionType f2,
- {bool fuzzyArrows: true}) {
- List<TypeParameterElement> params1 = f1.typeFormals;
- List<TypeParameterElement> params2 = f2.typeFormals;
- int count = params1.length;
- if (params2.length != count) {
- return false;
- }
- // We build up a substitution matching up the type parameters
- // from the two types, {variablesFresh/variables1} and
- // {variablesFresh/variables2}
- List<DartType> variables1 = new List<DartType>();
- List<DartType> variables2 = new List<DartType>();
- List<DartType> variablesFresh = new List<DartType>();
- for (int i = 0; i < count; i++) {
- TypeParameterElement p1 = params1[i];
- TypeParameterElement p2 = params2[i];
- TypeParameterElementImpl pFresh =
- new TypeParameterElementImpl(p2.name, -1);
-
- DartType variable1 = p1.type;
- DartType variable2 = p2.type;
- DartType variableFresh = new TypeParameterTypeImpl(pFresh);
-
- variables1.add(variable1);
- variables2.add(variable2);
- variablesFresh.add(variableFresh);
- DartType bound1 = p1.bound ?? DynamicTypeImpl.instance;
- DartType bound2 = p2.bound ?? DynamicTypeImpl.instance;
- bound1 = bound1.substitute2(variablesFresh, variables1);
- bound2 = bound2.substitute2(variablesFresh, variables2);
- pFresh.bound = bound2;
- if (!isSubtypeOf(bound2, bound1)) {
- return false;
- }
- }
- return _isFunctionSubtypeOf(
- f1.instantiate(variablesFresh), f2.instantiate(variablesFresh),
- fuzzyArrows: fuzzyArrows);
+ instantiateToBounds,
+ returnRelation: isSubtypeOf);
}
bool _isInterfaceSubtypeOf(
@@ -622,26 +538,12 @@
if (type2.isBottom) {
return type1;
}
+
// Let U be a type variable with upper bound B. The least upper bound of U
// and a type T is the least upper bound of B and T.
- while (type1 is TypeParameterType) {
- // TODO(paulberry): is this correct in the complex of F-bounded
- // polymorphism?
- DartType bound = (type1 as TypeParameterType).element.bound;
- if (bound == null) {
- bound = typeProvider.objectType;
- }
- type1 = bound;
- }
- while (type2 is TypeParameterType) {
- // TODO(paulberry): is this correct in the context of F-bounded
- // polymorphism?
- DartType bound = (type2 as TypeParameterType).element.bound;
- if (bound == null) {
- bound = typeProvider.objectType;
- }
- type2 = bound;
- }
+ type1 = type1.resolveToBound(typeProvider.objectType);
+ type2 = type2.resolveToBound(typeProvider.objectType);
+
// The least upper bound of a function type and an interface type T is the
// least upper bound of Function and T.
if (type1 is FunctionType && type2 is InterfaceType) {
@@ -790,7 +692,7 @@
/// Given the constraints that were given by calling [isSubtypeOf], find the
/// instantiation of the generic function that satisfies these constraints.
- FunctionType _infer(FunctionType fnType) {
+ FunctionType _infer(FunctionType fnType, {bool allowPartialSolution: false}) {
List<TypeParameterType> fnTypeParams =
TypeParameterTypeImpl.getTypes(fnType.typeFormals);
@@ -832,13 +734,22 @@
inferredTypes[i] =
inferredTypes[i].substitute2(inferredTypes, fnTypeParams);
- // See if this actually worked.
- // If not, fall back to the known upper bound (if any) or `dynamic`.
+ // See if the constraints on the type variable are satisfied.
+ //
+ // If not, bail out of the analysis, unless a partial solution was
+ // requested. If we are willing to accept a partial solution, fall back to
+ // the known upper bound (if any) or `dynamic` for this unsolvable type
+ // variable.
if (inferredTypes[i].isBottom ||
!isSubtypeOf(inferredTypes[i],
bound.upper.substitute2(inferredTypes, fnTypeParams)) ||
!isSubtypeOf(bound.lower.substitute2(inferredTypes, fnTypeParams),
inferredTypes[i])) {
+ // Unless a partial solution was requested, bail.
+ if (!allowPartialSolution) {
+ return null;
+ }
+
inferredTypes[i] = DynamicTypeImpl.instance;
if (typeParam.element.bound != null) {
inferredTypes[i] =
diff --git a/pkg/analyzer/lib/src/generated/utilities_collection.dart b/pkg/analyzer/lib/src/generated/utilities_collection.dart
index 453ee37..a1f6cd6 100644
--- a/pkg/analyzer/lib/src/generated/utilities_collection.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_collection.dart
@@ -7,8 +7,31 @@
import 'dart:collection';
import "dart:math" as math;
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart' show Token;
+
+/**
+ * Returns `true` if a and b contain equal elements in the same order.
+ */
+bool listsEqual(List a, List b) {
+ // TODO(rnystrom): package:collection also implements this, and analyzer
+ // already transitively depends on that package. Consider using it instead.
+ if (identical(a, b)) {
+ return true;
+ }
+
+ if (a.length != b.length) {
+ return false;
+ }
+
+ for (int i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
/**
* The class `BooleanArray` defines methods for operating on integers as if they were arrays
diff --git a/pkg/analyzer/lib/src/generated/utilities_dart.dart b/pkg/analyzer/lib/src/generated/utilities_dart.dart
index 5fe5e72..695f75e 100644
--- a/pkg/analyzer/lib/src/generated/utilities_dart.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_dart.dart
@@ -4,9 +4,25 @@
library analyzer.src.generated.utilities_dart;
+import 'package:analyzer/dart/ast/ast.dart' show AnnotatedNode, Comment;
+import 'package:analyzer/dart/ast/token.dart' show Token;
+import 'package:analyzer/src/generated/element.dart' show ElementImpl;
import 'package:analyzer/src/generated/java_core.dart';
/**
+ * If the given [node] has a documentation comment, remember its content
+ * and range into the given [element].
+ */
+void setElementDocumentationComment(ElementImpl element, AnnotatedNode node) {
+ Comment comment = node.documentationComment;
+ if (comment != null && comment.isDocumentation) {
+ element.documentationComment =
+ comment.tokens.map((Token t) => t.lexeme).join('\n');
+ element.setDocRange(comment.offset, comment.length);
+ }
+}
+
+/**
* Check whether [uri1] starts with (or 'is prefixed by') [uri2] by checking
* path segments.
*/
diff --git a/pkg/analyzer/lib/src/generated/utilities_general.dart b/pkg/analyzer/lib/src/generated/utilities_general.dart
index 1adc883..e0600dc 100644
--- a/pkg/analyzer/lib/src/generated/utilities_general.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_general.dart
@@ -20,6 +20,24 @@
value is bool ? value : toLowerCase(value) == 'true';
/**
+ * Safely convert the given [value] to a bool value, or return `null` if the
+ * value coult not be converted.
+ */
+bool toBool(Object value) {
+ if (value is bool) {
+ return value;
+ }
+ String string = toLowerCase(value);
+ if (string == 'true') {
+ return true;
+ }
+ if (string == 'false') {
+ return false;
+ }
+ return null;
+}
+
+/**
* Safely convert this [value] to lower case, returning `null` if [value] is
* null.
*/
diff --git a/pkg/analyzer/lib/src/summary/base.dart b/pkg/analyzer/lib/src/summary/base.dart
index a04476b..c4a4cdb 100644
--- a/pkg/analyzer/lib/src/summary/base.dart
+++ b/pkg/analyzer/lib/src/summary/base.dart
@@ -8,6 +8,21 @@
library analyzer.src.summary.base;
/**
+ * Annotation used in the summary IDL to indicate the id of a field. The set
+ * of ids used by a class must cover the contiguous range from 0 to N-1, where
+ * N is the number of fields.
+ *
+ * In order to preserve forwards and backwards compatibility, id numbers must
+ * be stable between releases. So when new fields are added they should take
+ * the next available id without renumbering other fields.
+ */
+class Id {
+ final int value;
+
+ const Id(this.value);
+}
+
+/**
* Instances of this class represent data that has been read from a summary.
*/
abstract class SummaryClass {
diff --git a/pkg/analyzer/lib/src/summary/flat_buffers.dart b/pkg/analyzer/lib/src/summary/flat_buffers.dart
index c56b298..c7a4f44 100644
--- a/pkg/analyzer/lib/src/summary/flat_buffers.dart
+++ b/pkg/analyzer/lib/src/summary/flat_buffers.dart
@@ -63,6 +63,8 @@
int _getUint32([int delta = 0]) =>
_buffer.getUint32(_offset + delta, Endianness.LITTLE_ENDIAN);
+ int _getUint8([int delta = 0]) => _buffer.getUint8(_offset + delta);
+
/**
* If the [byteList] is already a [Uint8List] return it.
* Otherwise return a [Uint8List] copy of the [byteList].
@@ -110,6 +112,12 @@
_VTable _currentVTable;
+ /**
+ * Map containing all strings that have been written so far. This allows us
+ * to avoid duplicating strings.
+ */
+ Map<String, Offset<String>> _strings = <String, Offset<String>>{};
+
Builder({this.initialSize: 1024}) {
reset();
}
@@ -120,9 +128,7 @@
* `0` for `false` and `1` for `true`.
*/
void addBool(int field, bool value, [bool def]) {
- if (_currentVTable == null) {
- throw new StateError('Start a table before adding values.');
- }
+ _ensureCurrentVTable();
if (value != null && value != def) {
int size = 1;
_prepare(size, 1);
@@ -136,9 +142,7 @@
* not added if the [value] is equal to [def].
*/
void addInt32(int field, int value, [int def]) {
- if (_currentVTable == null) {
- throw new StateError('Start a table before adding values.');
- }
+ _ensureCurrentVTable();
if (value != null && value != def) {
int size = 4;
_prepare(size, 1);
@@ -152,9 +156,7 @@
* not added if the [value] is equal to [def].
*/
void addInt8(int field, int value, [int def]) {
- if (_currentVTable == null) {
- throw new StateError('Start a table before adding values.');
- }
+ _ensureCurrentVTable();
if (value != null && value != def) {
int size = 1;
_prepare(size, 1);
@@ -167,9 +169,7 @@
* Add the [field] referencing an object with the given [offset].
*/
void addOffset(int field, Offset offset) {
- if (_currentVTable == null) {
- throw new StateError('Start a table before adding values.');
- }
+ _ensureCurrentVTable();
if (offset != null) {
_prepare(4, 1);
_trackField(field);
@@ -182,9 +182,7 @@
* is not added if the [value] is equal to [def].
*/
void addUint32(int field, int value, [int def]) {
- if (_currentVTable == null) {
- throw new StateError('Start a table before adding values.');
- }
+ _ensureCurrentVTable();
if (value != null && value != def) {
int size = 4;
_prepare(size, 1);
@@ -194,17 +192,31 @@
}
/**
+ * Add the [field] with the given 8-bit unsigned integer [value]. The field
+ * is not added if the [value] is equal to [def].
+ */
+ void addUint8(int field, int value, [int def]) {
+ _ensureCurrentVTable();
+ if (value != null && value != def) {
+ int size = 1;
+ _prepare(size, 1);
+ _trackField(field);
+ _setUint8AtTail(_buf, _tail, value);
+ }
+ }
+
+ /**
* End the current table and return its offset.
*/
Offset endTable() {
if (_currentVTable == null) {
throw new StateError('Start a table before ending it.');
}
- // Prepare the size of the current table.
- _currentVTable.tableSize = _tail - _currentTableEndTail;
// Prepare for writing the VTable.
_prepare(4, 1);
int tableTail = _tail;
+ // Prepare the size of the current table.
+ _currentVTable.tableSize = tableTail - _currentTableEndTail;
// Prepare the VTable to use for the current table.
int vTableTail;
{
@@ -301,10 +313,7 @@
* Write the given list of [values].
*/
Offset writeList(List<Offset> values) {
- if (_currentVTable != null) {
- throw new StateError(
- 'Cannot write a non-scalar value while writing a table.');
- }
+ _ensureNoVTable();
_prepare(4, 1 + values.length);
Offset result = new Offset(_tail);
int tail = _tail;
@@ -321,10 +330,7 @@
* Write the given list of 64-bit float [values].
*/
Offset writeListFloat64(List<double> values) {
- if (_currentVTable != null) {
- throw new StateError(
- 'Cannot write a non-scalar value while writing a table.');
- }
+ _ensureNoVTable();
_prepare(8, 1 + values.length);
Offset result = new Offset(_tail);
int tail = _tail;
@@ -341,10 +347,7 @@
* Write the given list of signed 32-bit integer [values].
*/
Offset writeListInt32(List<int> values) {
- if (_currentVTable != null) {
- throw new StateError(
- 'Cannot write a non-scalar value while writing a table.');
- }
+ _ensureNoVTable();
_prepare(4, 1 + values.length);
Offset result = new Offset(_tail);
int tail = _tail;
@@ -361,10 +364,7 @@
* Write the given list of unsigned 32-bit integer [values].
*/
Offset writeListUint32(List<int> values) {
- if (_currentVTable != null) {
- throw new StateError(
- 'Cannot write a non-scalar value while writing a table.');
- }
+ _ensureNoVTable();
_prepare(4, 1 + values.length);
Offset result = new Offset(_tail);
int tail = _tail;
@@ -378,28 +378,63 @@
}
/**
+ * Write the given list of unsigned 8-bit integer [values].
+ */
+ Offset writeListUint8(List<int> values) {
+ _ensureNoVTable();
+ _prepare(4, 1, additionalBytes: values.length);
+ Offset result = new Offset(_tail);
+ int tail = _tail;
+ _setUint32AtTail(_buf, tail, values.length);
+ tail -= 4;
+ for (int value in values) {
+ _setUint8AtTail(_buf, tail, value);
+ tail -= 1;
+ }
+ return result;
+ }
+
+ /**
* Write the given string [value] and return its [Offset], or `null` if
* the [value] is equal to [def].
*/
Offset<String> writeString(String value, [String def]) {
+ _ensureNoVTable();
+ if (value != def) {
+ return _strings.putIfAbsent(value, () {
+ // TODO(scheglov) optimize for ASCII strings
+ List<int> bytes = UTF8.encode(value);
+ int length = bytes.length;
+ _prepare(4, 1, additionalBytes: length);
+ Offset<String> result = new Offset(_tail);
+ _setUint32AtTail(_buf, _tail, length);
+ int offset = _buf.lengthInBytes - _tail + 4;
+ for (int i = 0; i < length; i++) {
+ _buf.setUint8(offset++, bytes[i]);
+ }
+ return result;
+ });
+ }
+ return null;
+ }
+
+ /**
+ * Throw an exception if there is not currently a vtable.
+ */
+ void _ensureCurrentVTable() {
+ if (_currentVTable == null) {
+ throw new StateError('Start a table before adding values.');
+ }
+ }
+
+ /**
+ * Throw an exception if there is currently a vtable.
+ */
+ void _ensureNoVTable() {
if (_currentVTable != null) {
throw new StateError(
'Cannot write a non-scalar value while writing a table.');
}
- if (value != def) {
- // TODO(scheglov) optimize for ASCII strings
- List<int> bytes = UTF8.encode(value);
- int length = bytes.length;
- _prepare(4, 1, additionalBytes: length);
- Offset<String> result = new Offset(_tail);
- _setUint32AtTail(_buf, _tail, length);
- int offset = _buf.lengthInBytes - _tail + 4;
- for (int i = 0; i < length; i++) {
- _buf.setUint8(offset++, bytes[i]);
- }
- return result;
- }
- return null;
}
/**
@@ -453,6 +488,10 @@
static void _setUint32AtTail(ByteData _buf, int tail, int x) {
_buf.setUint32(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN);
}
+
+ static void _setUint8AtTail(ByteData _buf, int tail, int x) {
+ _buf.setUint8(_buf.lengthInBytes - tail, x);
+ }
}
/**
@@ -511,7 +550,7 @@
@override
List<E> read(BufferPointer bp) =>
- new _FbInt32List<E>(_elementReader, bp.derefObject());
+ new _FbGenericList<E>(_elementReader, bp.derefObject());
}
/**
@@ -598,6 +637,21 @@
}
/**
+ * Reader of lists of 32-bit float values.
+ *
+ * The returned unmodifiable lists lazily read values on access.
+ */
+class Uint32ListReader extends Reader<List<int>> {
+ const Uint32ListReader();
+
+ @override
+ int get size => 4;
+
+ @override
+ List<int> read(BufferPointer bp) => new _FbUint32List(bp.derefObject());
+}
+
+/**
* The reader of unsigned 32-bit integers.
*/
class Uint32Reader extends Reader<int> {
@@ -611,21 +665,25 @@
}
/**
+ * The reader of unsigned 8-bit integers.
+ */
+class Uint8Reader extends Reader<int> {
+ const Uint8Reader() : super();
+
+ @override
+ int get size => 1;
+
+ @override
+ int read(BufferPointer bp) => bp._getUint8();
+}
+
+/**
* The list backed by 64-bit values - Uint64 length and Float64.
*/
class _FbFloat64List extends _FbList<double> {
- final BufferPointer bp;
-
- int _length;
List<double> _items;
- _FbFloat64List(this.bp);
-
- @override
- int get length {
- _length ??= bp._getUint32();
- return _length;
- }
+ _FbFloat64List(BufferPointer bp) : super(bp);
@override
double operator [](int i) {
@@ -641,29 +699,21 @@
}
/**
- * The list backed by 32-bit values - offsets or integers.
+ * List backed by a generic object which may have any size.
*/
-class _FbInt32List<E> extends _FbList<E> {
+class _FbGenericList<E> extends _FbList<E> {
final Reader<E> elementReader;
- final BufferPointer bp;
- int _length;
List<E> _items;
- _FbInt32List(this.elementReader, this.bp);
-
- @override
- int get length {
- _length ??= bp._getUint32();
- return _length;
- }
+ _FbGenericList(this.elementReader, BufferPointer bp) : super(bp);
@override
E operator [](int i) {
_items ??= new List<E>(length);
E item = _items[i];
if (item == null) {
- BufferPointer ref = bp._advance(4 + 4 * i);
+ BufferPointer ref = bp._advance(4 + elementReader.size * i);
item = elementReader.read(ref);
_items[i] = item;
}
@@ -675,6 +725,17 @@
* The base class for immutable lists read from flat buffers.
*/
abstract class _FbList<E> extends Object with ListMixin<E> implements List<E> {
+ final BufferPointer bp;
+ int _length;
+
+ _FbList(this.bp);
+
+ @override
+ int get length {
+ _length ??= bp._getUint32();
+ return _length;
+ }
+
@override
void set length(int i) =>
throw new StateError('Attempt to modify immutable list');
@@ -685,6 +746,26 @@
}
/**
+ * List backed by 32-bit unsigned integers.
+ */
+class _FbUint32List extends _FbList<int> {
+ List<int> _items;
+
+ _FbUint32List(BufferPointer bp) : super(bp);
+
+ @override
+ int operator [](int i) {
+ _items ??= new List<int>(length);
+ int item = _items[i];
+ if (item == null) {
+ item = bp._getUint32(4 + 4 * i);
+ _items[i] = item;
+ }
+ return item;
+ }
+}
+
+/**
* Class that describes the structure of a table.
*/
class _VTable {
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 8f2fe1e..5507871 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -14,11 +14,11 @@
const _ReferenceKindReader() : super();
@override
- int get size => 4;
+ int get size => 1;
@override
idl.ReferenceKind read(fb.BufferPointer bp) {
- int index = const fb.Uint32Reader().read(bp);
+ int index = const fb.Uint8Reader().read(bp);
return idl.ReferenceKind.values[index];
}
}
@@ -27,11 +27,11 @@
const _UnlinkedConstOperationReader() : super();
@override
- int get size => 4;
+ int get size => 1;
@override
idl.UnlinkedConstOperation read(fb.BufferPointer bp) {
- int index = const fb.Uint32Reader().read(bp);
+ int index = const fb.Uint8Reader().read(bp);
return idl.UnlinkedConstOperation.values[index];
}
}
@@ -40,11 +40,11 @@
const _UnlinkedConstructorInitializerKindReader() : super();
@override
- int get size => 4;
+ int get size => 1;
@override
idl.UnlinkedConstructorInitializerKind read(fb.BufferPointer bp) {
- int index = const fb.Uint32Reader().read(bp);
+ int index = const fb.Uint8Reader().read(bp);
return idl.UnlinkedConstructorInitializerKind.values[index];
}
}
@@ -53,11 +53,11 @@
const _UnlinkedExecutableKindReader() : super();
@override
- int get size => 4;
+ int get size => 1;
@override
idl.UnlinkedExecutableKind read(fb.BufferPointer bp) {
- int index = const fb.Uint32Reader().read(bp);
+ int index = const fb.Uint8Reader().read(bp);
return idl.UnlinkedExecutableKind.values[index];
}
}
@@ -66,11 +66,11 @@
const _UnlinkedParamKindReader() : super();
@override
- int get size => 4;
+ int get size => 1;
@override
idl.UnlinkedParamKind read(fb.BufferPointer bp) {
- int index = const fb.Uint32Reader().read(bp);
+ int index = const fb.Uint8Reader().read(bp);
return idl.UnlinkedParamKind.values[index];
}
}
@@ -205,19 +205,19 @@
}
fbBuilder.startTable();
if (offset_implicitFunctionTypeIndices != null) {
- fbBuilder.addOffset(0, offset_implicitFunctionTypeIndices);
+ fbBuilder.addOffset(4, offset_implicitFunctionTypeIndices);
}
if (_paramReference != null && _paramReference != 0) {
- fbBuilder.addUint32(1, _paramReference);
+ fbBuilder.addUint32(3, _paramReference);
}
if (_reference != null && _reference != 0) {
- fbBuilder.addUint32(2, _reference);
+ fbBuilder.addUint32(0, _reference);
}
if (_slot != null && _slot != 0) {
- fbBuilder.addUint32(3, _slot);
+ fbBuilder.addUint32(2, _slot);
}
if (offset_typeArguments != null) {
- fbBuilder.addOffset(4, offset_typeArguments);
+ fbBuilder.addOffset(1, offset_typeArguments);
}
return fbBuilder.endTable();
}
@@ -243,31 +243,31 @@
@override
List<int> get implicitFunctionTypeIndices {
- _implicitFunctionTypeIndices ??= const fb.ListReader<int>(const fb.Uint32Reader()).vTableGet(_bp, 0, const <int>[]);
+ _implicitFunctionTypeIndices ??= const fb.Uint32ListReader().vTableGet(_bp, 4, const <int>[]);
return _implicitFunctionTypeIndices;
}
@override
int get paramReference {
- _paramReference ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+ _paramReference ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
return _paramReference;
}
@override
int get reference {
- _reference ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+ _reference ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
return _reference;
}
@override
int get slot {
- _slot ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+ _slot ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
return _slot;
}
@override
List<idl.EntityRef> get typeArguments {
- _typeArguments ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 4, const <idl.EntityRef>[]);
+ _typeArguments ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 1, const <idl.EntityRef>[]);
return _typeArguments;
}
}
@@ -333,10 +333,10 @@
}
fbBuilder.startTable();
if (offset_parts != null) {
- fbBuilder.addOffset(0, offset_parts);
+ fbBuilder.addOffset(1, offset_parts);
}
if (offset_uri != null) {
- fbBuilder.addOffset(1, offset_uri);
+ fbBuilder.addOffset(0, offset_uri);
}
return fbBuilder.endTable();
}
@@ -359,13 +359,13 @@
@override
List<String> get parts {
- _parts ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 0, const <String>[]);
+ _parts ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
return _parts;
}
@override
String get uri {
- _uri ??= const fb.StringReader().vTableGet(_bp, 1, '');
+ _uri ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _uri;
}
}
@@ -455,13 +455,13 @@
fbBuilder.addUint32(0, _dependency);
}
if (_kind != null && _kind != idl.ReferenceKind.classOrEnum) {
- fbBuilder.addUint32(1, _kind.index);
+ fbBuilder.addUint8(3, _kind.index);
}
if (offset_name != null) {
- fbBuilder.addOffset(2, offset_name);
+ fbBuilder.addOffset(1, offset_name);
}
if (_unit != null && _unit != 0) {
- fbBuilder.addUint32(3, _unit);
+ fbBuilder.addUint32(2, _unit);
}
return fbBuilder.endTable();
}
@@ -492,19 +492,19 @@
@override
idl.ReferenceKind get kind {
- _kind ??= const _ReferenceKindReader().vTableGet(_bp, 1, idl.ReferenceKind.classOrEnum);
+ _kind ??= const _ReferenceKindReader().vTableGet(_bp, 3, idl.ReferenceKind.classOrEnum);
return _kind;
}
@override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 2, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 1, '');
return _name;
}
@override
int get unit {
- _unit ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+ _unit ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
return _unit;
}
}
@@ -644,16 +644,16 @@
fbBuilder.addOffset(0, offset_dependencies);
}
if (offset_exportNames != null) {
- fbBuilder.addOffset(1, offset_exportNames);
+ fbBuilder.addOffset(4, offset_exportNames);
}
if (offset_importDependencies != null) {
- fbBuilder.addOffset(2, offset_importDependencies);
+ fbBuilder.addOffset(1, offset_importDependencies);
}
if (_numPrelinkedDependencies != null && _numPrelinkedDependencies != 0) {
- fbBuilder.addUint32(3, _numPrelinkedDependencies);
+ fbBuilder.addUint32(2, _numPrelinkedDependencies);
}
if (offset_units != null) {
- fbBuilder.addOffset(4, offset_units);
+ fbBuilder.addOffset(3, offset_units);
}
return fbBuilder.endTable();
}
@@ -690,25 +690,25 @@
@override
List<idl.LinkedExportName> get exportNames {
- _exportNames ??= const fb.ListReader<idl.LinkedExportName>(const _LinkedExportNameReader()).vTableGet(_bp, 1, const <idl.LinkedExportName>[]);
+ _exportNames ??= const fb.ListReader<idl.LinkedExportName>(const _LinkedExportNameReader()).vTableGet(_bp, 4, const <idl.LinkedExportName>[]);
return _exportNames;
}
@override
List<int> get importDependencies {
- _importDependencies ??= const fb.ListReader<int>(const fb.Uint32Reader()).vTableGet(_bp, 2, const <int>[]);
+ _importDependencies ??= const fb.Uint32ListReader().vTableGet(_bp, 1, const <int>[]);
return _importDependencies;
}
@override
int get numPrelinkedDependencies {
- _numPrelinkedDependencies ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+ _numPrelinkedDependencies ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
return _numPrelinkedDependencies;
}
@override
List<idl.LinkedUnit> get units {
- _units ??= const fb.ListReader<idl.LinkedUnit>(const _LinkedUnitReader()).vTableGet(_bp, 4, const <idl.LinkedUnit>[]);
+ _units ??= const fb.ListReader<idl.LinkedUnit>(const _LinkedUnitReader()).vTableGet(_bp, 3, const <idl.LinkedUnit>[]);
return _units;
}
}
@@ -843,13 +843,13 @@
}
fbBuilder.startTable();
if (_containingReference != null && _containingReference != 0) {
- fbBuilder.addUint32(0, _containingReference);
+ fbBuilder.addUint32(5, _containingReference);
}
if (_dependency != null && _dependency != 0) {
fbBuilder.addUint32(1, _dependency);
}
if (_kind != null && _kind != idl.ReferenceKind.classOrEnum) {
- fbBuilder.addUint32(2, _kind.index);
+ fbBuilder.addUint8(2, _kind.index);
}
if (offset_name != null) {
fbBuilder.addOffset(3, offset_name);
@@ -858,7 +858,7 @@
fbBuilder.addUint32(4, _numTypeParameters);
}
if (_unit != null && _unit != 0) {
- fbBuilder.addUint32(5, _unit);
+ fbBuilder.addUint32(0, _unit);
}
return fbBuilder.endTable();
}
@@ -885,7 +885,7 @@
@override
int get containingReference {
- _containingReference ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
+ _containingReference ??= const fb.Uint32Reader().vTableGet(_bp, 5, 0);
return _containingReference;
}
@@ -915,7 +915,7 @@
@override
int get unit {
- _unit ??= const fb.Uint32Reader().vTableGet(_bp, 5, 0);
+ _unit ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
return _unit;
}
}
@@ -1405,43 +1405,43 @@
}
fbBuilder.startTable();
if (offset_annotations != null) {
- fbBuilder.addOffset(0, offset_annotations);
+ fbBuilder.addOffset(5, offset_annotations);
}
if (offset_documentationComment != null) {
- fbBuilder.addOffset(1, offset_documentationComment);
+ fbBuilder.addOffset(6, offset_documentationComment);
}
if (offset_executables != null) {
fbBuilder.addOffset(2, offset_executables);
}
if (offset_fields != null) {
- fbBuilder.addOffset(3, offset_fields);
+ fbBuilder.addOffset(4, offset_fields);
}
if (_hasNoSupertype == true) {
- fbBuilder.addBool(4, true);
+ fbBuilder.addBool(12, true);
}
if (offset_interfaces != null) {
- fbBuilder.addOffset(5, offset_interfaces);
+ fbBuilder.addOffset(7, offset_interfaces);
}
if (_isAbstract == true) {
- fbBuilder.addBool(6, true);
+ fbBuilder.addBool(8, true);
}
if (_isMixinApplication == true) {
- fbBuilder.addBool(7, true);
+ fbBuilder.addBool(11, true);
}
if (offset_mixins != null) {
- fbBuilder.addOffset(8, offset_mixins);
+ fbBuilder.addOffset(10, offset_mixins);
}
if (offset_name != null) {
- fbBuilder.addOffset(9, offset_name);
+ fbBuilder.addOffset(0, offset_name);
}
if (_nameOffset != null && _nameOffset != 0) {
- fbBuilder.addUint32(10, _nameOffset);
+ fbBuilder.addUint32(1, _nameOffset);
}
if (offset_supertype != null) {
- fbBuilder.addOffset(11, offset_supertype);
+ fbBuilder.addOffset(3, offset_supertype);
}
if (offset_typeParameters != null) {
- fbBuilder.addOffset(12, offset_typeParameters);
+ fbBuilder.addOffset(9, offset_typeParameters);
}
return fbBuilder.endTable();
}
@@ -1475,13 +1475,13 @@
@override
List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 5, const <idl.UnlinkedConst>[]);
return _annotations;
}
@override
idl.UnlinkedDocumentationComment get documentationComment {
- _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 1, null);
+ _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 6, null);
return _documentationComment;
}
@@ -1493,61 +1493,61 @@
@override
List<idl.UnlinkedVariable> get fields {
- _fields ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 3, const <idl.UnlinkedVariable>[]);
+ _fields ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 4, const <idl.UnlinkedVariable>[]);
return _fields;
}
@override
bool get hasNoSupertype {
- _hasNoSupertype ??= const fb.BoolReader().vTableGet(_bp, 4, false);
+ _hasNoSupertype ??= const fb.BoolReader().vTableGet(_bp, 12, false);
return _hasNoSupertype;
}
@override
List<idl.EntityRef> get interfaces {
- _interfaces ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 5, const <idl.EntityRef>[]);
+ _interfaces ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 7, const <idl.EntityRef>[]);
return _interfaces;
}
@override
bool get isAbstract {
- _isAbstract ??= const fb.BoolReader().vTableGet(_bp, 6, false);
+ _isAbstract ??= const fb.BoolReader().vTableGet(_bp, 8, false);
return _isAbstract;
}
@override
bool get isMixinApplication {
- _isMixinApplication ??= const fb.BoolReader().vTableGet(_bp, 7, false);
+ _isMixinApplication ??= const fb.BoolReader().vTableGet(_bp, 11, false);
return _isMixinApplication;
}
@override
List<idl.EntityRef> get mixins {
- _mixins ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 8, const <idl.EntityRef>[]);
+ _mixins ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 10, const <idl.EntityRef>[]);
return _mixins;
}
@override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 9, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _name;
}
@override
int get nameOffset {
- _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 10, 0);
+ _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
return _nameOffset;
}
@override
idl.EntityRef get supertype {
- _supertype ??= const _EntityRefReader().vTableGet(_bp, 11, null);
+ _supertype ??= const _EntityRefReader().vTableGet(_bp, 3, null);
return _supertype;
}
@override
List<idl.UnlinkedTypeParam> get typeParameters {
- _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 12, const <idl.UnlinkedTypeParam>[]);
+ _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 9, const <idl.UnlinkedTypeParam>[]);
return _typeParameters;
}
}
@@ -1616,10 +1616,10 @@
}
fbBuilder.startTable();
if (offset_hides != null) {
- fbBuilder.addOffset(0, offset_hides);
+ fbBuilder.addOffset(1, offset_hides);
}
if (offset_shows != null) {
- fbBuilder.addOffset(1, offset_shows);
+ fbBuilder.addOffset(0, offset_shows);
}
return fbBuilder.endTable();
}
@@ -1642,13 +1642,13 @@
@override
List<String> get hides {
- _hides ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 0, const <String>[]);
+ _hides ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
return _hides;
}
@override
List<String> get shows {
- _shows ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
+ _shows ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 0, const <String>[]);
return _shows;
}
}
@@ -1769,7 +1769,7 @@
offset_ints = fbBuilder.writeListUint32(_ints);
}
if (!(_operations == null || _operations.isEmpty)) {
- offset_operations = fbBuilder.writeListUint32(_operations.map((b) => b.index).toList());
+ offset_operations = fbBuilder.writeListUint8(_operations.map((b) => b.index).toList());
}
if (!(_references == null || _references.isEmpty)) {
offset_references = fbBuilder.writeList(_references.map((b) => b.finish(fbBuilder)).toList());
@@ -1779,22 +1779,22 @@
}
fbBuilder.startTable();
if (offset_doubles != null) {
- fbBuilder.addOffset(0, offset_doubles);
+ fbBuilder.addOffset(4, offset_doubles);
}
if (offset_ints != null) {
fbBuilder.addOffset(1, offset_ints);
}
if (_isInvalid == true) {
- fbBuilder.addBool(2, true);
+ fbBuilder.addBool(5, true);
}
if (offset_operations != null) {
- fbBuilder.addOffset(3, offset_operations);
+ fbBuilder.addOffset(0, offset_operations);
}
if (offset_references != null) {
- fbBuilder.addOffset(4, offset_references);
+ fbBuilder.addOffset(2, offset_references);
}
if (offset_strings != null) {
- fbBuilder.addOffset(5, offset_strings);
+ fbBuilder.addOffset(3, offset_strings);
}
return fbBuilder.endTable();
}
@@ -1821,37 +1821,37 @@
@override
List<double> get doubles {
- _doubles ??= const fb.Float64ListReader().vTableGet(_bp, 0, const <double>[]);
+ _doubles ??= const fb.Float64ListReader().vTableGet(_bp, 4, const <double>[]);
return _doubles;
}
@override
List<int> get ints {
- _ints ??= const fb.ListReader<int>(const fb.Uint32Reader()).vTableGet(_bp, 1, const <int>[]);
+ _ints ??= const fb.Uint32ListReader().vTableGet(_bp, 1, const <int>[]);
return _ints;
}
@override
bool get isInvalid {
- _isInvalid ??= const fb.BoolReader().vTableGet(_bp, 2, false);
+ _isInvalid ??= const fb.BoolReader().vTableGet(_bp, 5, false);
return _isInvalid;
}
@override
List<idl.UnlinkedConstOperation> get operations {
- _operations ??= const fb.ListReader<idl.UnlinkedConstOperation>(const _UnlinkedConstOperationReader()).vTableGet(_bp, 3, const <idl.UnlinkedConstOperation>[]);
+ _operations ??= const fb.ListReader<idl.UnlinkedConstOperation>(const _UnlinkedConstOperationReader()).vTableGet(_bp, 0, const <idl.UnlinkedConstOperation>[]);
return _operations;
}
@override
List<idl.EntityRef> get references {
- _references ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 4, const <idl.EntityRef>[]);
+ _references ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bp, 2, const <idl.EntityRef>[]);
return _references;
}
@override
List<String> get strings {
- _strings ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 5, const <String>[]);
+ _strings ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 3, const <String>[]);
return _strings;
}
}
@@ -1948,16 +1948,16 @@
}
fbBuilder.startTable();
if (offset_arguments != null) {
- fbBuilder.addOffset(0, offset_arguments);
+ fbBuilder.addOffset(3, offset_arguments);
}
if (offset_expression != null) {
fbBuilder.addOffset(1, offset_expression);
}
if (_kind != null && _kind != idl.UnlinkedConstructorInitializerKind.field) {
- fbBuilder.addUint32(2, _kind.index);
+ fbBuilder.addUint8(2, _kind.index);
}
if (offset_name != null) {
- fbBuilder.addOffset(3, offset_name);
+ fbBuilder.addOffset(0, offset_name);
}
return fbBuilder.endTable();
}
@@ -1982,7 +1982,7 @@
@override
List<idl.UnlinkedConst> get arguments {
- _arguments ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _arguments ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 3, const <idl.UnlinkedConst>[]);
return _arguments;
}
@@ -2000,7 +2000,7 @@
@override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 3, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _name;
}
}
@@ -2078,10 +2078,10 @@
fbBuilder.addUint32(0, _length);
}
if (_offset != null && _offset != 0) {
- fbBuilder.addUint32(1, _offset);
+ fbBuilder.addUint32(2, _offset);
}
if (offset_text != null) {
- fbBuilder.addOffset(2, offset_text);
+ fbBuilder.addOffset(1, offset_text);
}
return fbBuilder.endTable();
}
@@ -2111,13 +2111,13 @@
@override
int get offset {
- _offset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+ _offset ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
return _offset;
}
@override
String get text {
- _text ??= const fb.StringReader().vTableGet(_bp, 2, '');
+ _text ??= const fb.StringReader().vTableGet(_bp, 1, '');
return _text;
}
}
@@ -2225,19 +2225,19 @@
}
fbBuilder.startTable();
if (offset_annotations != null) {
- fbBuilder.addOffset(0, offset_annotations);
+ fbBuilder.addOffset(4, offset_annotations);
}
if (offset_documentationComment != null) {
- fbBuilder.addOffset(1, offset_documentationComment);
+ fbBuilder.addOffset(3, offset_documentationComment);
}
if (offset_name != null) {
- fbBuilder.addOffset(2, offset_name);
+ fbBuilder.addOffset(0, offset_name);
}
if (_nameOffset != null && _nameOffset != 0) {
- fbBuilder.addUint32(3, _nameOffset);
+ fbBuilder.addUint32(1, _nameOffset);
}
if (offset_values != null) {
- fbBuilder.addOffset(4, offset_values);
+ fbBuilder.addOffset(2, offset_values);
}
return fbBuilder.endTable();
}
@@ -2263,31 +2263,31 @@
@override
List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 4, const <idl.UnlinkedConst>[]);
return _annotations;
}
@override
idl.UnlinkedDocumentationComment get documentationComment {
- _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 1, null);
+ _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 3, null);
return _documentationComment;
}
@override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 2, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _name;
}
@override
int get nameOffset {
- _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+ _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
return _nameOffset;
}
@override
List<idl.UnlinkedEnumValue> get values {
- _values ??= const fb.ListReader<idl.UnlinkedEnumValue>(const _UnlinkedEnumValueReader()).vTableGet(_bp, 4, const <idl.UnlinkedEnumValue>[]);
+ _values ??= const fb.ListReader<idl.UnlinkedEnumValue>(const _UnlinkedEnumValueReader()).vTableGet(_bp, 2, const <idl.UnlinkedEnumValue>[]);
return _values;
}
}
@@ -2363,13 +2363,13 @@
}
fbBuilder.startTable();
if (offset_documentationComment != null) {
- fbBuilder.addOffset(0, offset_documentationComment);
+ fbBuilder.addOffset(2, offset_documentationComment);
}
if (offset_name != null) {
- fbBuilder.addOffset(1, offset_name);
+ fbBuilder.addOffset(0, offset_name);
}
if (_nameOffset != null && _nameOffset != 0) {
- fbBuilder.addUint32(2, _nameOffset);
+ fbBuilder.addUint32(1, _nameOffset);
}
return fbBuilder.endTable();
}
@@ -2393,19 +2393,19 @@
@override
idl.UnlinkedDocumentationComment get documentationComment {
- _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 0, null);
+ _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 2, null);
return _documentationComment;
}
@override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 1, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _name;
}
@override
int get nameOffset {
- _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+ _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
return _nameOffset;
}
}
@@ -2430,13 +2430,20 @@
bool _isConst;
bool _isExternal;
bool _isFactory;
+ bool _isRedirectedConstructor;
bool _isStatic;
idl.UnlinkedExecutableKind _kind;
+ List<UnlinkedExecutableBuilder> _localFunctions;
+ List<UnlinkedVariableBuilder> _localVariables;
String _name;
int _nameOffset;
List<UnlinkedParamBuilder> _parameters;
+ EntityRefBuilder _redirectedConstructor;
+ String _redirectedConstructorName;
EntityRefBuilder _returnType;
List<UnlinkedTypeParamBuilder> _typeParameters;
+ int _visibleLength;
+ int _visibleOffset;
@override
List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
@@ -2534,6 +2541,17 @@
}
@override
+ bool get isRedirectedConstructor => _isRedirectedConstructor ??= false;
+
+ /**
+ * Indicates whether the executable is a redirected constructor.
+ */
+ void set isRedirectedConstructor(bool _value) {
+ assert(!_finished);
+ _isRedirectedConstructor = _value;
+ }
+
+ @override
bool get isStatic => _isStatic ??= false;
/**
@@ -2561,6 +2579,28 @@
}
@override
+ List<UnlinkedExecutableBuilder> get localFunctions => _localFunctions ??= <UnlinkedExecutableBuilder>[];
+
+ /**
+ * The list of local functions.
+ */
+ void set localFunctions(List<UnlinkedExecutableBuilder> _value) {
+ assert(!_finished);
+ _localFunctions = _value;
+ }
+
+ @override
+ List<UnlinkedVariableBuilder> get localVariables => _localVariables ??= <UnlinkedVariableBuilder>[];
+
+ /**
+ * The list of local variables.
+ */
+ void set localVariables(List<UnlinkedVariableBuilder> _value) {
+ assert(!_finished);
+ _localVariables = _value;
+ }
+
+ @override
String get name => _name ??= '';
/**
@@ -2602,6 +2642,31 @@
}
@override
+ EntityRefBuilder get redirectedConstructor => _redirectedConstructor;
+
+ /**
+ * If [isRedirectedConstructor] and [isFactory] are both `true`, the
+ * constructor to which this constructor redirects; otherwise empty.
+ */
+ void set redirectedConstructor(EntityRefBuilder _value) {
+ assert(!_finished);
+ _redirectedConstructor = _value;
+ }
+
+ @override
+ String get redirectedConstructorName => _redirectedConstructorName ??= '';
+
+ /**
+ * If [isRedirectedConstructor] is `true` and [isFactory] is `false`, the
+ * name of the constructor that this constructor redirects to; otherwise
+ * empty.
+ */
+ void set redirectedConstructorName(String _value) {
+ assert(!_finished);
+ _redirectedConstructorName = _value;
+ }
+
+ @override
EntityRefBuilder get returnType => _returnType;
/**
@@ -2625,7 +2690,31 @@
_typeParameters = _value;
}
- UnlinkedExecutableBuilder({List<UnlinkedConstBuilder> annotations, List<UnlinkedConstructorInitializerBuilder> constantInitializers, UnlinkedDocumentationCommentBuilder documentationComment, int inferredReturnTypeSlot, bool isAbstract, bool isConst, bool isExternal, bool isFactory, bool isStatic, idl.UnlinkedExecutableKind kind, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters})
+ @override
+ int get visibleLength => _visibleLength ??= 0;
+
+ /**
+ * If a local function, the length of the visible range; zero otherwise.
+ */
+ void set visibleLength(int _value) {
+ assert(!_finished);
+ assert(_value == null || _value >= 0);
+ _visibleLength = _value;
+ }
+
+ @override
+ int get visibleOffset => _visibleOffset ??= 0;
+
+ /**
+ * If a local function, the beginning of the visible range; zero otherwise.
+ */
+ void set visibleOffset(int _value) {
+ assert(!_finished);
+ assert(_value == null || _value >= 0);
+ _visibleOffset = _value;
+ }
+
+ UnlinkedExecutableBuilder({List<UnlinkedConstBuilder> annotations, List<UnlinkedConstructorInitializerBuilder> constantInitializers, UnlinkedDocumentationCommentBuilder documentationComment, int inferredReturnTypeSlot, bool isAbstract, bool isConst, bool isExternal, bool isFactory, bool isRedirectedConstructor, bool isStatic, idl.UnlinkedExecutableKind kind, List<UnlinkedExecutableBuilder> localFunctions, List<UnlinkedVariableBuilder> localVariables, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder redirectedConstructor, String redirectedConstructorName, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters, int visibleLength, int visibleOffset})
: _annotations = annotations,
_constantInitializers = constantInitializers,
_documentationComment = documentationComment,
@@ -2634,13 +2723,20 @@
_isConst = isConst,
_isExternal = isExternal,
_isFactory = isFactory,
+ _isRedirectedConstructor = isRedirectedConstructor,
_isStatic = isStatic,
_kind = kind,
+ _localFunctions = localFunctions,
+ _localVariables = localVariables,
_name = name,
_nameOffset = nameOffset,
_parameters = parameters,
+ _redirectedConstructor = redirectedConstructor,
+ _redirectedConstructorName = redirectedConstructorName,
_returnType = returnType,
- _typeParameters = typeParameters;
+ _typeParameters = typeParameters,
+ _visibleLength = visibleLength,
+ _visibleOffset = visibleOffset;
fb.Offset finish(fb.Builder fbBuilder) {
assert(!_finished);
@@ -2648,8 +2744,12 @@
fb.Offset offset_annotations;
fb.Offset offset_constantInitializers;
fb.Offset offset_documentationComment;
+ fb.Offset offset_localFunctions;
+ fb.Offset offset_localVariables;
fb.Offset offset_name;
fb.Offset offset_parameters;
+ fb.Offset offset_redirectedConstructor;
+ fb.Offset offset_redirectedConstructorName;
fb.Offset offset_returnType;
fb.Offset offset_typeParameters;
if (!(_annotations == null || _annotations.isEmpty)) {
@@ -2661,12 +2761,24 @@
if (_documentationComment != null) {
offset_documentationComment = _documentationComment.finish(fbBuilder);
}
+ if (!(_localFunctions == null || _localFunctions.isEmpty)) {
+ offset_localFunctions = fbBuilder.writeList(_localFunctions.map((b) => b.finish(fbBuilder)).toList());
+ }
+ if (!(_localVariables == null || _localVariables.isEmpty)) {
+ offset_localVariables = fbBuilder.writeList(_localVariables.map((b) => b.finish(fbBuilder)).toList());
+ }
if (_name != null) {
offset_name = fbBuilder.writeString(_name);
}
if (!(_parameters == null || _parameters.isEmpty)) {
offset_parameters = fbBuilder.writeList(_parameters.map((b) => b.finish(fbBuilder)).toList());
}
+ if (_redirectedConstructor != null) {
+ offset_redirectedConstructor = _redirectedConstructor.finish(fbBuilder);
+ }
+ if (_redirectedConstructorName != null) {
+ offset_redirectedConstructorName = fbBuilder.writeString(_redirectedConstructorName);
+ }
if (_returnType != null) {
offset_returnType = _returnType.finish(fbBuilder);
}
@@ -2675,49 +2787,70 @@
}
fbBuilder.startTable();
if (offset_annotations != null) {
- fbBuilder.addOffset(0, offset_annotations);
+ fbBuilder.addOffset(6, offset_annotations);
}
if (offset_constantInitializers != null) {
- fbBuilder.addOffset(1, offset_constantInitializers);
+ fbBuilder.addOffset(14, offset_constantInitializers);
}
if (offset_documentationComment != null) {
- fbBuilder.addOffset(2, offset_documentationComment);
+ fbBuilder.addOffset(7, offset_documentationComment);
}
if (_inferredReturnTypeSlot != null && _inferredReturnTypeSlot != 0) {
- fbBuilder.addUint32(3, _inferredReturnTypeSlot);
+ fbBuilder.addUint32(5, _inferredReturnTypeSlot);
}
if (_isAbstract == true) {
- fbBuilder.addBool(4, true);
+ fbBuilder.addBool(10, true);
}
if (_isConst == true) {
- fbBuilder.addBool(5, true);
+ fbBuilder.addBool(12, true);
}
if (_isExternal == true) {
- fbBuilder.addBool(6, true);
+ fbBuilder.addBool(11, true);
}
if (_isFactory == true) {
- fbBuilder.addBool(7, true);
- }
- if (_isStatic == true) {
fbBuilder.addBool(8, true);
}
+ if (_isRedirectedConstructor == true) {
+ fbBuilder.addBool(13, true);
+ }
+ if (_isStatic == true) {
+ fbBuilder.addBool(9, true);
+ }
if (_kind != null && _kind != idl.UnlinkedExecutableKind.functionOrMethod) {
- fbBuilder.addUint32(9, _kind.index);
+ fbBuilder.addUint8(4, _kind.index);
+ }
+ if (offset_localFunctions != null) {
+ fbBuilder.addOffset(18, offset_localFunctions);
+ }
+ if (offset_localVariables != null) {
+ fbBuilder.addOffset(19, offset_localVariables);
}
if (offset_name != null) {
- fbBuilder.addOffset(10, offset_name);
+ fbBuilder.addOffset(1, offset_name);
}
if (_nameOffset != null && _nameOffset != 0) {
- fbBuilder.addUint32(11, _nameOffset);
+ fbBuilder.addUint32(0, _nameOffset);
}
if (offset_parameters != null) {
- fbBuilder.addOffset(12, offset_parameters);
+ fbBuilder.addOffset(2, offset_parameters);
+ }
+ if (offset_redirectedConstructor != null) {
+ fbBuilder.addOffset(15, offset_redirectedConstructor);
+ }
+ if (offset_redirectedConstructorName != null) {
+ fbBuilder.addOffset(17, offset_redirectedConstructorName);
}
if (offset_returnType != null) {
- fbBuilder.addOffset(13, offset_returnType);
+ fbBuilder.addOffset(3, offset_returnType);
}
if (offset_typeParameters != null) {
- fbBuilder.addOffset(14, offset_typeParameters);
+ fbBuilder.addOffset(16, offset_typeParameters);
+ }
+ if (_visibleLength != null && _visibleLength != 0) {
+ fbBuilder.addUint32(20, _visibleLength);
+ }
+ if (_visibleOffset != null && _visibleOffset != 0) {
+ fbBuilder.addUint32(21, _visibleOffset);
}
return fbBuilder.endTable();
}
@@ -2743,103 +2876,152 @@
bool _isConst;
bool _isExternal;
bool _isFactory;
+ bool _isRedirectedConstructor;
bool _isStatic;
idl.UnlinkedExecutableKind _kind;
+ List<idl.UnlinkedExecutable> _localFunctions;
+ List<idl.UnlinkedVariable> _localVariables;
String _name;
int _nameOffset;
List<idl.UnlinkedParam> _parameters;
+ idl.EntityRef _redirectedConstructor;
+ String _redirectedConstructorName;
idl.EntityRef _returnType;
List<idl.UnlinkedTypeParam> _typeParameters;
+ int _visibleLength;
+ int _visibleOffset;
@override
List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 6, const <idl.UnlinkedConst>[]);
return _annotations;
}
@override
List<idl.UnlinkedConstructorInitializer> get constantInitializers {
- _constantInitializers ??= const fb.ListReader<idl.UnlinkedConstructorInitializer>(const _UnlinkedConstructorInitializerReader()).vTableGet(_bp, 1, const <idl.UnlinkedConstructorInitializer>[]);
+ _constantInitializers ??= const fb.ListReader<idl.UnlinkedConstructorInitializer>(const _UnlinkedConstructorInitializerReader()).vTableGet(_bp, 14, const <idl.UnlinkedConstructorInitializer>[]);
return _constantInitializers;
}
@override
idl.UnlinkedDocumentationComment get documentationComment {
- _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 2, null);
+ _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 7, null);
return _documentationComment;
}
@override
int get inferredReturnTypeSlot {
- _inferredReturnTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+ _inferredReturnTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 5, 0);
return _inferredReturnTypeSlot;
}
@override
bool get isAbstract {
- _isAbstract ??= const fb.BoolReader().vTableGet(_bp, 4, false);
+ _isAbstract ??= const fb.BoolReader().vTableGet(_bp, 10, false);
return _isAbstract;
}
@override
bool get isConst {
- _isConst ??= const fb.BoolReader().vTableGet(_bp, 5, false);
+ _isConst ??= const fb.BoolReader().vTableGet(_bp, 12, false);
return _isConst;
}
@override
bool get isExternal {
- _isExternal ??= const fb.BoolReader().vTableGet(_bp, 6, false);
+ _isExternal ??= const fb.BoolReader().vTableGet(_bp, 11, false);
return _isExternal;
}
@override
bool get isFactory {
- _isFactory ??= const fb.BoolReader().vTableGet(_bp, 7, false);
+ _isFactory ??= const fb.BoolReader().vTableGet(_bp, 8, false);
return _isFactory;
}
@override
+ bool get isRedirectedConstructor {
+ _isRedirectedConstructor ??= const fb.BoolReader().vTableGet(_bp, 13, false);
+ return _isRedirectedConstructor;
+ }
+
+ @override
bool get isStatic {
- _isStatic ??= const fb.BoolReader().vTableGet(_bp, 8, false);
+ _isStatic ??= const fb.BoolReader().vTableGet(_bp, 9, false);
return _isStatic;
}
@override
idl.UnlinkedExecutableKind get kind {
- _kind ??= const _UnlinkedExecutableKindReader().vTableGet(_bp, 9, idl.UnlinkedExecutableKind.functionOrMethod);
+ _kind ??= const _UnlinkedExecutableKindReader().vTableGet(_bp, 4, idl.UnlinkedExecutableKind.functionOrMethod);
return _kind;
}
@override
+ List<idl.UnlinkedExecutable> get localFunctions {
+ _localFunctions ??= const fb.ListReader<idl.UnlinkedExecutable>(const _UnlinkedExecutableReader()).vTableGet(_bp, 18, const <idl.UnlinkedExecutable>[]);
+ return _localFunctions;
+ }
+
+ @override
+ List<idl.UnlinkedVariable> get localVariables {
+ _localVariables ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 19, const <idl.UnlinkedVariable>[]);
+ return _localVariables;
+ }
+
+ @override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 10, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 1, '');
return _name;
}
@override
int get nameOffset {
- _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 11, 0);
+ _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
return _nameOffset;
}
@override
List<idl.UnlinkedParam> get parameters {
- _parameters ??= const fb.ListReader<idl.UnlinkedParam>(const _UnlinkedParamReader()).vTableGet(_bp, 12, const <idl.UnlinkedParam>[]);
+ _parameters ??= const fb.ListReader<idl.UnlinkedParam>(const _UnlinkedParamReader()).vTableGet(_bp, 2, const <idl.UnlinkedParam>[]);
return _parameters;
}
@override
+ idl.EntityRef get redirectedConstructor {
+ _redirectedConstructor ??= const _EntityRefReader().vTableGet(_bp, 15, null);
+ return _redirectedConstructor;
+ }
+
+ @override
+ String get redirectedConstructorName {
+ _redirectedConstructorName ??= const fb.StringReader().vTableGet(_bp, 17, '');
+ return _redirectedConstructorName;
+ }
+
+ @override
idl.EntityRef get returnType {
- _returnType ??= const _EntityRefReader().vTableGet(_bp, 13, null);
+ _returnType ??= const _EntityRefReader().vTableGet(_bp, 3, null);
return _returnType;
}
@override
List<idl.UnlinkedTypeParam> get typeParameters {
- _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 14, const <idl.UnlinkedTypeParam>[]);
+ _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 16, const <idl.UnlinkedTypeParam>[]);
return _typeParameters;
}
+
+ @override
+ int get visibleLength {
+ _visibleLength ??= const fb.Uint32Reader().vTableGet(_bp, 20, 0);
+ return _visibleLength;
+ }
+
+ @override
+ int get visibleOffset {
+ _visibleOffset ??= const fb.Uint32Reader().vTableGet(_bp, 21, 0);
+ return _visibleOffset;
+ }
}
abstract class _UnlinkedExecutableMixin implements idl.UnlinkedExecutable {
@@ -2853,13 +3035,20 @@
"isConst": isConst,
"isExternal": isExternal,
"isFactory": isFactory,
+ "isRedirectedConstructor": isRedirectedConstructor,
"isStatic": isStatic,
"kind": kind,
+ "localFunctions": localFunctions,
+ "localVariables": localVariables,
"name": name,
"nameOffset": nameOffset,
"parameters": parameters,
+ "redirectedConstructor": redirectedConstructor,
+ "redirectedConstructorName": redirectedConstructorName,
"returnType": returnType,
"typeParameters": typeParameters,
+ "visibleLength": visibleLength,
+ "visibleOffset": visibleOffset,
};
}
@@ -2935,16 +3124,16 @@
}
fbBuilder.startTable();
if (offset_annotations != null) {
- fbBuilder.addOffset(0, offset_annotations);
+ fbBuilder.addOffset(3, offset_annotations);
}
if (_offset != null && _offset != 0) {
- fbBuilder.addUint32(1, _offset);
+ fbBuilder.addUint32(0, _offset);
}
if (_uriEnd != null && _uriEnd != 0) {
- fbBuilder.addUint32(2, _uriEnd);
+ fbBuilder.addUint32(1, _uriEnd);
}
if (_uriOffset != null && _uriOffset != 0) {
- fbBuilder.addUint32(3, _uriOffset);
+ fbBuilder.addUint32(2, _uriOffset);
}
return fbBuilder.endTable();
}
@@ -2969,25 +3158,25 @@
@override
List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 3, const <idl.UnlinkedConst>[]);
return _annotations;
}
@override
int get offset {
- _offset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+ _offset ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
return _offset;
}
@override
int get uriEnd {
- _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+ _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
return _uriEnd;
}
@override
int get uriOffset {
- _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+ _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
return _uriOffset;
}
}
@@ -3047,10 +3236,10 @@
}
fbBuilder.startTable();
if (offset_combinators != null) {
- fbBuilder.addOffset(0, offset_combinators);
+ fbBuilder.addOffset(1, offset_combinators);
}
if (offset_uri != null) {
- fbBuilder.addOffset(1, offset_uri);
+ fbBuilder.addOffset(0, offset_uri);
}
return fbBuilder.endTable();
}
@@ -3073,13 +3262,13 @@
@override
List<idl.UnlinkedCombinator> get combinators {
- _combinators ??= const fb.ListReader<idl.UnlinkedCombinator>(const _UnlinkedCombinatorReader()).vTableGet(_bp, 0, const <idl.UnlinkedCombinator>[]);
+ _combinators ??= const fb.ListReader<idl.UnlinkedCombinator>(const _UnlinkedCombinatorReader()).vTableGet(_bp, 1, const <idl.UnlinkedCombinator>[]);
return _combinators;
}
@override
String get uri {
- _uri ??= const fb.StringReader().vTableGet(_bp, 1, '');
+ _uri ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _uri;
}
}
@@ -3257,34 +3446,34 @@
}
fbBuilder.startTable();
if (offset_annotations != null) {
- fbBuilder.addOffset(0, offset_annotations);
+ fbBuilder.addOffset(8, offset_annotations);
}
if (offset_combinators != null) {
- fbBuilder.addOffset(1, offset_combinators);
+ fbBuilder.addOffset(4, offset_combinators);
}
if (_isDeferred == true) {
- fbBuilder.addBool(2, true);
+ fbBuilder.addBool(9, true);
}
if (_isImplicit == true) {
- fbBuilder.addBool(3, true);
+ fbBuilder.addBool(5, true);
}
if (_offset != null && _offset != 0) {
- fbBuilder.addUint32(4, _offset);
+ fbBuilder.addUint32(0, _offset);
}
if (_prefixOffset != null && _prefixOffset != 0) {
- fbBuilder.addUint32(5, _prefixOffset);
+ fbBuilder.addUint32(6, _prefixOffset);
}
if (_prefixReference != null && _prefixReference != 0) {
- fbBuilder.addUint32(6, _prefixReference);
+ fbBuilder.addUint32(7, _prefixReference);
}
if (offset_uri != null) {
- fbBuilder.addOffset(7, offset_uri);
+ fbBuilder.addOffset(1, offset_uri);
}
if (_uriEnd != null && _uriEnd != 0) {
- fbBuilder.addUint32(8, _uriEnd);
+ fbBuilder.addUint32(2, _uriEnd);
}
if (_uriOffset != null && _uriOffset != 0) {
- fbBuilder.addUint32(9, _uriOffset);
+ fbBuilder.addUint32(3, _uriOffset);
}
return fbBuilder.endTable();
}
@@ -3315,61 +3504,61 @@
@override
List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 8, const <idl.UnlinkedConst>[]);
return _annotations;
}
@override
List<idl.UnlinkedCombinator> get combinators {
- _combinators ??= const fb.ListReader<idl.UnlinkedCombinator>(const _UnlinkedCombinatorReader()).vTableGet(_bp, 1, const <idl.UnlinkedCombinator>[]);
+ _combinators ??= const fb.ListReader<idl.UnlinkedCombinator>(const _UnlinkedCombinatorReader()).vTableGet(_bp, 4, const <idl.UnlinkedCombinator>[]);
return _combinators;
}
@override
bool get isDeferred {
- _isDeferred ??= const fb.BoolReader().vTableGet(_bp, 2, false);
+ _isDeferred ??= const fb.BoolReader().vTableGet(_bp, 9, false);
return _isDeferred;
}
@override
bool get isImplicit {
- _isImplicit ??= const fb.BoolReader().vTableGet(_bp, 3, false);
+ _isImplicit ??= const fb.BoolReader().vTableGet(_bp, 5, false);
return _isImplicit;
}
@override
int get offset {
- _offset ??= const fb.Uint32Reader().vTableGet(_bp, 4, 0);
+ _offset ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
return _offset;
}
@override
int get prefixOffset {
- _prefixOffset ??= const fb.Uint32Reader().vTableGet(_bp, 5, 0);
+ _prefixOffset ??= const fb.Uint32Reader().vTableGet(_bp, 6, 0);
return _prefixOffset;
}
@override
int get prefixReference {
- _prefixReference ??= const fb.Uint32Reader().vTableGet(_bp, 6, 0);
+ _prefixReference ??= const fb.Uint32Reader().vTableGet(_bp, 7, 0);
return _prefixReference;
}
@override
String get uri {
- _uri ??= const fb.StringReader().vTableGet(_bp, 7, '');
+ _uri ??= const fb.StringReader().vTableGet(_bp, 1, '');
return _uri;
}
@override
int get uriEnd {
- _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 8, 0);
+ _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
return _uriEnd;
}
@override
int get uriOffset {
- _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 9, 0);
+ _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
return _uriOffset;
}
}
@@ -3403,6 +3592,8 @@
int _nameOffset;
List<UnlinkedParamBuilder> _parameters;
EntityRefBuilder _type;
+ int _visibleLength;
+ int _visibleOffset;
@override
List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
@@ -3529,7 +3720,31 @@
_type = _value;
}
- UnlinkedParamBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder defaultValue, int inferredTypeSlot, bool isFunctionTyped, bool isInitializingFormal, idl.UnlinkedParamKind kind, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder type})
+ @override
+ int get visibleLength => _visibleLength ??= 0;
+
+ /**
+ * The length of the visible range.
+ */
+ void set visibleLength(int _value) {
+ assert(!_finished);
+ assert(_value == null || _value >= 0);
+ _visibleLength = _value;
+ }
+
+ @override
+ int get visibleOffset => _visibleOffset ??= 0;
+
+ /**
+ * The beginning of the visible range.
+ */
+ void set visibleOffset(int _value) {
+ assert(!_finished);
+ assert(_value == null || _value >= 0);
+ _visibleOffset = _value;
+ }
+
+ UnlinkedParamBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder defaultValue, int inferredTypeSlot, bool isFunctionTyped, bool isInitializingFormal, idl.UnlinkedParamKind kind, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder type, int visibleLength, int visibleOffset})
: _annotations = annotations,
_defaultValue = defaultValue,
_inferredTypeSlot = inferredTypeSlot,
@@ -3539,7 +3754,9 @@
_name = name,
_nameOffset = nameOffset,
_parameters = parameters,
- _type = type;
+ _type = type,
+ _visibleLength = visibleLength,
+ _visibleOffset = visibleOffset;
fb.Offset finish(fb.Builder fbBuilder) {
assert(!_finished);
@@ -3566,34 +3783,40 @@
}
fbBuilder.startTable();
if (offset_annotations != null) {
- fbBuilder.addOffset(0, offset_annotations);
+ fbBuilder.addOffset(9, offset_annotations);
}
if (offset_defaultValue != null) {
- fbBuilder.addOffset(1, offset_defaultValue);
+ fbBuilder.addOffset(7, offset_defaultValue);
}
if (_inferredTypeSlot != null && _inferredTypeSlot != 0) {
fbBuilder.addUint32(2, _inferredTypeSlot);
}
if (_isFunctionTyped == true) {
- fbBuilder.addBool(3, true);
+ fbBuilder.addBool(5, true);
}
if (_isInitializingFormal == true) {
- fbBuilder.addBool(4, true);
+ fbBuilder.addBool(6, true);
}
if (_kind != null && _kind != idl.UnlinkedParamKind.required) {
- fbBuilder.addUint32(5, _kind.index);
+ fbBuilder.addUint8(4, _kind.index);
}
if (offset_name != null) {
- fbBuilder.addOffset(6, offset_name);
+ fbBuilder.addOffset(0, offset_name);
}
if (_nameOffset != null && _nameOffset != 0) {
- fbBuilder.addUint32(7, _nameOffset);
+ fbBuilder.addUint32(1, _nameOffset);
}
if (offset_parameters != null) {
fbBuilder.addOffset(8, offset_parameters);
}
if (offset_type != null) {
- fbBuilder.addOffset(9, offset_type);
+ fbBuilder.addOffset(3, offset_type);
+ }
+ if (_visibleLength != null && _visibleLength != 0) {
+ fbBuilder.addUint32(10, _visibleLength);
+ }
+ if (_visibleOffset != null && _visibleOffset != 0) {
+ fbBuilder.addUint32(11, _visibleOffset);
}
return fbBuilder.endTable();
}
@@ -3621,16 +3844,18 @@
int _nameOffset;
List<idl.UnlinkedParam> _parameters;
idl.EntityRef _type;
+ int _visibleLength;
+ int _visibleOffset;
@override
List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 9, const <idl.UnlinkedConst>[]);
return _annotations;
}
@override
idl.UnlinkedConst get defaultValue {
- _defaultValue ??= const _UnlinkedConstReader().vTableGet(_bp, 1, null);
+ _defaultValue ??= const _UnlinkedConstReader().vTableGet(_bp, 7, null);
return _defaultValue;
}
@@ -3642,31 +3867,31 @@
@override
bool get isFunctionTyped {
- _isFunctionTyped ??= const fb.BoolReader().vTableGet(_bp, 3, false);
+ _isFunctionTyped ??= const fb.BoolReader().vTableGet(_bp, 5, false);
return _isFunctionTyped;
}
@override
bool get isInitializingFormal {
- _isInitializingFormal ??= const fb.BoolReader().vTableGet(_bp, 4, false);
+ _isInitializingFormal ??= const fb.BoolReader().vTableGet(_bp, 6, false);
return _isInitializingFormal;
}
@override
idl.UnlinkedParamKind get kind {
- _kind ??= const _UnlinkedParamKindReader().vTableGet(_bp, 5, idl.UnlinkedParamKind.required);
+ _kind ??= const _UnlinkedParamKindReader().vTableGet(_bp, 4, idl.UnlinkedParamKind.required);
return _kind;
}
@override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 6, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _name;
}
@override
int get nameOffset {
- _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 7, 0);
+ _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
return _nameOffset;
}
@@ -3678,9 +3903,21 @@
@override
idl.EntityRef get type {
- _type ??= const _EntityRefReader().vTableGet(_bp, 9, null);
+ _type ??= const _EntityRefReader().vTableGet(_bp, 3, null);
return _type;
}
+
+ @override
+ int get visibleLength {
+ _visibleLength ??= const fb.Uint32Reader().vTableGet(_bp, 10, 0);
+ return _visibleLength;
+ }
+
+ @override
+ int get visibleOffset {
+ _visibleOffset ??= const fb.Uint32Reader().vTableGet(_bp, 11, 0);
+ return _visibleOffset;
+ }
}
abstract class _UnlinkedParamMixin implements idl.UnlinkedParam {
@@ -3696,6 +3933,8 @@
"nameOffset": nameOffset,
"parameters": parameters,
"type": type,
+ "visibleLength": visibleLength,
+ "visibleOffset": visibleOffset,
};
}
@@ -3757,13 +3996,13 @@
}
fbBuilder.startTable();
if (offset_annotations != null) {
- fbBuilder.addOffset(0, offset_annotations);
+ fbBuilder.addOffset(2, offset_annotations);
}
if (_uriEnd != null && _uriEnd != 0) {
- fbBuilder.addUint32(1, _uriEnd);
+ fbBuilder.addUint32(0, _uriEnd);
}
if (_uriOffset != null && _uriOffset != 0) {
- fbBuilder.addUint32(2, _uriOffset);
+ fbBuilder.addUint32(1, _uriOffset);
}
return fbBuilder.endTable();
}
@@ -3787,19 +4026,19 @@
@override
List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 2, const <idl.UnlinkedConst>[]);
return _annotations;
}
@override
int get uriEnd {
- _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+ _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
return _uriEnd;
}
@override
int get uriOffset {
- _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+ _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
return _uriOffset;
}
}
@@ -3816,25 +4055,12 @@
class UnlinkedPublicNameBuilder extends Object with _UnlinkedPublicNameMixin implements idl.UnlinkedPublicName {
bool _finished = false;
- List<UnlinkedPublicNameBuilder> _constMembers;
idl.ReferenceKind _kind;
+ List<UnlinkedPublicNameBuilder> _members;
String _name;
int _numTypeParameters;
@override
- List<UnlinkedPublicNameBuilder> get constMembers => _constMembers ??= <UnlinkedPublicNameBuilder>[];
-
- /**
- * If this [UnlinkedPublicName] is a class, the list of members which can be
- * referenced from constants - static constant fields, static methods, and
- * constructors. Otherwise empty.
- */
- void set constMembers(List<UnlinkedPublicNameBuilder> _value) {
- assert(!_finished);
- _constMembers = _value;
- }
-
- @override
idl.ReferenceKind get kind => _kind ??= idl.ReferenceKind.classOrEnum;
/**
@@ -3846,6 +4072,22 @@
}
@override
+ List<UnlinkedPublicNameBuilder> get members => _members ??= <UnlinkedPublicNameBuilder>[];
+
+ /**
+ * If this [UnlinkedPublicName] is a class, the list of members which can be
+ * referenced from constants or factory redirects - static constant fields,
+ * static methods, and constructors. Otherwise empty.
+ *
+ * Unnamed constructors are not included since they do not constitute a
+ * separate name added to any namespace.
+ */
+ void set members(List<UnlinkedPublicNameBuilder> _value) {
+ assert(!_finished);
+ _members = _value;
+ }
+
+ @override
String get name => _name ??= '';
/**
@@ -3869,32 +4111,32 @@
_numTypeParameters = _value;
}
- UnlinkedPublicNameBuilder({List<UnlinkedPublicNameBuilder> constMembers, idl.ReferenceKind kind, String name, int numTypeParameters})
- : _constMembers = constMembers,
- _kind = kind,
+ UnlinkedPublicNameBuilder({idl.ReferenceKind kind, List<UnlinkedPublicNameBuilder> members, String name, int numTypeParameters})
+ : _kind = kind,
+ _members = members,
_name = name,
_numTypeParameters = numTypeParameters;
fb.Offset finish(fb.Builder fbBuilder) {
assert(!_finished);
_finished = true;
- fb.Offset offset_constMembers;
+ fb.Offset offset_members;
fb.Offset offset_name;
- if (!(_constMembers == null || _constMembers.isEmpty)) {
- offset_constMembers = fbBuilder.writeList(_constMembers.map((b) => b.finish(fbBuilder)).toList());
+ if (!(_members == null || _members.isEmpty)) {
+ offset_members = fbBuilder.writeList(_members.map((b) => b.finish(fbBuilder)).toList());
}
if (_name != null) {
offset_name = fbBuilder.writeString(_name);
}
fbBuilder.startTable();
- if (offset_constMembers != null) {
- fbBuilder.addOffset(0, offset_constMembers);
- }
if (_kind != null && _kind != idl.ReferenceKind.classOrEnum) {
- fbBuilder.addUint32(1, _kind.index);
+ fbBuilder.addUint8(1, _kind.index);
+ }
+ if (offset_members != null) {
+ fbBuilder.addOffset(2, offset_members);
}
if (offset_name != null) {
- fbBuilder.addOffset(2, offset_name);
+ fbBuilder.addOffset(0, offset_name);
}
if (_numTypeParameters != null && _numTypeParameters != 0) {
fbBuilder.addUint32(3, _numTypeParameters);
@@ -3915,26 +4157,26 @@
_UnlinkedPublicNameImpl(this._bp);
- List<idl.UnlinkedPublicName> _constMembers;
idl.ReferenceKind _kind;
+ List<idl.UnlinkedPublicName> _members;
String _name;
int _numTypeParameters;
@override
- List<idl.UnlinkedPublicName> get constMembers {
- _constMembers ??= const fb.ListReader<idl.UnlinkedPublicName>(const _UnlinkedPublicNameReader()).vTableGet(_bp, 0, const <idl.UnlinkedPublicName>[]);
- return _constMembers;
- }
-
- @override
idl.ReferenceKind get kind {
_kind ??= const _ReferenceKindReader().vTableGet(_bp, 1, idl.ReferenceKind.classOrEnum);
return _kind;
}
@override
+ List<idl.UnlinkedPublicName> get members {
+ _members ??= const fb.ListReader<idl.UnlinkedPublicName>(const _UnlinkedPublicNameReader()).vTableGet(_bp, 2, const <idl.UnlinkedPublicName>[]);
+ return _members;
+ }
+
+ @override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 2, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _name;
}
@@ -3948,8 +4190,8 @@
abstract class _UnlinkedPublicNameMixin implements idl.UnlinkedPublicName {
@override
Map<String, Object> toMap() => {
- "constMembers": constMembers,
"kind": kind,
+ "members": members,
"name": name,
"numTypeParameters": numTypeParameters,
};
@@ -4025,13 +4267,13 @@
}
fbBuilder.startTable();
if (offset_exports != null) {
- fbBuilder.addOffset(0, offset_exports);
+ fbBuilder.addOffset(2, offset_exports);
}
if (offset_names != null) {
- fbBuilder.addOffset(1, offset_names);
+ fbBuilder.addOffset(0, offset_names);
}
if (offset_parts != null) {
- fbBuilder.addOffset(2, offset_parts);
+ fbBuilder.addOffset(1, offset_parts);
}
return fbBuilder.endTable();
}
@@ -4060,19 +4302,19 @@
@override
List<idl.UnlinkedExportPublic> get exports {
- _exports ??= const fb.ListReader<idl.UnlinkedExportPublic>(const _UnlinkedExportPublicReader()).vTableGet(_bp, 0, const <idl.UnlinkedExportPublic>[]);
+ _exports ??= const fb.ListReader<idl.UnlinkedExportPublic>(const _UnlinkedExportPublicReader()).vTableGet(_bp, 2, const <idl.UnlinkedExportPublic>[]);
return _exports;
}
@override
List<idl.UnlinkedPublicName> get names {
- _names ??= const fb.ListReader<idl.UnlinkedPublicName>(const _UnlinkedPublicNameReader()).vTableGet(_bp, 1, const <idl.UnlinkedPublicName>[]);
+ _names ??= const fb.ListReader<idl.UnlinkedPublicName>(const _UnlinkedPublicNameReader()).vTableGet(_bp, 0, const <idl.UnlinkedPublicName>[]);
return _names;
}
@override
List<String> get parts {
- _parts ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 2, const <String>[]);
+ _parts ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
return _parts;
}
}
@@ -4307,25 +4549,25 @@
}
fbBuilder.startTable();
if (offset_annotations != null) {
- fbBuilder.addOffset(0, offset_annotations);
+ fbBuilder.addOffset(4, offset_annotations);
}
if (offset_documentationComment != null) {
- fbBuilder.addOffset(1, offset_documentationComment);
+ fbBuilder.addOffset(6, offset_documentationComment);
}
if (offset_name != null) {
- fbBuilder.addOffset(2, offset_name);
+ fbBuilder.addOffset(0, offset_name);
}
if (_nameOffset != null && _nameOffset != 0) {
- fbBuilder.addUint32(3, _nameOffset);
+ fbBuilder.addUint32(1, _nameOffset);
}
if (offset_parameters != null) {
- fbBuilder.addOffset(4, offset_parameters);
+ fbBuilder.addOffset(3, offset_parameters);
}
if (offset_returnType != null) {
- fbBuilder.addOffset(5, offset_returnType);
+ fbBuilder.addOffset(2, offset_returnType);
}
if (offset_typeParameters != null) {
- fbBuilder.addOffset(6, offset_typeParameters);
+ fbBuilder.addOffset(5, offset_typeParameters);
}
return fbBuilder.endTable();
}
@@ -4353,43 +4595,43 @@
@override
List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 4, const <idl.UnlinkedConst>[]);
return _annotations;
}
@override
idl.UnlinkedDocumentationComment get documentationComment {
- _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 1, null);
+ _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 6, null);
return _documentationComment;
}
@override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 2, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _name;
}
@override
int get nameOffset {
- _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+ _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
return _nameOffset;
}
@override
List<idl.UnlinkedParam> get parameters {
- _parameters ??= const fb.ListReader<idl.UnlinkedParam>(const _UnlinkedParamReader()).vTableGet(_bp, 4, const <idl.UnlinkedParam>[]);
+ _parameters ??= const fb.ListReader<idl.UnlinkedParam>(const _UnlinkedParamReader()).vTableGet(_bp, 3, const <idl.UnlinkedParam>[]);
return _parameters;
}
@override
idl.EntityRef get returnType {
- _returnType ??= const _EntityRefReader().vTableGet(_bp, 5, null);
+ _returnType ??= const _EntityRefReader().vTableGet(_bp, 2, null);
return _returnType;
}
@override
List<idl.UnlinkedTypeParam> get typeParameters {
- _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 6, const <idl.UnlinkedTypeParam>[]);
+ _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bp, 5, const <idl.UnlinkedTypeParam>[]);
return _typeParameters;
}
}
@@ -4484,16 +4726,16 @@
}
fbBuilder.startTable();
if (offset_annotations != null) {
- fbBuilder.addOffset(0, offset_annotations);
+ fbBuilder.addOffset(3, offset_annotations);
}
if (offset_bound != null) {
- fbBuilder.addOffset(1, offset_bound);
+ fbBuilder.addOffset(2, offset_bound);
}
if (offset_name != null) {
- fbBuilder.addOffset(2, offset_name);
+ fbBuilder.addOffset(0, offset_name);
}
if (_nameOffset != null && _nameOffset != 0) {
- fbBuilder.addUint32(3, _nameOffset);
+ fbBuilder.addUint32(1, _nameOffset);
}
return fbBuilder.endTable();
}
@@ -4518,25 +4760,25 @@
@override
List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 3, const <idl.UnlinkedConst>[]);
return _annotations;
}
@override
idl.EntityRef get bound {
- _bound ??= const _EntityRefReader().vTableGet(_bp, 1, null);
+ _bound ??= const _EntityRefReader().vTableGet(_bp, 2, null);
return _bound;
}
@override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 2, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _name;
}
@override
int get nameOffset {
- _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+ _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
return _nameOffset;
}
}
@@ -4825,49 +5067,49 @@
}
fbBuilder.startTable();
if (offset_classes != null) {
- fbBuilder.addOffset(0, offset_classes);
+ fbBuilder.addOffset(2, offset_classes);
}
if (offset_enums != null) {
- fbBuilder.addOffset(1, offset_enums);
+ fbBuilder.addOffset(12, offset_enums);
}
if (offset_executables != null) {
- fbBuilder.addOffset(2, offset_executables);
+ fbBuilder.addOffset(4, offset_executables);
}
if (offset_exports != null) {
- fbBuilder.addOffset(3, offset_exports);
+ fbBuilder.addOffset(13, offset_exports);
}
if (offset_imports != null) {
- fbBuilder.addOffset(4, offset_imports);
+ fbBuilder.addOffset(5, offset_imports);
}
if (offset_libraryAnnotations != null) {
- fbBuilder.addOffset(5, offset_libraryAnnotations);
+ fbBuilder.addOffset(14, offset_libraryAnnotations);
}
if (offset_libraryDocumentationComment != null) {
- fbBuilder.addOffset(6, offset_libraryDocumentationComment);
+ fbBuilder.addOffset(9, offset_libraryDocumentationComment);
}
if (offset_libraryName != null) {
- fbBuilder.addOffset(7, offset_libraryName);
+ fbBuilder.addOffset(6, offset_libraryName);
}
if (_libraryNameLength != null && _libraryNameLength != 0) {
- fbBuilder.addUint32(8, _libraryNameLength);
+ fbBuilder.addUint32(7, _libraryNameLength);
}
if (_libraryNameOffset != null && _libraryNameOffset != 0) {
- fbBuilder.addUint32(9, _libraryNameOffset);
+ fbBuilder.addUint32(8, _libraryNameOffset);
}
if (offset_parts != null) {
- fbBuilder.addOffset(10, offset_parts);
+ fbBuilder.addOffset(11, offset_parts);
}
if (offset_publicNamespace != null) {
- fbBuilder.addOffset(11, offset_publicNamespace);
+ fbBuilder.addOffset(0, offset_publicNamespace);
}
if (offset_references != null) {
- fbBuilder.addOffset(12, offset_references);
+ fbBuilder.addOffset(1, offset_references);
}
if (offset_typedefs != null) {
- fbBuilder.addOffset(13, offset_typedefs);
+ fbBuilder.addOffset(10, offset_typedefs);
}
if (offset_variables != null) {
- fbBuilder.addOffset(14, offset_variables);
+ fbBuilder.addOffset(3, offset_variables);
}
return fbBuilder.endTable();
}
@@ -4908,91 +5150,91 @@
@override
List<idl.UnlinkedClass> get classes {
- _classes ??= const fb.ListReader<idl.UnlinkedClass>(const _UnlinkedClassReader()).vTableGet(_bp, 0, const <idl.UnlinkedClass>[]);
+ _classes ??= const fb.ListReader<idl.UnlinkedClass>(const _UnlinkedClassReader()).vTableGet(_bp, 2, const <idl.UnlinkedClass>[]);
return _classes;
}
@override
List<idl.UnlinkedEnum> get enums {
- _enums ??= const fb.ListReader<idl.UnlinkedEnum>(const _UnlinkedEnumReader()).vTableGet(_bp, 1, const <idl.UnlinkedEnum>[]);
+ _enums ??= const fb.ListReader<idl.UnlinkedEnum>(const _UnlinkedEnumReader()).vTableGet(_bp, 12, const <idl.UnlinkedEnum>[]);
return _enums;
}
@override
List<idl.UnlinkedExecutable> get executables {
- _executables ??= const fb.ListReader<idl.UnlinkedExecutable>(const _UnlinkedExecutableReader()).vTableGet(_bp, 2, const <idl.UnlinkedExecutable>[]);
+ _executables ??= const fb.ListReader<idl.UnlinkedExecutable>(const _UnlinkedExecutableReader()).vTableGet(_bp, 4, const <idl.UnlinkedExecutable>[]);
return _executables;
}
@override
List<idl.UnlinkedExportNonPublic> get exports {
- _exports ??= const fb.ListReader<idl.UnlinkedExportNonPublic>(const _UnlinkedExportNonPublicReader()).vTableGet(_bp, 3, const <idl.UnlinkedExportNonPublic>[]);
+ _exports ??= const fb.ListReader<idl.UnlinkedExportNonPublic>(const _UnlinkedExportNonPublicReader()).vTableGet(_bp, 13, const <idl.UnlinkedExportNonPublic>[]);
return _exports;
}
@override
List<idl.UnlinkedImport> get imports {
- _imports ??= const fb.ListReader<idl.UnlinkedImport>(const _UnlinkedImportReader()).vTableGet(_bp, 4, const <idl.UnlinkedImport>[]);
+ _imports ??= const fb.ListReader<idl.UnlinkedImport>(const _UnlinkedImportReader()).vTableGet(_bp, 5, const <idl.UnlinkedImport>[]);
return _imports;
}
@override
List<idl.UnlinkedConst> get libraryAnnotations {
- _libraryAnnotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 5, const <idl.UnlinkedConst>[]);
+ _libraryAnnotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 14, const <idl.UnlinkedConst>[]);
return _libraryAnnotations;
}
@override
idl.UnlinkedDocumentationComment get libraryDocumentationComment {
- _libraryDocumentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 6, null);
+ _libraryDocumentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 9, null);
return _libraryDocumentationComment;
}
@override
String get libraryName {
- _libraryName ??= const fb.StringReader().vTableGet(_bp, 7, '');
+ _libraryName ??= const fb.StringReader().vTableGet(_bp, 6, '');
return _libraryName;
}
@override
int get libraryNameLength {
- _libraryNameLength ??= const fb.Uint32Reader().vTableGet(_bp, 8, 0);
+ _libraryNameLength ??= const fb.Uint32Reader().vTableGet(_bp, 7, 0);
return _libraryNameLength;
}
@override
int get libraryNameOffset {
- _libraryNameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 9, 0);
+ _libraryNameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 8, 0);
return _libraryNameOffset;
}
@override
List<idl.UnlinkedPart> get parts {
- _parts ??= const fb.ListReader<idl.UnlinkedPart>(const _UnlinkedPartReader()).vTableGet(_bp, 10, const <idl.UnlinkedPart>[]);
+ _parts ??= const fb.ListReader<idl.UnlinkedPart>(const _UnlinkedPartReader()).vTableGet(_bp, 11, const <idl.UnlinkedPart>[]);
return _parts;
}
@override
idl.UnlinkedPublicNamespace get publicNamespace {
- _publicNamespace ??= const _UnlinkedPublicNamespaceReader().vTableGet(_bp, 11, null);
+ _publicNamespace ??= const _UnlinkedPublicNamespaceReader().vTableGet(_bp, 0, null);
return _publicNamespace;
}
@override
List<idl.UnlinkedReference> get references {
- _references ??= const fb.ListReader<idl.UnlinkedReference>(const _UnlinkedReferenceReader()).vTableGet(_bp, 12, const <idl.UnlinkedReference>[]);
+ _references ??= const fb.ListReader<idl.UnlinkedReference>(const _UnlinkedReferenceReader()).vTableGet(_bp, 1, const <idl.UnlinkedReference>[]);
return _references;
}
@override
List<idl.UnlinkedTypedef> get typedefs {
- _typedefs ??= const fb.ListReader<idl.UnlinkedTypedef>(const _UnlinkedTypedefReader()).vTableGet(_bp, 13, const <idl.UnlinkedTypedef>[]);
+ _typedefs ??= const fb.ListReader<idl.UnlinkedTypedef>(const _UnlinkedTypedefReader()).vTableGet(_bp, 10, const <idl.UnlinkedTypedef>[]);
return _typedefs;
}
@override
List<idl.UnlinkedVariable> get variables {
- _variables ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 14, const <idl.UnlinkedVariable>[]);
+ _variables ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 3, const <idl.UnlinkedVariable>[]);
return _variables;
}
}
@@ -5032,6 +5274,8 @@
int _nameOffset;
int _propagatedTypeSlot;
EntityRefBuilder _type;
+ int _visibleLength;
+ int _visibleOffset;
@override
List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
@@ -5172,7 +5416,31 @@
_type = _value;
}
- UnlinkedVariableBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder constExpr, UnlinkedDocumentationCommentBuilder documentationComment, int inferredTypeSlot, bool isConst, bool isFinal, bool isStatic, String name, int nameOffset, int propagatedTypeSlot, EntityRefBuilder type})
+ @override
+ int get visibleLength => _visibleLength ??= 0;
+
+ /**
+ * If a local variable, the length of the visible range; zero otherwise.
+ */
+ void set visibleLength(int _value) {
+ assert(!_finished);
+ assert(_value == null || _value >= 0);
+ _visibleLength = _value;
+ }
+
+ @override
+ int get visibleOffset => _visibleOffset ??= 0;
+
+ /**
+ * If a local variable, the beginning of the visible range; zero otherwise.
+ */
+ void set visibleOffset(int _value) {
+ assert(!_finished);
+ assert(_value == null || _value >= 0);
+ _visibleOffset = _value;
+ }
+
+ UnlinkedVariableBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder constExpr, UnlinkedDocumentationCommentBuilder documentationComment, int inferredTypeSlot, bool isConst, bool isFinal, bool isStatic, String name, int nameOffset, int propagatedTypeSlot, EntityRefBuilder type, int visibleLength, int visibleOffset})
: _annotations = annotations,
_constExpr = constExpr,
_documentationComment = documentationComment,
@@ -5183,7 +5451,9 @@
_name = name,
_nameOffset = nameOffset,
_propagatedTypeSlot = propagatedTypeSlot,
- _type = type;
+ _type = type,
+ _visibleLength = visibleLength,
+ _visibleOffset = visibleOffset;
fb.Offset finish(fb.Builder fbBuilder) {
assert(!_finished);
@@ -5210,37 +5480,43 @@
}
fbBuilder.startTable();
if (offset_annotations != null) {
- fbBuilder.addOffset(0, offset_annotations);
+ fbBuilder.addOffset(8, offset_annotations);
}
if (offset_constExpr != null) {
- fbBuilder.addOffset(1, offset_constExpr);
+ fbBuilder.addOffset(5, offset_constExpr);
}
if (offset_documentationComment != null) {
- fbBuilder.addOffset(2, offset_documentationComment);
+ fbBuilder.addOffset(10, offset_documentationComment);
}
if (_inferredTypeSlot != null && _inferredTypeSlot != 0) {
- fbBuilder.addUint32(3, _inferredTypeSlot);
+ fbBuilder.addUint32(9, _inferredTypeSlot);
}
if (_isConst == true) {
- fbBuilder.addBool(4, true);
- }
- if (_isFinal == true) {
- fbBuilder.addBool(5, true);
- }
- if (_isStatic == true) {
fbBuilder.addBool(6, true);
}
+ if (_isFinal == true) {
+ fbBuilder.addBool(7, true);
+ }
+ if (_isStatic == true) {
+ fbBuilder.addBool(4, true);
+ }
if (offset_name != null) {
- fbBuilder.addOffset(7, offset_name);
+ fbBuilder.addOffset(0, offset_name);
}
if (_nameOffset != null && _nameOffset != 0) {
- fbBuilder.addUint32(8, _nameOffset);
+ fbBuilder.addUint32(1, _nameOffset);
}
if (_propagatedTypeSlot != null && _propagatedTypeSlot != 0) {
- fbBuilder.addUint32(9, _propagatedTypeSlot);
+ fbBuilder.addUint32(2, _propagatedTypeSlot);
}
if (offset_type != null) {
- fbBuilder.addOffset(10, offset_type);
+ fbBuilder.addOffset(3, offset_type);
+ }
+ if (_visibleLength != null && _visibleLength != 0) {
+ fbBuilder.addUint32(11, _visibleLength);
+ }
+ if (_visibleOffset != null && _visibleOffset != 0) {
+ fbBuilder.addUint32(12, _visibleOffset);
}
return fbBuilder.endTable();
}
@@ -5269,72 +5545,86 @@
int _nameOffset;
int _propagatedTypeSlot;
idl.EntityRef _type;
+ int _visibleLength;
+ int _visibleOffset;
@override
List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 0, const <idl.UnlinkedConst>[]);
+ _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bp, 8, const <idl.UnlinkedConst>[]);
return _annotations;
}
@override
idl.UnlinkedConst get constExpr {
- _constExpr ??= const _UnlinkedConstReader().vTableGet(_bp, 1, null);
+ _constExpr ??= const _UnlinkedConstReader().vTableGet(_bp, 5, null);
return _constExpr;
}
@override
idl.UnlinkedDocumentationComment get documentationComment {
- _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 2, null);
+ _documentationComment ??= const _UnlinkedDocumentationCommentReader().vTableGet(_bp, 10, null);
return _documentationComment;
}
@override
int get inferredTypeSlot {
- _inferredTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+ _inferredTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 9, 0);
return _inferredTypeSlot;
}
@override
bool get isConst {
- _isConst ??= const fb.BoolReader().vTableGet(_bp, 4, false);
+ _isConst ??= const fb.BoolReader().vTableGet(_bp, 6, false);
return _isConst;
}
@override
bool get isFinal {
- _isFinal ??= const fb.BoolReader().vTableGet(_bp, 5, false);
+ _isFinal ??= const fb.BoolReader().vTableGet(_bp, 7, false);
return _isFinal;
}
@override
bool get isStatic {
- _isStatic ??= const fb.BoolReader().vTableGet(_bp, 6, false);
+ _isStatic ??= const fb.BoolReader().vTableGet(_bp, 4, false);
return _isStatic;
}
@override
String get name {
- _name ??= const fb.StringReader().vTableGet(_bp, 7, '');
+ _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
return _name;
}
@override
int get nameOffset {
- _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 8, 0);
+ _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
return _nameOffset;
}
@override
int get propagatedTypeSlot {
- _propagatedTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 9, 0);
+ _propagatedTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
return _propagatedTypeSlot;
}
@override
idl.EntityRef get type {
- _type ??= const _EntityRefReader().vTableGet(_bp, 10, null);
+ _type ??= const _EntityRefReader().vTableGet(_bp, 3, null);
return _type;
}
+
+ @override
+ int get visibleLength {
+ _visibleLength ??= const fb.Uint32Reader().vTableGet(_bp, 11, 0);
+ return _visibleLength;
+ }
+
+ @override
+ int get visibleOffset {
+ _visibleOffset ??= const fb.Uint32Reader().vTableGet(_bp, 12, 0);
+ return _visibleOffset;
+ }
}
abstract class _UnlinkedVariableMixin implements idl.UnlinkedVariable {
@@ -5351,6 +5641,8 @@
"nameOffset": nameOffset,
"propagatedTypeSlot": propagatedTypeSlot,
"type": type,
+ "visibleLength": visibleLength,
+ "visibleOffset": visibleOffset,
};
}
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 6ec0ded..fca673c 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -42,29 +42,17 @@
library analyzer.tool.summary.idl;
import 'base.dart' as base;
+import 'base.dart' show Id;
import 'format.dart' as generated;
/**
* Annotation describing information which is not part of Dart semantics; in
* other words, if this information (or any information it refers to) changes,
* static analysis and runtime behavior of the library are unaffected.
- *
- * TODO(paulberry): some informative information is currently missing from the
- * summary format.
*/
const informative = null;
/**
- * Annotation describing information which is not part of the public API to a
- * library; in other words, if this information (or any information it refers
- * to) changes, libraries outside this one are unaffected.
- *
- * TODO(paulberry): currently the summary format does not contain private
- * information.
- */
-const private = null;
-
-/**
* Annotation describing a class which can be the top level object in an
* encoded summary.
*/
@@ -97,6 +85,7 @@
* generic class, then the type arguments in [typeArguments] are applied
* first to the class and then to the method.
*/
+ @Id(4)
List<int> get implicitFunctionTypeIndices;
/**
@@ -118,12 +107,14 @@
* If the type being referred to is not a type parameter, [paramReference] is
* zero.
*/
+ @Id(3)
int get paramReference;
/**
* Index into [UnlinkedUnit.references] for the entity being referred to, or
* zero if this is a reference to a type parameter.
*/
+ @Id(0)
int get reference;
/**
@@ -133,6 +124,7 @@
*
* Otherwise zero.
*/
+ @Id(2)
int get slot;
/**
@@ -140,6 +132,7 @@
* type arguments used to instantiate it. Trailing type arguments of type
* `dynamic` are omitted.
*/
+ @Id(1)
List<EntityRef> get typeArguments;
}
@@ -152,6 +145,7 @@
* URI for the compilation units listed in the library's `part` declarations.
* These URIs are relative to the importing library.
*/
+ @Id(1)
List<String> get parts;
/**
@@ -161,6 +155,7 @@
* `d/e.dart`, the URI listed for `a.dart`'s dependency on `e.dart` will be
* `b/d/e.dart`.
*/
+ @Id(0)
String get uri;
}
@@ -173,17 +168,20 @@
* Index into [LinkedLibrary.dependencies] for the library in which the
* entity is defined.
*/
+ @Id(0)
int get dependency;
/**
* The kind of the entity being referred to.
*/
+ @Id(3)
ReferenceKind get kind;
/**
* Name of the exported entity. For an exported setter, this name includes
* the trailing '='.
*/
+ @Id(1)
String get name;
/**
@@ -192,6 +190,7 @@
* zero represents the defining compilation unit, and nonzero values
* represent parts in the order of the corresponding `part` declarations.
*/
+ @Id(2)
int get unit;
}
@@ -219,6 +218,7 @@
* anti-dependency (e.g. the result of type propagation or type inference
* depends on the lack of a certain declaration in the library).
*/
+ @Id(0)
List<LinkedDependency> get dependencies;
/**
@@ -228,12 +228,14 @@
*
* Sorted by name.
*/
+ @Id(4)
List<LinkedExportName> get exportNames;
/**
* For each import in [UnlinkedUnit.imports], an index into [dependencies]
* of the library being imported.
*/
+ @Id(1)
List<int> get importDependencies;
/**
@@ -241,6 +243,7 @@
* dependencies (that is, the number of libraries in the direct imports plus
* the transitive closure of exports, plus the library itself).
*/
+ @Id(2)
int get numPrelinkedDependencies;
/**
@@ -249,6 +252,7 @@
* followed by the summary of each part, in the order of the `part`
* declarations in the defining compilation unit.
*/
+ @Id(3)
List<LinkedUnit> get units;
}
@@ -267,6 +271,7 @@
* LinkedUnit.references[i].containingReference != 0, then
* LinkedUnit.references[i].containingReference < i.
*/
+ @Id(5)
int get containingReference;
/**
@@ -276,12 +281,14 @@
* Zero if this entity is contained within another entity (e.g. a class
* member), or if [kind] is [ReferenceKind.prefix].
*/
+ @Id(1)
int get dependency;
/**
* The kind of the entity being referred to. For the pseudo-types `dynamic`
* and `void`, the kind is [ReferenceKind.classOrEnum].
*/
+ @Id(2)
ReferenceKind get kind;
/**
@@ -289,12 +296,14 @@
* name of the entity being referred to. For the pseudo-type `dynamic`, the
* string is "dynamic". For the pseudo-type `void`, the string is "void".
*/
+ @Id(3)
String get name;
/**
* If the entity being referred to is generic, the number of type parameters
* it accepts. Otherwise zero.
*/
+ @Id(4)
int get numTypeParameters;
/**
@@ -306,6 +315,7 @@
* Zero if this entity is contained within another entity (e.g. a class
* member).
*/
+ @Id(0)
int get unit;
}
@@ -321,12 +331,14 @@
* additional elements are references that are only referred to implicitly
* (e.g. elements involved in inferred or propagated types).
*/
+ @Id(0)
List<LinkedReference> get references;
/**
* List associating slot ids found inside the unlinked summary for the
* compilation unit with propagated and inferred types.
*/
+ @Id(1)
List<EntityRef> get types;
}
@@ -399,21 +411,25 @@
/**
* Linked libraries.
*/
+ @Id(0)
List<LinkedLibrary> get linkedLibraries;
/**
* The list of URIs of items in [linkedLibraries], e.g. `dart:core`.
*/
+ @Id(1)
List<String> get linkedLibraryUris;
/**
* Unlinked information for the compilation units constituting the SDK.
*/
+ @Id(2)
List<UnlinkedUnit> get unlinkedUnits;
/**
* The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
*/
+ @Id(3)
List<String> get unlinkedUnitUris;
}
@@ -424,6 +440,7 @@
/**
* Annotations for this class.
*/
+ @Id(5)
List<UnlinkedConst> get annotations;
/**
@@ -431,53 +448,63 @@
* documentation comment.
*/
@informative
+ @Id(6)
UnlinkedDocumentationComment get documentationComment;
/**
* Executable objects (methods, getters, and setters) contained in the class.
*/
+ @Id(2)
List<UnlinkedExecutable> get executables;
/**
* Field declarations contained in the class.
*/
+ @Id(4)
List<UnlinkedVariable> get fields;
/**
* Indicates whether this class is the core "Object" class (and hence has no
* supertype)
*/
+ @Id(12)
bool get hasNoSupertype;
/**
* Interfaces appearing in an `implements` clause, if any.
*/
+ @Id(7)
List<EntityRef> get interfaces;
/**
* Indicates whether the class is declared with the `abstract` keyword.
*/
+ @Id(8)
bool get isAbstract;
/**
* Indicates whether the class is declared using mixin application syntax.
*/
+ @Id(11)
bool get isMixinApplication;
/**
* Mixins appearing in a `with` clause, if any.
*/
+ @Id(10)
List<EntityRef> get mixins;
/**
* Name of the class.
*/
+ @Id(0)
String get name;
/**
* Offset of the class name relative to the beginning of the file.
*/
@informative
+ @Id(1)
int get nameOffset;
/**
@@ -485,11 +512,13 @@
* explicitly declare a supertype (and hence has supertype `Object`), or (b)
* the class *is* `Object` (and hence has no supertype).
*/
+ @Id(3)
EntityRef get supertype;
/**
* Type parameters of the class, if any.
*/
+ @Id(9)
List<UnlinkedTypeParam> get typeParameters;
}
@@ -501,11 +530,13 @@
/**
* List of names which are hidden. Empty if this is a `show` combinator.
*/
+ @Id(1)
List<String> get hides;
/**
* List of names which are shown. Empty if this is a `hide` combinator.
*/
+ @Id(0)
List<String> get shows;
}
@@ -523,6 +554,7 @@
/**
* Sequence of 64-bit doubles consumed by the operation `pushDouble`.
*/
+ @Id(4)
List<double> get doubles;
/**
@@ -530,18 +562,21 @@
* `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
* `makeList`, and `makeMap`.
*/
+ @Id(1)
List<int> get ints;
/**
* Indicates whether the expression is not a valid potentially constant
* expression.
*/
+ @Id(5)
bool get isInvalid;
/**
* Sequence of operations to execute (starting with an empty stack) to form
* the constant value.
*/
+ @Id(0)
List<UnlinkedConstOperation> get operations;
/**
@@ -550,12 +585,14 @@
* that in the case of `pushReference` (and sometimes `invokeConstructor` the
* actual entity being referred to may be something other than a type.
*/
+ @Id(2)
List<EntityRef> get references;
/**
* Sequence of strings consumed by the operations `pushString` and
* `invokeConstructor`.
*/
+ @Id(3)
List<String> get strings;
}
@@ -857,17 +894,20 @@
* If [kind] is `thisInvocation` or `superInvocation`, the arguments of the
* invocation. Otherwise empty.
*/
+ @Id(3)
List<UnlinkedConst> get arguments;
/**
* If [kind] is `field`, the expression of the field initializer.
* Otherwise `null`.
*/
+ @Id(1)
UnlinkedConst get expression;
/**
* The kind of the constructor initializer (field, redirect, super).
*/
+ @Id(2)
UnlinkedConstructorInitializerKind get kind;
/**
@@ -876,6 +916,7 @@
* class, to redirect to. If [kind] is `superInvocation`, the name of the
* constructor, declared in the superclass, to invoke.
*/
+ @Id(0)
String get name;
}
@@ -906,12 +947,14 @@
/**
* Length of the documentation comment (prior to replacing '\r\n' with '\n').
*/
+ @Id(0)
int get length;
/**
* Offset of the beginning of the documentation comment relative to the
* beginning of the file.
*/
+ @Id(2)
int get offset;
/**
@@ -920,6 +963,7 @@
* References appearing within the doc comment in square brackets are not
* specially encoded.
*/
+ @Id(1)
String get text;
}
@@ -930,6 +974,7 @@
/**
* Annotations for this enum.
*/
+ @Id(4)
List<UnlinkedConst> get annotations;
/**
@@ -937,22 +982,26 @@
* comment.
*/
@informative
+ @Id(3)
UnlinkedDocumentationComment get documentationComment;
/**
* Name of the enum type.
*/
+ @Id(0)
String get name;
/**
* Offset of the enum name relative to the beginning of the file.
*/
@informative
+ @Id(1)
int get nameOffset;
/**
* Values listed in the enum declaration, in declaration order.
*/
+ @Id(2)
List<UnlinkedEnumValue> get values;
}
@@ -966,17 +1015,20 @@
* documentation comment.
*/
@informative
+ @Id(2)
UnlinkedDocumentationComment get documentationComment;
/**
* Name of the enumerated value.
*/
+ @Id(0)
String get name;
/**
* Offset of the enum value name relative to the beginning of the file.
*/
@informative
+ @Id(1)
int get nameOffset;
}
@@ -988,12 +1040,14 @@
/**
* Annotations for this executable.
*/
+ @Id(6)
List<UnlinkedConst> get annotations;
/**
* If a constant [UnlinkedExecutableKind.constructor], the constructor
* initializers. Otherwise empty.
*/
+ @Id(14)
List<UnlinkedConstructorInitializer> get constantInitializers;
/**
@@ -1001,6 +1055,7 @@
* documentation comment.
*/
@informative
+ @Id(7)
UnlinkedDocumentationComment get documentationComment;
/**
@@ -1010,48 +1065,74 @@
* no return type was inferred for this variable, so its static type is
* `dynamic`.
*/
+ @Id(5)
int get inferredReturnTypeSlot;
/**
* Indicates whether the executable is declared using the `abstract` keyword.
*/
+ @Id(10)
bool get isAbstract;
/**
* Indicates whether the executable is declared using the `const` keyword.
*/
+ @Id(12)
bool get isConst;
/**
* Indicates whether the executable is declared using the `external` keyword.
*/
+ @Id(11)
bool get isExternal;
/**
* Indicates whether the executable is declared using the `factory` keyword.
*/
+ @Id(8)
bool get isFactory;
/**
+ * Indicates whether the executable is a redirected constructor.
+ */
+ @Id(13)
+ bool get isRedirectedConstructor;
+
+ /**
* 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).
*/
+ @Id(9)
bool get isStatic;
/**
* The kind of the executable (function/method, getter, setter, or
* constructor).
*/
+ @Id(4)
UnlinkedExecutableKind get kind;
/**
+ * The list of local functions.
+ */
+ @Id(18)
+ List<UnlinkedExecutable> get localFunctions;
+
+ /**
+ * The list of local variables.
+ */
+ @Id(19)
+ List<UnlinkedVariable> get localVariables;
+
+ /**
* 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.
*/
+ @Id(1)
String get name;
/**
@@ -1061,6 +1142,7 @@
* offset of the second "C" in "class C { C(); }").
*/
@informative
+ @Id(0)
int get nameOffset;
/**
@@ -1068,19 +1150,49 @@
* parameters (hence this will be the empty list), and setters have a single
* parameter.
*/
+ @Id(2)
List<UnlinkedParam> get parameters;
/**
+ * If [isRedirectedConstructor] and [isFactory] are both `true`, the
+ * constructor to which this constructor redirects; otherwise empty.
+ */
+ @Id(15)
+ EntityRef get redirectedConstructor;
+
+ /**
+ * If [isRedirectedConstructor] is `true` and [isFactory] is `false`, the
+ * name of the constructor that this constructor redirects to; otherwise
+ * empty.
+ */
+ @Id(17)
+ String get redirectedConstructorName;
+
+ /**
* Declared return type of the executable. Absent if the executable is a
* constructor or the return type is implicit.
*/
+ @Id(3)
EntityRef get returnType;
/**
* Type parameters of the executable, if any. Empty if support for generic
* method syntax is disabled.
*/
+ @Id(16)
List<UnlinkedTypeParam> get typeParameters;
+
+ /**
+ * If a local function, the length of the visible range; zero otherwise.
+ */
+ @Id(20)
+ int get visibleLength;
+
+ /**
+ * If a local function, the beginning of the visible range; zero otherwise.
+ */
+ @Id(21)
+ int get visibleOffset;
}
/**
@@ -1116,12 +1228,14 @@
/**
* Annotations for this export directive.
*/
+ @Id(3)
List<UnlinkedConst> get annotations;
/**
* Offset of the "export" keyword.
*/
@informative
+ @Id(0)
int get offset;
/**
@@ -1129,6 +1243,7 @@
* file.
*/
@informative
+ @Id(1)
int get uriEnd;
/**
@@ -1136,6 +1251,7 @@
* the file.
*/
@informative
+ @Id(2)
int get uriOffset;
}
@@ -1147,11 +1263,13 @@
/**
* Combinators contained in this import declaration.
*/
+ @Id(1)
List<UnlinkedCombinator> get combinators;
/**
* URI used in the source code to reference the exported library.
*/
+ @Id(0)
String get uri;
}
@@ -1162,21 +1280,25 @@
/**
* Annotations for this import declaration.
*/
+ @Id(8)
List<UnlinkedConst> get annotations;
/**
* Combinators contained in this import declaration.
*/
+ @Id(4)
List<UnlinkedCombinator> get combinators;
/**
* Indicates whether the import declaration uses the `deferred` keyword.
*/
+ @Id(9)
bool get isDeferred;
/**
* Indicates whether the import declaration is implicit.
*/
+ @Id(5)
bool get isImplicit;
/**
@@ -1184,6 +1306,7 @@
* is true, zero.
*/
@informative
+ @Id(0)
int get offset;
/**
@@ -1191,6 +1314,7 @@
* if there is no prefix.
*/
@informative
+ @Id(6)
int get prefixOffset;
/**
@@ -1199,11 +1323,13 @@
*
* Note that multiple imports can declare the same prefix.
*/
+ @Id(7)
int get prefixReference;
/**
* URI used in the source code to reference the imported library.
*/
+ @Id(1)
String get uri;
/**
@@ -1211,6 +1337,7 @@
* file. If [isImplicit] is true, zero.
*/
@informative
+ @Id(2)
int get uriEnd;
/**
@@ -1218,6 +1345,7 @@
* the file. If [isImplicit] is true, zero.
*/
@informative
+ @Id(3)
int get uriOffset;
}
@@ -1228,6 +1356,7 @@
/**
* Annotations for this parameter.
*/
+ @Id(9)
List<UnlinkedConst> get annotations;
/**
@@ -1235,6 +1364,7 @@
* default value. Note that the presence of this expression does not mean
* that it is a valid, check [UnlinkedConst.isInvalid].
*/
+ @Id(7)
UnlinkedConst get defaultValue;
/**
@@ -1248,38 +1378,45 @@
* not specified, they always inherit the static type of the corresponding
* field.
*/
+ @Id(2)
int get inferredTypeSlot;
/**
* Indicates whether this is a function-typed parameter.
*/
+ @Id(5)
bool get isFunctionTyped;
/**
* Indicates whether this is an initializing formal parameter (i.e. it is
* declared using `this.` syntax).
*/
+ @Id(6)
bool get isInitializingFormal;
/**
* Kind of the parameter.
*/
+ @Id(4)
UnlinkedParamKind get kind;
/**
* Name of the parameter.
*/
+ @Id(0)
String get name;
/**
* Offset of the parameter name relative to the beginning of the file.
*/
@informative
+ @Id(1)
int get nameOffset;
/**
* If [isFunctionTyped] is `true`, the parameters of the function type.
*/
+ @Id(8)
List<UnlinkedParam> get parameters;
/**
@@ -1287,7 +1424,20 @@
* [isFunctionTyped] is `false`, the declared type. Absent if the type is
* implicit.
*/
+ @Id(3)
EntityRef get type;
+
+ /**
+ * The length of the visible range.
+ */
+ @Id(10)
+ int get visibleLength;
+
+ /**
+ * The beginning of the visible range.
+ */
+ @Id(11)
+ int get visibleOffset;
}
/**
@@ -1317,6 +1467,7 @@
/**
* Annotations for this part declaration.
*/
+ @Id(2)
List<UnlinkedConst> get annotations;
/**
@@ -1324,6 +1475,7 @@
* file.
*/
@informative
+ @Id(0)
int get uriEnd;
/**
@@ -1331,6 +1483,7 @@
* the file.
*/
@informative
+ @Id(1)
int get uriOffset;
}
@@ -1344,26 +1497,33 @@
*/
abstract class UnlinkedPublicName extends base.SummaryClass {
/**
- * If this [UnlinkedPublicName] is a class, the list of members which can be
- * referenced from constants - static constant fields, static methods, and
- * constructors. Otherwise empty.
- */
- List<UnlinkedPublicName> get constMembers;
-
- /**
* The kind of object referred to by the name.
*/
+ @Id(1)
ReferenceKind get kind;
/**
+ * If this [UnlinkedPublicName] is a class, the list of members which can be
+ * referenced from constants or factory redirects - static constant fields,
+ * static methods, and constructors. Otherwise empty.
+ *
+ * Unnamed constructors are not included since they do not constitute a
+ * separate name added to any namespace.
+ */
+ @Id(2)
+ List<UnlinkedPublicName> get members;
+
+ /**
* The name itself.
*/
+ @Id(0)
String get name;
/**
* If the entity being referred to is generic, the number of type parameters
* it accepts. Otherwise zero.
*/
+ @Id(3)
int get numTypeParameters;
}
@@ -1380,6 +1540,7 @@
/**
* Export declarations in the compilation unit.
*/
+ @Id(2)
List<UnlinkedExportPublic> get exports;
/**
@@ -1388,11 +1549,13 @@
* TODO(paulberry): consider sorting these names to reduce unnecessary
* relinking.
*/
+ @Id(0)
List<UnlinkedPublicName> get names;
/**
* URIs referenced by part declarations in the compilation unit.
*/
+ @Id(1)
List<String> get parts;
}
@@ -1405,6 +1568,7 @@
* Name of the entity being referred to. For the pseudo-type `dynamic`, the
* string is "dynamic". For the pseudo-type `void`, the string is "void".
*/
+ @Id(0)
String get name;
/**
@@ -1415,6 +1579,7 @@
* UnlinkedUnit.references[i].prefixReference != 0, then
* UnlinkedUnit.references[i].prefixReference < i.
*/
+ @Id(1)
int get prefixReference;
}
@@ -1425,6 +1590,7 @@
/**
* Annotations for this typedef.
*/
+ @Id(4)
List<UnlinkedConst> get annotations;
/**
@@ -1432,32 +1598,38 @@
* documentation comment.
*/
@informative
+ @Id(6)
UnlinkedDocumentationComment get documentationComment;
/**
* Name of the typedef.
*/
+ @Id(0)
String get name;
/**
* Offset of the typedef name relative to the beginning of the file.
*/
@informative
+ @Id(1)
int get nameOffset;
/**
* Parameters of the executable, if any.
*/
+ @Id(3)
List<UnlinkedParam> get parameters;
/**
* Return type of the typedef.
*/
+ @Id(2)
EntityRef get returnType;
/**
* Type parameters of the typedef, if any.
*/
+ @Id(5)
List<UnlinkedTypeParam> get typeParameters;
}
@@ -1468,23 +1640,27 @@
/**
* Annotations for this type parameter.
*/
+ @Id(3)
List<UnlinkedConst> get annotations;
/**
* Bound of the type parameter, if a bound is explicitly declared. Otherwise
* null.
*/
+ @Id(2)
EntityRef get bound;
/**
* Name of the type parameter.
*/
+ @Id(0)
String get name;
/**
* Offset of the type parameter name relative to the beginning of the file.
*/
@informative
+ @Id(1)
int get nameOffset;
}
@@ -1499,33 +1675,39 @@
/**
* Classes declared in the compilation unit.
*/
+ @Id(2)
List<UnlinkedClass> get classes;
/**
* Enums declared in the compilation unit.
*/
+ @Id(12)
List<UnlinkedEnum> get enums;
/**
* Top level executable objects (functions, getters, and setters) declared in
* the compilation unit.
*/
+ @Id(4)
List<UnlinkedExecutable> get executables;
/**
* Export declarations in the compilation unit.
*/
+ @Id(13)
List<UnlinkedExportNonPublic> get exports;
/**
* Import declarations in the compilation unit.
*/
+ @Id(5)
List<UnlinkedImport> get imports;
/**
* Annotations for the library declaration, or the empty list if there is no
* library declaration.
*/
+ @Id(14)
List<UnlinkedConst> get libraryAnnotations;
/**
@@ -1533,11 +1715,13 @@
* documentation comment.
*/
@informative
+ @Id(9)
UnlinkedDocumentationComment get libraryDocumentationComment;
/**
* Name of the library (from a "library" declaration, if present).
*/
+ @Id(6)
String get libraryName;
/**
@@ -1545,6 +1729,7 @@
* library has no name).
*/
@informative
+ @Id(7)
int get libraryNameLength;
/**
@@ -1552,16 +1737,19 @@
* the library has no name).
*/
@informative
+ @Id(8)
int get libraryNameOffset;
/**
* Part declarations in the compilation unit.
*/
+ @Id(11)
List<UnlinkedPart> get parts;
/**
* Unlinked public namespace of this compilation unit.
*/
+ @Id(0)
UnlinkedPublicNamespace get publicNamespace;
/**
@@ -1571,16 +1759,19 @@
* example [UnlinkedReference.prefixReference or
* UnlinkedImport.prefixReference]).
*/
+ @Id(1)
List<UnlinkedReference> get references;
/**
* Typedefs declared in the compilation unit.
*/
+ @Id(10)
List<UnlinkedTypedef> get typedefs;
/**
* Top level variables declared in the compilation unit.
*/
+ @Id(3)
List<UnlinkedVariable> get variables;
}
@@ -1592,6 +1783,7 @@
/**
* Annotations for this variable.
*/
+ @Id(8)
List<UnlinkedConst> get annotations;
/**
@@ -1599,6 +1791,7 @@
* expression in the initializer. Note that the presence of this expression
* does not mean that it is a valid, check [UnlinkedConst.isInvalid].
*/
+ @Id(5)
UnlinkedConst get constExpr;
/**
@@ -1606,6 +1799,7 @@
* documentation comment.
*/
@informative
+ @Id(10)
UnlinkedDocumentationComment get documentationComment;
/**
@@ -1614,16 +1808,19 @@
* there is no matching entry in [LinkedLibrary.types], then no type was
* inferred for this variable, so its static type is `dynamic`.
*/
+ @Id(9)
int get inferredTypeSlot;
/**
* Indicates whether the variable is declared using the `const` keyword.
*/
+ @Id(6)
bool get isConst;
/**
* Indicates whether the variable is declared using the `final` keyword.
*/
+ @Id(7)
bool get isFinal;
/**
@@ -1633,17 +1830,20 @@
* declared using the `static` keyword (even though they are considered
* static for semantic purposes).
*/
+ @Id(4)
bool get isStatic;
/**
* Name of the variable.
*/
+ @Id(0)
String get name;
/**
* Offset of the variable name relative to the beginning of the file.
*/
@informative
+ @Id(1)
int get nameOffset;
/**
@@ -1654,10 +1854,24 @@
*
* Non-propagable variables have a [propagatedTypeSlot] of zero.
*/
+ @Id(2)
int get propagatedTypeSlot;
/**
* Declared type of the variable. Absent if the type is implicit.
*/
+ @Id(3)
EntityRef get type;
+
+ /**
+ * If a local variable, the length of the visible range; zero otherwise.
+ */
+ @Id(11)
+ int get visibleLength;
+
+ /**
+ * If a local variable, the beginning of the visible range; zero otherwise.
+ */
+ @Id(12)
+ int get visibleOffset;
}
diff --git a/pkg/analyzer/lib/src/summary/prelink.dart b/pkg/analyzer/lib/src/summary/prelink.dart
index 82ab7c5..688abe5 100644
--- a/pkg/analyzer/lib/src/summary/prelink.dart
+++ b/pkg/analyzer/lib/src/summary/prelink.dart
@@ -194,9 +194,9 @@
aggregated.putIfAbsent(name.name, () {
if (name.kind == ReferenceKind.classOrEnum) {
Map<String, _Meaning> namespace = <String, _Meaning>{};
- name.constMembers.forEach((executable) {
- namespace[executable.name] = new _Meaning(unitNum,
- executable.kind, 0, executable.numTypeParameters);
+ name.members.forEach((executable) {
+ namespace[executable.name] = new _Meaning(
+ unitNum, executable.kind, 0, executable.numTypeParameters);
});
return new _ClassMeaning(
unitNum, dependency, name.numTypeParameters, namespace);
@@ -267,15 +267,14 @@
});
cls.executables.forEach((executable) {
ReferenceKind kind = null;
- if (executable.kind == UnlinkedExecutableKind.constructor &&
- executable.isConst) {
+ if (executable.kind == UnlinkedExecutableKind.constructor) {
kind = ReferenceKind.constructor;
} else if (executable.kind ==
UnlinkedExecutableKind.functionOrMethod &&
executable.isStatic) {
kind = ReferenceKind.method;
}
- if (kind != null) {
+ if (kind != null && executable.name.isNotEmpty) {
namespace[executable.name] = new _Meaning(
unitNum, kind, 0, executable.typeParameters.length);
}
@@ -424,6 +423,11 @@
continue;
}
}
+ // Anything prefixed with 'unresolved' is unresolved.
+ if (references[reference.prefixReference].kind ==
+ ReferenceKind.unresolved) {
+ namespace = const <String, _Meaning>{};
+ }
// Prefix references must always point to proper prefixes.
assert(namespace != null);
}
diff --git a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
index 4edd4cd..d6210db 100644
--- a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
+++ b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
@@ -71,7 +71,7 @@
for (VariableDeclaration field in member.fields.variables) {
String name = field.name.name;
if (isPublic(name)) {
- cls.constMembers.add(new UnlinkedPublicNameBuilder(
+ cls.members.add(new UnlinkedPublicNameBuilder(
name: name,
kind: ReferenceKind.propertyAccessor,
numTypeParameters: 0));
@@ -85,17 +85,18 @@
!member.isOperator) {
String name = member.name.name;
if (isPublic(name)) {
- cls.constMembers.add(new UnlinkedPublicNameBuilder(
+ cls.members.add(new UnlinkedPublicNameBuilder(
name: name,
kind: ReferenceKind.method,
numTypeParameters:
member.typeParameters?.typeParameters?.length ?? 0));
}
}
- if (member is ConstructorDeclaration && member.constKeyword != null) {
- String name = member.name != null ? member.name.name : '';
+ if (member is ConstructorDeclaration &&
+ member.name != null) {
+ String name = member.name.name;
if (isPublic(name)) {
- cls.constMembers.add(new UnlinkedPublicNameBuilder(
+ cls.members.add(new UnlinkedPublicNameBuilder(
name: name,
kind: ReferenceKind.constructor,
numTypeParameters: 0));
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 0a71496..de64232 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -7,6 +7,7 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
@@ -15,7 +16,6 @@
import 'package:analyzer/src/generated/element_handle.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/testing/ast_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
@@ -57,6 +57,14 @@
final bool strongMode;
/**
+ * Map of compilation units resynthesized from summaries. The two map keys
+ * are the first two elements of the element's location (the library URI and
+ * the compilation unit URI).
+ */
+ final Map<String, Map<String, CompilationUnitElement>> _resynthesizedUnits =
+ <String, Map<String, CompilationUnitElement>>{};
+
+ /**
* Map of top level elements resynthesized from summaries. The three map
* keys are the first three elements of the element's location (the library
* URI, the compilation unit URI, and the name of the top level declaration).
@@ -101,6 +109,20 @@
// Resynthesize locally.
if (components.length == 1) {
return getLibraryElement(libraryUri);
+ } else if (components.length == 2) {
+ Map<String, CompilationUnitElement> libraryMap =
+ _resynthesizedUnits[libraryUri];
+ if (libraryMap == null) {
+ getLibraryElement(libraryUri);
+ libraryMap = _resynthesizedUnits[libraryUri];
+ assert(libraryMap != null);
+ }
+ String unitUri = components[1];
+ CompilationUnitElement element = libraryMap[unitUri];
+ if (element == null) {
+ throw new Exception('Unit element not found in summary: $location');
+ }
+ return element;
} else if (components.length == 3 || components.length == 4) {
Map<String, Map<String, Element>> libraryMap =
_resynthesizedElements[libraryUri];
@@ -169,7 +191,8 @@
_LibraryResynthesizer libraryResynthesizer = new _LibraryResynthesizer(
this, serializedLibrary, serializedUnits, librarySource);
LibraryElement library = libraryResynthesizer.buildLibrary();
- _resynthesizedElements[uri] = libraryResynthesizer.resummarizedElements;
+ _resynthesizedUnits[uri] = libraryResynthesizer.resynthesizedUnits;
+ _resynthesizedElements[uri] = libraryResynthesizer.resynthesizedElements;
return library;
});
}
@@ -416,13 +439,9 @@
case UnlinkedConstOperation.pushReference:
EntityRef ref = uc.references[refPtr++];
_ReferenceInfo info = resynthesizer.referenceInfos[ref.reference];
- if (info.element != null) {
- SimpleIdentifier node = AstFactory.identifier3(info.name);
- node.staticElement = info.element;
- _push(node);
- } else {
- throw new StateError('Unsupported reference ${ref.toMap()}');
- }
+ SimpleIdentifier node = AstFactory.identifier3(info.name);
+ node.staticElement = info.element;
+ _push(node);
break;
case UnlinkedConstOperation.invokeConstructor:
_pushInstanceCreation();
@@ -467,28 +486,6 @@
throw new StateError('Unsupported type $type');
}
- /**
- * Return the [ConstructorElement] by applying [typeArgumentRefs] to the
- * given linked [info]. Both cases when [info] is a [ClassElement] and
- * [ConstructorElement] are supported.
- */
- _DeferredConstructorElement _createConstructorElement(
- _ReferenceInfo info, List<EntityRef> typeArgumentRefs) {
- bool isClass = info.element is ClassElement;
- _ReferenceInfo classInfo = isClass ? info : info.enclosing;
- List<DartType> typeArguments =
- typeArgumentRefs.map(resynthesizer.buildType).toList();
- InterfaceType classType = classInfo.buildType((i) {
- if (i < typeArguments.length) {
- return typeArguments[i];
- } else {
- return DynamicTypeImpl.instance;
- }
- }, const <int>[]);
- String name = isClass ? '' : info.name;
- return new _DeferredConstructorElement(classType, name);
- }
-
InterpolationElement _newInterpolationElement(Expression expr) {
if (expr is SimpleStringLiteral) {
return new InterpolationString(expr.literal, expr.value);
@@ -526,17 +523,51 @@
EntityRef ref = uc.references[refPtr++];
_ReferenceInfo info = resynthesizer.referenceInfos[ref.reference];
// prepare ConstructorElement
+ TypeName typeNode;
String constructorName;
- if (info.element is ConstructorElement) {
- constructorName = info.name;
- } else if (info.element is ClassElement) {
- constructorName = null;
+ ConstructorElement constructorElement;
+ if (info.element != null) {
+ if (info.element is ConstructorElement) {
+ constructorName = info.name;
+ } else if (info.element is ClassElement) {
+ constructorName = null;
+ } else {
+ throw new StateError('Unsupported element for invokeConstructor '
+ '${info.element?.runtimeType}');
+ }
+ InterfaceType definingType =
+ resynthesizer._createConstructorDefiningType(info, ref.typeArguments);
+ constructorElement =
+ resynthesizer._createConstructorElement(definingType, info);
+ typeNode = _buildTypeAst(definingType);
} else {
- throw new StateError('Unsupported element for invokeConstructor '
- '${info.element?.runtimeType}');
+ if (info.enclosing != null) {
+ if (info.enclosing.enclosing != null) {
+ PrefixedIdentifier typeName = AstFactory.identifier5(
+ info.enclosing.enclosing.name, info.enclosing.name);
+ typeName.prefix.staticElement = info.enclosing.enclosing.element;
+ typeName.identifier.staticElement = info.enclosing.element;
+ typeName.identifier.staticType = info.enclosing.type;
+ typeNode = AstFactory.typeName3(typeName);
+ typeNode.type = info.enclosing.type;
+ constructorName = info.name;
+ } else if (info.enclosing.element != null) {
+ SimpleIdentifier typeName =
+ AstFactory.identifier3(info.enclosing.name);
+ typeName.staticElement = info.enclosing.element;
+ typeName.staticType = info.enclosing.type;
+ typeNode = AstFactory.typeName3(typeName);
+ typeNode.type = info.enclosing.type;
+ constructorName = info.name;
+ } else {
+ typeNode = AstFactory.typeName3(
+ AstFactory.identifier5(info.enclosing.name, info.name));
+ constructorName = null;
+ }
+ } else {
+ typeNode = AstFactory.typeName4(info.name);
+ }
}
- _DeferredConstructorElement constructorElement =
- _createConstructorElement(info, ref.typeArguments);
// prepare arguments
List<Expression> arguments;
{
@@ -551,8 +582,6 @@
arguments[index] = AstFactory.namedExpression2(name, arguments[index]);
}
}
- // create TypeName
- TypeName typeNode = _buildTypeAst(constructorElement.definingType);
// create ConstructorName
ConstructorName constructorNode;
if (constructorName != null) {
@@ -606,11 +635,20 @@
/**
* The constructor element that has been resynthesized from a summary. The
* actual element won't be constructed until it is requested. But properties
- * [definingType], [displayName], [enclosingElement] and [name] can be used
- * without creating the actual element.
+ * [displayName], [enclosingElement] and [name] can be used without creating
+ * the actual element.
*/
class _DeferredConstructorElement extends ConstructorElementHandle {
- final InterfaceType definingType;
+ /**
+ * The type defining this constructor element. If [_isMember] is `false`,
+ * then the type parameters of [_definingType] are not guaranteed to be
+ * valid.
+ */
+ final InterfaceType _definingType;
+
+ /**
+ * The constructor name.
+ */
final String name;
factory _DeferredConstructorElement(InterfaceType definingType, String name) {
@@ -621,24 +659,21 @@
}
_DeferredConstructorElement._(
- this.definingType, this.name, ElementLocation location)
+ this._definingType, this.name, ElementLocation location)
: super(null, location);
@override
- Element get actualElement {
- ConstructorElement element = enclosingElement.getNamedConstructor(name);
- return new ConstructorMember(element, definingType);
- }
+ Element get actualElement => enclosingElement.getNamedConstructor(name);
@override
- AnalysisContext get context => definingType.element.context;
+ AnalysisContext get context => _definingType.element.context;
@override
String get displayName => name;
@override
ClassElement get enclosingElement {
- return definingType.element;
+ return _definingType.element;
}
}
@@ -714,23 +749,32 @@
ConstructorElementImpl currentConstructor;
/**
+ * Map of compilation unit elements that have been resynthesized so far. The
+ * key is the URI of the compilation unit.
+ */
+ final Map<String, CompilationUnitElement> resynthesizedUnits =
+ <String, CompilationUnitElement>{};
+
+ /**
* Map of top level elements that have been resynthesized so far. The first
* key is the URI of the compilation unit; the second is the name of the top
* level element.
*/
- final Map<String, Map<String, Element>> resummarizedElements =
+ final Map<String, Map<String, Element>> resynthesizedElements =
<String, Map<String, Element>>{};
/**
* Type parameters for the generic class, typedef, or executable currently
- * being resynthesized, if any. If multiple entities with type parameters
- * are nested (e.g. a generic executable inside a generic class), this is the
- * concatenation of all type parameters from all declarations currently in
- * force, with the outermost declaration appearing first. If there are no
- * type parameters, or we are not currently resynthesizing a class, typedef,
- * or executable, then this is an empty list.
+ * being resynthesized, if any. This is a list of lists; if multiple
+ * entities with type parameters are nested (e.g. a generic executable inside
+ * a generic class), then the zeroth element of [currentTypeParameters]
+ * contains the type parameters for the outermost nested entity, and further
+ * elements contain the type parameters for entities that are more deeply
+ * nested. If we are not currently resynthesizing a class, typedef, or
+ * executable, then this is an empty list.
*/
- List<TypeParameterElement> currentTypeParameters = <TypeParameterElement>[];
+ final List<List<TypeParameterElement>> currentTypeParameters =
+ <List<TypeParameterElement>>[];
/**
* If a class is currently being resynthesized, map from field name to the
@@ -758,13 +802,6 @@
}
/**
- * Return a list of type arguments corresponding to [currentTypeParameters].
- */
- List<TypeParameterType> get currentTypeArguments => currentTypeParameters
- ?.map((TypeParameterElement param) => param.type)
- ?.toList();
-
- /**
* Build the annotations for the given [element].
*/
void buildAnnotations(
@@ -802,80 +839,78 @@
* Resynthesize a [ClassElement] and place it in [unitHolder].
*/
void buildClass(UnlinkedClass serializedClass) {
- try {
- currentTypeParameters =
- serializedClass.typeParameters.map(buildTypeParameter).toList();
- for (int i = 0; i < serializedClass.typeParameters.length; i++) {
- finishTypeParameter(
- serializedClass.typeParameters[i], currentTypeParameters[i]);
+ ClassElementImpl classElement =
+ new ClassElementImpl(serializedClass.name, serializedClass.nameOffset);
+ classElement.typeParameters =
+ buildTypeParameters(serializedClass.typeParameters);
+ classElement.abstract = serializedClass.isAbstract;
+ classElement.mixinApplication = serializedClass.isMixinApplication;
+ InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement);
+ if (serializedClass.supertype != null) {
+ classElement.supertype = buildType(serializedClass.supertype);
+ } else if (!serializedClass.hasNoSupertype) {
+ if (isCoreLibrary) {
+ delayedObjectSubclasses.add(classElement);
+ } else {
+ classElement.supertype = summaryResynthesizer.typeProvider.objectType;
}
- ClassElementImpl classElement = new ClassElementImpl(
- serializedClass.name, serializedClass.nameOffset);
- classElement.abstract = serializedClass.isAbstract;
- classElement.mixinApplication = serializedClass.isMixinApplication;
- InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement);
- if (serializedClass.supertype != null) {
- classElement.supertype = buildType(serializedClass.supertype);
- } else if (!serializedClass.hasNoSupertype) {
- if (isCoreLibrary) {
- delayedObjectSubclasses.add(classElement);
- } else {
- classElement.supertype = summaryResynthesizer.typeProvider.objectType;
- }
- }
- classElement.interfaces =
- serializedClass.interfaces.map(buildType).toList();
- classElement.mixins = serializedClass.mixins.map(buildType).toList();
- classElement.typeParameters = currentTypeParameters;
- ElementHolder memberHolder = new ElementHolder();
- fields = <String, FieldElementImpl>{};
- for (UnlinkedVariable serializedVariable in serializedClass.fields) {
- buildVariable(serializedVariable, memberHolder);
- }
- bool constructorFound = false;
- constructors = <String, ConstructorElementImpl>{};
- for (UnlinkedExecutable serializedExecutable
- in serializedClass.executables) {
- switch (serializedExecutable.kind) {
- case UnlinkedExecutableKind.constructor:
- constructorFound = true;
- buildConstructor(
- serializedExecutable, memberHolder, correspondingType);
- break;
- case UnlinkedExecutableKind.functionOrMethod:
- case UnlinkedExecutableKind.getter:
- case UnlinkedExecutableKind.setter:
- buildExecutable(serializedExecutable, memberHolder);
- break;
- }
- }
- if (!serializedClass.isMixinApplication) {
- if (!constructorFound) {
- // Synthesize implicit constructors.
- ConstructorElementImpl constructor =
- new ConstructorElementImpl('', -1);
- constructor.synthetic = true;
- constructor.returnType = correspondingType;
- constructor.type = new FunctionTypeImpl.elementWithNameAndArgs(
- constructor, null, currentTypeArguments, false);
- memberHolder.addConstructor(constructor);
- }
- classElement.constructors = memberHolder.constructors;
- }
- classElement.accessors = memberHolder.accessors;
- classElement.fields = memberHolder.fields;
- classElement.methods = memberHolder.methods;
- correspondingType.typeArguments = currentTypeArguments;
- classElement.type = correspondingType;
- buildDocumentation(classElement, serializedClass.documentationComment);
- buildAnnotations(classElement, serializedClass.annotations);
- resolveConstructorInitializers(classElement);
- unitHolder.addType(classElement);
- } finally {
- currentTypeParameters = <TypeParameterElement>[];
- fields = null;
- constructors = null;
}
+ classElement.interfaces =
+ serializedClass.interfaces.map(buildType).toList();
+ classElement.mixins = serializedClass.mixins.map(buildType).toList();
+ ElementHolder memberHolder = new ElementHolder();
+ fields = <String, FieldElementImpl>{};
+ for (UnlinkedVariable serializedVariable in serializedClass.fields) {
+ buildVariable(serializedVariable, memberHolder);
+ }
+ bool constructorFound = false;
+ constructors = <String, ConstructorElementImpl>{};
+ for (UnlinkedExecutable serializedExecutable
+ in serializedClass.executables) {
+ switch (serializedExecutable.kind) {
+ case UnlinkedExecutableKind.constructor:
+ constructorFound = true;
+ buildConstructor(
+ serializedExecutable, memberHolder, correspondingType);
+ break;
+ case UnlinkedExecutableKind.functionOrMethod:
+ case UnlinkedExecutableKind.getter:
+ case UnlinkedExecutableKind.setter:
+ if (serializedExecutable.isStatic) {
+ currentTypeParameters.removeLast();
+ }
+ buildExecutable(serializedExecutable, memberHolder);
+ if (serializedExecutable.isStatic) {
+ currentTypeParameters.add(classElement.typeParameters);
+ }
+ break;
+ }
+ }
+ if (!serializedClass.isMixinApplication) {
+ if (!constructorFound) {
+ // Synthesize implicit constructors.
+ ConstructorElementImpl constructor = new ConstructorElementImpl('', -1);
+ constructor.synthetic = true;
+ constructor.returnType = correspondingType;
+ constructor.type = new FunctionTypeImpl.elementWithNameAndArgs(
+ constructor, null, getCurrentTypeArguments(), false);
+ memberHolder.addConstructor(constructor);
+ }
+ classElement.constructors = memberHolder.constructors;
+ }
+ classElement.accessors = memberHolder.accessors;
+ classElement.fields = memberHolder.fields;
+ classElement.methods = memberHolder.methods;
+ correspondingType.typeArguments = getCurrentTypeArguments();
+ classElement.type = correspondingType;
+ buildDocumentation(classElement, serializedClass.documentationComment);
+ buildAnnotations(classElement, serializedClass.annotations);
+ resolveConstructorInitializers(classElement);
+ unitHolder.addType(classElement);
+ currentTypeParameters.removeLast();
+ assert(currentTypeParameters.isEmpty);
+ fields = null;
+ constructors = null;
}
/**
@@ -939,6 +974,26 @@
.constantInitializers
.map(buildConstantInitializer)
.toList();
+ if (serializedExecutable.isRedirectedConstructor) {
+ if (serializedExecutable.isFactory) {
+ EntityRef redirectedConstructor =
+ serializedExecutable.redirectedConstructor;
+ _ReferenceInfo info = referenceInfos[redirectedConstructor.reference];
+ List<EntityRef> typeArguments = redirectedConstructor.typeArguments;
+ currentConstructor.redirectedConstructor = _createConstructorElement(
+ _createConstructorDefiningType(info, typeArguments), info);
+ } else {
+ List<String> locationComponents =
+ currentCompilationUnit.location.components.toList();
+ locationComponents.add(classType.name);
+ locationComponents.add(serializedExecutable.redirectedConstructorName);
+ currentConstructor.redirectedConstructor =
+ new _DeferredConstructorElement._(
+ classType,
+ serializedExecutable.redirectedConstructorName,
+ new ElementLocationImpl.con3(locationComponents));
+ }
+ }
holder.addConstructor(currentConstructor);
currentConstructor = null;
}
@@ -988,6 +1043,7 @@
for (UnlinkedEnumValue serializedEnumValue in serializedEnum.values) {
ConstFieldElementImpl valueField = new ConstFieldElementImpl(
serializedEnumValue.name, serializedEnumValue.nameOffset);
+ buildDocumentation(valueField, serializedEnumValue.documentationComment);
valueField.const3 = true;
valueField.static = true;
valueField.type = enumType;
@@ -1052,9 +1108,6 @@
type = executableElement.parameters[0].type;
}
holder.addAccessor(executableElement);
- // TODO(paulberry): consider removing implicit variables from the
- // element model; the spec doesn't call for them, and they cause
- // trouble when getters/setters exist in different parts.
PropertyInducingElementImpl implicitVariable;
if (isTopLevel) {
implicitVariable = buildImplicitTopLevelVariable(name, kind, holder);
@@ -1084,13 +1137,8 @@
*/
void buildExecutableCommonParts(ExecutableElementImpl executableElement,
UnlinkedExecutable serializedExecutable) {
- List<TypeParameterType> oldTypeArguments = currentTypeArguments;
- int oldTypeParametersLength = currentTypeParameters.length;
- if (serializedExecutable.typeParameters.isNotEmpty) {
- executableElement.typeParameters =
- serializedExecutable.typeParameters.map(buildTypeParameter).toList();
- currentTypeParameters.addAll(executableElement.typeParameters);
- }
+ executableElement.typeParameters =
+ buildTypeParameters(serializedExecutable.typeParameters);
executableElement.parameters =
serializedExecutable.parameters.map(buildParameter).toList();
if (serializedExecutable.kind == UnlinkedExecutableKind.constructor) {
@@ -1107,13 +1155,16 @@
serializedExecutable.returnType == null;
}
executableElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
- executableElement, null, oldTypeArguments, false);
+ executableElement, null, getCurrentTypeArguments(skipLevels: 1), false);
executableElement.external = serializedExecutable.isExternal;
- currentTypeParameters.removeRange(
- oldTypeParametersLength, currentTypeParameters.length);
buildDocumentation(
executableElement, serializedExecutable.documentationComment);
buildAnnotations(executableElement, serializedExecutable.annotations);
+ executableElement.functions =
+ serializedExecutable.localFunctions.map(buildLocalFunction).toList();
+ executableElement.localVariables =
+ serializedExecutable.localVariables.map(buildLocalVariable).toList();
+ currentTypeParameters.removeLast();
}
/**
@@ -1412,36 +1463,78 @@
}
/**
+ * Resynthesize a local [FunctionElement].
+ */
+ FunctionElement buildLocalFunction(UnlinkedExecutable serializedExecutable) {
+ FunctionElementImpl element = new FunctionElementImpl(
+ serializedExecutable.name, serializedExecutable.nameOffset);
+ if (serializedExecutable.visibleOffset != 0) {
+ element.setVisibleRange(serializedExecutable.visibleOffset,
+ serializedExecutable.visibleLength);
+ }
+ buildExecutableCommonParts(element, serializedExecutable);
+ return element;
+ }
+
+ /**
+ * Resynthesize a [LocalVariableElement].
+ */
+ LocalVariableElement buildLocalVariable(UnlinkedVariable serializedVariable) {
+ LocalVariableElementImpl element;
+ if (serializedVariable.constExpr != null) {
+ ConstLocalVariableElementImpl constElement =
+ new ConstLocalVariableElementImpl(
+ serializedVariable.name, serializedVariable.nameOffset);
+ element = constElement;
+ constElement.constantInitializer =
+ _buildConstExpression(serializedVariable.constExpr);
+ } else {
+ element = new LocalVariableElementImpl(
+ serializedVariable.name, serializedVariable.nameOffset);
+ }
+ if (serializedVariable.visibleOffset != 0) {
+ element.setVisibleRange(
+ serializedVariable.visibleOffset, serializedVariable.visibleLength);
+ }
+ buildVariableCommonParts(element, serializedVariable);
+ return element;
+ }
+
+ /**
* Resynthesize a [ParameterElement].
*/
ParameterElement buildParameter(UnlinkedParam serializedParameter) {
ParameterElementImpl parameterElement;
if (serializedParameter.isInitializingFormal) {
FieldFormalParameterElementImpl initializingParameter;
- if (serializedParameter.defaultValue != null) {
+ if (serializedParameter.kind == UnlinkedParamKind.required) {
+ initializingParameter = new FieldFormalParameterElementImpl(
+ serializedParameter.name, serializedParameter.nameOffset);
+ } else {
DefaultFieldFormalParameterElementImpl defaultParameter =
new DefaultFieldFormalParameterElementImpl(
serializedParameter.name, serializedParameter.nameOffset);
initializingParameter = defaultParameter;
- defaultParameter.constantInitializer =
- _buildConstExpression(serializedParameter.defaultValue);
- } else {
- initializingParameter = new FieldFormalParameterElementImpl(
- serializedParameter.name, serializedParameter.nameOffset);
+ if (serializedParameter.defaultValue != null) {
+ defaultParameter.constantInitializer =
+ _buildConstExpression(serializedParameter.defaultValue);
+ }
}
parameterElement = initializingParameter;
initializingParameter.field = fields[serializedParameter.name];
} else {
- if (serializedParameter.defaultValue != null) {
+ if (serializedParameter.kind == UnlinkedParamKind.required) {
+ parameterElement = new ParameterElementImpl(
+ serializedParameter.name, serializedParameter.nameOffset);
+ } else {
DefaultParameterElementImpl defaultParameter =
new DefaultParameterElementImpl(
serializedParameter.name, serializedParameter.nameOffset);
parameterElement = defaultParameter;
- defaultParameter.constantInitializer =
- _buildConstExpression(serializedParameter.defaultValue);
- } else {
- parameterElement = new ParameterElementImpl(
- serializedParameter.name, serializedParameter.nameOffset);
+ if (serializedParameter.defaultValue != null) {
+ defaultParameter.constantInitializer =
+ _buildConstExpression(serializedParameter.defaultValue);
+ }
}
}
buildAnnotations(parameterElement, serializedParameter.annotations);
@@ -1455,7 +1548,7 @@
parameterTypeElement.shareParameters(parameterElement.parameters);
parameterTypeElement.returnType = buildType(serializedParameter.type);
parameterElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
- parameterTypeElement, null, currentTypeArguments, false);
+ parameterTypeElement, null, getCurrentTypeArguments(), false);
} else {
if (serializedParameter.isInitializingFormal &&
serializedParameter.type == null) {
@@ -1503,6 +1596,17 @@
}
/**
+ * Handle the parts that are common to top level variables and fields.
+ */
+ void buildPropertyIntroducingElementCommonParts(
+ PropertyInducingElementImpl element,
+ UnlinkedVariable serializedVariable) {
+ buildVariableCommonParts(element, serializedVariable);
+ element.propagatedType =
+ buildLinkedType(serializedVariable.propagatedTypeSlot);
+ }
+
+ /**
* Build a [DartType] object based on a [EntityRef]. This [DartType]
* may refer to elements in other libraries than the library being
* deserialized, so handles are used to avoid having to deserialize other
@@ -1517,10 +1621,7 @@
}
}
if (type.paramReference != 0) {
- // TODO(paulberry): make this work for generic methods.
- return currentTypeParameters[
- currentTypeParameters.length - type.paramReference]
- .type;
+ return getTypeParameterFromScope(type.paramReference);
} else {
DartType getTypeArgument(int i) {
if (i < type.typeArguments.length) {
@@ -1540,30 +1641,23 @@
* [unitHolder].
*/
void buildTypedef(UnlinkedTypedef serializedTypedef) {
- try {
- currentTypeParameters =
- serializedTypedef.typeParameters.map(buildTypeParameter).toList();
- for (int i = 0; i < serializedTypedef.typeParameters.length; i++) {
- finishTypeParameter(
- serializedTypedef.typeParameters[i], currentTypeParameters[i]);
- }
- FunctionTypeAliasElementImpl functionTypeAliasElement =
- new FunctionTypeAliasElementImpl(
- serializedTypedef.name, serializedTypedef.nameOffset);
- functionTypeAliasElement.parameters =
- serializedTypedef.parameters.map(buildParameter).toList();
- functionTypeAliasElement.returnType =
- buildType(serializedTypedef.returnType);
- functionTypeAliasElement.type =
- new FunctionTypeImpl.forTypedef(functionTypeAliasElement);
- functionTypeAliasElement.typeParameters = currentTypeParameters;
- buildDocumentation(
- functionTypeAliasElement, serializedTypedef.documentationComment);
- buildAnnotations(functionTypeAliasElement, serializedTypedef.annotations);
- unitHolder.addTypeAlias(functionTypeAliasElement);
- } finally {
- currentTypeParameters = <TypeParameterElement>[];
- }
+ FunctionTypeAliasElementImpl functionTypeAliasElement =
+ new FunctionTypeAliasElementImpl(
+ serializedTypedef.name, serializedTypedef.nameOffset);
+ functionTypeAliasElement.typeParameters =
+ buildTypeParameters(serializedTypedef.typeParameters);
+ functionTypeAliasElement.parameters =
+ serializedTypedef.parameters.map(buildParameter).toList();
+ functionTypeAliasElement.returnType =
+ buildType(serializedTypedef.returnType);
+ functionTypeAliasElement.type =
+ new FunctionTypeImpl.forTypedef(functionTypeAliasElement);
+ buildDocumentation(
+ functionTypeAliasElement, serializedTypedef.documentationComment);
+ buildAnnotations(functionTypeAliasElement, serializedTypedef.annotations);
+ unitHolder.addTypeAlias(functionTypeAliasElement);
+ currentTypeParameters.removeLast();
+ assert(currentTypeParameters.isEmpty);
}
/**
@@ -1585,6 +1679,22 @@
}
/**
+ * Build [TypeParameterElement]s corresponding to the type parameters in
+ * [serializedTypeParameters] and store them in [currentTypeParameters].
+ * Also return them.
+ */
+ List<TypeParameterElement> buildTypeParameters(
+ List<UnlinkedTypeParam> serializedTypeParameters) {
+ List<TypeParameterElement> typeParameters =
+ serializedTypeParameters.map(buildTypeParameter).toList();
+ currentTypeParameters.add(typeParameters);
+ for (int i = 0; i < serializedTypeParameters.length; i++) {
+ finishTypeParameter(serializedTypeParameters[i], typeParameters[i]);
+ }
+ return typeParameters;
+ }
+
+ /**
* Resynthesize a [TopLevelVariableElement] or [FieldElement].
*/
void buildVariable(UnlinkedVariable serializedVariable,
@@ -1602,7 +1712,7 @@
element = new TopLevelVariableElementImpl(
serializedVariable.name, serializedVariable.nameOffset);
}
- buildVariableCommonParts(element, serializedVariable);
+ buildPropertyIntroducingElementCommonParts(element, serializedVariable);
unitHolder.addTopLevelVariable(element);
buildImplicitAccessors(element, unitHolder);
} else {
@@ -1617,7 +1727,7 @@
element = new FieldElementImpl(
serializedVariable.name, serializedVariable.nameOffset);
}
- buildVariableCommonParts(element, serializedVariable);
+ buildPropertyIntroducingElementCommonParts(element, serializedVariable);
element.static = serializedVariable.isStatic;
holder.addField(element);
buildImplicitAccessors(element, holder);
@@ -1626,17 +1736,15 @@
}
/**
- * Handle the parts that are common to top level variables and fields.
+ * Handle the parts that are common to variables.
*/
- void buildVariableCommonParts(PropertyInducingElementImpl element,
- UnlinkedVariable serializedVariable) {
+ void buildVariableCommonParts(
+ VariableElementImpl element, UnlinkedVariable serializedVariable) {
element.type = buildLinkedType(serializedVariable.inferredTypeSlot) ??
buildType(serializedVariable.type);
element.const3 = serializedVariable.isConst;
element.final2 = serializedVariable.isFinal;
element.hasImplicitType = serializedVariable.type == null;
- element.propagatedType =
- buildLinkedType(serializedVariable.propagatedTypeSlot);
buildDocumentation(element, serializedVariable.documentationComment);
buildAnnotations(element, serializedVariable.annotations);
}
@@ -1665,6 +1773,25 @@
}
/**
+ * Return a list of type arguments corresponding to [currentTypeParameters],
+ * skipping the innermost [skipLevels] nesting levels.
+ *
+ * Type parameters are listed in nesting order from innermost to outermost,
+ * and then in declaration order. So for instance if we are resynthesizing a
+ * method declared as `class C<T, U> { void m<V, W>() { ... } }`, then the
+ * type parameters will be returned in the order `[V, W, T, U]`.
+ */
+ List<DartType> getCurrentTypeArguments({int skipLevels: 0}) {
+ assert(currentTypeParameters.length >= skipLevels);
+ List<DartType> result = <DartType>[];
+ for (int i = currentTypeParameters.length - 1 - skipLevels; i >= 0; i--) {
+ result.addAll(currentTypeParameters[i]
+ .map((TypeParameterElement param) => param.type));
+ }
+ return result;
+ }
+
+ /**
* Build the components of an [ElementLocationImpl] for the entity in the
* given [unit] of the dependency located at [dependencyIndex], and having
* the given [name].
@@ -1701,6 +1828,24 @@
}
/**
+ * Get the type parameter from the surrounding scope whose De Bruijn index is
+ * [index].
+ */
+ DartType getTypeParameterFromScope(int index) {
+ for (int i = currentTypeParameters.length - 1; i >= 0; i--) {
+ List<TypeParameterElement> paramsAtThisNestingLevel =
+ currentTypeParameters[i];
+ int numParamsAtThisNestingLevel = paramsAtThisNestingLevel.length;
+ if (index <= numParamsAtThisNestingLevel) {
+ return paramsAtThisNestingLevel[numParamsAtThisNestingLevel - index]
+ .type;
+ }
+ index -= numParamsAtThisNestingLevel;
+ }
+ throw new StateError('Type parameter not found');
+ }
+
+ /**
* Populate [referenceInfos] with the correct information for the current
* compilation unit.
*/
@@ -1710,7 +1855,6 @@
referenceInfos = new List<_ReferenceInfo>(numLinkedReferences);
for (int i = 0; i < numLinkedReferences; i++) {
LinkedReference linkedReference = linkedUnit.references[i];
- _ReferenceInfo enclosingInfo = null;
String name;
int containingReference;
if (i < numUnlinkedReferences) {
@@ -1720,12 +1864,14 @@
name = linkedUnit.references[i].name;
containingReference = linkedUnit.references[i].containingReference;
}
+ _ReferenceInfo enclosingInfo =
+ containingReference != 0 ? referenceInfos[containingReference] : null;
Element element;
DartType type;
int numTypeParameters = linkedReference.numTypeParameters;
if (linkedReference.kind == ReferenceKind.unresolved) {
type = summaryResynthesizer.typeProvider.undefinedType;
- element = type.element;
+ element = null;
} else if (name == 'dynamic') {
type = summaryResynthesizer.typeProvider.dynamicType;
element = type.element;
@@ -1734,10 +1880,8 @@
element = type.element;
} else {
List<String> locationComponents;
- if (containingReference != 0 &&
- referenceInfos[containingReference].element is ClassElement) {
+ if (enclosingInfo != null && enclosingInfo.element is ClassElement) {
String identifier = _getElementIdentifier(name, linkedReference.kind);
- enclosingInfo = referenceInfos[containingReference];
locationComponents =
enclosingInfo.element.location.components.toList();
locationComponents.add(identifier);
@@ -1831,7 +1975,9 @@
for (PropertyAccessorElementImpl accessor in unit.accessors) {
elementMap[accessor.identifier] = accessor;
}
- resummarizedElements[absoluteUri] = elementMap;
+ resynthesizedUnits[absoluteUri] = unit;
+ resynthesizedElements[absoluteUri] = elementMap;
+ assert(currentTypeParameters.isEmpty);
}
/**
@@ -1891,6 +2037,43 @@
<String>['dart:core', 'dart:core', 'String', 'length?']));
/**
+ * Return the defining type for a [ConstructorElement] by applying
+ * [typeArgumentRefs] to the given linked [info].
+ */
+ InterfaceType _createConstructorDefiningType(
+ _ReferenceInfo info, List<EntityRef> typeArgumentRefs) {
+ bool isClass = info.element is ClassElement;
+ _ReferenceInfo classInfo = isClass ? info : info.enclosing;
+ List<DartType> typeArguments = typeArgumentRefs.map(buildType).toList();
+ return classInfo.buildType((i) {
+ if (i < typeArguments.length) {
+ return typeArguments[i];
+ } else {
+ return DynamicTypeImpl.instance;
+ }
+ }, const <int>[]);
+ }
+
+ /**
+ * Return the [ConstructorElement] corresponding to the given linked [info],
+ * using the [classType] which has already been computed (e.g. by
+ * [_createConstructorDefiningType]). Both cases when [info] is a
+ * [ClassElement] and [ConstructorElement] are supported.
+ */
+ ConstructorElement _createConstructorElement(
+ InterfaceType classType, _ReferenceInfo info) {
+ bool isClass = info.element is ClassElement;
+ String name = isClass ? '' : info.name;
+ _DeferredConstructorElement element =
+ new _DeferredConstructorElement(classType, name);
+ if (info.numTypeParameters != 0) {
+ return new ConstructorMember(element, classType);
+ } else {
+ return element;
+ }
+ }
+
+ /**
* If the given [kind] is a top-level or class member property accessor, and
* the given [name] does not end with `=`, i.e. does not denote a setter,
* return the getter identifier by appending `?`.
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index e5f4c4f..a3d915b 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -5,8 +5,8 @@
library serialization.summarize_ast;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
@@ -93,9 +93,8 @@
Expression target = access.target;
if (target is Identifier) {
EntityRefBuilder targetRef = serializeIdentifier(target);
- return new EntityRefBuilder(
- reference: visitor.serializeReference(
- targetRef.reference, access.propertyName.name));
+ return new EntityRefBuilder(reference: visitor.serializeReference(
+ targetRef.reference, access.propertyName.name));
} else {
// TODO(scheglov) should we handle other targets in malformed constants?
throw new StateError('Unexpected target type: ${target.runtimeType}');
@@ -170,7 +169,7 @@
/**
* Visitor used to create a summary from an AST.
*/
-class _SummarizeAstVisitor extends SimpleAstVisitor {
+class _SummarizeAstVisitor extends RecursiveAstVisitor {
/**
* List of objects which should be written to [UnlinkedUnit.classes].
*/
@@ -182,8 +181,8 @@
final List<UnlinkedEnumBuilder> enums = <UnlinkedEnumBuilder>[];
/**
- * List of objects which should be written to [UnlinkedUnit.executables]
- * or [UnlinkedClass.executables].
+ * List of objects which should be written to [UnlinkedUnit.executables],
+ * [UnlinkedClass.executables] or [UnlinkedExecutable.localFunctions].
*/
List<UnlinkedExecutableBuilder> executables = <UnlinkedExecutableBuilder>[];
@@ -204,8 +203,8 @@
final List<UnlinkedTypedefBuilder> typedefs = <UnlinkedTypedefBuilder>[];
/**
- * List of objects which should be written to [UnlinkedUnit.variables] or
- * [UnlinkedClass.fields].
+ * List of objects which should be written to [UnlinkedUnit.variables],
+ * [UnlinkedClass.fields] or [UnlinkedExecutable.localVariables].
*/
List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[];
@@ -285,10 +284,9 @@
int numSlots = 0;
/**
- * A flag indicating whether a variable declaration is in the context of a
- * field declaration.
+ * The [Block] that is being visited now, or `null` for non-local contexts.
*/
- bool inFieldContext = false;
+ Block enclosingBlock = null;
/**
* Create a slot id for storing a propagated or inferred type.
@@ -303,8 +301,6 @@
String className, NodeList<ClassMember> members) {
_Scope scope = new _Scope();
for (ClassMember member in members) {
- // TODO(paulbery): consider replacing these if-tests with dynamic method
- // dispatch.
if (member is MethodDeclaration) {
if (member.isSetter || member.isOperator) {
// We don't have to handle setters or operators because the only
@@ -330,7 +326,7 @@
*/
List<UnlinkedConstBuilder> serializeAnnotations(
NodeList<Annotation> annotations) {
- if (annotations.isEmpty) {
+ if (annotations == null || annotations.isEmpty) {
return const <UnlinkedConstBuilder>[];
}
return annotations.map((Annotation a) {
@@ -533,11 +529,32 @@
if (returnType == null && !isSemanticallyStatic) {
b.inferredReturnTypeSlot = assignTypeSlot();
}
+ b.visibleOffset = enclosingBlock?.offset;
+ b.visibleLength = enclosingBlock?.length;
+ serializeFunctionBody(b, body);
scopes.removeLast();
assert(scopes.length == oldScopesLength);
return b;
}
+ void serializeFunctionBody(UnlinkedExecutableBuilder b, FunctionBody body) {
+ if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
+ for (UnlinkedParamBuilder parameter in b.parameters) {
+ parameter.visibleOffset = body.offset;
+ parameter.visibleLength = body.length;
+ }
+ }
+ List<UnlinkedExecutableBuilder> oldExecutables = executables;
+ List<UnlinkedVariableBuilder> oldVariables = variables;
+ executables = <UnlinkedExecutableBuilder>[];
+ variables = <UnlinkedVariableBuilder>[];
+ body.accept(this);
+ b.localFunctions = executables;
+ b.localVariables = variables;
+ executables = oldExecutables;
+ variables = oldVariables;
+ }
+
/**
* Serialize the return type and parameters of a function-typed formal
* parameter and store them in [b].
@@ -719,7 +736,8 @@
b.type = serializeTypeName(variables.type);
b.documentationComment = serializeDocumentation(documentationComment);
b.annotations = serializeAnnotations(annotations);
- if (variable.isConst || variable.isFinal && inFieldContext) {
+ if (variable.isConst ||
+ variable.isFinal && isField && !isDeclaredStatic) {
Expression initializer = variable.initializer;
if (initializer != null) {
b.constExpr = serializeConstExpr(initializer);
@@ -734,11 +752,21 @@
(variable.initializer != null || !isSemanticallyStatic)) {
b.inferredTypeSlot = assignTypeSlot();
}
+ b.visibleOffset = enclosingBlock?.offset;
+ b.visibleLength = enclosingBlock?.length;
this.variables.add(b);
}
}
@override
+ void visitBlock(Block node) {
+ Block oldBlock = enclosingBlock;
+ enclosingBlock = node;
+ super.visitBlock(node);
+ enclosingBlock = oldBlock;
+ }
+
+ @override
void visitClassDeclaration(ClassDeclaration node) {
TypeName superclass =
node.extendsClause == null ? null : node.extendsClause.superclass;
@@ -785,7 +813,22 @@
.map((FormalParameter p) => p.accept(this))
.toList();
b.kind = UnlinkedExecutableKind.constructor;
- b.isFactory = node.factoryKeyword != null;
+ if (node.factoryKeyword != null) {
+ b.isFactory = true;
+ if (node.redirectedConstructor != null) {
+ b.isRedirectedConstructor = true;
+ b.redirectedConstructor = new _ConstExprSerializer(this, null)
+ .serializeConstructorName(node.redirectedConstructor.type,
+ node.redirectedConstructor.name);
+ }
+ } else {
+ for (ConstructorInitializer initializer in node.initializers) {
+ if (initializer is RedirectingConstructorInvocation) {
+ b.isRedirectedConstructor = true;
+ b.redirectedConstructorName = initializer.constructorName?.name;
+ }
+ }
+ }
b.isConst = node.constKeyword != null;
b.isExternal = node.externalKeyword != null;
b.documentationComment = serializeDocumentation(node.documentationComment);
@@ -800,6 +843,7 @@
}))
.toList();
}
+ serializeFunctionBody(b, node.body);
executables.add(b);
}
@@ -820,7 +864,10 @@
b.nameOffset = node.name.offset;
b.values = node.constants
.map((EnumConstantDeclaration value) => new UnlinkedEnumValueBuilder(
- name: value.name.name, nameOffset: value.name.offset))
+ documentationComment:
+ serializeDocumentation(value.documentationComment),
+ name: value.name.name,
+ nameOffset: value.name.offset))
.toList();
b.documentationComment = serializeDocumentation(node.documentationComment);
b.annotations = serializeAnnotations(node.metadata);
@@ -837,13 +884,8 @@
@override
void visitFieldDeclaration(FieldDeclaration node) {
- try {
- inFieldContext = true;
- serializeVariables(node.fields, node.staticKeyword != null,
- node.documentationComment, node.metadata, true);
- } finally {
- inFieldContext = false;
- }
+ serializeVariables(node.fields, node.staticKeyword != null,
+ node.documentationComment, node.metadata, true);
}
@override
@@ -995,6 +1037,11 @@
return b;
}
+ @override
+ void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+ serializeVariables(node.variables, false, null, null, false);
+ }
+
/**
* Helper method to determine if a given [typeName] refers to `dynamic`.
*/
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
index b644788..9e63ff8 100644
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -4,8 +4,8 @@
library serialization.summarize_const_expr;
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index 168e91b..b631287 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -7,9 +7,11 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
@@ -187,7 +189,7 @@
kind: ReferenceKind.classOrEnum,
name: cls.name,
numTypeParameters: cls.typeParameters.length,
- constMembers: serializeClassConstMembers(cls)));
+ members: serializeClassConstMembers(cls)));
}
}
for (ClassElement enm in compilationUnit.enums) {
@@ -293,6 +295,7 @@
* parameter [type].
*/
int findTypeParameterIndex(TypeParameterType type, Element context) {
+ Element originalContext = context;
int index = 0;
while (context != null) {
List<TypeParameterElement> typeParameters;
@@ -314,7 +317,8 @@
}
context = context.enclosingElement;
}
- throw new StateError('Unbound type parameter $type');
+ throw new StateError(
+ 'Unbound type parameter $type (${originalContext?.location})');
}
/**
@@ -404,6 +408,12 @@
* Otherwise return `null`.
*/
List<UnlinkedPublicNameBuilder> serializeClassConstMembers(ClassElement cls) {
+ if (cls.isMixinApplication) {
+ // Mixin application members can't be determined directly from the AST so
+ // we can't store them in UnlinkedPublicName.
+ // TODO(paulberry): find somewhere else to store them.
+ return null;
+ }
if (cls.kind == ElementKind.CLASS) {
List<UnlinkedPublicNameBuilder> bs = <UnlinkedPublicNameBuilder>[];
for (FieldElement field in cls.fields) {
@@ -425,7 +435,7 @@
}
}
for (ConstructorElement constructor in cls.constructors) {
- if (constructor.isConst && constructor.isPublic) {
+ if (constructor.isPublic && constructor.name.isNotEmpty) {
// TODO(paulberry): should numTypeParameters include class params?
bs.add(new UnlinkedPublicNameBuilder(
name: constructor.name,
@@ -532,6 +542,32 @@
b.kind = UnlinkedExecutableKind.constructor;
b.isConst = executableElement.isConst;
b.isFactory = executableElement.isFactory;
+ ConstructorElement redirectedConstructor =
+ executableElement.redirectedConstructor;
+ if (redirectedConstructor != null) {
+ b.isRedirectedConstructor = true;
+ if (executableElement.isFactory) {
+ InterfaceType returnType = redirectedConstructor is ConstructorMember
+ ? redirectedConstructor.definingType
+ : redirectedConstructor.enclosingElement.type;
+ EntityRefBuilder typeRef =
+ serializeTypeRef(returnType, executableElement);
+ if (redirectedConstructor.name.isNotEmpty) {
+ String name = redirectedConstructor.name;
+ int typeId = typeRef.reference;
+ LinkedReference typeLinkedRef = linkedReferences[typeId];
+ int refId = serializeUnlinkedReference(
+ name, ReferenceKind.constructor,
+ unit: typeLinkedRef.unit, prefixReference: typeId);
+ b.redirectedConstructor = new EntityRefBuilder(
+ reference: refId, typeArguments: typeRef.typeArguments);
+ } else {
+ b.redirectedConstructor = typeRef;
+ }
+ } else {
+ b.redirectedConstructorName = redirectedConstructor.name;
+ }
+ }
if (executableElement.isConst &&
executableElement.constantInitializers != null) {
Set<String> constructorParameterNames =
@@ -553,6 +589,17 @@
b.isExternal = executableElement.isExternal;
b.documentationComment = serializeDocumentation(executableElement);
b.annotations = serializeAnnotations(executableElement);
+ if (executableElement is FunctionElement) {
+ SourceRange visibleRange = executableElement.visibleRange;
+ if (visibleRange != null) {
+ b.visibleOffset = visibleRange.offset;
+ b.visibleLength = visibleRange.length;
+ }
+ }
+ b.localFunctions =
+ executableElement.functions.map(serializeExecutable).toList();
+ b.localVariables =
+ executableElement.localVariables.map(serializeVariable).toList();
return b;
}
@@ -653,6 +700,13 @@
b.defaultValue = serializeConstExpr(initializer);
}
}
+ {
+ SourceRange visibleRange = parameter.visibleRange;
+ if (visibleRange != null) {
+ b.visibleOffset = visibleRange.offset;
+ b.visibleLength = visibleRange.length;
+ }
+ }
return b;
}
@@ -660,14 +714,8 @@
* Serialize the given [prefix] into an index into the references table.
*/
int serializePrefix(PrefixElement element) {
- return referenceMap.putIfAbsent(element, () {
- assert(unlinkedReferences.length == linkedReferences.length);
- int index = unlinkedReferences.length;
- unlinkedReferences.add(new UnlinkedReferenceBuilder(name: element.name));
- linkedReferences
- .add(new LinkedReferenceBuilder(kind: ReferenceKind.prefix));
- return index;
- });
+ return referenceMap.putIfAbsent(element,
+ () => serializeUnlinkedReference(element.name, ReferenceKind.prefix));
}
/**
@@ -789,6 +837,23 @@
}
/**
+ * Create a new entry in the references table ([UnlinkedLibrary.references]
+ * and [LinkedLibrary.references]) representing an entity having the given
+ * [name] and [kind]. If [unit] is given, it is the index of the compilation
+ * unit containing the entity being referred to. If [prefixReference] is
+ * given, it indicates the entry in the references table for the prefix.
+ */
+ int serializeUnlinkedReference(String name, ReferenceKind kind,
+ {int unit: 0, int prefixReference: 0}) {
+ assert(unlinkedReferences.length == linkedReferences.length);
+ int index = unlinkedReferences.length;
+ unlinkedReferences.add(new UnlinkedReferenceBuilder(
+ name: name, prefixReference: prefixReference));
+ linkedReferences.add(new LinkedReferenceBuilder(kind: kind, unit: unit));
+ return index;
+ }
+
+ /**
* Return the index of the entry in the references table
* ([UnlinkedLibrary.references] and [LinkedLibrary.references]) used for
* unresolved references. A new entry is added to the table if necessary to
@@ -800,12 +865,8 @@
// the element model. For the moment we use a name that can't possibly
// ever exist.
if (unresolvedReferenceIndex == null) {
- assert(unlinkedReferences.length == linkedReferences.length);
- unresolvedReferenceIndex = unlinkedReferences.length;
- unlinkedReferences
- .add(new UnlinkedReferenceBuilder(name: '*unresolved*'));
- linkedReferences
- .add(new LinkedReferenceBuilder(kind: ReferenceKind.unresolved));
+ return serializeUnlinkedReference(
+ '*unresolved*', ReferenceKind.unresolved);
}
return unresolvedReferenceIndex;
}
@@ -813,7 +874,7 @@
/**
* Serialize the given [variable], creating an [UnlinkedVariable].
*/
- UnlinkedVariableBuilder serializeVariable(PropertyInducingElement variable) {
+ UnlinkedVariableBuilder serializeVariable(VariableElement variable) {
UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
b.name = variable.name;
b.nameOffset = variable.nameOffset;
@@ -832,16 +893,26 @@
b.constExpr = serializeConstExpr(initializer);
}
}
- if (b.isFinal || b.isConst) {
- b.propagatedTypeSlot = storeLinkedType(variable.propagatedType, variable);
- } else {
- // Variable is not propagable.
- assert(variable.propagatedType == null);
+ if (variable is PropertyInducingElement) {
+ if (b.isFinal || b.isConst) {
+ b.propagatedTypeSlot =
+ storeLinkedType(variable.propagatedType, variable);
+ } else {
+ // Variable is not propagable.
+ assert(variable.propagatedType == null);
+ }
}
if (variable.hasImplicitType &&
(variable.initializer != null || !variable.isStatic)) {
b.inferredTypeSlot = storeInferredType(variable.type, variable);
}
+ if (variable is LocalVariableElement) {
+ SourceRange visibleRange = variable.visibleRange;
+ if (visibleRange != null) {
+ b.visibleOffset = visibleRange.offset;
+ b.visibleLength = visibleRange.length;
+ }
+ }
return b;
}
@@ -896,22 +967,21 @@
unit = dependentLibrary.units.indexOf(unitElement);
assert(unit != -1);
}
- LinkedReferenceBuilder linkedReference = new LinkedReferenceBuilder(
- dependency: librarySerializer.serializeDependency(dependentLibrary),
- kind: _getReferenceKind(element),
- unit: unit);
- if (element is TypeParameterizedElement) {
- linkedReference.numTypeParameters = element.typeParameters.length;
- }
+ ReferenceKind kind = _getReferenceKind(element);
String name = element == null ? 'void' : element.name;
+ int index;
+ LinkedReferenceBuilder linkedReference;
if (linked) {
- linkedReference.name = name;
+ linkedReference =
+ new LinkedReferenceBuilder(kind: kind, unit: unit, name: name);
Element enclosing = element?.enclosingElement;
if (enclosing is ClassElement) {
linkedReference.containingReference =
_getElementReferenceId(enclosing, linked: linked);
- linkedReference.numTypeParameters += enclosing.typeParameters.length;
+ linkedReference.numTypeParameters = enclosing.typeParameters.length;
}
+ index = linkedReferences.length;
+ linkedReferences.add(linkedReference);
} else {
assert(unlinkedReferences.length == linkedReferences.length);
int prefixReference = 0;
@@ -929,24 +999,22 @@
} else {
prefixReference = _getElementReferenceId(enclosing, linked: linked);
}
- unlinkedReferences.add(new UnlinkedReferenceBuilder(
- name: name, prefixReference: prefixReference));
+ index = serializeUnlinkedReference(name, kind,
+ prefixReference: prefixReference, unit: unit);
+ linkedReference = linkedReferences[index];
}
- int index = linkedReferences.length;
- linkedReferences.add(linkedReference);
+ linkedReference.dependency =
+ librarySerializer.serializeDependency(dependentLibrary);
+ if (element is TypeParameterizedElement) {
+ linkedReference.numTypeParameters += element.typeParameters.length;
+ }
return index;
});
}
int _getLengthPropertyReference(int prefix) {
- assert(unlinkedReferences.length == linkedReferences.length);
- int index = linkedReferences.length;
- unlinkedReferences.add(
- new UnlinkedReferenceBuilder(name: 'length', prefixReference: prefix));
- LinkedReferenceBuilder linkedReference =
- new LinkedReferenceBuilder(kind: ReferenceKind.length);
- linkedReferences.add(linkedReference);
- return index;
+ return serializeUnlinkedReference('length', ReferenceKind.length,
+ prefixReference: prefix);
}
}
@@ -999,25 +1067,42 @@
@override
EntityRefBuilder serializeConstructorName(
TypeName type, SimpleIdentifier name) {
- EntityRefBuilder typeRef = serializer.serializeTypeRef(type.type, null);
+ EntityRefBuilder typeRef = serializeType(type);
if (name == null) {
return typeRef;
} else {
- int typeId = typeRef.reference;
- LinkedReference typeLinkedRef = serializer.linkedReferences[typeId];
- serializer.unlinkedReferences.add(new UnlinkedReferenceBuilder(
- name: name.name, prefixReference: typeId));
- int refId = serializer.linkedReferences.length;
- serializer.linkedReferences.add(new LinkedReferenceBuilder(
- kind: ReferenceKind.constructor, unit: typeLinkedRef.unit));
+ LinkedReference typeLinkedRef =
+ serializer.linkedReferences[typeRef.reference];
+ int refId = serializer.serializeUnlinkedReference(
+ name.name,
+ name.staticElement != null
+ ? ReferenceKind.constructor
+ : ReferenceKind.unresolved,
+ prefixReference: typeRef.reference,
+ unit: typeLinkedRef.unit);
return new EntityRefBuilder(
reference: refId, typeArguments: typeRef.typeArguments);
}
}
- EntityRefBuilder serializeIdentifier(Identifier identifier) {
+ EntityRefBuilder serializeIdentifier(Identifier identifier,
+ {int prefixReference: 0}) {
Element element = identifier.staticElement;
- assert(element != null);
+ // Unresolved identifier.
+ if (element == null) {
+ int reference;
+ if (identifier is PrefixedIdentifier) {
+ int prefix = serializeIdentifier(identifier.prefix).reference;
+ reference = serializer.serializeUnlinkedReference(
+ identifier.identifier.name, ReferenceKind.unresolved,
+ prefixReference: prefix);
+ } else {
+ reference = serializer.serializeUnlinkedReference(
+ identifier.name, ReferenceKind.unresolved,
+ prefixReference: prefixReference);
+ }
+ return new EntityRefBuilder(reference: reference);
+ }
// The only supported instance property accessor - `length`.
if (identifier is PrefixedIdentifier &&
element is PropertyAccessorElement &&
@@ -1040,7 +1125,19 @@
@override
EntityRefBuilder serializePropertyAccess(PropertyAccess access) {
Element element = access.propertyName.staticElement;
- assert(element != null);
+ // Unresolved property access.
+ if (element == null) {
+ Expression target = access.target;
+ if (target is Identifier) {
+ EntityRefBuilder targetRef = serializeIdentifier(target);
+ EntityRefBuilder propertyRef = serializeIdentifier(access.propertyName,
+ prefixReference: targetRef.reference);
+ return new EntityRefBuilder(reference: propertyRef.reference);
+ } else {
+ // TODO(scheglov) should we handle other targets in malformed constants?
+ throw new StateError('Unexpected target type: ${target.runtimeType}');
+ }
+ }
// The only supported instance property accessor - `length`.
Expression target = access.target;
if (target is Identifier &&
@@ -1058,6 +1155,12 @@
@override
EntityRefBuilder serializeType(TypeName typeName) {
+ if (typeName != null) {
+ DartType type = typeName.type;
+ if (type == null || type.isUndefined) {
+ return serializeIdentifier(typeName.name);
+ }
+ }
DartType type = typeName != null ? typeName.type : DynamicTypeImpl.instance;
return serializer.serializeTypeRef(type, null);
}
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index b12a34e..2108b74 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -16,21 +16,7 @@
show DartUriResolver, Source, SourceFactory, SourceKind;
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/resynthesize.dart';
-import 'package:analyzer/src/task/dart.dart'
- show
- CONSTANT_VALUE,
- 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/src/task/dart.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/model.dart'
show AnalysisTarget, ResultDescriptor, TargetedResult;
@@ -55,20 +41,22 @@
@override
bool compute(CacheEntry entry, ResultDescriptor result) {
if (result == TYPE_PROVIDER) {
-// print('SummarySdkAnalysisContext: $result');
entry.setValue(result, typeProvider, TargetedResult.EMPTY_LIST);
return true;
}
AnalysisTarget target = entry.target;
- // TODO(scheglov) we don't actually update "evaluationResult" yet
- if (result == CONSTANT_VALUE) {
- if (target.source != null && target.source.isInSystemLibrary) {
- entry.setValue(result, target, TargetedResult.EMPTY_LIST);
- return true;
- }
+ // Only SDK sources after this point.
+ if (target.source == null || !target.source.isInSystemLibrary) {
+ return false;
}
- if (target is Source && target.isInSystemLibrary) {
-// print('SummarySdkAnalysisContext: $result of $target');
+// print('SummarySdkAnalysisContext: $result of $target');
+ // Constant expressions are always resolved in summaries.
+ if (result == CONSTANT_EXPRESSION_RESOLVED &&
+ target is ConstantEvaluationTarget) {
+ entry.setValue(result, true, TargetedResult.EMPTY_LIST);
+ return true;
+ }
+ if (target is Source) {
if (result == LIBRARY_ELEMENT1 ||
result == LIBRARY_ELEMENT2 ||
result == LIBRARY_ELEMENT3 ||
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index c001aed..b492bb2 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -7,6 +7,7 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -15,6 +16,8 @@
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
@@ -23,9 +26,9 @@
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/generated/visitors.dart';
import 'package:analyzer/src/plugin/engine_plugin.dart';
import 'package:analyzer/src/services/lint.dart';
@@ -268,6 +271,13 @@
new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT9', false);
/**
+ * The [Element]s defined in a [LibrarySpecificUnit].
+ */
+final ListResultDescriptor<Element> DEFINED_ELEMENTS =
+ new ListResultDescriptor<Element>('DEFINED_ELEMENTS', null,
+ cachingPolicy: ELEMENT_CACHING_POLICY);
+
+/**
* The sources representing the export closure of a library.
* The [Source]s include only library sources, not their units.
*
@@ -1358,7 +1368,8 @@
// set the library documentation to the docs associated with the first
// directive in the compilation unit.
if (definingCompilationUnit.directives.isNotEmpty) {
- _setDoc(libraryElement, definingCompilationUnit.directives.first);
+ setElementDocumentationComment(
+ libraryElement, definingCompilationUnit.directives.first);
}
//
@@ -1401,19 +1412,6 @@
}
/**
- * If the given [node] has a documentation comment, remember its content
- * and range into the given [element].
- */
- void _setDoc(ElementImpl element, AnnotatedNode node) {
- Comment comment = node.documentationComment;
- if (comment != null && comment.isDocumentation) {
- element.documentationComment =
- comment.tokens.map((Token t) => t.lexeme).join('\n');
- element.setDocRange(comment.offset, comment.length);
- }
- }
-
- /**
* Return a map from the names of the inputs of this kind of task to the task
* input descriptors describing those inputs for a task with the given
* [libSource].
@@ -2226,6 +2224,9 @@
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask',
createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]);
+ // Prefix for comments ignoring error codes.
+ static const String _normalizedIgnorePrefix = '//#ignore:';
+
DartErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@@ -2250,12 +2251,91 @@
errorLists.add(errors);
}
}
+
+ //
+ // Filter ignored errors.
+ //
+ List<AnalysisError> errors =
+ _filterIgnores(AnalysisError.mergeLists(errorLists));
+
//
// Record outputs.
//
- outputs[DART_ERRORS] = AnalysisError.mergeLists(errorLists);
+ outputs[DART_ERRORS] = errors;
}
+ List<AnalysisError> _filterIgnores(List<AnalysisError> errors) {
+ if (errors.isEmpty) {
+ return errors;
+ }
+
+ List<AnalysisError> filtered = <AnalysisError>[];
+
+ // Sort errors.
+ errors.sort((AnalysisError e1, AnalysisError e2) => e1.offset - e2.offset);
+
+ Source source = target;
+ String contents = context.getContents(source).data;
+ Scanner scanner = new Scanner(source, new CharSequenceReader(contents),
+ AnalysisErrorListener.NULL_LISTENER);
+
+ // Scan.
+ Token token = scanner.tokenize();
+ LineInfo lineInfo = new LineInfo(scanner.lineStarts);
+
+ int errorIndex = 0;
+
+ // Step through tokens looking for comments.
+ while (errorIndex < errors.length && token.type != TokenType.EOF) {
+ // Find leading comment.
+ Token comments = token.precedingComments;
+ while (comments?.next != null) {
+ comments = comments.next;
+ }
+
+ // Normalize content.
+ String comment =
+ comments?.lexeme?.toLowerCase()?.replaceAll(new RegExp(r'\s+'), '');
+
+ // Check for ignores.
+ if (comment != null && comment.startsWith(_normalizedIgnorePrefix)) {
+ int affectedLine = lineInfo.getLocation(token.offset).lineNumber;
+
+ // Process all affected errors.
+ while (errorIndex < errors.length) {
+ AnalysisError currentError = errors[errorIndex++];
+ int errorLine = lineInfo.getLocation(currentError.offset).lineNumber;
+ if (errorLine < affectedLine) {
+ filtered.add(currentError);
+ } else if (errorLine == affectedLine) {
+ // Check for an ignore.
+ if (!_isIgnoredBy(currentError, comment)) {
+ filtered.add(currentError);
+ }
+ } else {
+ // Back up index and break.
+ --errorIndex;
+ break;
+ }
+ }
+ }
+
+ token = token.next;
+ }
+
+ // Add remaining errors.
+ if (errorIndex < errors.length) {
+ filtered.addAll(errors.sublist(errorIndex));
+ }
+
+ return filtered;
+ }
+
+ bool _isIgnoredBy(AnalysisError error, String comment) => comment
+ .substring(_normalizedIgnorePrefix.length)
+ .split(',')
+ .contains(error.errorCode.name.toLowerCase());
+
/**
* Return a map from the names of the inputs of this kind of task to the task
* input descriptors describing those inputs for a task with the
@@ -2538,7 +2618,7 @@
'GatherUsedLocalElementsTask',
createTask,
buildInputs,
- <ResultDescriptor>[USED_LOCAL_ELEMENTS]);
+ <ResultDescriptor>[DEFINED_ELEMENTS, USED_LOCAL_ELEMENTS]);
GatherUsedLocalElementsTask(
InternalAnalysisContext context, AnalysisTarget target)
@@ -2553,7 +2633,7 @@
CompilationUnitElement unitElement = unit.element;
LibraryElement libraryElement = unitElement.library;
//
- // Prepare used local elements.
+ // Prepare defined and used local elements.
//
GatherUsedLocalElementsVisitor visitor =
new GatherUsedLocalElementsVisitor(libraryElement);
@@ -2561,6 +2641,7 @@
//
// Record outputs.
//
+ outputs[DEFINED_ELEMENTS] = visitor.definedElements;
outputs[USED_LOCAL_ELEMENTS] = visitor.usedElements;
}
@@ -2594,6 +2675,11 @@
static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
/**
+ * The name of a list of [DEFINED_ELEMENTS] for each library unit input.
+ */
+ static const String DEFINED_ELEMENTS_INPUT = 'DEFINED_ELEMENTS';
+
+ /**
* The name of a list of [USED_LOCAL_ELEMENTS] for each library unit input.
*/
static const String USED_LOCAL_ELEMENTS_INPUT = 'USED_LOCAL_ELEMENTS';
@@ -2639,6 +2725,8 @@
CompilationUnit unit = getRequiredInput(RESOLVED_UNIT_INPUT);
List<UsedImportedElements> usedImportedElementsList =
getRequiredInput(USED_IMPORTED_ELEMENTS_INPUT);
+ List<List<Element>> definedElementsList =
+ getRequiredInput(DEFINED_ELEMENTS_INPUT);
List<UsedLocalElements> usedLocalElementsList =
getRequiredInput(USED_LOCAL_ELEMENTS_INPUT);
CompilationUnitElement unitElement = unit.element;
@@ -2663,7 +2751,11 @@
new UsedLocalElements.merge(usedLocalElementsList);
UnusedLocalElementsVerifier visitor =
new UnusedLocalElementsVerifier(errorListener, usedElements);
- unitElement.accept(visitor);
+ for (List<Element> definedElements in definedElementsList) {
+ for (Element element in definedElements) {
+ element.accept(visitor);
+ }
+ }
}
// Dart2js analysis.
if (analysisOptions.dart2jsHint) {
@@ -2695,6 +2787,8 @@
Source libSource = unit.library;
return <String, TaskInput>{
RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(unit),
+ DEFINED_ELEMENTS_INPUT:
+ LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(DEFINED_ELEMENTS),
USED_LOCAL_ELEMENTS_INPUT:
LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(USED_LOCAL_ELEMENTS),
USED_IMPORTED_ELEMENTS_INPUT:
diff --git a/pkg/analyzer/lib/src/task/html.dart b/pkg/analyzer/lib/src/task/html.dart
index 01cdd5a..90e78bd 100644
--- a/pkg/analyzer/lib/src/task/html.dart
+++ b/pkg/analyzer/lib/src/task/html.dart
@@ -7,10 +7,10 @@
import 'dart:collection';
import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/plugin/engine_plugin.dart';
import 'package:analyzer/src/task/general.dart';
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index 4f674ef..b3b3512 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -7,13 +7,14 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
/**
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 4a6483c..9b96c6a 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -30,6 +30,11 @@
final _OptionsProcessor _processor = new _OptionsProcessor();
+void applyToAnalysisOptions(
+ AnalysisOptionsImpl options, Map<String, Object> optionMap) {
+ _processor.applyToAnalysisOptions(options, optionMap);
+}
+
/// Configure this [context] based on configuration details specified in
/// the given [options]. If [options] is `null`, default values are applied.
void configureContextOptions(
@@ -412,6 +417,28 @@
class _OptionsProcessor {
static final Map<String, Object> defaults = {'analyzer': {}};
+ /**
+ * Apply the options in the given [optionMap] to the given analysis [options].
+ */
+ void applyToAnalysisOptions(
+ AnalysisOptionsImpl options, Map<String, Object> optionMap) {
+ if (optionMap == null) {
+ return;
+ }
+ var analyzer = optionMap[AnalyzerOptions.analyzer];
+ if (analyzer is! Map) {
+ return;
+ }
+ // Process strong mode option.
+ var strongMode = analyzer[AnalyzerOptions.strong_mode];
+ if (strongMode is bool) {
+ options.strongMode = strongMode;
+ }
+ // Process language options.
+ var language = analyzer[AnalyzerOptions.language];
+ _applyLanguageOptions(options, language);
+ }
+
/// Configure [context] based on the given [options] (which can be `null`
/// to restore [defaults]).
void configure(AnalysisContext context, Map<String, Object> options) {
@@ -493,4 +520,34 @@
context.analysisOptions = options;
}
}
+
+ void _applyLanguageOption(
+ AnalysisOptionsImpl options, Object feature, Object value) {
+ bool boolValue = toBool(value);
+ if (boolValue != null) {
+ if (feature == AnalyzerOptions.enableAsync) {
+ options.enableAsync = boolValue;
+ }
+ if (feature == AnalyzerOptions.enableSuperMixins) {
+ options.enableSuperMixins = boolValue;
+ }
+ if (feature == AnalyzerOptions.enableGenericMethods) {
+ options.enableGenericMethods = boolValue;
+ }
+ }
+ }
+
+ void _applyLanguageOptions(AnalysisOptionsImpl options, Object configs) {
+ if (configs is YamlMap) {
+ configs.nodes.forEach((key, value) {
+ if (key is YamlScalar && value is YamlScalar) {
+ String feature = key.value?.toString();
+ _applyLanguageOption(options, feature, value.value);
+ }
+ });
+ } else if (configs is Map) {
+ configs
+ .forEach((key, value) => _applyLanguageOption(options, key, value));
+ }
+ }
}
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index a67251e7..b391517 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -8,12 +8,12 @@
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType;
import 'package:analyzer/src/generated/type_system.dart';
import 'info.dart';
@@ -569,15 +569,7 @@
final Coercion c = _coerceTo(fromT, toT);
if (c is Identity) return null;
if (c is CoercionError) return new StaticTypeError(rules, expr, toT);
- var reason = null;
-
- var errors = <String>[];
-
- var ok = _inferExpression(expr, toT, errors);
- if (ok) return InferredType.create(rules, expr, toT);
- reason = (errors.isNotEmpty) ? errors.first : null;
-
- if (c is Cast) return DownCast.create(rules, expr, c, reason: reason);
+ if (c is Cast) return DownCast.create(rules, expr, c);
assert(false);
return null;
}
@@ -800,17 +792,6 @@
return null;
}
- /// Checks if we can perform downwards inference on [e] tp get type [t].
- /// If it is not possible, this will add a message to [errors].
- bool _inferExpression(Expression e, DartType t, List<String> errors) {
- DartType staticType = e.staticType ?? DynamicTypeImpl.instance;
- if (rules.isSubtypeOf(staticType, t)) {
- return true;
- }
- errors.add("$e cannot be typed as $t");
- return false;
- }
-
/// Returns `true` if the expression is a dynamic function call or method
/// invocation.
bool _isDynamicCall(Expression call) {
diff --git a/pkg/analyzer/lib/src/task/strong/info.dart b/pkg/analyzer/lib/src/task/strong/info.dart
index 8295439..c3a5839 100644
--- a/pkg/analyzer/lib/src/task/strong/info.dart
+++ b/pkg/analyzer/lib/src/task/strong/info.dart
@@ -107,8 +107,7 @@
// Factory to create correct DownCast variant.
static StaticInfo create(
- StrongTypeSystemImpl rules, Expression expression, Cast cast,
- {String reason}) {
+ StrongTypeSystemImpl rules, Expression expression, Cast cast) {
final fromT = cast.fromType;
final toT = cast.toType;
@@ -127,14 +126,15 @@
if (expression is Literal || expression is FunctionExpression) {
// fromT should be an exact type - this will almost certainly fail at
// runtime.
- return new StaticTypeError(rules, expression, toT, reason: reason);
+ return new StaticTypeError(rules, expression, toT);
}
+
if (expression is InstanceCreationExpression) {
ConstructorElement e = expression.staticElement;
if (e == null || !e.isFactory) {
// fromT should be an exact type - this will almost certainly fail at
// runtime.
- return new StaticTypeError(rules, expression, toT, reason: reason);
+ return new StaticTypeError(rules, expression, toT);
}
}
@@ -148,7 +148,7 @@
// declaration, will have an exact type, so we know a downcast will fail.
if (element is FunctionElement ||
element is MethodElement && element.isStatic) {
- return new StaticTypeError(rules, expression, toT, reason: reason);
+ return new StaticTypeError(rules, expression, toT);
}
// TODO(vsm): Change this to an assert when we have generic methods and
@@ -556,19 +556,15 @@
class StaticTypeError extends StaticError {
final DartType baseType;
final DartType expectedType;
- String reason = null;
- StaticTypeError(TypeSystem rules, Expression expression, this.expectedType,
- {this.reason})
+ StaticTypeError(TypeSystem rules, Expression expression, this.expectedType)
: baseType = expression.staticType ?? DynamicTypeImpl.instance,
super(expression);
@override
List<Object> get arguments => [node, baseType, expectedType];
@override
- String get message =>
- 'Type check failed: {0} ({1}) is not of type {2}' +
- ((reason == null) ? '' : ' because $reason');
+ String get message => 'Type check failed: {0} ({1}) is not of type {2}';
@override
String get name => 'STRONG_MODE_STATIC_TYPE_ERROR';
diff --git a/pkg/analyzer/lib/src/task/yaml.dart b/pkg/analyzer/lib/src/task/yaml.dart
index 8ce7ec1..1e1951c 100644
--- a/pkg/analyzer/lib/src/task/yaml.dart
+++ b/pkg/analyzer/lib/src/task/yaml.dart
@@ -5,10 +5,10 @@
library analyzer.src.task.yaml;
import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/task/general.dart';
import 'package:analyzer/task/general.dart';
diff --git a/pkg/analyzer/lib/task/dart.dart b/pkg/analyzer/lib/task/dart.dart
index ea132e3..3dbea46 100644
--- a/pkg/analyzer/lib/task/dart.dart
+++ b/pkg/analyzer/lib/task/dart.dart
@@ -5,9 +5,9 @@
library analyzer.task.dart;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/task/dart.dart';
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 893b888..c376533 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.27.2-alpha.1
+version: 0.27.2
author: Dart Team <misc@dartlang.org>
description: Static analyzer for Dart.
homepage: http://www.dartlang.org
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index f8d51f1..7be2b72 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -5,8 +5,8 @@
library analyzer.test.dart.ast.ast_test;
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/testing/ast_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:unittest/unittest.dart';
@@ -502,7 +502,7 @@
list.addAll(nodes);
expect(list, hasLength(3));
AstNode fourthNode = AstFactory.integer(0);
- expect(javaListSet(list, 1, fourthNode), same(secondNode));
+ list[1] = fourthNode;
expect(list, hasLength(3));
expect(list[0], same(firstNode));
expect(list[1], same(fourthNode));
@@ -513,7 +513,7 @@
AstNode node = AstFactory.booleanLiteral(true);
NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
try {
- javaListSet(list, -1, node);
+ list[-1] = node;
fail("Expected IndexOutOfBoundsException");
} on RangeError {
// Expected
@@ -524,7 +524,7 @@
AstNode node = AstFactory.booleanLiteral(true);
NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
try {
- javaListSet(list, 1, node);
+ list[1] = node;
fail("Expected IndexOutOfBoundsException");
} on RangeError {
// Expected
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 2061e63..3eb5cd0 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -5,6 +5,7 @@
library analyzer.test.generated.all_the_rest_test;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
@@ -18,7 +19,6 @@
import 'package:analyzer/src/generated/java_engine_io.dart';
import 'package:analyzer/src/generated/java_io.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/sdk_io.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -606,6 +606,7 @@
expect(type.isAbstract, isFalse);
expect(type.isMixinApplication, isFalse);
expect(type.isSynthetic, isFalse);
+ expect(type.documentationComment, '/// aaa');
_assertHasDocRange(type, 50, 7);
}
@@ -849,6 +850,7 @@
expect(constructors, hasLength(1));
ConstructorElement constructor = constructors[0];
expect(constructor, isNotNull);
+ expect(constructor.documentationComment, '/// aaa');
_assertHasDocRange(constructor, 50, 7);
expect(constructor.isExternal, isFalse);
expect(constructor.isFactory, isFalse);
@@ -1034,6 +1036,7 @@
expect(enums, hasLength(1));
ClassElement enumElement = enums[0];
expect(enumElement, isNotNull);
+ expect(enumElement.documentationComment, '/// aaa');
_assertHasDocRange(enumElement, 50, 7);
expect(enumElement.name, enumName);
}
@@ -1057,6 +1060,7 @@
FieldElement firstField = fields[0];
expect(firstField, isNotNull);
+ expect(firstField.documentationComment, '/// aaa');
_assertHasDocRange(firstField, 50, 7);
expect(firstField.name, firstFieldName);
expect(firstField.initializer, isNull);
@@ -1066,6 +1070,7 @@
FieldElement secondField = fields[1];
expect(secondField, isNotNull);
+ expect(secondField.documentationComment, '/// aaa');
_assertHasDocRange(secondField, 50, 7);
expect(secondField.name, secondFieldName);
expect(secondField.initializer, isNull);
@@ -1181,6 +1186,7 @@
expect(accessors, hasLength(1));
PropertyAccessorElement accessor = accessors[0];
expect(accessor, isNotNull);
+ expect(accessor.documentationComment, '/// aaa');
_assertHasDocRange(accessor, 50, 7);
expect(accessor.name, functionName);
expect(declaration.element, same(accessor));
@@ -1216,6 +1222,7 @@
expect(functions, hasLength(1));
FunctionElement function = functions[0];
expect(function, isNotNull);
+ expect(function.documentationComment, '/// aaa');
_assertHasDocRange(function, 50, 7);
expect(function.hasImplicitReturnType, isFalse);
expect(function.name, functionName);
@@ -1245,6 +1252,7 @@
expect(accessors, hasLength(1));
PropertyAccessorElement accessor = accessors[0];
expect(accessor, isNotNull);
+ expect(accessor.documentationComment, '/// aaa');
_assertHasDocRange(accessor, 50, 7);
expect(accessor.hasImplicitReturnType, isTrue);
expect(accessor.name, "$functionName=");
@@ -1323,6 +1331,7 @@
expect(aliases, hasLength(1));
FunctionTypeAliasElement alias = aliases[0];
expect(alias, isNotNull);
+ expect(alias.documentationComment, '/// aaa');
_assertHasDocRange(alias, 50, 7);
expect(alias.name, aliasName);
expect(alias.parameters, hasLength(0));
@@ -1488,6 +1497,7 @@
expect(field.setter, isNull);
PropertyAccessorElement getter = field.getter;
expect(getter, isNotNull);
+ expect(getter.documentationComment, '/// aaa');
_assertHasDocRange(getter, 50, 7);
expect(getter.hasImplicitReturnType, isTrue);
expect(getter.isAbstract, isFalse);
@@ -1598,6 +1608,7 @@
expect(methods, hasLength(1));
MethodElement method = methods[0];
expect(method, isNotNull);
+ expect(method.documentationComment, '/// aaa');
_assertHasDocRange(method, 50, 7);
expect(method.hasImplicitReturnType, isFalse);
expect(method.name, methodName);
@@ -1672,6 +1683,7 @@
PropertyAccessorElement setter = field.setter;
expect(setter, isNotNull);
+ expect(setter.documentationComment, '/// aaa');
_assertHasDocRange(setter, 50, 7);
expect(setter.hasImplicitReturnType, isTrue);
expect(setter.isAbstract, isFalse);
@@ -2235,10 +2247,12 @@
TopLevelVariableElement variable1 = variables[0];
expect(variable1, isNotNull);
+ expect(variable1.documentationComment, '/// aaa');
_assertHasDocRange(variable1, 50, 7);
TopLevelVariableElement variable2 = variables[1];
expect(variable2, isNotNull);
+ expect(variable2.documentationComment, '/// aaa');
_assertHasDocRange(variable2, 50, 7);
}
@@ -2782,6 +2796,9 @@
String firstName = "ONE";
EnumDeclaration enumDeclaration =
AstFactory.enumDeclaration2("E", [firstName]);
+ enumDeclaration.constants[0].documentationComment = AstFactory
+ .documentationComment(
+ [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
ClassElement enumElement = _buildElement(enumDeclaration);
List<FieldElement> fields = enumElement.fields;
@@ -2807,6 +2824,9 @@
expect(constant.name, firstName);
expect(constant.isStatic, isTrue);
expect((constant as FieldElementImpl).evaluationResult, isNotNull);
+ expect(constant.documentationComment, '/// aaa');
+ expect(constant.docRange.offset, 50);
+ expect(constant.docRange.length, 7);
_assertGetter(constant);
}
@@ -3951,32 +3971,6 @@
}
}
-/**
- * Instances of the class `MockDartSdk` implement a [DartSdk].
- */
-class MockDartSdk implements DartSdk {
- @override
- AnalysisContext get context => null;
-
- @override
- List<SdkLibrary> get sdkLibraries => null;
-
- @override
- String get sdkVersion => null;
-
- @override
- List<String> get uris => null;
-
- @override
- Source fromFileUri(Uri uri) => null;
-
- @override
- SdkLibrary getSdkLibrary(String dartUri) => null;
-
- @override
- Source mapDartUri(String dartUri) => null;
-}
-
@reflectiveTest
class SDKLibrariesReaderTest extends EngineTestCase {
void test_readFrom_dart2js() {
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index 4b611b7..bb9ba02 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -5,15 +5,15 @@
library analyzer.test.constant_test;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/testing/ast_factory.dart';
@@ -41,6 +41,8 @@
runReflectiveTests(ReferenceFinderTest);
}
+const int LONG_MAX_VALUE = 0x7fffffffffffffff;
+
/**
* Implementation of [ConstantEvaluationValidator] used during unit tests;
* verifies that any nodes referenced during constant evaluation are present in
@@ -622,10 +624,10 @@
return new List<Annotation>.from(annotations);
}
- Set<ConstantEvaluationTarget> _findConstants() {
+ List<ConstantEvaluationTarget> _findConstants() {
ConstantFinder finder = new ConstantFinder(_context, _source, _source);
_node.accept(finder);
- Set<ConstantEvaluationTarget> constants = finder.constantsToCompute;
+ List<ConstantEvaluationTarget> constants = finder.constantsToCompute;
expect(constants, isNotNull);
return constants;
}
@@ -4213,7 +4215,7 @@
*
* @param expected the expected result of the operation
* @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
+ * @param rightOperand the right operand to the operation
* @throws EvaluationException if the result is an exception when it should not be
*/
void _assertShiftRight(DartObjectImpl expected, DartObjectImpl leftOperand,
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index 4620528..8d6bf51 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -302,6 +302,18 @@
expect(setterName.staticElement, same(setterElement));
}
+ void test_visitFunctionExpression() {
+ String code = r'''
+main(List<String> items) {
+ items.forEach((item) {});
+}
+''';
+ CompilationUnit unit = resolveSource(code);
+ // re-resolve
+ _cloneResolveUnit(unit);
+ // no other validations than built into DeclarationResolver
+ }
+
void test_visitMethodDeclaration_getter_duplicate() {
String code = r'''
class C {
diff --git a/pkg/analyzer/test/generated/error_suppression_test.dart b/pkg/analyzer/test/generated/error_suppression_test.dart
new file mode 100644
index 0000000..560a2c2
--- /dev/null
+++ b/pkg/analyzer/test/generated/error_suppression_test.dart
@@ -0,0 +1,152 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+
+import '../reflective_tests.dart';
+import '../utils.dart';
+import 'resolver_test.dart';
+
+main() {
+ initializeTestEnvironment();
+ runReflectiveTests(ErrorSuppressionTest);
+}
+
+@reflectiveTest
+class ErrorSuppressionTest extends ResolverTestCase {
+ void test_error_code_mismatch() {
+ Source source = addSource('''
+//# ignore: const_initialized_with_non_constant_value
+int x = '';
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [
+ StaticTypeWarningCode.INVALID_ASSIGNMENT,
+ CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+ ]);
+ }
+
+ void test_ignore_first() {
+ Source source = addSource('''
+//# ignore: invalid_assignment
+int x = '';
+// ... but no ignore here ...
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source,
+ [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
+ }
+
+ void test_ignore_second() {
+ Source source = addSource('''
+//INVALID_ASSIGNMENT
+int x = '';
+//# ignore: const_initialized_with_non_constant_value
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
+ void test_invalid_error_code() {
+ Source source = addSource('''
+//# ignore: right_format_wrong_code
+int x = '';
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [
+ StaticTypeWarningCode.INVALID_ASSIGNMENT,
+ CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+ ]);
+ }
+
+ void test_missing_error_codes() {
+ Source source = addSource('''
+ int x = 3;
+//# ignore:
+const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [
+ StaticTypeWarningCode.INVALID_ASSIGNMENT,
+ CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+ ]);
+ }
+
+ void test_missing_metadata_prefix() {
+ Source source = addSource('''
+// ignore: invalid_assignment
+String y = 3; //INVALID_ASSIGNMENT
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
+ void test_multiple_comments() {
+ Source source = addSource('''
+int x = ''; //This is the first comment...
+//# ignore: const_initialized_with_non_constant_value
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
+ void test_multiple_ignores() {
+ Source source = addSource('''
+int x = 3;
+//# ignore: invalid_assignment, const_initialized_with_non_constant_value
+const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, []);
+ }
+
+ void test_multiple_ignores_whitespace_variant_1() {
+ Source source = addSource('''
+int x = 3;
+//#ignore:invalid_assignment,const_initialized_with_non_constant_value
+const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, []);
+ }
+
+ void test_multiple_ignores_whitespace_variant_2() {
+ Source source = addSource('''
+int x = 3;
+//#ignore: invalid_assignment,const_initialized_with_non_constant_value
+const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, []);
+ }
+
+ void test_multiple_ignores_whitespace_variant_3() {
+ Source source = addSource('''
+int x = 3;
+//# ignore: invalid_assignment,const_initialized_with_non_constant_value
+const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, []);
+ }
+
+ void test_no_ignores() {
+ Source source = addSource('''
+int x = ''; //INVALID_ASSIGNMENT
+const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [
+ StaticTypeWarningCode.INVALID_ASSIGNMENT,
+ CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 9e3b75a..5c52f17 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -5,11 +5,14 @@
library analyzer.test.generated.incremental_resolver_test;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/incremental_logger.dart' as logging;
@@ -18,7 +21,6 @@
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/testing/ast_factory.dart';
import 'package:analyzer/src/generated/testing/element_factory.dart';
@@ -42,81 +44,81 @@
void initializeTestEnvironment() {}
-void _assertEqualError(AnalysisError incrError, AnalysisError fullError) {
- if (incrError.errorCode != fullError.errorCode ||
- incrError.source != fullError.source ||
- incrError.offset != fullError.offset ||
- incrError.length != fullError.length ||
- incrError.message != fullError.message) {
+void _assertEqualError(AnalysisError incError, AnalysisError fullError) {
+ if (incError.errorCode != fullError.errorCode ||
+ incError.source != fullError.source ||
+ incError.offset != fullError.offset ||
+ incError.length != fullError.length ||
+ incError.message != fullError.message) {
StringBuffer buffer = new StringBuffer();
buffer.writeln('Found error does not match expected error:');
- if (incrError.errorCode == fullError.errorCode) {
+ if (incError.errorCode == fullError.errorCode) {
buffer.write(' errorCode = ');
buffer.write(fullError.errorCode.uniqueName);
} else {
buffer.write(' Expected errorCode = ');
buffer.write(fullError.errorCode.uniqueName);
buffer.write(' found ');
- buffer.write(incrError.errorCode.uniqueName);
+ buffer.write(incError.errorCode.uniqueName);
}
buffer.writeln();
- if (incrError.source == fullError.source) {
+ if (incError.source == fullError.source) {
buffer.write(' source = ');
buffer.write(fullError.source);
} else {
buffer.write(' Expected source = ');
buffer.write(fullError.source);
buffer.write(' found ');
- buffer.write(incrError.source);
+ buffer.write(incError.source);
}
buffer.writeln();
- if (incrError.offset == fullError.offset) {
+ if (incError.offset == fullError.offset) {
buffer.write(' offset = ');
buffer.write(fullError.offset);
} else {
buffer.write(' Expected offset = ');
buffer.write(fullError.offset);
buffer.write(' found ');
- buffer.write(incrError.offset);
+ buffer.write(incError.offset);
}
buffer.writeln();
- if (incrError.length == fullError.length) {
+ if (incError.length == fullError.length) {
buffer.write(' length = ');
buffer.write(fullError.length);
} else {
buffer.write(' Expected length = ');
buffer.write(fullError.length);
buffer.write(' found ');
- buffer.write(incrError.length);
+ buffer.write(incError.length);
}
buffer.writeln();
- if (incrError.message == fullError.message) {
+ if (incError.message == fullError.message) {
buffer.write(' message = ');
buffer.write(fullError.message);
} else {
buffer.write(' Expected message = ');
buffer.write(fullError.message);
buffer.write(' found ');
- buffer.write(incrError.message);
+ buffer.write(incError.message);
}
fail(buffer.toString());
}
}
void _assertEqualErrors(
- List<AnalysisError> incrErrors, List<AnalysisError> fullErrors) {
- expect(incrErrors, hasLength(fullErrors.length));
- if (incrErrors.isNotEmpty) {
- incrErrors.sort((a, b) => a.offset - b.offset);
+ List<AnalysisError> incErrors, List<AnalysisError> fullErrors) {
+ expect(incErrors, hasLength(fullErrors.length));
+ if (incErrors.isNotEmpty) {
+ incErrors.sort((a, b) => a.offset - b.offset);
}
if (fullErrors.isNotEmpty) {
fullErrors.sort((a, b) => a.offset - b.offset);
}
- int length = incrErrors.length;
+ int length = incErrors.length;
for (int i = 0; i < length; i++) {
- AnalysisError incrError = incrErrors[i];
+ AnalysisError incError = incErrors[i];
AnalysisError fullError = fullErrors[i];
- _assertEqualError(incrError, fullError);
+ _assertEqualError(incError, fullError);
}
}
@@ -3611,13 +3613,15 @@
print(x + 1);
}
''');
- _updateAndValidate(r'''
+ _updateAndValidate(
+ r'''
int f() => 0;
main() {
const x = f();
print(x + 2);
}
-''');
+''',
+ expectCachePostConstantsValid: false);
}
void test_dartDoc_beforeField() {
@@ -4206,6 +4210,21 @@
''');
}
+ void test_hasElementAfter_defaultParameter() {
+ _resolveUnit(r'''
+main() {
+ print(1);
+}
+otherFunction([p = 0]) {}
+''');
+ _updateAndValidate(r'''
+main() {
+ print(2);
+}
+otherFunction([p = 0]) {}
+''');
+ }
+
void test_inBody_expression() {
_resolveUnit(r'''
class A {
@@ -4550,11 +4569,13 @@
const v = const [Unknown];
}
''');
- _updateAndValidate(r'''
+ _updateAndValidate(
+ r'''
main() {
const v = const [Unknown];
}
-''');
+''',
+ expectCachePostConstantsValid: false);
}
void test_updateErrors_addNew_hint1() {
@@ -4828,14 +4849,65 @@
}
}
- void _assertEqualLineInfo(LineInfo incrLineInfo, LineInfo fullLineInfo) {
+ void _assertCacheResults({bool expectCachePostConstantsValid: true}) {
+ _assertCacheSourceResult(TOKEN_STREAM);
+ _assertCacheSourceResult(SCAN_ERRORS);
+ _assertCacheSourceResult(PARSED_UNIT);
+ _assertCacheSourceResult(PARSE_ERRORS);
+ _assertCacheSourceResult(LIBRARY_ELEMENT1);
+ _assertCacheSourceResult(LIBRARY_ELEMENT2);
+ _assertCacheSourceResult(LIBRARY_ELEMENT3);
+ _assertCacheSourceResult(LIBRARY_ELEMENT4);
+ _assertCacheSourceResult(LIBRARY_ELEMENT5);
+ _assertCacheSourceResult(LIBRARY_ELEMENT6);
+ _assertCacheSourceResult(LIBRARY_ELEMENT7);
+ _assertCacheSourceResult(LIBRARY_ELEMENT8);
+ if (expectCachePostConstantsValid) {
+ _assertCacheSourceResult(LIBRARY_ELEMENT);
+ }
+ _assertCacheUnitResult(RESOLVED_UNIT1);
+ _assertCacheUnitResult(RESOLVED_UNIT2);
+ _assertCacheUnitResult(RESOLVED_UNIT3);
+ _assertCacheUnitResult(RESOLVED_UNIT4);
+ _assertCacheUnitResult(RESOLVED_UNIT5);
+ _assertCacheUnitResult(RESOLVED_UNIT6);
+ _assertCacheUnitResult(RESOLVED_UNIT7);
+ _assertCacheUnitResult(RESOLVED_UNIT8);
+ _assertCacheUnitResult(RESOLVED_UNIT9);
+ _assertCacheUnitResult(RESOLVED_UNIT10);
+ if (expectCachePostConstantsValid) {
+ _assertCacheUnitResult(RESOLVED_UNIT11);
+ _assertCacheUnitResult(RESOLVED_UNIT);
+ }
+ }
+
+ /**
+ * Assert that the [result] of [source] is not INVALID.
+ */
+ void _assertCacheSourceResult(ResultDescriptor result) {
+ AnalysisCache cache = analysisContext2.analysisCache;
+ CacheState state = cache.getState(source, result);
+ expect(state, isNot(CacheState.INVALID), reason: result.toString());
+ }
+
+ /**
+ * Assert that the [result] of the defining unit [source] is not INVALID.
+ */
+ void _assertCacheUnitResult(ResultDescriptor result) {
+ AnalysisCache cache = analysisContext2.analysisCache;
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+ CacheState state = cache.getState(target, result);
+ expect(state, isNot(CacheState.INVALID), reason: result.toString());
+ }
+
+ void _assertEqualLineInfo(LineInfo incLineInfo, LineInfo fullLineInfo) {
for (int offset = 0; offset < 1000; offset++) {
- LineInfo_Location incrLocation = incrLineInfo.getLocation(offset);
+ LineInfo_Location incLocation = incLineInfo.getLocation(offset);
LineInfo_Location fullLocation = fullLineInfo.getLocation(offset);
- if (incrLocation.lineNumber != fullLocation.lineNumber ||
- incrLocation.columnNumber != fullLocation.columnNumber) {
+ if (incLocation.lineNumber != fullLocation.lineNumber ||
+ incLocation.columnNumber != fullLocation.columnNumber) {
fail('At offset $offset ' +
- '(${incrLocation.lineNumber}, ${incrLocation.columnNumber})' +
+ '(${incLocation.lineNumber}, ${incLocation.columnNumber})' +
' != ' +
'(${fullLocation.lineNumber}, ${fullLocation.columnNumber})');
}
@@ -4871,6 +4943,7 @@
void _updateAndValidate(String newCode,
{bool expectedSuccess: true,
+ bool expectCachePostConstantsValid: true,
bool compareWithFull: true,
bool runTasksBeforeIncremental: true}) {
// Run any pending tasks tasks.
@@ -4890,6 +4963,10 @@
expect(newUnit.element, isNot(same(oldUnitElement)));
return;
}
+ // The cache must still have enough results to make the incremental
+ // resolution useful.
+ _assertCacheResults(
+ expectCachePostConstantsValid: expectCachePostConstantsValid);
// The existing CompilationUnit[Element] should be updated.
expect(newUnit, same(oldUnit));
expect(newUnit.element, same(oldUnitElement));
@@ -4925,37 +5002,37 @@
_checkCacheEntries(analysisContext2.analysisCache);
}
- static void _assertEqualToken(Token incrToken, Token fullToken) {
-// print('[${incrToken.offset}] |$incrToken| vs. [${fullToken.offset}] |$fullToken|');
- expect(incrToken.type, fullToken.type);
- expect(incrToken.offset, fullToken.offset);
- expect(incrToken.length, fullToken.length);
- expect(incrToken.lexeme, fullToken.lexeme);
+ static void _assertEqualToken(Token incToken, Token fullToken) {
+// print('[${incToken.offset}] |$incToken| vs. [${fullToken.offset}] |$fullToken|');
+ expect(incToken.type, fullToken.type);
+ expect(incToken.offset, fullToken.offset);
+ expect(incToken.length, fullToken.length);
+ expect(incToken.lexeme, fullToken.lexeme);
}
static void _assertEqualTokens(
- CompilationUnit incrUnit, CompilationUnit fullUnit) {
- Token incrToken = incrUnit.beginToken;
+ CompilationUnit incUnit, CompilationUnit fullUnit) {
+ Token incToken = incUnit.beginToken;
Token fullToken = fullUnit.beginToken;
- while (incrToken.type != TokenType.EOF && fullToken.type != TokenType.EOF) {
- _assertEqualToken(incrToken, fullToken);
+ while (incToken.type != TokenType.EOF && fullToken.type != TokenType.EOF) {
+ _assertEqualToken(incToken, fullToken);
// comments
{
- Token incrComment = incrToken.precedingComments;
+ Token incComment = incToken.precedingComments;
Token fullComment = fullToken.precedingComments;
while (true) {
if (fullComment == null) {
- expect(incrComment, isNull);
+ expect(incComment, isNull);
break;
}
- expect(incrComment, isNotNull);
- _assertEqualToken(incrComment, fullComment);
- incrComment = incrComment.next;
+ expect(incComment, isNotNull);
+ _assertEqualToken(incComment, fullComment);
+ incComment = incComment.next;
fullComment = fullComment.next;
}
}
// next tokens
- incrToken = incrToken.next;
+ incToken = incToken.next;
fullToken = fullToken.next;
}
}
diff --git a/pkg/analyzer/test/generated/incremental_scanner_test.dart b/pkg/analyzer/test/generated/incremental_scanner_test.dart
index fad6244..2c21e61 100644
--- a/pkg/analyzer/test/generated/incremental_scanner_test.dart
+++ b/pkg/analyzer/test/generated/incremental_scanner_test.dart
@@ -4,9 +4,11 @@
library analyzer.test.generated.incremental_scanner_test;
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/incremental_scanner.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:unittest/unittest.dart';
diff --git a/pkg/analyzer/test/generated/java_core_test.dart b/pkg/analyzer/test/generated/java_core_test.dart
index 0a914ec..f98895e 100644
--- a/pkg/analyzer/test/generated/java_core_test.dart
+++ b/pkg/analyzer/test/generated/java_core_test.dart
@@ -12,30 +12,6 @@
main() {
initializeTestEnvironment();
group('Character', () {
- group('isDigit', () {
- test('digits', () {
- expect(Character.isDigit('0'.codeUnitAt(0)), isTrue);
- expect(Character.isDigit('1'.codeUnitAt(0)), isTrue);
- expect(Character.isDigit('9'.codeUnitAt(0)), isTrue);
- });
-
- test('letters', () {
- expect(Character.isDigit('a'.codeUnitAt(0)), isFalse);
- expect(Character.isDigit('b'.codeUnitAt(0)), isFalse);
- expect(Character.isDigit('z'.codeUnitAt(0)), isFalse);
- expect(Character.isDigit('C'.codeUnitAt(0)), isFalse);
- expect(Character.isDigit('D'.codeUnitAt(0)), isFalse);
- expect(Character.isDigit('Y'.codeUnitAt(0)), isFalse);
- });
-
- test('other', () {
- expect(Character.isDigit(' '.codeUnitAt(0)), isFalse);
- expect(Character.isDigit('.'.codeUnitAt(0)), isFalse);
- expect(Character.isDigit('-'.codeUnitAt(0)), isFalse);
- expect(Character.isDigit('+'.codeUnitAt(0)), isFalse);
- });
- });
-
group('isLetter', () {
test('digits', () {
expect(Character.isLetter('0'.codeUnitAt(0)), isFalse);
@@ -83,73 +59,5 @@
expect(Character.isLetterOrDigit('+'.codeUnitAt(0)), isFalse);
});
});
-
- group('isLowerCase', () {
- test('ASCII digits', () {
- expect(Character.isLowerCase('0'.codeUnitAt(0)), isFalse);
- expect(Character.isLowerCase('9'.codeUnitAt(0)), isFalse);
- });
-
- test('ASCII lower', () {
- expect(Character.isLowerCase('a'.codeUnitAt(0)), isTrue);
- expect(Character.isLowerCase('s'.codeUnitAt(0)), isTrue);
- expect(Character.isLowerCase('z'.codeUnitAt(0)), isTrue);
- });
-
- test('ASCII upper', () {
- expect(Character.isLowerCase('A'.codeUnitAt(0)), isFalse);
- expect(Character.isLowerCase('S'.codeUnitAt(0)), isFalse);
- expect(Character.isLowerCase('Z'.codeUnitAt(0)), isFalse);
- });
- });
-
- group('isUpperCase', () {
- test('ASCII digits', () {
- expect(Character.isUpperCase('0'.codeUnitAt(0)), isFalse);
- expect(Character.isUpperCase('9'.codeUnitAt(0)), isFalse);
- });
-
- test('ASCII lower', () {
- expect(Character.isUpperCase('a'.codeUnitAt(0)), isFalse);
- expect(Character.isUpperCase('s'.codeUnitAt(0)), isFalse);
- expect(Character.isUpperCase('z'.codeUnitAt(0)), isFalse);
- });
-
- test('ASCII upper', () {
- expect(Character.isUpperCase('A'.codeUnitAt(0)), isTrue);
- expect(Character.isUpperCase('S'.codeUnitAt(0)), isTrue);
- expect(Character.isUpperCase('Z'.codeUnitAt(0)), isTrue);
- });
- });
-
- test('toLowerCase', () {
- expect(Character.toLowerCase('A'.codeUnitAt(0)), 'a'.codeUnitAt(0));
- expect(Character.toLowerCase('B'.codeUnitAt(0)), 'b'.codeUnitAt(0));
- expect(Character.toLowerCase('Z'.codeUnitAt(0)), 'z'.codeUnitAt(0));
- expect(Character.toLowerCase('c'.codeUnitAt(0)), 'c'.codeUnitAt(0));
- expect(Character.toLowerCase('0'.codeUnitAt(0)), '0'.codeUnitAt(0));
- });
-
- test('toUpperCase', () {
- expect(Character.toUpperCase('a'.codeUnitAt(0)), 'A'.codeUnitAt(0));
- expect(Character.toUpperCase('b'.codeUnitAt(0)), 'B'.codeUnitAt(0));
- expect(Character.toUpperCase('z'.codeUnitAt(0)), 'Z'.codeUnitAt(0));
- expect(Character.toUpperCase('C'.codeUnitAt(0)), 'C'.codeUnitAt(0));
- expect(Character.toUpperCase('0'.codeUnitAt(0)), '0'.codeUnitAt(0));
- });
-
- test('isWhitespace', () {
- expect(Character.isWhitespace('\t'.codeUnitAt(0)), isTrue);
- expect(Character.isWhitespace(' '.codeUnitAt(0)), isTrue);
- expect(Character.isWhitespace('\n'.codeUnitAt(0)), isTrue);
- expect(Character.isWhitespace('\r'.codeUnitAt(0)), isTrue);
- expect(Character.isWhitespace('.'.codeUnitAt(0)), isFalse);
- expect(Character.isWhitespace('0'.codeUnitAt(0)), isFalse);
- expect(Character.isWhitespace('9'.codeUnitAt(0)), isFalse);
- expect(Character.isWhitespace('a'.codeUnitAt(0)), isFalse);
- expect(Character.isWhitespace('z'.codeUnitAt(0)), isFalse);
- expect(Character.isWhitespace('A'.codeUnitAt(0)), isFalse);
- expect(Character.isWhitespace('Z'.codeUnitAt(0)), isFalse);
- });
});
}
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 2b33566..72186b4 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -5,16 +5,19 @@
library analyzer.test.generated.parser_test;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/incremental_scanner.dart';
import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart' show Source;
import 'package:analyzer/src/generated/testing/ast_factory.dart';
import 'package:analyzer/src/generated/testing/element_factory.dart';
@@ -505,6 +508,16 @@
BinaryExpression, expression.leftOperand);
}
+ void test_topLevelFunction_nestedGenericFunction() {
+ enableGenericMethods = true;
+ parseCompilationUnitWithOptions('''
+void f() {
+ void g<T>() {
+ }
+}
+''');
+ }
+
void _validate_assignableExpression_arguments_normal_chain_typeArguments(
String code) {
PropertyAccess propertyAccess1 = parseExpression(code);
@@ -2871,6 +2884,30 @@
parse3(methodName, _EMPTY_ARGUMENTS, source, errorCodes);
/**
+ * Parse the given [source] as a compilation unit. Throw an exception if the
+ * source could not be parsed, if the compilation errors in the source do not
+ * match those that are expected, or if the result would have been `null`.
+ */
+ CompilationUnit parseCompilationUnitWithOptions(String source,
+ [List<ErrorCode> errorCodes = ErrorCode.EMPTY_LIST]) {
+ GatheringErrorListener listener = new GatheringErrorListener();
+ Scanner scanner =
+ new Scanner(null, new CharSequenceReader(source), listener);
+ listener.setLineInfo(new TestSource(), scanner.lineStarts);
+ Token token = scanner.tokenize();
+ Parser parser = createParser(listener);
+ parser.parseAsync = parseAsync;
+ parser.parseFunctionBodies = parseFunctionBodies;
+ parser.parseConditionalDirectives = enableConditionalDirectives;
+ parser.parseGenericMethods = enableGenericMethods;
+ parser.parseGenericMethodComments = enableGenericMethodComments;
+ CompilationUnit unit = parser.parseCompilationUnit(token);
+ expect(unit, isNotNull);
+ listener.assertErrorsWithCodes(errorCodes);
+ return unit;
+ }
+
+ /**
* Parse the given source as an expression.
*
* @param source the source to be parsed
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 01b0b73..4210fef 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -7,6 +7,7 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -23,7 +24,6 @@
import 'package:analyzer/src/generated/java_io.dart';
import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
import 'package:analyzer/src/generated/source_io.dart';
@@ -7868,6 +7868,11 @@
if (node.name == "void") {
return null;
}
+ if (node.staticType != null &&
+ node.staticType.isDynamic &&
+ node.staticElement == null) {
+ return null;
+ }
AstNode parent = node.parent;
if (parent is MethodInvocation) {
MethodInvocation invocation = parent;
@@ -10225,6 +10230,79 @@
expect(type.name, 'Foo');
}
}
+
+ void test_staticMethods_classTypeParameters() {
+ String code = r'''
+class C<T> {
+ static void m() => null;
+}
+main() {
+ print(C.m);
+}
+''';
+ _resolveTestUnit(code);
+ SimpleIdentifier identifier = _findIdentifier('m);');
+ FunctionTypeImpl type = identifier.staticType;
+ expect(type.toString(), '() → void');
+ expect(type.typeParameters, isEmpty,
+ reason: 'static methods should not have type parameters');
+ expect(type.typeArguments, isEmpty,
+ reason: 'static methods should not have type arguments');
+ expect(type.typeFormals, isEmpty,
+ reason: 'this static method is not generic');
+ }
+
+ void test_staticMethods_classTypeParameters_genericMethod() {
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ options.enableGenericMethods = true;
+ resetWithOptions(options);
+ String code = r'''
+class C<T> {
+ static void m<S>(S s) {
+ void f<U>(S s, U u) {}
+ print(f);
+ }
+}
+main() {
+ print(C.m);
+}
+''';
+ _resolveTestUnit(code);
+ // C - m
+ TypeParameterType typeS;
+ {
+ SimpleIdentifier identifier = _findIdentifier('m);');
+ FunctionTypeImpl type = identifier.staticType;
+ expect(type.toString(), '<S>(S) → void');
+ expect(type.typeParameters, isEmpty,
+ reason: 'static methods should not have type parameters');
+ expect(type.typeArguments, isEmpty,
+ reason: 'static methods should not have type arguments');
+ expect(type.typeFormals.toString(), '[S]');
+ typeS = type.typeFormals[0].type;
+
+ type = type.instantiate([DynamicTypeImpl.instance]);
+ expect(type.toString(), '(dynamic) → void');
+ expect(type.typeParameters.toString(), '[S]');
+ expect(type.typeArguments, [DynamicTypeImpl.instance]);
+ expect(type.typeFormals, isEmpty);
+ }
+ // C - m - f
+ {
+ SimpleIdentifier identifier = _findIdentifier('f);');
+ FunctionTypeImpl type = identifier.staticType;
+ expect(type.toString(), '<U>(S, U) → void');
+ expect(type.typeParameters.toString(), '[S]');
+ expect(type.typeArguments.toString(), '[S]');
+ expect(type.typeFormals.toString(), '[U]');
+
+ type = type.instantiate([DynamicTypeImpl.instance]);
+ expect(type.toString(), '(S, dynamic) → void');
+ expect(type.typeParameters.toString(), '[S, U]');
+ expect(type.typeArguments, [typeS, DynamicTypeImpl.instance]);
+ expect(type.typeFormals, isEmpty);
+ }
+ }
}
@reflectiveTest
@@ -13388,11 +13466,8 @@
MethodElementImpl e = f.staticElement;
expect(e.typeParameters.toString(), '[T]');
expect(e.type.typeFormals.toString(), '[T]');
- // TODO(jmesserly): we could get rid of this {E/E} substitution, but it's
- // probably harmless, as E won't be used in the function (error verifier
- // checks this), and {E/E} is a no-op anyway.
- expect(e.type.typeParameters.toString(), '[E]');
- expect(e.type.typeArguments.toString(), '[E]');
+ expect(e.type.typeParameters.toString(), '[]');
+ expect(e.type.typeArguments.toString(), '[]');
expect(e.type.toString(), '<T>(T) → T');
FunctionType ft = e.type.instantiate([typeProvider.stringType]);
@@ -13779,6 +13854,18 @@
expect(declaration.initializer.propagatedType, isNull);
}
+ void test_genericMethod_nestedBound() {
+ String code = r'''
+class Foo<T extends num> {
+ void method/*<U extends T>*/(dynamic/*=U*/ u) {
+ u.abs();
+ }
+}
+''';
+ // Just validate that there is no warning on the call to `.abs()`.
+ _resolveTestUnit(code);
+ }
+
void test_genericMethod_nestedCapture() {
_resolveTestUnit(r'''
class C<T> {
@@ -13855,6 +13942,11 @@
// TODO(jmesserly): we can't use assertErrors because STRONG_MODE_* errors
// from CodeChecker don't have working equality.
List<AnalysisError> errors = analysisContext2.computeErrors(source);
+
+ // Sort errors by name.
+ errors.sort((AnalysisError e1, AnalysisError e2) =>
+ e1.errorCode.name.compareTo(e2.errorCode.name));
+
expect(errors.map((e) => e.errorCode.name), [
'INVALID_METHOD_OVERRIDE_RETURN_TYPE',
'STRONG_MODE_INVALID_METHOD_OVERRIDE'
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index d0d8949..071231e 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -4,8 +4,11 @@
library analyzer.test.generated.scanner_test;
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:unittest/unittest.dart';
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index cfab206..5f5d0ef 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -6,7 +6,9 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_core.dart' show formatList;
import 'package:analyzer/src/generated/source_io.dart';
+import 'package:unittest/unittest.dart';
import '../reflective_tests.dart';
import '../utils.dart';
@@ -15,6 +17,7 @@
main() {
initializeTestEnvironment();
runReflectiveTests(StaticTypeWarningCodeTest);
+ runReflectiveTests(StrongModeStaticTypeWarningCodeTest);
}
@reflectiveTest
@@ -2153,3 +2156,33 @@
verify([source]);
}
}
+
+@reflectiveTest
+class StrongModeStaticTypeWarningCodeTest extends ResolverTestCase {
+ void setUp() {
+ super.setUp();
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ options.strongMode = true;
+ resetWithOptions(options);
+ }
+
+ void test_genericMethodWrongNumberOfTypeArguments() {
+ Source source = addSource('''
+f() {}
+main() {
+ f/*<int>*/();
+}
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(
+ source, [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+ for (AnalysisError error in analysisContext2.computeErrors(source)) {
+ if (error.errorCode ==
+ StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS) {
+ expect(error.message,
+ formatList(error.errorCode.message, ['() → dynamic', 0, 1]));
+ }
+ }
+ verify([source]);
+ }
+}
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index 8a0b3d2..4785daf 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -12,6 +12,7 @@
import 'constant_test.dart' as constant_test;
import 'declaration_resolver_test.dart' as declaration_resolver_test;
import 'engine_test.dart' as engine_test;
+import 'error_suppression_test.dart' as error_suppression_test;
import 'incremental_resolver_test.dart' as incremental_resolver_test;
import 'incremental_scanner_test.dart' as incremental_scanner_test;
import 'java_core_test.dart' as java_core_test;
@@ -35,6 +36,7 @@
constant_test.main();
declaration_resolver_test.main();
engine_test.main();
+ error_suppression_test.main();
incremental_resolver_test.main();
incremental_scanner_test.main();
java_core_test.main();
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 5e6cfa4..51f5fcd 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -6,8 +6,7 @@
import 'dart:collection';
-import 'package:analyzer/dart/ast/ast.dart'
- show AstNode, SimpleIdentifier;
+import 'package:analyzer/dart/ast/ast.dart' show AstNode, SimpleIdentifier;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -647,6 +646,8 @@
TestSourceWithUri(String path, this.uri, [String content])
: super(path, content);
+ String get encoding => uri.toString();
+
UriKind get uriKind {
if (uri == null) {
return UriKind.FILE_URI;
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index 32b2487..f2a2a9e 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -7,11 +7,14 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/java_engine.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/generated/testing/ast_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
@@ -278,6 +281,13 @@
_assertCloneUnit('library l; var a;');
}
+ void test_visitCompilationUnit_directive_withComment() {
+ _assertCloneUnit(r'''
+/// aaa
+/// bbb
+library l;''');
+ }
+
void test_visitCompilationUnit_empty() {
_assertCloneUnit('');
}
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 326e6a2..cbcfacf 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -16,11 +16,11 @@
import 'package:analyzer/src/cancelable_future.dart';
import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_collection.dart';
import 'package:analyzer/src/task/dart.dart';
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index b67c4a5..9bf1b79 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -13,11 +13,10 @@
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
-class MockSdk implements DartSdk {
- static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary(
- 'dart:core',
- '/lib/core/core.dart',
- '''
+const _MockSdkLibrary _LIB_CORE = const _MockSdkLibrary(
+ 'dart:core',
+ '/lib/core/core.dart',
+ '''
library dart.core;
import 'dart:async';
@@ -40,9 +39,11 @@
abstract class String implements Comparable<String> {
external factory String.fromCharCodes(Iterable<int> charCodes,
[int start = 0, int end]);
+ String operator +(String other) => null;
bool get isEmpty => false;
bool get isNotEmpty => false;
int get length => 0;
+ String substring(int len) => null;
String toUpperCase();
List<int> get codeUnits;
}
@@ -115,10 +116,10 @@
const Object override = const _Override();
''');
- static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary(
- 'dart:async',
- '/lib/async/async.dart',
- '''
+const _MockSdkLibrary _LIB_ASYNC = const _MockSdkLibrary(
+ 'dart:async',
+ '/lib/async/async.dart',
+ '''
library dart.async;
import 'dart:math';
@@ -126,37 +127,36 @@
part 'stream.dart';
class Future<T> {
+ factory Future(computation()) => null;
factory Future.delayed(Duration duration, [T computation()]) => null;
- factory Future.value([value]) => null;
+ factory Future.value([T value]) => null;
- static Future<List</*<T>*/> wait/*<T>*/(
+ static Future<List/*<T>*/> wait/*<T>*/(
Iterable<Future/*<T>*/> futures) => null;
Future/*<R>*/ then/*<R>*/(/*=R*/ onValue(T value)) => null;
}
''',
- const <_MockSdkFile>[
- const _MockSdkFile(
- '/lib/async/stream.dart',
- r'''
+ const <String, String>{
+ '/lib/async/stream.dart': r'''
part of dart.async;
class Stream<T> {}
abstract class StreamTransformer<S, T> {}
-''')
- ]);
+'''
+ });
- static const _MockSdkLibrary LIB_COLLECTION = const _MockSdkLibrary(
- 'dart:collection',
- '/lib/collection/collection.dart',
- '''
+const _MockSdkLibrary _LIB_COLLECTION = const _MockSdkLibrary(
+ 'dart:collection',
+ '/lib/collection/collection.dart',
+ '''
library dart.collection;
abstract class HashMap<K, V> implements Map<K, V> {}
''');
- static const _MockSdkLibrary LIB_CONVERT = const _MockSdkLibrary(
- 'dart:convert',
- '/lib/convert/convert.dart',
- '''
+const _MockSdkLibrary _LIB_CONVERT = const _MockSdkLibrary(
+ 'dart:convert',
+ '/lib/convert/convert.dart',
+ '''
library dart.convert;
import 'dart:async';
@@ -165,10 +165,21 @@
class JsonDecoder extends Converter<String, Object> {}
''');
- static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary(
- 'dart:math',
- '/lib/math/math.dart',
- '''
+const _MockSdkLibrary _LIB_FOREIGN_HELPER = const _MockSdkLibrary(
+ 'dart:_foreign_helper',
+ '/lib/_foreign_helper/_foreign_helper.dart',
+ '''
+library dart._foreign_helper;
+
+JS(String typeDescription, String codeTemplate,
+ [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11])
+{}
+''');
+
+const _MockSdkLibrary _LIB_MATH = const _MockSdkLibrary(
+ 'dart:math',
+ '/lib/math/math.dart',
+ '''
library dart.math;
const double E = 2.718281828459045;
@@ -188,23 +199,25 @@
}
''');
- static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary(
- 'dart:html',
- '/lib/html/dartium/html_dartium.dart',
- '''
+const _MockSdkLibrary _LIB_HTML = const _MockSdkLibrary(
+ 'dart:html',
+ '/lib/html/dartium/html_dartium.dart',
+ '''
library dart.html;
class HtmlElement {}
''');
- static const List<SdkLibrary> LIBRARIES = const [
- LIB_CORE,
- LIB_ASYNC,
- LIB_COLLECTION,
- LIB_CONVERT,
- LIB_MATH,
- LIB_HTML,
- ];
+const List<SdkLibrary> _LIBRARIES = const [
+ _LIB_CORE,
+ _LIB_ASYNC,
+ _LIB_COLLECTION,
+ _LIB_CONVERT,
+ _LIB_FOREIGN_HELPER,
+ _LIB_MATH,
+ _LIB_HTML,
+];
+class MockSdk implements DartSdk {
final resource.MemoryResourceProvider provider =
new resource.MemoryResourceProvider();
@@ -213,13 +226,14 @@
*/
AnalysisContextImpl _analysisContext;
- MockSdk() {
- LIBRARIES.forEach((_MockSdkLibrary library) {
+ MockSdk({bool dartAsync: true})
+ : sdkLibraries = dartAsync ? _LIBRARIES : [_LIB_CORE] {
+ for (_MockSdkLibrary library in sdkLibraries) {
provider.newFile(library.path, library.content);
- library.parts.forEach((file) {
- provider.newFile(file.path, file.content);
+ library.parts.forEach((String path, String content) {
+ provider.newFile(path, content);
});
- });
+ }
}
@override
@@ -233,21 +247,14 @@
}
@override
- List<SdkLibrary> get sdkLibraries => LIBRARIES;
+ final List<SdkLibrary> sdkLibraries;
@override
- String get sdkVersion => throw unimplemented;
-
- UnimplementedError get unimplemented => new UnimplementedError();
+ String get sdkVersion => throw new UnimplementedError();
@override
- List<String> get uris {
- List<String> uris = <String>[];
- for (SdkLibrary library in LIBRARIES) {
- uris.add(library.shortName);
- }
- return uris;
- }
+ List<String> get uris =>
+ sdkLibraries.map((SdkLibrary library) => library.shortName).toList();
@override
Source fromFileUri(Uri uri) {
@@ -256,7 +263,7 @@
if (!filePath.startsWith("$libPath/")) {
return null;
}
- for (SdkLibrary library in LIBRARIES) {
+ for (SdkLibrary library in sdkLibraries) {
String libraryPath = library.path;
if (filePath.replaceAll('\\', '/') == libraryPath) {
try {
@@ -299,6 +306,7 @@
"dart:async/stream.dart": "/lib/async/stream.dart",
"dart:collection": "/lib/collection/collection.dart",
"dart:convert": "/lib/convert/convert.dart",
+ "dart:_foreign_helper": "/lib/_foreign_helper/_foreign_helper.dart",
"dart:math": "/lib/math/math.dart"
};
@@ -315,44 +323,35 @@
}
}
-class _MockSdkFile {
- final String path;
- final String content;
-
- const _MockSdkFile(this.path, this.content);
-}
-
class _MockSdkLibrary implements SdkLibrary {
final String shortName;
final String path;
final String content;
- final List<_MockSdkFile> parts;
+ final Map<String, String> parts;
const _MockSdkLibrary(this.shortName, this.path, this.content,
- [this.parts = const <_MockSdkFile>[]]);
+ [this.parts = const <String, String>{}]);
@override
- String get category => throw unimplemented;
+ String get category => throw new UnimplementedError();
@override
- bool get isDart2JsLibrary => throw unimplemented;
+ bool get isDart2JsLibrary => throw new UnimplementedError();
@override
- bool get isDocumented => throw unimplemented;
+ bool get isDocumented => throw new UnimplementedError();
@override
- bool get isImplementation => throw unimplemented;
+ bool get isImplementation => throw new UnimplementedError();
@override
- bool get isInternal => throw unimplemented;
+ bool get isInternal => throw new UnimplementedError();
@override
- bool get isShared => throw unimplemented;
+ bool get isShared => throw new UnimplementedError();
@override
- bool get isVmLibrary => throw unimplemented;
-
- UnimplementedError get unimplemented => new UnimplementedError();
+ bool get isVmLibrary => throw new UnimplementedError();
}
/**
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index 8531637..f3a0e4c 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -5,11 +5,11 @@
library analyzer.test.src.dart.ast.utilities_test;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/java_engine.dart' show Predicate;
import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/testing/ast_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:unittest/unittest.dart';
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 3f0aa84..f907ae3 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -1857,6 +1857,14 @@
expect(paramType.prunedTypedefs[0], same(f));
}
+ void test_resolveToBound() {
+ FunctionElementImpl f = ElementFactory.functionElement('f');
+ FunctionTypeImpl type = f.type;
+
+ // Returns this.
+ expect(type.resolveToBound(null), same(type));
+ }
+
void test_returnType_pruned_no_type_arguments() {
FunctionTypeAliasElementImpl f =
ElementFactory.functionTypeAliasElement('f');
@@ -3392,6 +3400,14 @@
expect(typeA.lookUpSetter("s", library), isNull);
}
+ void test_resolveToBound() {
+ InterfaceTypeImpl type =
+ ElementFactory.classElement2("A").type as InterfaceTypeImpl;
+
+ // Returns this.
+ expect(type.resolveToBound(null), same(type));
+ }
+
void test_setTypeArguments() {
InterfaceTypeImpl type =
ElementFactory.classElement2("A").type as InterfaceTypeImpl;
@@ -3936,6 +3952,36 @@
expect(typeParameterTypeT.isMoreSpecificThan(classS.type), isTrue);
}
+ void test_resolveToBound_unbound() {
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(
+ new TypeParameterElementImpl.forNode(AstFactory.identifier3("E")));
+ // Returns whatever type is passed to resolveToBound().
+ expect(type.resolveToBound(VoidTypeImpl.instance),
+ same(VoidTypeImpl.instance));
+ }
+
+ void test_resolveToBound_bound() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstFactory.identifier3("E"));
+ element.bound = classS.type;
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+ expect(type.resolveToBound(null), same(classS.type));
+ }
+
+ void test_resolveToBound_nestedBound() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl elementE =
+ new TypeParameterElementImpl.forNode(AstFactory.identifier3("E"));
+ elementE.bound = classS.type;
+ TypeParameterTypeImpl typeE = new TypeParameterTypeImpl(elementE);
+ TypeParameterElementImpl elementF =
+ new TypeParameterElementImpl.forNode(AstFactory.identifier3("F"));
+ elementF.bound = typeE;
+ TypeParameterTypeImpl typeF = new TypeParameterTypeImpl(elementE);
+ expect(typeF.resolveToBound(null), same(classS.type));
+ }
+
void test_substitute_equal() {
TypeParameterElementImpl element =
new TypeParameterElementImpl.forNode(AstFactory.identifier3("E"));
@@ -3995,6 +4041,11 @@
void test_isVoid() {
expect(_voidType.isVoid, isTrue);
}
+
+ void test_resolveToBound() {
+ // Returns this.
+ expect(_voidType.resolveToBound(null), same(_voidType));
+ }
}
class _FunctionTypeImplTest_isSubtypeOf_baseCase_classFunction
diff --git a/pkg/analyzer/test/src/mock_sdk.dart b/pkg/analyzer/test/src/mock_sdk.dart
deleted file mode 100644
index bfef108..0000000
--- a/pkg/analyzer/test/src/mock_sdk.dart
+++ /dev/null
@@ -1,327 +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 analyzer.test.src.mock_sdk;
-
-import 'package:analyzer/file_system/file_system.dart' as resource;
-import 'package:analyzer/file_system/memory_file_system.dart' as resource;
-import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-class MockSdk implements DartSdk {
- static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary(
- 'dart:core',
- '/lib/core/core.dart',
- '''
-library dart.core;
-
-import 'dart:async';
-
-class Object {
- bool operator ==(other) => identical(this, other);
- String toString() => 'a string';
- int get hashCode => 0;
-}
-
-class Function {}
-class StackTrace {}
-class Symbol {}
-class Type {}
-
-abstract class Comparable<T> {
- int compareTo(T other);
-}
-
-abstract class String implements Comparable<String> {
- external factory String.fromCharCodes(Iterable<int> charCodes,
- [int start = 0, int end]);
- bool get isEmpty => false;
- bool get isNotEmpty => false;
- int get length => 0;
- String toUpperCase();
- List<int> get codeUnits;
-}
-
-class bool extends Object {}
-abstract class num implements Comparable<num> {
- bool operator <(num other);
- bool operator <=(num other);
- bool operator >(num other);
- bool operator >=(num other);
- num operator +(num other);
- num operator -(num other);
- num operator *(num other);
- num operator /(num other);
- int toInt();
- num abs();
- int round();
-}
-abstract class int extends num {
- bool get isEven => false;
- int operator -();
- external static int parse(String source,
- { int radix,
- int onError(String source) });
-}
-class double extends num {}
-class DateTime extends Object {}
-class Null extends Object {}
-
-class Deprecated extends Object {
- final String expires;
- const Deprecated(this.expires);
-}
-const Object deprecated = const Deprecated("next release");
-
-class Iterator<E> {
- bool moveNext();
- E get current;
-}
-
-abstract class Iterable<E> {
- Iterator<E> get iterator;
- bool get isEmpty;
-}
-
-abstract class List<E> implements Iterable<E> {
- void add(E value);
- E operator [](int index);
- void operator []=(int index, E value);
- Iterator<E> get iterator => null;
- void clear();
-}
-
-abstract class Map<K, V> extends Object {
- Iterable<K> get keys;
-}
-
-external bool identical(Object a, Object b);
-
-void print(Object object) {}
-
-class _Override {
- const _Override();
-}
-const Object override = const _Override();
-''');
-
- static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary(
- 'dart:async',
- '/lib/async/async.dart',
- '''
-library dart.async;
-
-import 'dart:math';
-
-class Future<T> {
- factory Future.delayed(Duration duration, [T computation()]) => null;
- factory Future.value([value]) => null;
- static Future wait(List<Future> futures) => null;
-}
-
-class Stream<T> {}
-abstract class StreamTransformer<S, T> {}
-''');
-
- static const _MockSdkLibrary LIB_COLLECTION = const _MockSdkLibrary(
- 'dart:collection',
- '/lib/collection/collection.dart',
- '''
-library dart.collection;
-
-abstract class HashMap<K, V> implements Map<K, V> {}
-''');
-
- static const _MockSdkLibrary LIB_CONVERT = const _MockSdkLibrary(
- 'dart:convert',
- '/lib/convert/convert.dart',
- '''
-library dart.convert;
-
-import 'dart:async';
-
-abstract class Converter<S, T> implements StreamTransformer {}
-class JsonDecoder extends Converter<String, Object> {}
-''');
-
- static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary(
- 'dart:math',
- '/lib/math/math.dart',
- '''
-library dart.math;
-const double E = 2.718281828459045;
-const double PI = 3.1415926535897932;
-const double LN10 = 2.302585092994046;
-num min(num a, num b) => 0;
-num max(num a, num b) => 0;
-external double cos(num x);
-external double sin(num x);
-external double sqrt(num x);
-class Random {
- bool nextBool() => true;
- double nextDouble() => 2.0;
- int nextInt() => 1;
-}
-''');
-
- static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary(
- 'dart:html',
- '/lib/html/dartium/html_dartium.dart',
- '''
-library dart.html;
-class HtmlElement {}
-''');
-
- static const List<SdkLibrary> LIBRARIES = const [
- LIB_CORE,
- LIB_ASYNC,
- LIB_COLLECTION,
- LIB_CONVERT,
- LIB_MATH,
- LIB_HTML,
- ];
-
- static const List<SdkLibrary> LIBRARIES_NO_ASYNC = const [
- LIB_CORE,
- ];
-
- final resource.MemoryResourceProvider provider =
- new resource.MemoryResourceProvider();
-
- /**
- * The [AnalysisContext] which is used for all of the sources.
- */
- InternalAnalysisContext _analysisContext;
-
- MockSdk({bool dartAsync: true}) {
- List<SdkLibrary> libraries = dartAsync ? LIBRARIES : LIBRARIES_NO_ASYNC;
- libraries.forEach((_MockSdkLibrary library) {
- provider.newFile(library.path, library.content);
- });
- }
-
- @override
- AnalysisContext get context {
- if (_analysisContext == null) {
- _analysisContext = new SdkAnalysisContext();
- SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
- _analysisContext.sourceFactory = factory;
- }
- return _analysisContext;
- }
-
- @override
- List<SdkLibrary> get sdkLibraries => LIBRARIES;
-
- @override
- String get sdkVersion => throw unimplemented;
-
- UnimplementedError get unimplemented => new UnimplementedError();
-
- @override
- List<String> get uris {
- List<String> uris = <String>[];
- for (SdkLibrary library in LIBRARIES) {
- uris.add(library.shortName);
- }
- return uris;
- }
-
- @override
- Source fromFileUri(Uri uri) {
- String filePath = uri.path;
- String libPath = '/lib';
- if (!filePath.startsWith("$libPath/")) {
- return null;
- }
- for (SdkLibrary library in LIBRARIES) {
- String libraryPath = library.path;
- if (filePath.replaceAll('\\', '/') == libraryPath) {
- try {
- resource.File file = provider.getResource(uri.path);
- Uri dartUri = Uri.parse(library.shortName);
- return file.createSource(dartUri);
- } catch (exception) {
- return null;
- }
- }
- if (filePath.startsWith("$libraryPath/")) {
- String pathInLibrary = filePath.substring(libraryPath.length + 1);
- String path = '${library.shortName}/$pathInLibrary';
- try {
- resource.File file = provider.getResource(uri.path);
- Uri dartUri = new Uri(scheme: 'dart', path: path);
- return file.createSource(dartUri);
- } catch (exception) {
- return null;
- }
- }
- }
- return null;
- }
-
- @override
- SdkLibrary getSdkLibrary(String dartUri) {
- // getSdkLibrary() is only used to determine whether a library is internal
- // to the SDK. The mock SDK doesn't have any internals, so it's safe to
- // return null.
- return null;
- }
-
- @override
- Source mapDartUri(String dartUri) {
- const Map<String, String> uriToPath = const {
- "dart:core": "/lib/core/core.dart",
- "dart:html": "/lib/html/dartium/html_dartium.dart",
- "dart:async": "/lib/async/async.dart",
- "dart:collection": "/lib/collection/collection.dart",
- "dart:convert": "/lib/convert/convert.dart",
- "dart:math": "/lib/math/math.dart"
- };
-
- String path = uriToPath[dartUri];
- if (path != null) {
- resource.File file = provider.getResource(path);
- Uri uri = new Uri(scheme: 'dart', path: dartUri.substring(5));
- return file.createSource(uri);
- }
-
- // If we reach here then we tried to use a dartUri that's not in the
- // table above.
- return null;
- }
-}
-
-class _MockSdkLibrary implements SdkLibrary {
- final String shortName;
- final String path;
- final String content;
-
- const _MockSdkLibrary(this.shortName, this.path, this.content);
-
- @override
- String get category => throw unimplemented;
-
- @override
- bool get isDart2JsLibrary => throw unimplemented;
-
- @override
- bool get isDocumented => throw unimplemented;
-
- @override
- bool get isImplementation => throw unimplemented;
-
- @override
- bool get isInternal => throw unimplemented;
-
- @override
- bool get isShared => throw unimplemented;
-
- @override
- bool get isVmLibrary => throw unimplemented;
-
- UnimplementedError get unimplemented => new UnimplementedError();
-}
diff --git a/pkg/analyzer/test/src/summary/flat_buffers_test.dart b/pkg/analyzer/test/src/summary/flat_buffers_test.dart
index 7ceed57..361973b 100644
--- a/pkg/analyzer/test/src/summary/flat_buffers_test.dart
+++ b/pkg/analyzer/test/src/summary/flat_buffers_test.dart
@@ -4,6 +4,8 @@
library test.src.summary.flat_buffers_test;
+import 'dart:typed_data';
+
import 'package:analyzer/src/summary/flat_buffers.dart';
import 'package:unittest/unittest.dart';
@@ -86,6 +88,39 @@
expect(const Int32Reader().vTableGet(object, 1, 15), 20);
}
+ void test_table_format() {
+ Uint8List byteList;
+ {
+ Builder builder = new Builder(initialSize: 0);
+ builder.startTable();
+ builder.addInt32(0, 10);
+ builder.addInt32(1, 20);
+ builder.addInt32(2, 30);
+ byteList = builder.finish(builder.endTable());
+ }
+ // Convert byteList to a ByteData so that we can read data from it.
+ ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
+ // First 4 bytes are an offset to the table data.
+ int tableDataLoc = byteData.getUint32(0, Endianness.LITTLE_ENDIAN);
+ // First 4 bytes of the table data are a backwards offset to the vtable.
+ int vTableLoc = tableDataLoc -
+ byteData.getInt32(tableDataLoc, Endianness.LITTLE_ENDIAN);
+ // First 2 bytes of the vtable are the size of the vtable in bytes, which
+ // should be 10.
+ expect(byteData.getUint16(vTableLoc, Endianness.LITTLE_ENDIAN), 10);
+ // Next 2 bytes are the size of the object in bytes (including the vtable
+ // pointer), which should be 16.
+ expect(byteData.getUint16(vTableLoc + 2, Endianness.LITTLE_ENDIAN), 16);
+ // Remaining 6 bytes are the offsets within the object where the ints are
+ // located.
+ for (int i = 0; i < 3; i++) {
+ int offset =
+ byteData.getUint16(vTableLoc + 4 + 2 * i, Endianness.LITTLE_ENDIAN);
+ expect(byteData.getInt32(tableDataLoc + offset, Endianness.LITTLE_ENDIAN),
+ 10 + 10 * i);
+ }
+ }
+
void test_table_types() {
List<int> byteList;
{
@@ -98,6 +133,7 @@
builder.addOffset(3, stringOffset);
builder.addInt32(4, 40);
builder.addUint32(5, 0x9ABCDEF0);
+ builder.addUint8(6, 0x9A);
Offset offset = builder.endTable();
byteList = builder.finish(offset);
}
@@ -109,6 +145,23 @@
expect(const StringReader().vTableGet(object, 3), '12345');
expect(const Int32Reader().vTableGet(object, 4), 40);
expect(const Uint32Reader().vTableGet(object, 5), 0x9ABCDEF0);
+ expect(const Uint8Reader().vTableGet(object, 6), 0x9A);
+ }
+
+ void test_writeList_of_Uint32() {
+ List<int> values = <int>[10, 100, 12345, 0x9abcdef0];
+ // write
+ List<int> byteList;
+ {
+ Builder builder = new Builder(initialSize: 0);
+ Offset offset = builder.writeListUint32(values);
+ byteList = builder.finish(offset);
+ }
+ // read and verify
+ BufferPointer root = new BufferPointer.fromBytes(byteList);
+ List<int> items = const Uint32ListReader().read(root);
+ expect(items, hasLength(4));
+ expect(items, orderedEquals(values));
}
void test_writeList_ofFloat64() {
@@ -227,6 +280,20 @@
expect(items, hasLength(3));
expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0]));
}
+
+ void test_writeList_ofUint8() {
+ List<int> byteList;
+ {
+ Builder builder = new Builder(initialSize: 0);
+ Offset offset = builder.writeListUint8(<int>[1, 2, 0x9A]);
+ byteList = builder.finish(offset);
+ }
+ // read and verify
+ BufferPointer root = new BufferPointer.fromBytes(byteList);
+ List<int> items = const ListReader<int>(const Uint8Reader()).read(root);
+ expect(items, hasLength(3));
+ expect(items, orderedEquals(<int>[1, 2, 0x9A]));
+ }
}
class StringListWrapperImpl {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index a19d1fa..3f6d653 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -131,6 +131,49 @@
}
}
+ void checkPossibleLocalElements(Element resynthesized, Element original) {
+ if (original is! LocalElement && resynthesized is! LocalElement) {
+ return;
+ }
+ // TODO(scheglov) add support for parameters
+ if (original is ParameterElement && resynthesized is ParameterElement) {
+ return;
+ }
+ if (original is LocalElement && resynthesized is LocalElement) {
+ expect(resynthesized.visibleRange, original.visibleRange);
+ } else {
+ fail('Incompatible local elements '
+ '${resynthesized.runtimeType} vs. ${original.runtimeType}');
+ }
+ }
+
+ void checkPossibleMember(
+ Element resynthesized, Element original, String desc) {
+ Element resynthesizedNonHandle = resynthesized is ElementHandle
+ ? resynthesized.actualElement
+ : resynthesized;
+ if (original is Member) {
+ expect(resynthesizedNonHandle, new isInstanceOf<Member>(), reason: desc);
+ if (resynthesizedNonHandle is Member) {
+ List<DartType> resynthesizedTypeArguments =
+ resynthesizedNonHandle.definingType.typeArguments;
+ List<DartType> originalTypeArguments =
+ original.definingType.typeArguments;
+ expect(
+ resynthesizedTypeArguments, hasLength(originalTypeArguments.length),
+ reason: desc);
+ for (int i = 0; i < originalTypeArguments.length; i++) {
+ compareTypeImpls(resynthesizedTypeArguments[i],
+ originalTypeArguments[i], '$desc type argument $i');
+ }
+ }
+ } else {
+ expect(
+ resynthesizedNonHandle, isNot(new isInstanceOf<ConstructorMember>()),
+ reason: desc);
+ }
+ }
+
void compareClassElements(
ClassElementImpl resynthesized, ClassElementImpl original, String desc) {
compareElements(resynthesized, original, desc);
@@ -330,7 +373,14 @@
} else if (o is IntegerLiteral && r is IntegerLiteral) {
expect(r.value, o.value, reason: desc);
} else if (o is DoubleLiteral && r is DoubleLiteral) {
- expect(r.value, o.value, reason: desc);
+ if (r.value != null &&
+ r.value.isNaN &&
+ o.value != null &&
+ o.value.isNaN) {
+ // NaN is not comparable.
+ } else {
+ expect(r.value, o.value, reason: desc);
+ }
} else if (o is StringInterpolation && r is StringInterpolation) {
compareConstAstLists(r.elements, o.elements, desc);
} else if (o is StringLiteral && r is StringLiteral) {
@@ -372,7 +422,7 @@
ConstructorName rConstructor = r.constructorName;
expect(oConstructor, isNotNull, reason: desc);
expect(rConstructor, isNotNull, reason: desc);
- compareElements(
+ compareConstructorElements(
rConstructor.staticElement, oConstructor.staticElement, desc);
TypeName oType = oConstructor.type;
TypeName rType = rConstructor.type;
@@ -425,12 +475,26 @@
}
}
- void compareConstructorElements(ConstructorElementImpl resynthesized,
- ConstructorElementImpl original, String desc) {
+ void compareConstructorElements(ConstructorElement resynthesized,
+ ConstructorElement original, String desc) {
+ if (original == null && resynthesized == null) {
+ return;
+ }
compareExecutableElements(resynthesized, original, desc);
- compareConstAstLists(resynthesized.constantInitializers,
- original.constantInitializers, desc);
- // TODO(paulberry): test redirectedConstructor
+ if (original.isConst) {
+ ConstructorElementImpl resynthesizedImpl =
+ getActualElement(resynthesized, desc);
+ ConstructorElementImpl originalImpl = getActualElement(original, desc);
+ compareConstAstLists(resynthesizedImpl.constantInitializers,
+ originalImpl.constantInitializers, desc);
+ }
+ if (original.redirectedConstructor == null) {
+ expect(resynthesized.redirectedConstructor, isNull, reason: desc);
+ } else {
+ compareConstructorElements(resynthesized.redirectedConstructor,
+ original.redirectedConstructor, '$desc redirectedConstructor');
+ }
+ checkPossibleMember(resynthesized, original, desc);
}
void compareElementAnnotations(ElementAnnotationImpl resynthesized,
@@ -448,7 +512,18 @@
}
void compareElements(Element resynthesized, Element original, String desc) {
+ ElementImpl rImpl = getActualElement(resynthesized, desc);
+ ElementImpl oImpl = getActualElement(original, desc);
+ if (oImpl == null && rImpl == null) {
+ return;
+ }
+ if (oImpl is PrefixElement) {
+ // TODO(scheglov) prefixes cannot be resynthesized
+ return;
+ }
+ expect(original, isNotNull);
expect(resynthesized, isNotNull);
+ expect(rImpl.runtimeType, oImpl.runtimeType);
expect(resynthesized.kind, original.kind);
expect(resynthesized.location, original.location, reason: desc);
expect(resynthesized.name, original.name);
@@ -459,20 +534,17 @@
compareMetadata(resynthesized.metadata, original.metadata, desc);
// Modifiers are a pain to test via handles. So just test them via the
// actual element.
- ElementImpl actualResynthesized = getActualElement(resynthesized, desc);
- ElementImpl actualOriginal = getActualElement(original, desc);
for (Modifier modifier in Modifier.values) {
- bool got = actualResynthesized.hasModifier(modifier);
- bool want = actualOriginal.hasModifier(modifier);
+ bool got = rImpl.hasModifier(modifier);
+ bool want = oImpl.hasModifier(modifier);
expect(got, want,
reason: 'Mismatch in $desc.$modifier: got $got, want $want');
}
// Validate members.
- if (actualOriginal is Member) {
- expect(actualResynthesized, new isInstanceOf<Member>(), reason: desc);
+ if (oImpl is Member) {
+ expect(rImpl, new isInstanceOf<Member>(), reason: desc);
} else {
- expect(actualResynthesized, isNot(new isInstanceOf<Member>()),
- reason: desc);
+ expect(rImpl, isNot(new isInstanceOf<Member>()), reason: desc);
}
}
@@ -496,6 +568,24 @@
original.typeParameters[i],
'$desc type parameter ${original.typeParameters[i].name}');
}
+ if (original is! Member) {
+ List<FunctionElement> rFunctions = resynthesized.functions;
+ List<FunctionElement> oFunctions = original.functions;
+ expect(rFunctions, hasLength(oFunctions.length));
+ for (int i = 0; i < oFunctions.length; i++) {
+ compareFunctionElements(rFunctions[i], oFunctions[i],
+ '$desc local function ${oFunctions[i].name}');
+ }
+ }
+ if (original is! Member) {
+ List<LocalVariableElement> rVariables = resynthesized.localVariables;
+ List<LocalVariableElement> oVariables = original.localVariables;
+ expect(rVariables, hasLength(oVariables.length));
+ for (int i = 0; i < oVariables.length; i++) {
+ compareVariableElements(rVariables[i], oVariables[i],
+ '$desc local variable ${oVariables[i].name}');
+ }
+ }
}
void compareExportElements(ExportElementImpl resynthesized,
@@ -513,12 +603,12 @@
void compareFieldElements(
FieldElementImpl resynthesized, FieldElementImpl original, String desc) {
comparePropertyInducingElements(resynthesized, original, desc);
- // TODO(paulberry): test evaluationResult
}
void compareFunctionElements(
FunctionElement resynthesized, FunctionElement original, String desc) {
compareExecutableElements(resynthesized, original, desc);
+ checkPossibleLocalElements(resynthesized, original);
}
void compareFunctionTypeAliasElements(
@@ -609,8 +699,8 @@
}
}
- void compareParameterElements(ParameterElementImpl resynthesized,
- ParameterElementImpl original, String desc) {
+ void compareParameterElements(
+ ParameterElement resynthesized, ParameterElement original, String desc) {
compareVariableElements(resynthesized, original, desc);
expect(resynthesized.parameters.length, original.parameters.length);
for (int i = 0; i < resynthesized.parameters.length; i++) {
@@ -639,7 +729,6 @@
void comparePrefixElements(PrefixElementImpl resynthesized,
PrefixElementImpl original, String desc) {
compareElements(resynthesized, original, desc);
- // TODO(paulberry): test _importedLibraries.
}
void comparePropertyAccessorElements(
@@ -678,7 +767,6 @@
TopLevelVariableElementImpl original,
String desc) {
comparePropertyInducingElements(resynthesized, original, desc);
- // TODO(paulberry): test evaluationResult
}
void compareTypeImpls(
@@ -752,9 +840,14 @@
}
} else if (resynthesized is VoidTypeImpl && original is VoidTypeImpl) {
expect(resynthesized, same(original));
+ } else if (resynthesized is DynamicTypeImpl &&
+ original is UndefinedTypeImpl) {
+ // TODO(scheglov) In the strong mode constant variable like
+ // `var V = new Unresolved()` gets `UndefinedTypeImpl`, and it gets
+ // `DynamicTypeImpl` in the spec mode.
} else if (resynthesized.runtimeType != original.runtimeType) {
- fail(
- 'Type mismatch: expected ${original.runtimeType}, got ${resynthesized.runtimeType}');
+ fail('Type mismatch: expected ${original.runtimeType},'
+ ' got ${resynthesized.runtimeType} ($desc)');
} else {
fail('Unimplemented comparison for ${original.runtimeType}');
}
@@ -768,18 +861,24 @@
expect(resynthesized.uriEnd, original.uriEnd, reason: desc);
}
- void compareVariableElements(VariableElementImpl resynthesized,
- VariableElementImpl original, String desc) {
+ void compareVariableElements(
+ VariableElement resynthesized, VariableElement original, String desc) {
compareElements(resynthesized, original, desc);
compareTypes(resynthesized.type, original.type, desc);
- if (original is ConstVariableElement) {
- Expression initializer = resynthesized.constantInitializer;
+ VariableElementImpl originalActual = getActualElement(original, desc);
+ if (originalActual is ConstVariableElement) {
+ VariableElementImpl resynthesizedActual =
+ getActualElement(resynthesized, desc);
+ Expression initializer = resynthesizedActual.constantInitializer;
if (constantInitializersAreInvalid) {
_assertUnresolvedIdentifier(initializer, desc);
} else {
- compareConstAsts(initializer, original.constantInitializer, desc);
+ compareConstAsts(initializer, originalActual.constantInitializer,
+ '$desc initializer');
}
}
+ checkPossibleMember(resynthesized, original, desc);
+ checkPossibleLocalElements(resynthesized, original);
}
/**
@@ -848,10 +947,16 @@
}
ElementImpl getActualElement(Element element, String desc) {
- if (element is ElementImpl) {
+ if (element == null) {
+ return null;
+ } else if (element is ElementImpl) {
return element;
} else if (element is ElementHandle) {
- return getActualElement(element.actualElement, desc);
+ Element actualElement = element.actualElement;
+ // A handle should never point to a member, because if it did, then
+ // "is Member" checks on the handle would produce the wrong result.
+ expect(actualElement, isNot(new isInstanceOf<Member>()), reason: desc);
+ return getActualElement(actualElement, desc);
} else if (element is Member) {
return getActualElement(element.baseElement, desc);
} else {
@@ -1034,6 +1139,22 @@
checkLibrary('class C { var x; C(this.x); }');
}
+ test_class_constructor_fieldFormal_named_noDefault() {
+ checkLibrary('class C { int x; C({this.x}); }');
+ }
+
+ test_class_constructor_fieldFormal_named_withDefault() {
+ checkLibrary('class C { int x; C({this.x: 42}); }');
+ }
+
+ test_class_constructor_fieldFormal_optional_noDefault() {
+ checkLibrary('class C { int x; C([this.x]); }');
+ }
+
+ test_class_constructor_fieldFormal_optional_withDefault() {
+ checkLibrary('class C { int x; C([this.x = 42]); }');
+ }
+
test_class_constructor_implicit() {
checkLibrary('class C {}');
}
@@ -1348,6 +1469,56 @@
''');
}
+ test_const_invokeConstructor_named_unresolved() {
+ checkLibrary(
+ r'''
+class C {}
+const V = const C.named();
+''',
+ allowErrors: true);
+ }
+
+ test_const_invokeConstructor_named_unresolved2() {
+ checkLibrary(
+ r'''
+const V = const C.named();
+''',
+ allowErrors: true);
+ }
+
+ test_const_invokeConstructor_named_unresolved3() {
+ addLibrarySource(
+ '/a.dart',
+ r'''
+class C {
+}
+''');
+ checkLibrary(
+ r'''
+import 'a.dart' as p;
+const V = const p.C.named();
+''',
+ allowErrors: true);
+ }
+
+ test_const_invokeConstructor_named_unresolved4() {
+ addLibrarySource('/a.dart', '');
+ checkLibrary(
+ r'''
+import 'a.dart' as p;
+const V = const p.C.named();
+''',
+ allowErrors: true);
+ }
+
+ test_const_invokeConstructor_named_unresolved5() {
+ checkLibrary(
+ r'''
+const V = const p.C.named();
+''',
+ allowErrors: true);
+ }
+
test_const_invokeConstructor_unnamed() {
checkLibrary(r'''
class C {
@@ -1385,6 +1556,32 @@
''');
}
+ test_const_invokeConstructor_unnamed_unresolved() {
+ checkLibrary(
+ r'''
+const V = const C();
+''',
+ allowErrors: true);
+ }
+
+ test_const_invokeConstructor_unnamed_unresolved2() {
+ addLibrarySource('/a.dart', '');
+ checkLibrary(
+ r'''
+import 'a.dart' as p;
+const V = const p.C();
+''',
+ allowErrors: true);
+ }
+
+ test_const_invokeConstructor_unnamed_unresolved3() {
+ checkLibrary(
+ r'''
+const V = const p.C();
+''',
+ allowErrors: true);
+ }
+
test_const_length_ofClassConstField() {
checkLibrary(r'''
class C {
@@ -1502,7 +1699,9 @@
const C.positional([p = 1 + 2]);
const C.named({p: 1 + 2});
void methodPositional([p = 1 + 2]) {}
+ void methodPositionalWithoutDefault([p]) {}
void methodNamed({p: 1 + 2}) {}
+ void methodNamedWithoutDefault({p}) {}
}
''');
}
@@ -1691,6 +1890,37 @@
''');
}
+ test_const_reference_unresolved_prefix0() {
+ checkLibrary(
+ r'''
+const V = foo;
+''',
+ allowErrors: true);
+ }
+
+ test_const_reference_unresolved_prefix1() {
+ checkLibrary(
+ r'''
+class C {}
+const v = C.foo;
+''',
+ allowErrors: true);
+ }
+
+ test_const_reference_unresolved_prefix2() {
+ addLibrarySource(
+ '/foo.dart',
+ '''
+class C {}
+''');
+ checkLibrary(
+ r'''
+import 'foo.dart' as p;
+const v = p.C.foo;
+''',
+ allowErrors: true);
+ }
+
test_const_topLevel_binary() {
checkLibrary(r'''
const vEqual = 1 == 2;
@@ -1897,6 +2127,234 @@
''');
}
+ test_constructor_redirected_factory_named() {
+ checkLibrary('''
+class C {
+ factory C() = D.named;
+ C._();
+}
+class D extends C {
+ D.named() : super._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_named_generic() {
+ checkLibrary('''
+class C<T, U> {
+ factory C() = D<U, T>.named;
+ C._();
+}
+class D<T, U> extends C<U, T> {
+ D.named() : super._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_named_imported() {
+ addLibrarySource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D extends C {
+ D.named() : super._();
+}
+''');
+ checkLibrary('''
+import 'foo.dart';
+class C {
+ factory C() = D.named;
+ C._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_named_imported_generic() {
+ addLibrarySource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+ D.named() : super._();
+}
+''');
+ checkLibrary('''
+import 'foo.dart';
+class C<T, U> {
+ factory C() = D<U, T>.named;
+ C._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_named_prefixed() {
+ addLibrarySource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D extends C {
+ D.named() : super._();
+}
+''');
+ checkLibrary('''
+import 'foo.dart' as foo;
+class C {
+ factory C() = foo.D.named;
+ C._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_named_prefixed_generic() {
+ addLibrarySource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+ D.named() : super._();
+}
+''');
+ checkLibrary('''
+import 'foo.dart' as foo;
+class C<T, U> {
+ factory C() = foo.D<U, T>.named;
+ C._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_unnamed() {
+ checkLibrary('''
+class C {
+ factory C() = D;
+ C._();
+}
+class D extends C {
+ D() : super._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_unnamed_generic() {
+ checkLibrary('''
+class C<T, U> {
+ factory C() = D<U, T>;
+ C._();
+}
+class D<T, U> extends C<U, T> {
+ D() : super._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_unnamed_imported() {
+ addLibrarySource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D extends C {
+ D() : super._();
+}
+''');
+ checkLibrary('''
+import 'foo.dart';
+class C {
+ factory C() = D;
+ C._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_unnamed_imported_generic() {
+ addLibrarySource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+ D() : super._();
+}
+''');
+ checkLibrary('''
+import 'foo.dart';
+class C<T, U> {
+ factory C() = D<U, T>;
+ C._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_unnamed_prefixed() {
+ addLibrarySource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D extends C {
+ D() : super._();
+}
+''');
+ checkLibrary('''
+import 'foo.dart' as foo;
+class C {
+ factory C() = foo.D;
+ C._();
+}
+''');
+ }
+
+ test_constructor_redirected_factory_unnamed_prefixed_generic() {
+ addLibrarySource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+ D() : super._();
+}
+''');
+ checkLibrary('''
+import 'foo.dart' as foo;
+class C<T, U> {
+ factory C() = foo.D<U, T>;
+ C._();
+}
+''');
+ }
+
+ test_constructor_redirected_thisInvocation_named() {
+ checkLibrary('''
+class C {
+ C.named();
+ C() : this.named();
+}
+''');
+ }
+
+ test_constructor_redirected_thisInvocation_named_generic() {
+ checkLibrary('''
+class C<T> {
+ C.named();
+ C() : this.named();
+}
+''');
+ }
+
+ test_constructor_redirected_thisInvocation_unnamed() {
+ checkLibrary('''
+class C {
+ C();
+ C.named() : this();
+}
+''');
+ }
+
+ test_constructor_redirected_thisInvocation_unnamed_generic() {
+ checkLibrary('''
+class C<T> {
+ C();
+ C.named() : this();
+}
+''');
+ }
+
test_core() {
String uri = 'dart:core';
LibraryElementImpl original =
@@ -2015,15 +2473,15 @@
' abstract class D { int get v; }');
}
- test_field_inferred_type_nonstatic_explicit_initialized() {
+ test_field_inferred_type_nonStatic_explicit_initialized() {
checkLibrary('class C { num v = 0; }');
}
- test_field_inferred_type_nonstatic_implicit_initialized() {
+ test_field_inferred_type_nonStatic_implicit_initialized() {
checkLibrary('class C { var v = 0; }');
}
- test_field_inferred_type_nonstatic_implicit_uninitialized() {
+ test_field_inferred_type_nonStatic_implicit_uninitialized() {
checkLibrary(
'class C extends D { var v; } abstract class D { int get v; }');
}
@@ -2105,12 +2563,10 @@
}
test_function_parameter_kind_named() {
- // TODO(paulberry): also test default value.
checkLibrary('f({x}) {}');
}
test_function_parameter_kind_positional() {
- // TODO(paulberry): also test default value.
checkLibrary('f([x]) {}');
}
@@ -2164,6 +2620,18 @@
checkLibrary('f() {} g() {}');
}
+ test_generic_gClass_gMethodStatic() {
+ resetWithOptions(new AnalysisOptionsImpl()..enableGenericMethods = true);
+ checkLibrary('''
+class C<T, U> {
+ static void m<V, W>(V v, W w) {
+ void f<X, Y>(V v, W w, X x, Y y) {
+ }
+ }
+}
+''');
+ }
+
test_getElement_constructor_named() {
ConstructorElement original = resolve2(addSource('class C { C.named(); }'))
.getType('C')
@@ -2227,6 +2695,14 @@
comparePropertyAccessorElements(resynthesized, original, 'C.setter f');
}
+ test_getElement_unit() {
+ Source source = addSource('class C { f() {} }');
+ CompilationUnitElement original = resolve2(source).definingCompilationUnit;
+ expect(original, isNotNull);
+ CompilationUnitElement resynthesized = validateGetElement(original);
+ compareCompilationUnitElements(resynthesized, original);
+ }
+
test_getter_documented() {
checkLibrary('''
// Extra comment so doc comment offset != 0
@@ -2240,7 +2716,7 @@
checkLibrary('external int get x;');
}
- test_getter_inferred_type_nonstatic_implicit_return() {
+ test_getter_inferred_type_nonStatic_implicit_return() {
checkLibrary(
'class C extends D { get f => null; } abstract class D { int get f; }');
}
@@ -2343,6 +2819,102 @@
checkLibrary('library foo.bar;');
}
+ test_localFunctions() {
+ checkLibrary(r'''
+f() {
+ f1() {}
+ {
+ f2() {}
+ }
+}
+''');
+ }
+
+ test_localFunctions_inConstructor() {
+ checkLibrary(r'''
+class C {
+ C() {
+ f() {}
+ }
+}
+''');
+ }
+
+ test_localFunctions_inMethod() {
+ checkLibrary(r'''
+class C {
+ m() {
+ f() {}
+ }
+}
+''');
+ }
+
+ test_localFunctions_inTopLevelGetter() {
+ checkLibrary(r'''
+get g {
+ f() {}
+}
+''');
+ }
+
+ test_localVariables_inConstructor() {
+ checkLibrary(r'''
+class C {
+ C() {
+ int v;
+ f() {}
+ }
+}
+''');
+ }
+
+ test_localVariables_inLocalFunction() {
+ checkLibrary(r'''
+f() {
+ f1() {
+ int v1 = 1;
+ } // 2
+ f2() {
+ int v1 = 1;
+ f3() {
+ int v2 = 1;
+ }
+ }
+}
+''');
+ }
+
+ test_localVariables_inMethod() {
+ checkLibrary(r'''
+class C {
+ m() {
+ int v;
+ }
+}
+''');
+ }
+
+ test_localVariables_inTopLevelFunction() {
+ checkLibrary(r'''
+main() {
+ int v1 = 1;
+ {
+ const String v2 = 'bbb';
+ }
+ Map<int, List<double>> v3;
+}
+''');
+ }
+
+ test_localVariables_inTopLevelGetter() {
+ checkLibrary(r'''
+get g {
+ int v;
+}
+''');
+ }
+
test_main_class() {
checkLibrary('class main {}');
}
@@ -2542,12 +3114,12 @@
}''');
}
- test_method_inferred_type_nonstatic_implicit_param() {
+ test_method_inferred_type_nonStatic_implicit_param() {
checkLibrary('class C extends D { void f(value) {} }'
' abstract class D { void f(int value); }');
}
- test_method_inferred_type_nonstatic_implicit_return() {
+ test_method_inferred_type_nonStatic_implicit_return() {
checkLibrary(
'class C extends D { f() => null; } abstract class D { int f(); }');
}
@@ -2583,6 +3155,62 @@
checkLibrary('class C { void f<T, U>(T x(U u)) {} }');
}
+ test_nested_generic_functions_in_generic_class_with_function_typed_params() {
+ checkLibrary('''
+class C<T, U> {
+ void g<V, W>() {
+ void h<X, Y>(void p(T t, U u, V v, W w, X x, Y y)) {
+ }
+ }
+}
+''');
+ }
+
+ test_nested_generic_functions_in_generic_class_with_local_variables() {
+ checkLibrary('''
+class C<T, U> {
+ void g<V, W>() {
+ void h<X, Y>() {
+ T t;
+ U u;
+ V v;
+ W w;
+ X x;
+ Y y;
+ }
+ }
+}
+''');
+ }
+
+ test_nested_generic_functions_with_function_typed_param() {
+ checkLibrary('''
+void f<T, U>() {
+ void g<V, W>() {
+ void h<X, Y>(void p(T t, U u, V v, W w, X x, Y y)) {
+ }
+ }
+}
+''');
+ }
+
+ test_nested_generic_functions_with_local_variables() {
+ checkLibrary('''
+void f<T, U>() {
+ void g<V, W>() {
+ void h<X, Y>() {
+ T t;
+ U u;
+ V v;
+ W w;
+ X x;
+ Y y;
+ }
+ }
+}
+''');
+ }
+
test_operator() {
checkLibrary('class C { C operator+(C other) => null; }');
}
@@ -2611,6 +3239,50 @@
checkLibrary('class C { bool operator<=(C other) => false; }');
}
+ test_parameterTypeNotInferred_constructor() {
+ // Strong mode doesn't do type inference on constructor parameters, so it's
+ // ok that we don't store inferred type info for them in summaries.
+ checkLibrary('''
+class C {
+ C.positional([x = 1]);
+ C.named({x: 1});
+}
+''');
+ }
+
+ test_parameterTypeNotInferred_initializingFormal() {
+ // Strong mode doesn't do type inference on initializing formals, so it's
+ // ok that we don't store inferred type info for them in summaries.
+ checkLibrary('''
+class C {
+ var x;
+ C.positional([this.x = 1]);
+ C.named({this.x: 1});
+}
+''');
+ }
+
+ test_parameterTypeNotInferred_staticMethod() {
+ // Strong mode doesn't do type inference on parameters of static methods,
+ // so it's ok that we don't store inferred type info for them in summaries.
+ checkLibrary('''
+class C {
+ static void positional([x = 1]) {}
+ static void named({x: 1}) {}
+}
+''');
+ }
+
+ test_parameterTypeNotInferred_topLevelFunction() {
+ // Strong mode doesn't do type inference on parameters of top level
+ // functions, so it's ok that we don't store inferred type info for them in
+ // summaries.
+ checkLibrary('''
+void positional([x = 1]) {}
+void named({x: 1}) {}
+''');
+ }
+
test_parts() {
addNamedSource('/a.dart', 'part of my.lib;');
addNamedSource('/b.dart', 'part of my.lib;');
@@ -2630,7 +3302,7 @@
checkLibrary('external void set x(int value);');
}
- test_setter_inferred_type_nonstatic_implicit_param() {
+ test_setter_inferred_type_nonStatic_implicit_param() {
checkLibrary('class C extends D { void set f(value) {} }'
' abstract class D { void set f(int value); }');
}
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
index af0ad99..4e4cc1e 100644
--- a/pkg/analyzer/test/src/summary/summarize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
@@ -6,9 +6,11 @@
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/prelink.dart';
import 'package:analyzer/src/summary/summarize_ast.dart';
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 63009b8..5e2f084 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -7,11 +7,12 @@
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/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/generated/source_io.dart';
import 'package:analyzer/src/summary/base.dart';
@@ -327,7 +328,7 @@
int numTypeParameters: 0}) {
if (strongMode) {
checkLinkedTypeSlot(slotId, absoluteUri, relativeUri, expectedName,
- allowTypeParameters: allowTypeParameters,
+ allowTypeArguments: allowTypeParameters,
expectedKind: expectedKind,
expectedTargetUnit: expectedTargetUnit,
linkedSourceUnit: linkedSourceUnit,
@@ -363,8 +364,8 @@
/**
* Verify that the given [typeRef] represents a reference to a type declared
* in a file reachable via [absoluteUri] and [relativeUri], having name
- * [expectedName]. If [allowTypeParameters] is true, allow the type
- * reference to supply type parameters. [expectedKind] is the kind of object
+ * [expectedName]. If [allowTypeArguments] is true, allow the type
+ * reference to supply type arguments. [expectedKind] is the kind of object
* referenced. [linkedSourceUnit] and [unlinkedSourceUnit] refer to the
* compilation unit within which the [typeRef] appears; if not specified they
* are assumed to refer to the defining compilation unit.
@@ -375,7 +376,7 @@
*/
void checkLinkedTypeRef(EntityRef typeRef, String absoluteUri,
String relativeUri, String expectedName,
- {bool allowTypeParameters: false,
+ {bool allowTypeArguments: false,
ReferenceKind expectedKind: ReferenceKind.classOrEnum,
int expectedTargetUnit: 0,
LinkedUnit linkedSourceUnit,
@@ -386,7 +387,7 @@
reason: 'No entry in linkedSourceUnit.types matching slotId');
expect(typeRef.paramReference, 0);
int index = typeRef.reference;
- if (!allowTypeParameters) {
+ if (!allowTypeArguments) {
expect(typeRef.typeArguments, isEmpty);
}
checkReferenceIndex(index, absoluteUri, relativeUri, expectedName,
@@ -400,8 +401,8 @@
/**
* Verify that the given [slotId] represents a reference to a type declared
* in a file reachable via [absoluteUri] and [relativeUri], having name
- * [expectedName]. If [allowTypeParameters] is true, allow the type
- * reference to supply type parameters. [expectedKind] is the kind of object
+ * [expectedName]. If [allowTypeArguments] is true, allow the type
+ * reference to supply type arguments. [expectedKind] is the kind of object
* referenced. [linkedSourceUnit] and [unlinkedSourceUnit] refer to the
* compilation unit within which the [typeRef] appears; if not specified they
* are assumed to refer to the defining compilation unit.
@@ -412,7 +413,7 @@
*/
void checkLinkedTypeSlot(
int slotId, String absoluteUri, String relativeUri, String expectedName,
- {bool allowTypeParameters: false,
+ {bool allowTypeArguments: false,
ReferenceKind expectedKind: ReferenceKind.classOrEnum,
int expectedTargetUnit: 0,
LinkedUnit linkedSourceUnit,
@@ -429,7 +430,7 @@
absoluteUri,
relativeUri,
expectedName,
- allowTypeParameters: allowTypeParameters,
+ allowTypeArguments: allowTypeArguments,
expectedKind: expectedKind,
expectedTargetUnit: expectedTargetUnit,
linkedSourceUnit: linkedSourceUnit,
@@ -467,6 +468,9 @@
* reference, return the [UnlinkedReference] that is used to make the
* explicit reference. If the type reference in question is an implicit
* reference, return `null`.
+ *
+ * TODO(scheglov) remove [checkAstDerivedDataOverride] once elements-based
+ * serializer can record unresolved information.
*/
UnlinkedReference checkReferenceIndex(int referenceIndex, String absoluteUri,
String relativeUri, String expectedName,
@@ -474,7 +478,8 @@
int expectedTargetUnit: 0,
LinkedUnit linkedSourceUnit,
UnlinkedUnit unlinkedSourceUnit,
- int numTypeParameters: 0}) {
+ int numTypeParameters: 0,
+ bool checkAstDerivedDataOverride: false}) {
linkedSourceUnit ??= definingUnit;
unlinkedSourceUnit ??= unlinkedUnits[0];
LinkedReference referenceResolution =
@@ -504,7 +509,9 @@
} else {
checkDependency(referenceResolution.dependency, absoluteUri, relativeUri);
}
- if (expectedKind == ReferenceKind.unresolved && !checkAstDerivedData) {
+ if (expectedKind == ReferenceKind.unresolved &&
+ !checkAstDerivedData &&
+ !checkAstDerivedDataOverride) {
// summarize_elements.dart isn't yet able to record the name of
// unresolved references. TODO(paulberry): fix this.
expect(name, '*unresolved*');
@@ -534,6 +541,9 @@
* target of the [typeRef] is expected to appear; if not specified it is
* assumed to be the defining compilation unit. [numTypeParameters] is the
* number of type parameters of the thing being referred to.
+ *
+ * TODO(scheglov) remove [checkAstDerivedDataOverride] once elements-based
+ * serializer can record unresolved information.
*/
void checkTypeRef(EntityRef typeRef, String absoluteUri, String relativeUri,
String expectedName,
@@ -544,7 +554,8 @@
int expectedTargetUnit: 0,
LinkedUnit linkedSourceUnit,
UnlinkedUnit unlinkedSourceUnit,
- int numTypeParameters: 0}) {
+ int numTypeParameters: 0,
+ bool checkAstDerivedDataOverride: false}) {
linkedSourceUnit ??= definingUnit;
expect(typeRef, new isInstanceOf<EntityRef>());
expect(typeRef.paramReference, 0);
@@ -558,10 +569,13 @@
expectedTargetUnit: expectedTargetUnit,
linkedSourceUnit: linkedSourceUnit,
unlinkedSourceUnit: unlinkedSourceUnit,
- numTypeParameters: numTypeParameters);
+ numTypeParameters: numTypeParameters,
+ checkAstDerivedDataOverride: checkAstDerivedDataOverride);
expect(reference, isNotNull,
reason: 'Unlinked type refs must refer to an explicit reference');
- if (expectedKind == ReferenceKind.unresolved && !checkAstDerivedData) {
+ if (expectedKind == ReferenceKind.unresolved &&
+ !checkAstDerivedData &&
+ !checkAstDerivedDataOverride) {
// summarize_elements.dart isn't yet able to record the prefix of
// unresolved references. TODO(paulberry): fix this.
expect(reference.prefixReference, 0);
@@ -580,6 +594,7 @@
: expectation.relativeUri ?? relativeUri,
expectation.name,
expectedKind: expectation.kind,
+ checkAstDerivedDataOverride: checkAstDerivedDataOverride,
expectedTargetUnit: expectedTargetUnit,
linkedSourceUnit: linkedSourceUnit,
unlinkedSourceUnit: unlinkedSourceUnit,
@@ -614,20 +629,6 @@
checkTypeRef(typeRef, null, null, 'void');
}
- fail_enum_value_documented() {
- // TODO(paulberry): currently broken because of dartbug.com/25385
- String text = '''
-enum E {
- /**
- * Docs
- */
- v
-}''';
- UnlinkedEnumValue value = serializeEnumText(text).values[0];
- expect(value.documentationComment, isNotNull);
- checkDocumentationComment(value.documentationComment, text);
- }
-
/**
* Find the class with the given [className] in the summary, and return its
* [UnlinkedClass] data structure. If [unit] is not given, the class is
@@ -1099,17 +1100,17 @@
// executables
Map<String, UnlinkedPublicName> executablesMap =
<String, UnlinkedPublicName>{};
- className.constMembers.forEach((e) => executablesMap[e.name] = e);
+ className.members.forEach((e) => executablesMap[e.name] = e);
expect(executablesMap, hasLength(2));
{
UnlinkedPublicName executable = executablesMap['fieldStaticConst'];
expect(executable.kind, ReferenceKind.propertyAccessor);
- expect(executable.constMembers, isEmpty);
+ expect(executable.members, isEmpty);
}
{
UnlinkedPublicName executable = executablesMap['methodStaticPublic'];
expect(executable.kind, ReferenceKind.method);
- expect(executable.constMembers, isEmpty);
+ expect(executable.members, isEmpty);
}
}
@@ -1131,18 +1132,18 @@
// executables
Map<String, UnlinkedPublicName> executablesMap =
<String, UnlinkedPublicName>{};
- className.constMembers.forEach((e) => executablesMap[e.name] = e);
+ className.members.forEach((e) => executablesMap[e.name] = e);
expect(executablesMap, hasLength(2));
{
- UnlinkedPublicName executable = executablesMap[''];
- expect(executable.kind, ReferenceKind.constructor);
- expect(executable.constMembers, isEmpty);
- }
- {
UnlinkedPublicName executable =
executablesMap['constructorNamedPublicConst'];
expect(executable.kind, ReferenceKind.constructor);
- expect(executable.constMembers, isEmpty);
+ expect(executable.members, isEmpty);
+ }
+ {
+ UnlinkedPublicName executable = executablesMap['constructorNamedPublic'];
+ expect(executable.kind, ReferenceKind.constructor);
+ expect(executable.members, isEmpty);
}
}
@@ -1969,6 +1970,123 @@
]);
}
+ test_constExpr_invokeConstructor_unresolved_named() {
+ UnlinkedVariable variable = serializeVariableText(
+ '''
+class C {}
+const v = const C.foo();
+''',
+ allowErrors: true);
+ _assertUnlinkedConst(variable.constExpr, operators: [
+ UnlinkedConstOperation.invokeConstructor,
+ ], ints: [
+ 0,
+ 0
+ ], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+ expectedKind: ReferenceKind.unresolved,
+ checkAstDerivedDataOverride: true,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+ ])
+ ]);
+ }
+
+ test_constExpr_invokeConstructor_unresolved_named2() {
+ UnlinkedVariable variable = serializeVariableText(
+ '''
+const v = const C.foo();
+''',
+ allowErrors: true);
+ _assertUnlinkedConst(variable.constExpr, operators: [
+ UnlinkedConstOperation.invokeConstructor,
+ ], ints: [
+ 0,
+ 0
+ ], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+ expectedKind: ReferenceKind.unresolved,
+ checkAstDerivedDataOverride: true,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.unresolved, 'C')
+ ])
+ ]);
+ }
+
+ test_constExpr_invokeConstructor_unresolved_named_prefixed() {
+ addNamedSource(
+ '/a.dart',
+ '''
+class C {
+}
+''');
+ UnlinkedVariable variable = serializeVariableText(
+ '''
+import 'a.dart' as p;
+const v = const p.C.foo();
+''',
+ allowErrors: true);
+ _assertUnlinkedConst(variable.constExpr, operators: [
+ UnlinkedConstOperation.invokeConstructor,
+ ], ints: [
+ 0,
+ 0
+ ], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+ expectedKind: ReferenceKind.unresolved,
+ checkAstDerivedDataOverride: true,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
+ absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
+ new _PrefixExpectation(ReferenceKind.prefix, 'p',
+ inLibraryDefiningUnit: true)
+ ])
+ ]);
+ }
+
+ test_constExpr_invokeConstructor_unresolved_named_prefixed2() {
+ addNamedSource('/a.dart', '');
+ UnlinkedVariable variable = serializeVariableText(
+ '''
+import 'a.dart' as p;
+const v = const p.C.foo();
+''',
+ allowErrors: true);
+ _assertUnlinkedConst(variable.constExpr, operators: [
+ UnlinkedConstOperation.invokeConstructor,
+ ], ints: [
+ 0,
+ 0
+ ], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+ expectedKind: ReferenceKind.unresolved,
+ checkAstDerivedDataOverride: true,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.unresolved, 'C'),
+ new _PrefixExpectation(ReferenceKind.prefix, 'p',
+ inLibraryDefiningUnit: true)
+ ])
+ ]);
+ }
+
+ test_constExpr_invokeConstructor_unresolved_unnamed() {
+ UnlinkedVariable variable = serializeVariableText(
+ '''
+const v = const Foo();
+''',
+ allowErrors: true);
+ _assertUnlinkedConst(variable.constExpr, operators: [
+ UnlinkedConstOperation.invokeConstructor,
+ ], ints: [
+ 0,
+ 0
+ ], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, null, 'Foo',
+ expectedKind: ReferenceKind.unresolved,
+ checkAstDerivedDataOverride: true)
+ ]);
+ }
+
test_constExpr_length_classConstField() {
UnlinkedVariable variable = serializeVariableText('''
class C {
@@ -2679,6 +2797,67 @@
_assertUnlinkedConst(variable.constExpr, isInvalid: true);
}
+ test_constExpr_pushReference_unresolved_prefix0() {
+ UnlinkedVariable variable = serializeVariableText(
+ '''
+const v = foo;
+''',
+ allowErrors: true);
+ _assertUnlinkedConst(variable.constExpr, operators: [
+ UnlinkedConstOperation.pushReference
+ ], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+ expectedKind: ReferenceKind.unresolved,
+ checkAstDerivedDataOverride: true)
+ ]);
+ }
+
+ test_constExpr_pushReference_unresolved_prefix1() {
+ UnlinkedVariable variable = serializeVariableText(
+ '''
+class C {}
+const v = C.foo;
+''',
+ allowErrors: true);
+ _assertUnlinkedConst(variable.constExpr, operators: [
+ UnlinkedConstOperation.pushReference
+ ], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+ expectedKind: ReferenceKind.unresolved,
+ checkAstDerivedDataOverride: true,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+ ])
+ ]);
+ }
+
+ test_constExpr_pushReference_unresolved_prefix2() {
+ addNamedSource(
+ '/a.dart',
+ '''
+class C {}
+''');
+ UnlinkedVariable variable = serializeVariableText(
+ '''
+import 'a.dart' as p;
+const v = p.C.foo;
+''',
+ allowErrors: true);
+ _assertUnlinkedConst(variable.constExpr, operators: [
+ UnlinkedConstOperation.pushReference
+ ], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, null, 'foo',
+ expectedKind: ReferenceKind.unresolved,
+ checkAstDerivedDataOverride: true,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
+ absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
+ new _PrefixExpectation(ReferenceKind.prefix, 'p',
+ inLibraryDefiningUnit: true),
+ ])
+ ]);
+ }
+
test_constExpr_pushString_adjacent() {
UnlinkedVariable variable =
serializeVariableText('const v = "aaa" "b" "ccc";');
@@ -2746,6 +2925,11 @@
expect(executable.returnType, isNull);
expect(executable.isExternal, isFalse);
expect(executable.nameOffset, text.indexOf('C();'));
+ expect(executable.isRedirectedConstructor, isFalse);
+ expect(executable.redirectedConstructor, isNull);
+ expect(executable.redirectedConstructorName, isEmpty);
+ expect(executable.visibleOffset, 0);
+ expect(executable.visibleLength, 0);
}
test_constructor_anonymous() {
@@ -3162,6 +3346,358 @@
expect(ctor.parameters[0].inferredTypeSlot, 0);
}
+ test_constructor_redirected_factory_named() {
+ String text = '''
+class C {
+ factory C() = D.named;
+ C._();
+}
+class D extends C {
+ D.named() : super._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+ expectedKind: ReferenceKind.constructor,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'D')
+ ]);
+ }
+
+ test_constructor_redirected_factory_named_generic() {
+ String text = '''
+class C<T, U> {
+ factory C() = D<U, T>.named;
+ C._();
+}
+class D<T, U> extends C<U, T> {
+ D.named() : super._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+ expectedKind: ReferenceKind.constructor,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
+ numTypeParameters: 2)
+ ],
+ allowTypeParameters: true);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+ }
+
+ test_constructor_redirected_factory_named_imported() {
+ addNamedSource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D extends C {
+ D.named() : super._();
+}
+''');
+ String text = '''
+import 'foo.dart';
+class C {
+ factory C() = D.named;
+ C._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+ expectedKind: ReferenceKind.constructor,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
+ absoluteUri: absUri('/foo.dart'), relativeUri: 'foo.dart')
+ ]);
+ }
+
+ test_constructor_redirected_factory_named_imported_generic() {
+ addNamedSource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+ D.named() : super._();
+}
+''');
+ String text = '''
+import 'foo.dart';
+class C<T, U> {
+ factory C() = D<U, T>.named;
+ C._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+ expectedKind: ReferenceKind.constructor,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
+ numTypeParameters: 2,
+ absoluteUri: absUri('/foo.dart'),
+ relativeUri: 'foo.dart')
+ ],
+ allowTypeParameters: true);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+ }
+
+ test_constructor_redirected_factory_named_prefixed() {
+ addNamedSource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D extends C {
+ D.named() : super._();
+}
+''');
+ String text = '''
+import 'foo.dart' as foo;
+class C {
+ factory C() = foo.D.named;
+ C._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+ expectedKind: ReferenceKind.constructor,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
+ absoluteUri: absUri('/foo.dart'), relativeUri: 'foo.dart'),
+ new _PrefixExpectation(ReferenceKind.prefix, 'foo')
+ ]);
+ }
+
+ test_constructor_redirected_factory_named_prefixed_generic() {
+ addNamedSource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+ D.named() : super._();
+}
+''');
+ String text = '''
+import 'foo.dart' as foo;
+class C<T, U> {
+ factory C() = foo.D<U, T>.named;
+ C._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(executable.redirectedConstructor, null, null, 'named',
+ expectedKind: ReferenceKind.constructor,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'D',
+ numTypeParameters: 2,
+ absoluteUri: absUri('/foo.dart'),
+ relativeUri: 'foo.dart'),
+ new _PrefixExpectation(ReferenceKind.prefix, 'foo')
+ ],
+ allowTypeParameters: true);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+ }
+
+ test_constructor_redirected_factory_unnamed() {
+ String text = '''
+class C {
+ factory C() = D;
+ C._();
+}
+class D extends C {
+ D() : super._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(executable.redirectedConstructor, null, null, 'D');
+ }
+
+ test_constructor_redirected_factory_unnamed_generic() {
+ String text = '''
+class C<T, U> {
+ factory C() = D<U, T>;
+ C._();
+}
+class D<T, U> extends C<U, T> {
+ D() : super._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(executable.redirectedConstructor, null, null, 'D',
+ allowTypeParameters: true, numTypeParameters: 2);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+ }
+
+ test_constructor_redirected_factory_unnamed_imported() {
+ addNamedSource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D extends C {
+ D() : super._();
+}
+''');
+ String text = '''
+import 'foo.dart';
+class C {
+ factory C() = D;
+ C._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(
+ executable.redirectedConstructor, absUri('/foo.dart'), 'foo.dart', 'D');
+ }
+
+ test_constructor_redirected_factory_unnamed_imported_generic() {
+ addNamedSource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+ D() : super._();
+}
+''');
+ String text = '''
+import 'foo.dart';
+class C<T, U> {
+ factory C() = D<U, T>;
+ C._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(
+ executable.redirectedConstructor, absUri('/foo.dart'), 'foo.dart', 'D',
+ allowTypeParameters: true, numTypeParameters: 2);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+ }
+
+ test_constructor_redirected_factory_unnamed_prefixed() {
+ addNamedSource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D extends C {
+ D() : super._();
+}
+''');
+ String text = '''
+import 'foo.dart' as foo;
+class C {
+ factory C() = foo.D;
+ C._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(
+ executable.redirectedConstructor, absUri('/foo.dart'), 'foo.dart', 'D',
+ expectedPrefix: 'foo');
+ }
+
+ test_constructor_redirected_factory_unnamed_prefixed_generic() {
+ addNamedSource(
+ '/foo.dart',
+ '''
+import 'test.dart';
+class D<T, U> extends C<U, T> {
+ D() : super._();
+}
+''');
+ String text = '''
+import 'foo.dart' as foo;
+class C<T, U> {
+ factory C() = foo.D<U, T>;
+ C._();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isTrue);
+ expect(executable.redirectedConstructorName, isEmpty);
+ checkTypeRef(
+ executable.redirectedConstructor, absUri('/foo.dart'), 'foo.dart', 'D',
+ allowTypeParameters: true, numTypeParameters: 2, expectedPrefix: 'foo');
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[0], 1);
+ checkParamTypeRef(executable.redirectedConstructor.typeArguments[1], 2);
+ }
+
+ test_constructor_redirected_thisInvocation_named() {
+ String text = '''
+class C {
+ C() : this.named();
+ C.named();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isFalse);
+ expect(executable.redirectedConstructorName, 'named');
+ expect(executable.redirectedConstructor, isNull);
+ }
+
+ test_constructor_redirected_thisInvocation_unnamed() {
+ String text = '''
+class C {
+ C.named() : this();
+ C();
+}
+''';
+ UnlinkedExecutable executable =
+ serializeClassText(text, className: 'C').executables[0];
+ expect(executable.isRedirectedConstructor, isTrue);
+ expect(executable.isFactory, isFalse);
+ expect(executable.redirectedConstructorName, isEmpty);
+ expect(executable.redirectedConstructor, isNull);
+ }
+
test_constructor_return_type() {
UnlinkedExecutable executable = findExecutable('',
executables: serializeClassText('class C { C(); }').executables);
@@ -3372,6 +3908,19 @@
expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
}
+ test_enum_value_documented() {
+ String text = '''
+enum E {
+ /**
+ * Docs
+ */
+ v
+}''';
+ UnlinkedEnumValue value = serializeEnumText(text).values[0];
+ expect(value.documentationComment, isNotNull);
+ checkDocumentationComment(value.documentationComment, text);
+ }
+
test_executable_abstract() {
UnlinkedExecutable executable =
serializeClassText('abstract class C { f(); }').executables[0];
@@ -3391,6 +3940,8 @@
expect(executable.returnType, isNull);
expect(executable.isExternal, isFalse);
expect(executable.nameOffset, text.indexOf('f'));
+ expect(executable.visibleOffset, 0);
+ expect(executable.visibleLength, 0);
expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
expect(unlinkedUnits[0].publicNamespace.names[0].kind,
ReferenceKind.topLevelFunction);
@@ -3452,12 +4003,194 @@
expect(executable.parameters, isEmpty);
}
+ test_executable_localFunctions() {
+ String code = r'''
+f() { // 1
+ f1() {}
+ { // 2
+ f2() {}
+ } // 3
+} // 4
+''';
+ UnlinkedExecutable executable = serializeExecutableText(code);
+ List<UnlinkedExecutable> functions = executable.localFunctions;
+ expect(functions, hasLength(2));
+ {
+ UnlinkedExecutable f1 = functions.singleWhere((v) => v.name == 'f1');
+ _assertExecutableVisible(code, f1, '{ // 1', '} // 4');
+ }
+ {
+ UnlinkedExecutable f2 = functions.singleWhere((v) => v.name == 'f2');
+ _assertExecutableVisible(code, f2, '{ // 2', '} // 3');
+ }
+ }
+
+ test_executable_localVariables_empty() {
+ UnlinkedExecutable executable = serializeExecutableText(r'''
+f() {
+}
+''');
+ expect(executable.localVariables, isEmpty);
+ }
+
+ test_executable_localVariables_inConstructor() {
+ String code = r'''
+class C {
+ C() { // 1
+ int v;
+ } // 2
+}
+''';
+ UnlinkedExecutable executable =
+ findExecutable('', executables: serializeClassText(code).executables);
+ List<UnlinkedVariable> variables = executable.localVariables;
+ expect(variables, hasLength(1));
+ {
+ UnlinkedVariable v = variables.singleWhere((v) => v.name == 'v');
+ _assertVariableVisible(code, v, '{ // 1', '} // 2');
+ checkTypeRef(v.type, 'dart:core', 'dart:core', 'int');
+ }
+ }
+
+ test_executable_localVariables_inLocalFunctions() {
+ String code = r'''
+f() {
+ f1() { // 1
+ int v1 = 1;
+ } // 2
+ f2() { // 3
+ int v1 = 1;
+ f3() { // 4
+ int v2 = 1;
+ } // 5
+ } // 6
+} // 7
+''';
+ UnlinkedExecutable executable = serializeExecutableText(code);
+ List<UnlinkedExecutable> functions = executable.localFunctions;
+ expect(functions, hasLength(2));
+ // f - f1
+ {
+ UnlinkedExecutable f1 = functions.singleWhere((v) => v.name == 'f1');
+ List<UnlinkedVariable> variables = f1.localVariables;
+ expect(variables, hasLength(1));
+ // f1 - v1
+ UnlinkedVariable v1 = variables.singleWhere((v) => v.name == 'v1');
+ _assertVariableVisible(code, v1, '{ // 1', '} // 2');
+ checkTypeRef(v1.type, 'dart:core', 'dart:core', 'int');
+ }
+ // f - f2
+ {
+ UnlinkedExecutable f2 = functions.singleWhere((v) => v.name == 'f2');
+ List<UnlinkedVariable> variables2 = f2.localVariables;
+ List<UnlinkedExecutable> functions2 = f2.localFunctions;
+ expect(variables2, hasLength(1));
+ expect(functions2, hasLength(1));
+ // f - f2 - v1
+ UnlinkedVariable v1 = variables2.singleWhere((v) => v.name == 'v1');
+ _assertVariableVisible(code, v1, '{ // 3', '} // 6');
+ checkTypeRef(v1.type, 'dart:core', 'dart:core', 'int');
+ // f - f2 - f3
+ UnlinkedExecutable f3 = functions2.singleWhere((v) => v.name == 'f3');
+ _assertExecutableVisible(code, f3, '{ // 3', '} // 6');
+ List<UnlinkedVariable> variables3 = f3.localVariables;
+ List<UnlinkedExecutable> functions3 = f3.localFunctions;
+ expect(variables3, hasLength(1));
+ expect(functions3, hasLength(0));
+ // f - f3 - v2
+ UnlinkedVariable v2 = variables3.singleWhere((v) => v.name == 'v2');
+ _assertVariableVisible(code, v2, '{ // 4', '} // 5');
+ checkTypeRef(v2.type, 'dart:core', 'dart:core', 'int');
+ }
+ }
+
+ test_executable_localVariables_inMethod() {
+ String code = r'''
+class C {
+ m() { // 1
+ int v;
+ f() {}
+ } // 2
+}
+''';
+ UnlinkedExecutable executable =
+ findExecutable('m', executables: serializeClassText(code).executables);
+ {
+ List<UnlinkedExecutable> functions = executable.localFunctions;
+ expect(functions, hasLength(1));
+ UnlinkedExecutable f = functions.singleWhere((v) => v.name == 'f');
+ _assertExecutableVisible(code, f, '{ // 1', '} // 2');
+ }
+ {
+ List<UnlinkedVariable> variables = executable.localVariables;
+ expect(variables, hasLength(1));
+ UnlinkedVariable v = variables.singleWhere((v) => v.name == 'v');
+ _assertVariableVisible(code, v, '{ // 1', '} // 2');
+ checkTypeRef(v.type, 'dart:core', 'dart:core', 'int');
+ }
+ }
+
+ test_executable_localVariables_inTopLevelFunction() {
+ String code = r'''
+f() { // 1
+ int v1 = 1;
+ { // 2
+ int v2 = 2;
+ } // 3
+ var v3 = 3;
+} // 4
+''';
+ UnlinkedExecutable executable = serializeExecutableText(code);
+ List<UnlinkedVariable> variables = executable.localVariables;
+ expect(variables, hasLength(3));
+ {
+ UnlinkedVariable v1 = variables.singleWhere((v) => v.name == 'v1');
+ _assertVariableVisible(code, v1, '{ // 1', '} // 4');
+ checkTypeRef(v1.type, 'dart:core', 'dart:core', 'int');
+ }
+ {
+ UnlinkedVariable v2 = variables.singleWhere((v) => v.name == 'v2');
+ _assertVariableVisible(code, v2, '{ // 2', '} // 3');
+ checkTypeRef(v2.type, 'dart:core', 'dart:core', 'int');
+ }
+ {
+ UnlinkedVariable v3 = variables.singleWhere((v) => v.name == 'v3');
+ _assertVariableVisible(code, v3, '{ // 1', '} // 4');
+ expect(v3.type, isNull);
+ }
+ }
+
+ test_executable_localVariables_inTopLevelGetter() {
+ String code = r'''
+get g { // 1
+ int v;
+ f() {}
+} // 2
+''';
+ UnlinkedExecutable executable = serializeExecutableText(code, 'g');
+ {
+ List<UnlinkedExecutable> functions = executable.localFunctions;
+ expect(functions, hasLength(1));
+ UnlinkedExecutable f = functions.singleWhere((v) => v.name == 'f');
+ _assertExecutableVisible(code, f, '{ // 1', '} // 2');
+ }
+ {
+ List<UnlinkedVariable> variables = executable.localVariables;
+ expect(variables, hasLength(1));
+ UnlinkedVariable v = variables.singleWhere((v) => v.name == 'v');
+ _assertVariableVisible(code, v, '{ // 1', '} // 2');
+ checkTypeRef(v.type, 'dart:core', 'dart:core', 'int');
+ }
+ }
+
test_executable_member_function() {
UnlinkedExecutable executable = findExecutable('f',
executables: serializeClassText('class C { f() {} }').executables);
expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
expect(executable.returnType, isNull);
expect(executable.isExternal, isFalse);
+ expect(executable.visibleOffset, 0);
+ expect(executable.visibleLength, 0);
}
test_executable_member_function_explicit_return() {
@@ -4227,6 +4960,15 @@
UnlinkedVariable variable =
serializeClassText('class C { static int i; }').fields[0];
expect(variable.isStatic, isTrue);
+ expect(variable.constExpr, isNull);
+ }
+
+ test_field_static_final() {
+ UnlinkedVariable variable =
+ serializeClassText('class C { static final int i = 0; }').fields[0];
+ expect(variable.isStatic, isTrue);
+ expect(variable.isFinal, isTrue);
+ expect(variable.constExpr, isNull);
}
test_fully_linked_references_follow_other_references() {
@@ -4269,6 +5011,25 @@
expect(f.inferredReturnTypeSlot, 0);
}
+ test_generic_gClass_gMethodStatic() {
+ UnlinkedClass cls = serializeClassText('''
+class C<T, U> {
+ static void m<V, W>(V v, W w) {
+ void f<X, Y>(V v, W w, X x, Y y) {
+ }
+ }
+}
+''');
+ UnlinkedExecutable m = cls.executables[0];
+ UnlinkedExecutable f = m.localFunctions[0];
+ checkParamTypeRef(m.parameters[0].type, 2);
+ checkParamTypeRef(m.parameters[1].type, 1);
+ checkParamTypeRef(f.parameters[0].type, 4);
+ checkParamTypeRef(f.parameters[1].type, 3);
+ checkParamTypeRef(f.parameters[2].type, 2);
+ checkParamTypeRef(f.parameters[3].type, 1);
+ }
+
test_generic_method_in_generic_class() {
UnlinkedClass cls = serializeClassText(
'class C<T, U> { void m<V, W>(T t, U u, V v, W w) {} }');
@@ -4579,7 +5340,7 @@
EntityRef type = getTypeRefForSlot(cls.fields[0].inferredTypeSlot);
// Check that v has inferred type Map<T, int>.
checkLinkedTypeRef(type, 'dart:core', 'dart:core', 'Map',
- allowTypeParameters: true, numTypeParameters: 2);
+ allowTypeArguments: true, numTypeParameters: 2);
checkParamTypeRef(type.typeArguments[0], 1);
checkLinkedTypeRef(type.typeArguments[1], 'dart:core', 'dart:core', 'int');
}
@@ -5188,6 +5949,113 @@
expect(f.inferredReturnTypeSlot, 0);
}
+ test_nested_generic_functions() {
+ UnlinkedExecutable executable = serializeExecutableText('''
+void f<T, U>() {
+ void g<V, W>() {
+ void h<X, Y>() {
+ T t;
+ U u;
+ V v;
+ W w;
+ X x;
+ Y y;
+ }
+ }
+}
+''');
+ expect(executable.typeParameters, hasLength(2));
+ expect(executable.localFunctions[0].typeParameters, hasLength(2));
+ expect(executable.localFunctions[0].localFunctions[0].typeParameters,
+ hasLength(2));
+ List<UnlinkedVariable> localVariables =
+ executable.localFunctions[0].localFunctions[0].localVariables;
+ checkParamTypeRef(findVariable('t', variables: localVariables).type, 6);
+ checkParamTypeRef(findVariable('u', variables: localVariables).type, 5);
+ checkParamTypeRef(findVariable('v', variables: localVariables).type, 4);
+ checkParamTypeRef(findVariable('w', variables: localVariables).type, 3);
+ checkParamTypeRef(findVariable('x', variables: localVariables).type, 2);
+ checkParamTypeRef(findVariable('y', variables: localVariables).type, 1);
+ }
+
+ test_nested_generic_functions_in_generic_class() {
+ UnlinkedClass cls = serializeClassText('''
+class C<T, U> {
+ void g<V, W>() {
+ void h<X, Y>() {
+ T t;
+ U u;
+ V v;
+ W w;
+ X x;
+ Y y;
+ }
+ }
+}
+''');
+ expect(cls.typeParameters, hasLength(2));
+ expect(cls.executables[0].typeParameters, hasLength(2));
+ expect(cls.executables[0].localFunctions[0].typeParameters, hasLength(2));
+ List<UnlinkedVariable> localVariables =
+ cls.executables[0].localFunctions[0].localVariables;
+ checkParamTypeRef(findVariable('t', variables: localVariables).type, 6);
+ checkParamTypeRef(findVariable('u', variables: localVariables).type, 5);
+ checkParamTypeRef(findVariable('v', variables: localVariables).type, 4);
+ checkParamTypeRef(findVariable('w', variables: localVariables).type, 3);
+ checkParamTypeRef(findVariable('x', variables: localVariables).type, 2);
+ checkParamTypeRef(findVariable('y', variables: localVariables).type, 1);
+ }
+
+ test_parameter_visibleRange_abstractMethod() {
+ UnlinkedExecutable m = findExecutable('m',
+ executables:
+ serializeClassText('abstract class C { m(p); }').executables,
+ failIfAbsent: true);
+ _assertParameterZeroVisibleRange(m.parameters[0]);
+ }
+
+ test_parameter_visibleRange_function_blockBody() {
+ String text = r'''
+f(x) { // 1
+ f2(y) { // 2
+ } // 3
+} // 4
+''';
+ UnlinkedExecutable f = serializeExecutableText(text);
+ UnlinkedExecutable f2 = f.localFunctions[0];
+ _assertParameterVisible(text, f.parameters[0], '{ // 1', '} // 4');
+ _assertParameterVisible(text, f2.parameters[0], '{ // 2', '} // 3');
+ }
+
+ test_parameter_visibleRange_function_emptyBody() {
+ UnlinkedExecutable f = serializeExecutableText('external f(x);');
+ _assertParameterZeroVisibleRange(f.parameters[0]);
+ }
+
+ test_parameter_visibleRange_function_expressionBody() {
+ String text = r'''
+f(x) => 42;
+''';
+ UnlinkedExecutable f = serializeExecutableText(text);
+ _assertParameterVisible(text, f.parameters[0], '=>', ';');
+ }
+
+ test_parameter_visibleRange_inFunctionTypedParameter() {
+ String text = 'f(g(p)) {}';
+ UnlinkedExecutable f = serializeExecutableText(text);
+ UnlinkedParam g = f.parameters[0];
+ UnlinkedParam p = g.parameters[0];
+ expect(g.name, 'g');
+ expect(p.name, 'p');
+ _assertParameterVisible(text, g, '{', '}');
+ _assertParameterZeroVisibleRange(p);
+ }
+
+ test_parameter_visibleRange_typedef() {
+ UnlinkedTypedef type = serializeTypedefText('typedef F(x);');
+ _assertParameterZeroVisibleRange(type.parameters[0]);
+ }
+
test_part_declaration() {
addNamedSource('/a.dart', 'part of my.lib;');
String text = 'library my.lib; part "a.dart"; // <-part';
@@ -5900,7 +6768,7 @@
UnlinkedVariable v = serializeVariableText('final v = <int, dynamic>{};');
EntityRef type = getTypeRefForSlot(v.propagatedTypeSlot);
checkLinkedTypeRef(type, 'dart:core', 'dart:core', 'Map',
- allowTypeParameters: true, numTypeParameters: 2);
+ allowTypeArguments: true, numTypeParameters: 2);
expect(type.typeArguments, hasLength(1));
checkLinkedTypeRef(type.typeArguments[0], 'dart:core', 'dart:core', 'int');
}
@@ -5974,6 +6842,29 @@
}
}
+ void _assertExecutableVisible(String code, UnlinkedExecutable f,
+ String visibleBegin, String visibleEnd) {
+ int expectedVisibleOffset = code.indexOf(visibleBegin);
+ int expectedVisibleLength =
+ code.indexOf(visibleEnd) - expectedVisibleOffset + 1;
+ expect(f.visibleOffset, expectedVisibleOffset);
+ expect(f.visibleLength, expectedVisibleLength);
+ }
+
+ void _assertParameterVisible(
+ String code, UnlinkedParam p, String visibleBegin, String visibleEnd) {
+ int expectedVisibleOffset = code.indexOf(visibleBegin);
+ int expectedVisibleLength =
+ code.indexOf(visibleEnd) - expectedVisibleOffset + 1;
+ expect(p.visibleOffset, expectedVisibleOffset);
+ expect(p.visibleLength, expectedVisibleLength);
+ }
+
+ void _assertParameterZeroVisibleRange(UnlinkedParam p) {
+ expect(p.visibleOffset, isZero);
+ expect(p.visibleLength, isZero);
+ }
+
void _assertUnlinkedConst(UnlinkedConst constExpr,
{bool isInvalid: false,
List<UnlinkedConstOperation> operators: const <UnlinkedConstOperation>[],
@@ -5993,6 +6884,15 @@
referenceValidators[i](constExpr.references[i]);
}
}
+
+ void _assertVariableVisible(
+ String code, UnlinkedVariable v, String visibleBegin, String visibleEnd) {
+ int expectedVisibleOffset = code.indexOf(visibleBegin);
+ int expectedVisibleLength =
+ code.indexOf(visibleEnd) - expectedVisibleOffset + 1;
+ expect(v.visibleOffset, expectedVisibleOffset);
+ expect(v.visibleLength, expectedVisibleLength);
+ }
}
/**
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index a259e62..21c2fd3 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -5,6 +5,7 @@
library analyzer.test.src.task.dart_test;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -15,7 +16,6 @@
show AnalysisOptions, AnalysisOptionsImpl, CacheState;
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/services/lint.dart';
@@ -32,7 +32,7 @@
import '../../reflective_tests.dart';
import '../../utils.dart';
import '../context/abstract_context.dart';
-import '../mock_sdk.dart';
+import '../context/mock_sdk.dart';
main() {
initializeTestEnvironment();
@@ -2240,6 +2240,8 @@
@reflectiveTest
class GatherUsedLocalElementsTaskTest extends _AbstractDartTaskTest {
+ List<Element> definedElements;
+ Set<String> definedElementNames;
UsedLocalElements usedElements;
Set<String> usedElementNames;
@@ -2304,6 +2306,7 @@
}''');
_computeUsedElements(source);
// validate
+ expect(definedElementNames, unorderedEquals(['main', 'v1', 'v2']));
expect(usedElementNames, unorderedEquals(['v2']));
}
@@ -2323,14 +2326,30 @@
''');
_computeUsedElements(source);
// validate
+ expect(definedElementNames,
+ unorderedEquals(['A', '_m1', '_m2', 'main', 'a', 'p']));
expect(usedElementNames, unorderedEquals(['A', 'a', 'p', '_m2']));
expect(usedElements.members, unorderedEquals(['_m2', '_m3']));
}
+ test_perform_unresolvedImportWithPrefix() {
+ Source source = newSource(
+ '/test.dart',
+ r'''
+import 'x' as p;
+''');
+ _computeUsedElements(source);
+ // validate
+ expect(definedElementNames, isEmpty);
+ expect(usedElementNames, isEmpty);
+ }
+
void _computeUsedElements(Source source) {
LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
computeResult(target, USED_LOCAL_ELEMENTS,
matcher: isGatherUsedLocalElementsTask);
+ definedElements = outputs[DEFINED_ELEMENTS];
+ definedElementNames = definedElements.map((e) => e.name).toSet();
usedElements = outputs[USED_LOCAL_ELEMENTS];
usedElementNames = usedElements.elements.map((e) => e.name).toSet();
}
@@ -4048,10 +4067,12 @@
* Verify that the mutated states of the given [variable] correspond to the
* [mutatedInClosure] and [mutatedInScope] matchers.
*/
- void expectMutated(VariableElement variable, Matcher mutatedInClosure,
- Matcher mutatedInScope) {
+ void expectMutated(FunctionBody body, VariableElement variable,
+ bool mutatedInClosure, bool mutatedInScope) {
expect(variable.isPotentiallyMutatedInClosure, mutatedInClosure);
expect(variable.isPotentiallyMutatedInScope, mutatedInScope);
+ expect(body.isPotentiallyMutatedInClosure(variable), mutatedInClosure);
+ expect(body.isPotentiallyMutatedInScope(variable), mutatedInScope);
}
test_created_resolved_unit() {
@@ -4101,11 +4122,13 @@
matcher: isResolveVariableReferencesTask);
// validate
CompilationUnit unit = outputs[RESOLVED_UNIT4];
- FunctionElement main = unit.element.functions[0];
- expectMutated(main.localVariables[0], isFalse, isFalse);
- expectMutated(main.localVariables[1], isFalse, isTrue);
- expectMutated(main.localVariables[2], isTrue, isTrue);
- expectMutated(main.localVariables[3], isTrue, isTrue);
+ FunctionDeclaration mainDeclaration = unit.declarations[0];
+ FunctionBody body = mainDeclaration.functionExpression.body;
+ FunctionElement main = mainDeclaration.element;
+ expectMutated(body, main.localVariables[0], false, false);
+ expectMutated(body, main.localVariables[1], false, true);
+ expectMutated(body, main.localVariables[2], true, true);
+ expectMutated(body, main.localVariables[3], true, true);
}
test_perform_parameter() {
@@ -4126,11 +4149,13 @@
matcher: isResolveVariableReferencesTask);
// validate
CompilationUnit unit = outputs[RESOLVED_UNIT4];
- FunctionElement main = unit.element.functions[0];
- expectMutated(main.parameters[0], isFalse, isFalse);
- expectMutated(main.parameters[1], isFalse, isTrue);
- expectMutated(main.parameters[2], isTrue, isTrue);
- expectMutated(main.parameters[3], isTrue, isTrue);
+ FunctionDeclaration mainDeclaration = unit.declarations[0];
+ FunctionBody body = mainDeclaration.functionExpression.body;
+ FunctionElement main = mainDeclaration.element;
+ expectMutated(body, main.parameters[0], false, false);
+ expectMutated(body, main.parameters[1], false, true);
+ expectMutated(body, main.parameters[2], true, true);
+ expectMutated(body, main.parameters[3], true, true);
}
}
diff --git a/pkg/analyzer/test/src/task/dart_work_manager_test.dart b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
index 315e061..c6d3f1d 100644
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart' show ScannerErrorCode;
import 'package:analyzer/src/generated/engine.dart'
show
AnalysisErrorInfo,
@@ -15,7 +16,6 @@
InternalAnalysisContext;
import 'package:analyzer/src/generated/error.dart' show AnalysisError;
import 'package:analyzer/src/generated/java_engine.dart' show CaughtException;
-import 'package:analyzer/src/generated/scanner.dart' show ScannerErrorCode;
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/testing/ast_factory.dart';
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 0a00961..cc7047e 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -1161,12 +1161,47 @@
test('uninferred closure', () {
checkFile('''
- typedef num Num2Num(num x);
- void main() {
- Num2Num g = /*info:INFERRED_TYPE_CLOSURE,severe:STATIC_TYPE_ERROR*/(int x) { return x; };
- print(g(42));
- }
- ''');
+ typedef num Num2Num(num x);
+ void main() {
+ Num2Num g = /*info:INFERRED_TYPE_CLOSURE,severe:STATIC_TYPE_ERROR*/(int x) { return x; };
+ print(g(42));
+ }
+ ''');
+ });
+
+ test('subtype of universal type', () {
+ checkFile('''
+ void main() {
+ nonGenericFn(x) => null;
+ {
+ /*=R*/ f/*<P, R>*/(/*=P*/ p) => null;
+ /*=T*/ g/*<S, T>*/(/*=S*/ s) => null;
+
+ var local = f;
+ local = g; // valid
+
+ // Non-generic function cannot subtype a generic one.
+ local = /*severe:STATIC_TYPE_ERROR*/(x) => null;
+ local = /*severe:STATIC_TYPE_ERROR*/nonGenericFn;
+ }
+ {
+ Iterable/*<R>*/ f/*<P, R>*/(List/*<P>*/ p) => null;
+ List/*<T>*/ g/*<S, T>*/(Iterable/*<S>*/ s) => null;
+
+ var local = f;
+ local = g; // valid
+
+ var local2 = g;
+ local = local2;
+ local2 = /*severe:STATIC_TYPE_ERROR*/f;
+ local2 = /*warning:DOWN_CAST_COMPOSITE*/local;
+
+ // Non-generic function cannot subtype a generic one.
+ local = /*severe:STATIC_TYPE_ERROR*/(x) => null;
+ local = /*severe:STATIC_TYPE_ERROR*/nonGenericFn;
+ }
+ }
+ ''');
});
});
@@ -2597,8 +2632,8 @@
// different.
// TODO(sigmund): should we merge these as well?
class T1 extends Object
- with /*severe:INVALID_METHOD_OVERRIDE*/M1
- with /*severe:INVALID_METHOD_OVERRIDE*/M2
+ with /*severe:INVALID_METHOD_OVERRIDE*/M1,
+ /*severe:INVALID_METHOD_OVERRIDE*/M2
implements I1 {
}
''');
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 663ee78..2e7981e 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -1491,6 +1491,75 @@
''');
});
+ test('downwards inference on generic function expressions', () {
+ checkFile('''
+ void main () {
+ {
+ String f/*<S>*/(int x) => null;
+ var v = f;
+ v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) => null;
+ v = /*<T>*/(int x) => "hello";
+ v = /*severe:STATIC_TYPE_ERROR*//*<T>*/(String x) => "hello";
+ v = /*severe:STATIC_TYPE_ERROR*//*<T>*/(int x) => 3;
+ v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) {return /*severe:STATIC_TYPE_ERROR*/3;};
+ }
+ {
+ String f/*<S>*/(int x) => null;
+ var v = f;
+ v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => null;
+ v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => "hello";
+ v = /*info:INFERRED_TYPE_CLOSURE, severe:STATIC_TYPE_ERROR*//*<T>*/(x) => 3;
+ v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) {return /*severe:STATIC_TYPE_ERROR*/3;};
+ v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) {return /*severe:STATIC_TYPE_ERROR*/x;};
+ }
+ {
+ List<String> f/*<S>*/(int x) => null;
+ var v = f;
+ v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) => null;
+ v = /*<T>*/(int x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
+ v = /*severe:STATIC_TYPE_ERROR*//*<T>*/(String x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
+ v = /*<T>*/(int x) => /*info:INFERRED_TYPE_LITERAL*/[/*severe:STATIC_TYPE_ERROR*/3];
+ v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) {return /*info:INFERRED_TYPE_LITERAL*/[/*severe:STATIC_TYPE_ERROR*/3];};
+ }
+ {
+ int int2int/*<S>*/(int x) => null;
+ String int2String/*<T>*/(int x) => null;
+ String string2String/*<T>*/(String x) => null;
+ var x = int2int;
+ x = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x;
+ x = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x+1;
+ var y = int2String;
+ y = /*info:INFERRED_TYPE_CLOSURE, severe:STATIC_TYPE_ERROR*//*<T>*/(x) => x;
+ y = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/x.substring(3);
+ var z = string2String;
+ z = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x.substring(3);
+ }
+ }
+ ''');
+ });
+
+ test('downwards inference on function<T> using the T', () {
+ checkFile('''
+ void main () {
+ {
+ /*=T*/ f/*<T>*/(/*=T*/ x) => null;
+ var v1 = f;
+ v1 = /*info:INFERRED_TYPE_CLOSURE*//*<S>*/(x) => x;
+ }
+ {
+ /*=List<T>*/ f/*<T>*/(/*=T*/ x) => null;
+ var v2 = f;
+ v2 = /*info:INFERRED_TYPE_CLOSURE*//*<S>*/(x) => /*info:INFERRED_TYPE_LITERAL*/[x];
+ Iterable<int> r = v2(42);
+ Iterable<String> s = v2('hello');
+ Iterable<List<int>> t = v2(<int>[]);
+ Iterable<num> u = v2(42);
+ Iterable<num> v = v2/*<num>*/(42);
+ }
+ }
+ ''');
+ });
+
test('downwards inference initializing formal, default formal', () {
checkFile('''
typedef T Function2<S, T>([S x]);
@@ -1500,7 +1569,7 @@
Foo.named([List<int> x = /*info:INFERRED_TYPE_LITERAL*/const [1]]);
}
void f([List<int> l = /*info:INFERRED_TYPE_LITERAL*/const [1]]) {}
-// We do this inference in an early task but don't preserve the infos.
+ // We do this inference in an early task but don't preserve the infos.
Function2<List<int>, String> g = /*pass should be info:INFERRED_TYPE_CLOSURE*/([llll = /*info:INFERRED_TYPE_LITERAL*/const [1]]) => "hello";
''');
});
@@ -1696,14 +1765,23 @@
takeIIO(new C().m);
takeDDO(new C().m);
- takeOOI(/*severe:STATIC_TYPE_ERROR*/new C().m);
- takeIDI(/*severe:STATIC_TYPE_ERROR*/new C().m);
- takeDID(/*severe:STATIC_TYPE_ERROR*/new C().m);
-
// Note: this is a warning because a downcast of a method tear-off could work
- // (derived method can be a subtype).
+ // (derived method can be a subtype):
+ //
+ // class D extends C {
+ // S m<S extends num>(Object x, Object y);
+ // }
+ //
+ // That's legal because we're loosening parameter types.
+ //
takeOON(/*warning:DOWN_CAST_COMPOSITE*/new C().m);
takeOOO(/*warning:DOWN_CAST_COMPOSITE*/new C().m);
+
+ // Note: this is a warning because a downcast of a method tear-off could work
+ // in "normal" Dart, due to bivariance.
+ takeOOI(/*warning:DOWN_CAST_COMPOSITE*/new C().m);
+ takeIDI(/*warning:DOWN_CAST_COMPOSITE*/new C().m);
+ takeDID(/*warning:DOWN_CAST_COMPOSITE*/new C().m);
}
void takeIII(int fn(int a, int b)) {}
@@ -1722,6 +1800,55 @@
void takeDDO(Object fn(double a, double b)) {}
''');
});
+
+ // Regression test for https://github.com/dart-lang/sdk/issues/25668
+ test('infer generic method type', () {
+ checkFile('''
+class C {
+ /*=T*/ m/*<T>*/(/*=T*/ x) => x;
+}
+class D extends C {
+ m/*<S>*/(x) => x;
+}
+main() {
+ int y = new D().m/*<int>*/(42);
+ print(y);
+}
+ ''');
+ });
+
+ test('do not infer invalid override of generic method', () {
+ checkFile('''
+class C {
+ /*=T*/ m/*<T>*/(/*=T*/ x) => x;
+}
+class D extends C {
+ /*severe:INVALID_METHOD_OVERRIDE*/m(x) => x;
+}
+main() {
+ int y = /*info:DYNAMIC_CAST*/new D().m/*<int>*/(42);
+ print(y);
+}
+ ''');
+ });
+
+ test('correctly recognize generic upper bound', () {
+ // Regression test for https://github.com/dart-lang/sdk/issues/25740.
+ checkFile('''
+class Foo<T extends Pattern> {
+ void method/*<U extends T>*/(dynamic/*=U*/ u) {}
+}
+main() {
+ new Foo().method/*<String>*/("str");
+ new Foo();
+
+ new Foo<String>().method("str");
+ new Foo().method("str");
+
+ new Foo<String>().method(/*severe:STATIC_TYPE_ERROR*/42);
+}
+ ''');
+ });
});
// Regression test for https://github.com/dart-lang/dev_compiler/issues/47
@@ -1747,34 +1874,4 @@
''');
});
- // Regression test for https://github.com/dart-lang/sdk/issues/25668
- test('infer generic method type', () {
- checkFile('''
-class C {
- /*=T*/ m/*<T>*/(/*=T*/ x) => x;
-}
-class D extends C {
- m/*<S>*/(x) => x;
-}
-main() {
- int y = new D().m/*<int>*/(42);
- print(y);
-}
- ''');
- });
-
- test('do not infer invalid override of generic method', () {
- checkFile('''
-class C {
- /*=T*/ m/*<T>*/(/*=T*/ x) => x;
-}
-class D extends C {
- /*severe:INVALID_METHOD_OVERRIDE*/m(x) => x;
-}
-main() {
- int y = /*info:DYNAMIC_CAST*/new D().m/*<int>*/(42);
- print(y);
-}
- ''');
- });
}
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index 83c0477..e858a37 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -7,14 +7,13 @@
library analyzer.test.src.task.strong.strong_test_helper;
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/context/context.dart' show SdkAnalysisContext;
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer/src/task/strong/checker.dart';
@@ -22,30 +21,11 @@
import 'package:source_span/source_span.dart';
import 'package:unittest/unittest.dart';
+import '../../context/mock_sdk.dart';
MemoryResourceProvider files;
bool _checkCalled;
-initStrongModeTests() {
- setUp(() {
- AnalysisEngine.instance.processRequiredPlugins();
- files = new MemoryResourceProvider();
- _checkCalled = false;
- });
-
- tearDown(() {
- // This is a sanity check, in case only addFile is called.
- expect(_checkCalled, true, reason: 'must call check() method in test case');
- files = null;
- });
-}
-
-/// Adds a file using [addFile] and calls [check].
-void checkFile(String content) {
- addFile(content);
- check();
-}
-
/// Adds a file to check. The file should contain:
///
/// * all expected failures are listed in the source code using comments
@@ -80,20 +60,17 @@
expect(files.getFile('/main.dart').exists, true,
reason: '`/main.dart` is missing');
- var uriResolver = new TestUriResolver(files);
+ var uriResolver = new _TestUriResolver(files);
// Enable task model strong mode
var context = AnalysisEngine.instance.createAnalysisContext();
context.analysisOptions.strongMode = true;
context.analysisOptions.strongModeHints = true;
- context.sourceFactory = new SourceFactory([
- new MockDartSdk(_mockSdkSources, reportMissing: true).resolver,
- uriResolver
- ]);
+ context.sourceFactory =
+ new SourceFactory([new DartUriResolver(new MockSdk()), uriResolver]);
// Run the checker on /main.dart.
Source mainSource = uriResolver.resolveAbsolute(new Uri.file('/main.dart'));
- var initialLibrary =
- context.resolveCompilationUnit2(mainSource, mainSource);
+ var initialLibrary = context.resolveCompilationUnit2(mainSource, mainSource);
var collector = new _ErrorCollector();
var checker = new CodeChecker(
@@ -113,120 +90,26 @@
var librarySource = context.getLibrariesContaining(source).single;
var resolved = context.resolveCompilationUnit2(source, librarySource);
- var analyzerErrors = context
- .getErrors(source)
- .errors
- .where((error) =>
- error.errorCode.name.startsWith('STRONG_MODE_INFERRED_TYPE'))
- .toList();
- errors.addAll(analyzerErrors);
+ errors.addAll(context.getErrors(source).errors.where((error) =>
+ error.errorCode.name.startsWith('STRONG_MODE_INFERRED_TYPE')));
checker.visitCompilationUnit(resolved);
- new _ExpectedErrorVisitor(errors).validate(resolved);
+ _expectErrors(resolved, errors);
}
}
}
-/// Sample mock SDK sources.
-final Map<String, String> _mockSdkSources = {
- // The list of types below is derived from:
- // * types we use via our smoke queries, including HtmlElement and
- // types from `_typeHandlers` (deserialize.dart)
- // * types that are used internally by the resolver (see
- // _initializeFrom in resolver.dart).
- 'dart:core': '''
- library dart.core;
-
- void print(Object o) {}
-
- class Object {
- int get hashCode {}
- Type get runtimeType {}
- String toString(){}
- bool ==(other){}
- }
- class Function {}
- class StackTrace {}
- class Symbol {}
- class Type {}
-
- class String {
- String operator +(String other) {}
- String substring(int len) {}
- }
- class bool {}
- class num {
- num operator +(num other) {}
- }
- class int extends num {
- bool operator<(num other) {}
- int operator-() {}
- }
- class double extends num {}
- class DateTime {}
- class Null {}
-
- class Deprecated {
- final String expires;
- const Deprecated(this.expires);
- }
- const Object deprecated = const Deprecated("next release");
- class _Override { const _Override(); }
- const Object override = const _Override();
- class _Proxy { const _Proxy(); }
- const Object proxy = const _Proxy();
-
- class Iterable<E> {
- Iterable/*<R>*/ map/*<R>*/(/*=R*/ f(E e));
-
- /*=R*/ fold/*<R>*/(/*=R*/ initialValue,
- /*=R*/ combine(/*=R*/ previousValue, E element));
- }
- class List<E> implements Iterable<E> {
- List([int length]);
- List.filled(int length, E fill);
- }
- class Map<K, V> {
- Iterable<K> get keys {}
- }
- ''',
- 'dart:async': '''
- library dart.async;
- class Future<T> {
- Future(computation()) {}
- Future.value(T t) {}
- static Future<List/*<T>*/> wait/*<T>*/(
- Iterable<Future/*<T>*/> futures) => null;
- Future/*<R>*/ then/*<R>*/(/*=R*/ onValue(T value)) => null;
- }
- class Stream<T> {}
- ''',
- 'dart:html': '''
- library dart.html;
- class HtmlElement {}
- ''',
- 'dart:math': '''
- library dart.math;
- class Random {
- bool nextBool() {}
- }
- num/*=T*/ min/*<T extends num>*/(num/*=T*/ a, num/*=T*/ b) => null;
- num/*=T*/ max/*<T extends num>*/(num/*=T*/ a, num/*=T*/ b) => null;
- ''',
-
- 'dart:_foreign_helper': '''
- library dart._foreign_helper;
-
- JS(String typeDescription, String codeTemplate,
- [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11])
- {}
- '''
-};
+/// Adds a file using [addFile] and calls [check].
+void checkFile(String content) {
+ addFile(content);
+ check();
+}
SourceSpanWithContext createSpanHelper(
- LineInfo lineInfo, int start, int end, Source source, String content) {
+ LineInfo lineInfo, int start, Source source, String content,
+ {int end}) {
var startLoc = locationForOffset(lineInfo, source.uri, start);
- var endLoc = locationForOffset(lineInfo, source.uri, end);
+ var endLoc = locationForOffset(lineInfo, source.uri, end ?? start);
var lineStart = startLoc.offset - startLoc.column;
// Find the end of the line. This is not exposed directly on LineInfo, but
@@ -238,6 +121,11 @@
while (lineEnd < content.length &&
lineInfo.getLocation(++lineEnd).lineNumber == lineNum);
+ if (end == null) {
+ end = lineEnd;
+ endLoc = locationForOffset(lineInfo, source.uri, lineEnd);
+ }
+
var text = content.substring(start, end);
var lineText = content.substring(lineStart, lineEnd);
return new SourceSpanWithContext(startLoc, endLoc, text, lineText);
@@ -255,6 +143,20 @@
}
}
+initStrongModeTests() {
+ setUp(() {
+ AnalysisEngine.instance.processRequiredPlugins();
+ files = new MemoryResourceProvider();
+ _checkCalled = false;
+ });
+
+ tearDown(() {
+ // This is a sanity check, in case only addFile is called.
+ expect(_checkCalled, true, reason: 'must call check() method in test case');
+ files = null;
+ });
+}
+
// TODO(jmesserly): can we reuse the same mock SDK as Analyzer tests?
SourceLocation locationForOffset(LineInfo lineInfo, Uri uri, int offset) {
var loc = lineInfo.getLocation(offset);
@@ -277,77 +179,121 @@
return results;
}
-/// Dart SDK which contains a mock implementation of the SDK libraries. May be
-/// used to speed up execution when most of the core libraries is not needed.
-class MockDartSdk implements DartSdk {
- final Map<Uri, _MockSdkSource> _sources = {};
- final bool reportMissing;
- final Map<String, SdkLibrary> _libs = {};
- final String sdkVersion = '0';
- final AnalysisContext context = new SdkAnalysisContext();
- DartUriResolver _resolver;
- MockDartSdk(Map<String, String> sources, {this.reportMissing}) {
- sources.forEach((uriString, contents) {
- var uri = Uri.parse(uriString);
- _sources[uri] = new _MockSdkSource(uri, contents);
- _libs[uriString] = new SdkLibraryImpl(uri.path)
- ..setDart2JsLibrary()
- ..setVmLibrary();
- });
- _resolver = new DartUriResolver(this);
- context.sourceFactory = new SourceFactory([_resolver]);
- }
- DartUriResolver get resolver => _resolver;
+Level _actualErrorLevel(AnalysisError actual) {
+ return const <ErrorSeverity, Level>{
+ ErrorSeverity.ERROR: Level.SEVERE,
+ ErrorSeverity.WARNING: Level.WARNING,
+ ErrorSeverity.INFO: Level.INFO
+ }[actual.errorCode.errorSeverity];
+}
- List<SdkLibrary> get sdkLibraries => _libs.values.toList();
+void _expectErrors(CompilationUnit unit, List<AnalysisError> actualErrors) {
+ var expectedErrors = _findExpectedErrors(unit.beginToken);
- List<String> get uris => _sources.keys.map((uri) => '$uri').toList();
- Source fromEncoding(UriKind kind, Uri uri) {
- if (kind != UriKind.DART_URI) {
- throw new UnsupportedError('expected dart: uri kind, got $kind.');
+ // Categorize the differences, if any.
+ var unreported = <_ErrorExpectation>[];
+ var different = <_ErrorExpectation, AnalysisError>{};
+
+ for (var expected in expectedErrors) {
+ AnalysisError actual = expected._removeMatchingActual(actualErrors);
+ if (actual != null) {
+ if (_actualErrorLevel(actual) != expected.level ||
+ errorCodeName(actual.errorCode) != expected.typeName) {
+ different[expected] = actual;
+ }
+ } else {
+ unreported.add(expected);
}
- return _getSource(uri);
}
- @override
- Source fromFileUri(Uri uri) {
- throw new UnsupportedError('MockDartSdk.fromFileUri');
- }
+ // Whatever is left was an unexpected error.
+ List<AnalysisError> unexpected = actualErrors;
- SdkLibrary getSdkLibrary(String dartUri) => _libs[dartUri];
-
- Source mapDartUri(String dartUri) => _getSource(Uri.parse(dartUri));
-
- Source _getSource(Uri uri) {
- var src = _sources[uri];
- if (src == null) {
- if (reportMissing) print('warning: missing mock for $uri.');
- _sources[uri] =
- src = new _MockSdkSource(uri, 'library dart.${uri.path};');
- }
- return src;
+ if (unreported.isNotEmpty || unexpected.isNotEmpty || different.isNotEmpty) {
+ _reportFailure(unit, unreported, unexpected, different);
}
}
-class TestUriResolver extends ResourceUriResolver {
- final MemoryResourceProvider provider;
- TestUriResolver(provider)
- : provider = provider,
- super(provider);
+List<_ErrorExpectation> _findExpectedErrors(Token beginToken) {
+ var expectedErrors = <_ErrorExpectation>[];
- @override
- Source resolveAbsolute(Uri uri, [Uri actualUri]) {
- if (uri.scheme == 'package') {
- return (provider.getResource('/packages/' + uri.path) as File)
- .createSource(uri);
+ // Collect expectations like "severe:STATIC_TYPE_ERROR" from comment tokens.
+ for (Token t = beginToken; t.type != TokenType.EOF; t = t.next) {
+ for (CommentToken c = t.precedingComments; c != null; c = c.next) {
+ if (c.type == TokenType.MULTI_LINE_COMMENT) {
+ String value = c.lexeme.substring(2, c.lexeme.length - 2);
+ if (value.contains(':')) {
+ var offset = c.end;
+ if (c.next?.type == TokenType.GENERIC_METHOD_TYPE_LIST) {
+ offset += 2;
+ }
+ for (var expectCode in value.split(',')) {
+ var expected = _ErrorExpectation.parse(offset, expectCode);
+ if (expected != null) {
+ expectedErrors.add(expected);
+ }
+ }
+ }
+ }
}
- return super.resolveAbsolute(uri, actualUri);
}
+ return expectedErrors;
+}
+
+void _reportFailure(
+ CompilationUnit unit,
+ List<_ErrorExpectation> unreported,
+ List<AnalysisError> unexpected,
+ Map<_ErrorExpectation, AnalysisError> different) {
+ // Get the source code. This reads the data again, but it's safe because
+ // all tests use memory file system.
+ var sourceCode = unit.element.source.contents.data;
+
+ String formatActualError(AnalysisError error) {
+ int offset = error.offset;
+ int length = error.length;
+ var span = createSpanHelper(
+ unit.lineInfo, offset, unit.element.source, sourceCode,
+ end: offset + length);
+ var levelName = _actualErrorLevel(error).name.toLowerCase();
+ return '@$offset $levelName: [${errorCodeName(error.errorCode)}]\n' +
+ span.message(error.message);
+ }
+
+ String formatExpectedError(_ErrorExpectation error) {
+ int offset = error.offset;
+ var span = createSpanHelper(
+ unit.lineInfo, offset, unit.element.source, sourceCode);
+ var levelName = error.level.toString().toLowerCase();
+ return '@$offset $levelName: [${error.typeName}]\n' + span.message('');
+ }
+
+ var message = new StringBuffer();
+ if (unreported.isNotEmpty) {
+ message.writeln('Expected errors that were not reported:');
+ unreported.map(formatExpectedError).forEach(message.writeln);
+ message.writeln();
+ }
+ if (unexpected.isNotEmpty) {
+ message.writeln('Errors that were not expected:');
+ unexpected.map(formatActualError).forEach(message.writeln);
+ message.writeln();
+ }
+ if (different.isNotEmpty) {
+ message.writeln('Errors that were reported, but different than expected:');
+ different.forEach((expected, actual) {
+ message.writeln('Expected: ' + formatExpectedError(expected));
+ message.writeln('Actual: ' + formatActualError(actual));
+ });
+ message.writeln();
+ }
+ fail('Checker errors do not match expected errors:\n\n$message');
}
class _ErrorCollector implements AnalysisErrorListener {
List<AnalysisError> errors;
final bool hints;
+
_ErrorCollector({this.hints: true});
void onError(AnalysisError error) {
@@ -361,26 +307,39 @@
/// Describes an expected message that should be produced by the checker.
class _ErrorExpectation {
+ final int offset;
final Level level;
final String typeName;
- _ErrorExpectation(this.level, this.typeName);
- String toString() => '$level $typeName';
+ _ErrorExpectation(this.offset, this.level, this.typeName);
- static _ErrorExpectation parse(String descriptor) {
+ String toString() =>
+ '@$offset ${level.toString().toLowerCase()}: [$typeName]';
+
+ AnalysisError _removeMatchingActual(List<AnalysisError> actualErrors) {
+ for (var actual in actualErrors) {
+ if (actual.offset == offset) {
+ actualErrors.remove(actual);
+ return actual;
+ }
+ }
+ return null;
+ }
+
+ static _ErrorExpectation parse(int offset, String descriptor) {
descriptor = descriptor.trim();
var tokens = descriptor.split(' ');
- if (tokens.length == 1) return _parse(tokens[0]);
+ if (tokens.length == 1) return _parse(offset, tokens[0]);
expect(tokens.length, 4, reason: 'invalid error descriptor');
expect(tokens[1], "should", reason: 'invalid error descriptor');
expect(tokens[2], "be", reason: 'invalid error descriptor');
if (tokens[0] == "pass") return null;
// TODO(leafp) For now, we just use whatever the current expectation is,
// eventually we could do more automated reporting here.
- return _parse(tokens[0]);
+ return _parse(offset, tokens[0]);
}
- static _ErrorExpectation _parse(String descriptor) {
+ static _ErrorExpectation _parse(offset, String descriptor) {
var tokens = descriptor.split(':');
expect(tokens.length, 2, reason: 'invalid error descriptor');
var name = tokens[0].toUpperCase();
@@ -392,155 +351,22 @@
reason: 'invalid level in error descriptor: `${tokens[0]}`');
expect(typeName, isNotNull,
reason: 'invalid type in error descriptor: ${tokens[1]}');
- return new _ErrorExpectation(level, typeName);
+ return new _ErrorExpectation(offset, level, typeName);
}
}
-class _ExpectedErrorVisitor extends UnifyingAstVisitor {
- final Set<AnalysisError> _actualErrors;
- CompilationUnit _unit;
- String _unitSourceCode;
+class _TestUriResolver extends ResourceUriResolver {
+ final MemoryResourceProvider provider;
+ _TestUriResolver(provider)
+ : provider = provider,
+ super(provider);
- _ExpectedErrorVisitor(List<AnalysisError> actualErrors)
- : _actualErrors = new Set.from(actualErrors);
-
- validate(CompilationUnit unit) {
- _unit = unit;
- // This reads the file. Only safe because tests use MemoryFileSystem.
- _unitSourceCode = unit.element.source.contents.data;
-
- // Visit the compilation unit.
- unit.accept(this);
-
- if (_actualErrors.isNotEmpty) {
- var actualMsgs = _actualErrors.map(_formatActualError).join('\n');
- fail('Unexpected errors reported by checker:\n\n$actualMsgs');
+ @override
+ Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+ if (uri.scheme == 'package') {
+ return (provider.getResource('/packages/' + uri.path) as File)
+ .createSource(uri);
}
+ return super.resolveAbsolute(uri, actualUri);
}
-
- visitNode(AstNode node) {
- var token = node.beginToken;
- var comment = token.precedingComments;
- // Use error marker found in an immediately preceding comment,
- // and attach it to the outermost expression that starts at that token.
- if (comment != null) {
- while (comment.next != null) {
- comment = comment.next;
- }
- if (comment.end == token.offset && node.parent.beginToken != token) {
- var commentText = '$comment';
- var start = commentText.lastIndexOf('/*');
- var end = commentText.lastIndexOf('*/');
- if (start != -1 &&
- end != -1 &&
- !commentText.startsWith('/*<', start) &&
- !commentText.startsWith('/*=', start)) {
- expect(start, lessThan(end));
- var errors = commentText.substring(start + 2, end).split(',');
- var expectations =
- errors.map(_ErrorExpectation.parse).where((x) => x != null);
-
- for (var e in expectations) {
- _expectError(node, e);
- }
- }
- }
- }
- return super.visitNode(node);
- }
-
- Level _actualErrorLevel(AnalysisError actual) {
- return const <ErrorSeverity, Level>{
- ErrorSeverity.ERROR: Level.SEVERE,
- ErrorSeverity.WARNING: Level.WARNING,
- ErrorSeverity.INFO: Level.INFO
- }[actual.errorCode.errorSeverity];
- }
-
- SourceSpan _createSpan(int offset, int len) {
- return createSpanHelper(_unit.lineInfo, offset, offset + len,
- _unit.element.source, _unitSourceCode);
- }
-
- void _expectError(AstNode node, _ErrorExpectation expected) {
- // See if we can find the expected error in our actual errors
- for (var actual in _actualErrors) {
- if (actual.offset == node.offset && actual.length == node.length) {
- var actualMsg = _formatActualError(actual);
- expect(_actualErrorLevel(actual), expected.level,
- reason: 'expected different error code at:\n\n$actualMsg');
- expect(errorCodeName(actual.errorCode), expected.typeName,
- reason: 'expected different error type at:\n\n$actualMsg');
-
- // We found it. Stop the search.
- _actualErrors.remove(actual);
- return;
- }
- }
-
- var span = _createSpan(node.offset, node.length);
- var levelName = expected.level.name.toLowerCase();
- var msg = span.message(expected.typeName, color: _colorOf(levelName));
- fail('expected error was not reported at:\n\n$levelName: $msg');
- }
-
- String _formatActualError(AnalysisError actual) {
- var span = _createSpan(actual.offset, actual.length);
- var levelName = _actualErrorLevel(actual).name.toLowerCase();
- var msg = span.message(actual.message, color: _colorOf(levelName));
- return '$levelName: [${errorCodeName(actual.errorCode)}] $msg';
- }
-
- /// Returns an ANSII color escape sequence corresponding to [levelName].
- ///
- /// Colors are defined for: severe, error, warning, or info.
- /// Returns null if the level name is not recognized.
- String _colorOf(String levelName) {
- const String CYAN_COLOR = '\u001b[36m';
- const String MAGENTA_COLOR = '\u001b[35m';
- const String RED_COLOR = '\u001b[31m';
-
- levelName = levelName.toLowerCase();
- if (levelName == 'shout' || levelName == 'severe' || levelName == 'error') {
- return RED_COLOR;
- }
- if (levelName == 'warning') return MAGENTA_COLOR;
- if (levelName == 'info') return CYAN_COLOR;
- return null;
- }
-}
-
-class _MockSdkSource implements Source {
- /// Absolute URI which this source can be imported from.
- final Uri uri;
- final String _contents;
-
- final int modificationStamp = 1;
-
- _MockSdkSource(this.uri, this._contents);
-
- TimestampedData<String> get contents =>
- new TimestampedData(modificationStamp, _contents);
-
- String get encoding => "${uriKind.encoding}$uri";
-
- String get fullName => shortName;
-
- int get hashCode => uri.hashCode;
-
- bool get isInSystemLibrary => true;
-
- String get shortName => uri.path;
-
- Source get source => this;
-
- UriKind get uriKind => UriKind.DART_URI;
-
- bool exists() => true;
-
- Source resolveRelative(Uri relativeUri) =>
- throw new UnsupportedError('not expecting relative urls in dart: mocks');
-
- Uri resolveRelativeUri(Uri relativeUri) =>
- throw new UnsupportedError('not expecting relative urls in dart: mocks');
}
diff --git a/pkg/analyzer/tool/summary/build_sdk_summaries.dart b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
index 2e680da..8e6c5fc 100644
--- a/pkg/analyzer/tool/summary/build_sdk_summaries.dart
+++ b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
@@ -44,8 +44,8 @@
//
// Build spec and strong summaries.
//
- _buildSummary(sdkPath, outputDirectoryPath, false);
- _buildSummary(sdkPath, outputDirectoryPath, true);
+ new _Builder(sdkPath, outputDirectoryPath, false).build();
+ new _Builder(sdkPath, outputDirectoryPath, true).build();
}
/**
@@ -54,58 +54,92 @@
const BINARY_NAME = "build_sdk_summaries";
/**
- * Build a strong or spec mode summary for the Dart SDK at [sdkPath].
- */
-void _buildSummary(
- String sdkPath, String outputDirectoryPath, bool strongMode) {
- print('Generating ${strongMode ? 'strong' : 'spec'} mode summary.');
- Stopwatch sw = new Stopwatch()..start();
- //
- // Prepare SDK.
- //
- DirectoryBasedDartSdk sdk = new DirectoryBasedDartSdk(new JavaFile(sdkPath));
- AnalysisContext context = sdk.context;
- context.analysisOptions = new AnalysisOptionsImpl()..strongMode = strongMode;
- //
- // Serialize each SDK library.
- //
- List<String> linkedLibraryUris = <String>[];
- List<LinkedLibraryBuilder> linkedLibraries = <LinkedLibraryBuilder>[];
- List<String> unlinkedUnitUris = <String>[];
- List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[];
- for (SdkLibrary lib in sdk.sdkLibraries) {
- Source librarySource = sdk.mapDartUri(lib.shortName);
- LibraryElement libraryElement =
- context.computeLibraryElement(librarySource);
- LibrarySerializationResult libraryResult =
- serializeLibrary(libraryElement, context.typeProvider, strongMode);
- linkedLibraryUris.add(lib.shortName);
- linkedLibraries.add(libraryResult.linked);
- unlinkedUnitUris.addAll(libraryResult.unitUris);
- unlinkedUnits.addAll(libraryResult.unlinkedUnits);
- }
- //
- // Write the whole SDK bundle.
- //
- SdkBundleBuilder sdkBundle = new SdkBundleBuilder(
- linkedLibraryUris: linkedLibraryUris,
- linkedLibraries: linkedLibraries,
- unlinkedUnitUris: unlinkedUnitUris,
- unlinkedUnits: unlinkedUnits);
- String outputFilePath =
- join(outputDirectoryPath, strongMode ? 'strong.sum' : 'spec.sum');
- File file = new File(outputFilePath);
- file.writeAsBytesSync(sdkBundle.toBuffer(), mode: FileMode.WRITE_ONLY);
- //
- // Done.
- //
- print('\tDone in ${sw.elapsedMilliseconds} ms.');
-}
-
-/**
* Print information about how to use the SDK summaries builder.
*/
void _printUsage() {
print('Usage: $BINARY_NAME output_directory_path [sdk_path]');
print('Build files spec.sum and strong.sum in the output directory.');
}
+
+class _Builder {
+ final String sdkPath;
+ final String outputDirectoryPath;
+ final bool strongMode;
+
+ AnalysisContext context;
+ final Set<Source> processedSources = new Set<Source>();
+
+ final List<String> linkedLibraryUris = <String>[];
+ final List<LinkedLibraryBuilder> linkedLibraries = <LinkedLibraryBuilder>[];
+ final List<String> unlinkedUnitUris = <String>[];
+ final List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[];
+
+ _Builder(this.sdkPath, this.outputDirectoryPath, this.strongMode);
+
+ /**
+ * Build a strong or spec mode summary for the Dart SDK at [sdkPath].
+ */
+ void build() {
+ print('Generating ${strongMode ? 'strong' : 'spec'} mode summary.');
+ Stopwatch sw = new Stopwatch()..start();
+ //
+ // Prepare SDK.
+ //
+ DirectoryBasedDartSdk sdk =
+ new DirectoryBasedDartSdk(new JavaFile(sdkPath));
+ sdk.useSummary = false;
+ context = sdk.context;
+ context.analysisOptions = new AnalysisOptionsImpl()
+ ..strongMode = strongMode;
+ //
+ // Serialize each SDK library.
+ //
+ for (SdkLibrary lib in sdk.sdkLibraries) {
+ Source libSource = sdk.mapDartUri(lib.shortName);
+ _serializeLibrary(libSource);
+ }
+ //
+ // Write the whole SDK bundle.
+ //
+ SdkBundleBuilder sdkBundle = new SdkBundleBuilder(
+ linkedLibraryUris: linkedLibraryUris,
+ linkedLibraries: linkedLibraries,
+ unlinkedUnitUris: unlinkedUnitUris,
+ unlinkedUnits: unlinkedUnits);
+ String outputFilePath =
+ join(outputDirectoryPath, strongMode ? 'strong.sum' : 'spec.sum');
+ File file = new File(outputFilePath);
+ file.writeAsBytesSync(sdkBundle.toBuffer(), mode: FileMode.WRITE_ONLY);
+ //
+ // Done.
+ //
+ print('\tDone in ${sw.elapsedMilliseconds} ms.');
+ }
+
+ /**
+ * Serialize the library with the given [source] and all its direct or
+ * indirect imports and exports.
+ */
+ void _serializeLibrary(Source source) {
+ if (!processedSources.add(source)) {
+ return;
+ }
+ LibraryElement element = context.computeLibraryElement(source);
+ _serializeSingleLibrary(element);
+ element.importedLibraries.forEach((e) => _serializeLibrary(e.source));
+ element.exportedLibraries.forEach((e) => _serializeLibrary(e.source));
+ }
+
+ /**
+ * Serialize the library with the given [element].
+ */
+ void _serializeSingleLibrary(LibraryElement element) {
+ String uri = element.source.uri.toString();
+ LibrarySerializationResult libraryResult =
+ serializeLibrary(element, context.typeProvider, strongMode);
+ linkedLibraryUris.add(uri);
+ linkedLibraries.add(libraryResult.linked);
+ unlinkedUnitUris.addAll(libraryResult.unitUris);
+ unlinkedUnits.addAll(libraryResult.unlinkedUnits);
+ }
+}
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index 5c2d2bf..ba4a49e 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -23,11 +23,13 @@
import 'dart:io' hide File;
import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:path/path.dart';
@@ -82,6 +84,7 @@
*/
void checkIdl() {
_idl.classes.forEach((String name, idlModel.ClassDeclaration cls) {
+ Map<int, String> idsUsed = <int, String>{};
for (idlModel.FieldDeclaration field in cls.fields) {
String fieldName = field.name;
idlModel.FieldType type = field.type;
@@ -101,6 +104,16 @@
'$name.$fieldName: illegal type (list of ${type.typeName})');
}
}
+ if (idsUsed.containsKey(field.id)) {
+ throw new Exception('$name.$fieldName: id ${field.id} already used by'
+ ' ${idsUsed[field.id]}');
+ }
+ idsUsed[field.id] = fieldName;
+ }
+ for (int i = 0; i < idsUsed.length; i++) {
+ if (!idsUsed.containsKey(i)) {
+ throw new Exception('$name: no field uses id $i');
+ }
}
});
}
@@ -193,9 +206,10 @@
}
for (ClassMember classMember in decl.members) {
if (classMember is MethodDeclaration && classMember.isGetter) {
+ String desc = '${cls.name}.${classMember.name.name}';
TypeName type = classMember.returnType;
if (type == null) {
- throw new Exception('Class member needs a type: $classMember');
+ throw new Exception('Class member needs a type: $desc');
}
bool isList = false;
if (type.name.name == 'List' &&
@@ -207,11 +221,34 @@
if (type.typeArguments != null) {
throw new Exception('Cannot handle type arguments in `$type`');
}
+ int id;
+ for (Annotation annotation in classMember.metadata) {
+ if (annotation.name.name == 'Id') {
+ if (id != null) {
+ throw new Exception(
+ 'Duplicate @id annotation ($classMember)');
+ }
+ if (annotation.arguments.arguments.length != 1) {
+ throw new Exception(
+ '@Id must be passed exactly one argument ($desc)');
+ }
+ Expression expression = annotation.arguments.arguments[0];
+ if (expression is IntegerLiteral) {
+ id = expression.value;
+ } else {
+ throw new Exception(
+ '@Id parameter must be an integer literal ($desc)');
+ }
+ }
+ }
+ if (id == null) {
+ throw new Exception('Missing @id annotation ($desc)');
+ }
String doc = _getNodeDoc(lineInfo, classMember);
idlModel.FieldType fieldType =
new idlModel.FieldType(type.name.name, isList);
cls.fields.add(new idlModel.FieldDeclaration(
- doc, classMember.name.name, fieldType));
+ doc, classMember.name.name, fieldType, id));
} else if (classMember is ConstructorDeclaration &&
classMember.name.name == 'fromBuffer') {
// Ignore `fromBuffer` declarations; they simply forward to the
@@ -404,7 +441,7 @@
out('assert(!_finished);');
out('_finished = true;');
// Write objects and remember Offset(s).
- cls.fields.asMap().forEach((index, idlModel.FieldDeclaration field) {
+ for (idlModel.FieldDeclaration field in cls.fields) {
idlModel.FieldType fieldType = field.type;
String offsetName = 'offset_' + field.name;
if (fieldType.isList ||
@@ -412,8 +449,8 @@
_idl.classes.containsKey(fieldType.typeName)) {
out('fb.Offset $offsetName;');
}
- });
- cls.fields.asMap().forEach((index, idlModel.FieldDeclaration field) {
+ }
+ for (idlModel.FieldDeclaration field in cls.fields) {
idlModel.FieldType fieldType = field.type;
String valueName = '_' + field.name;
String offsetName = 'offset_' + field.name;
@@ -428,7 +465,7 @@
} else if (_idl.enums.containsKey(fieldType.typeName)) {
String itemCode = 'b.index';
String listCode = '$valueName.map((b) => $itemCode).toList()';
- writeCode = '$offsetName = fbBuilder.writeListUint32($listCode);';
+ writeCode = '$offsetName = fbBuilder.writeListUint8($listCode);';
} else if (fieldType.typeName == 'int') {
writeCode =
'$offsetName = fbBuilder.writeListUint32($valueName);';
@@ -457,10 +494,11 @@
});
out('}');
}
- });
+ }
// Write the table.
out('fbBuilder.startTable();');
- cls.fields.asMap().forEach((index, idlModel.FieldDeclaration field) {
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ int index = field.id;
idlModel.FieldType fieldType = field.type;
String valueName = '_' + field.name;
String condition = '$valueName != null';
@@ -479,7 +517,7 @@
writeCode = 'fbBuilder.addUint32($index, $valueName);';
} else if (_idl.enums.containsKey(fieldType.typeName)) {
condition += ' && $valueName != ${defaultValue(fieldType, true)}';
- writeCode = 'fbBuilder.addUint32($index, $valueName.index);';
+ writeCode = 'fbBuilder.addUint8($index, $valueName.index);';
}
if (writeCode == null) {
throw new UnimplementedError('Writing type ${fieldType.typeName}');
@@ -489,7 +527,7 @@
out(writeCode);
});
out('}');
- });
+ }
out('return fbBuilder.endTable();');
});
out('}');
@@ -505,12 +543,12 @@
out('const $readerName() : super();');
out();
out('@override');
- out('int get size => 4;');
+ out('int get size => 1;');
out();
out('@override');
out('${idlPrefix(name)} read(fb.BufferPointer bp) {');
indent(() {
- out('int index = const fb.Uint32Reader().read(bp);');
+ out('int index = const fb.Uint8Reader().read(bp);');
out('return ${idlPrefix(name)}.values[index];');
});
out('}');
@@ -536,7 +574,8 @@
out('$returnType _$fieldName;');
}
// Write getters.
- cls.fields.asMap().forEach((index, field) {
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ int index = field.id;
String fieldName = field.name;
idlModel.FieldType type = field.type;
String typeName = type.typeName;
@@ -545,8 +584,7 @@
String def = defaultValue(type, false);
if (type.isList) {
if (typeName == 'int') {
- String itemCode = 'const fb.Uint32Reader()';
- readCode = 'const fb.ListReader<int>($itemCode)';
+ readCode = 'const fb.Uint32ListReader()';
} else if (typeName == 'double') {
readCode = 'const fb.Float64ListReader()';
} else if (typeName == 'String') {
@@ -583,7 +621,7 @@
out('return _$fieldName;');
});
out('}');
- });
+ }
});
out('}');
}
diff --git a/pkg/analyzer/tool/summary/idl_model.dart b/pkg/analyzer/tool/summary/idl_model.dart
index 9317215..fca1054 100644
--- a/pkg/analyzer/tool/summary/idl_model.dart
+++ b/pkg/analyzer/tool/summary/idl_model.dart
@@ -74,7 +74,12 @@
*/
final FieldType type;
- FieldDeclaration(String documentation, String name, this.type)
+ /**
+ * The id of the field.
+ */
+ final int id;
+
+ FieldDeclaration(String documentation, String name, this.type, this.id)
: super(documentation, name);
}
diff --git a/pkg/analyzer/tool/summary/stats.dart b/pkg/analyzer/tool/summary/stats.dart
new file mode 100644
index 0000000..da524a0
--- /dev/null
+++ b/pkg/analyzer/tool/summary/stats.dart
@@ -0,0 +1,103 @@
+// 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.
+
+/**
+ * This file contains code for collecting statistics about the use of fields in
+ * a summary file.
+ */
+library analyzer.tool.summary.stats;
+
+import 'dart:io';
+import 'dart:mirrors';
+
+import 'package:analyzer/src/summary/base.dart';
+import 'package:analyzer/src/summary/idl.dart';
+
+main(List<String> args) {
+ if (args.length != 1) {
+ _printUsage();
+ exitCode = 1;
+ return;
+ }
+
+ String inputFilePath = args[0];
+
+ // Read the input.
+ SdkBundle bundle =
+ new SdkBundle.fromBuffer(new File(inputFilePath).readAsBytesSync());
+
+ // Compute and output stats.
+ Stats stats = new Stats();
+ stats.record(bundle);
+ stats.dump();
+}
+
+/**
+ * The name of the stats tool.
+ */
+const String BINARY_NAME = "stats";
+
+/**
+ * Print information about how to use the stats tool.
+ */
+void _printUsage() {
+ print('Usage: $BINARY_NAME input_file_path');
+}
+
+/**
+ * An instance of [Stats] keeps track of statistics about the use of fields in
+ * summary objects.
+ */
+class Stats {
+ /**
+ * Map from type to field name to a count of how often the field is used.
+ */
+ Map<Type, Map<String, int>> counts = <Type, Map<String, int>>{};
+
+ /**
+ * Print out statistics gathered so far.
+ */
+ void dump() {
+ counts.forEach((Type type, Map<String, int> typeCounts) {
+ print(type);
+ List<String> keys = typeCounts.keys.toList();
+ keys.sort((String a, String b) => typeCounts[b].compareTo(typeCounts[a]));
+ for (String key in keys) {
+ print(' $key: ${typeCounts[key]}');
+ }
+ print('');
+ });
+ }
+
+ /**
+ * Record statistics for [obj] and all objects it refers to.
+ */
+ void record(SummaryClass obj) {
+ Map<String, int> typeCounts =
+ counts.putIfAbsent(obj.runtimeType, () => <String, int>{});
+ obj.toMap().forEach((String key, Object value) {
+ if (value == null ||
+ value == 0 ||
+ value == false ||
+ value == '' ||
+ value is List && value.isEmpty ||
+ reflect(value).type.isEnum && (value as dynamic).index == 0) {
+ return;
+ }
+ if (!typeCounts.containsKey(key)) {
+ typeCounts[key] = 0;
+ }
+ typeCounts[key]++;
+ if (value is SummaryClass) {
+ record(value);
+ } else if (value is List) {
+ value.forEach((Object element) {
+ if (element is SummaryClass) {
+ record(element);
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/pkg/analyzer/tool/task_dependency_graph/tasks.dot b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
index 3953adc..1f14eda 100644
--- a/pkg/analyzer/tool/task_dependency_graph/tasks.dot
+++ b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
@@ -76,6 +76,8 @@
DART_ERRORS [shape=box]
DART_SCRIPTS -> ScanDartTask
DART_SCRIPTS [shape=box]
+ DEFINED_ELEMENTS -> GenerateHintsTask
+ DEFINED_ELEMENTS [shape=box]
DartErrorsTask -> DART_ERRORS
EXPLICITLY_IMPORTED_LIBRARIES [shape=box]
EXPORTED_LIBRARIES -> BuildDirectiveElementsTask
@@ -88,6 +90,7 @@
EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT11
EvaluateUnitConstantsTask -> RESOLVED_UNIT11
GatherUsedImportedElementsTask -> USED_IMPORTED_ELEMENTS
+ GatherUsedLocalElementsTask -> DEFINED_ELEMENTS
GatherUsedLocalElementsTask -> USED_LOCAL_ELEMENTS
GenerateHintsTask -> HINTS
GenerateLintsTask -> LINTS
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 58e4359..3de4b4d 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -290,7 +290,9 @@
packagesRequiringFullParse = null;
}
return (Source source) {
- if (source.uri.scheme == 'dart') {
+ if (options.sourceFiles.contains(source.fullName)) {
+ return true;
+ } else if (source.uri.scheme == 'dart') {
return options.showSdkWarnings;
} else if (source.uri.scheme == 'package') {
if (packagesRequiringFullParse == null) {
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 4b37788..e6b4f4c 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1795,6 +1795,18 @@
uri = currentElement.compilationUnit.script.resourceUri;
assert(invariant(currentElement, () {
+ bool sameToken(Token token, Token sought) {
+ if (token == sought) return true;
+ if (token.stringValue == '>>' ||
+ token.stringValue == '>>>') {
+ // `>>` and `>>>` are converted to `>` in the parser when needed.
+ return sought.stringValue == '>' &&
+ token.charOffset <= sought.charOffset &&
+ sought.charOffset < token.charEnd;
+ }
+ return false;
+ }
+
/// Check that [begin] and [end] can be found between [from] and [to].
validateToken(Token from, Token to) {
if (from == null || to == null) return true;
@@ -1802,10 +1814,10 @@
bool foundEnd = false;
Token token = from;
while (true) {
- if (token == begin) {
+ if (sameToken(token, begin)) {
foundBegin = true;
}
- if (token == end) {
+ if (sameToken(token, end)) {
foundEnd = true;
}
if (foundBegin && foundEnd) {
@@ -1859,7 +1871,7 @@
}
SourceSpan spanFromNode(Node node) {
- return spanFromTokens(node.getBeginToken(), node.getEndToken());
+ return spanFromTokens(node.getBeginToken(), node.getPrefixEndToken());
}
SourceSpan spanFromElement(Element element) {
diff --git a/pkg/compiler/lib/src/cps_ir/builtin_operator.dart b/pkg/compiler/lib/src/cps_ir/builtin_operator.dart
index 2db4ac5..7992821 100644
--- a/pkg/compiler/lib/src/cps_ir/builtin_operator.dart
+++ b/pkg/compiler/lib/src/cps_ir/builtin_operator.dart
@@ -18,7 +18,7 @@
/// In all cases, the word "null" refers to the Dart null object, corresponding
/// to both JS null and JS undefined.
///
-/// Some operators, notably [IsFloor] and [IsNumberAndFloor], take "repeated"
+/// Some operators, notably [IsFloor] and [IsInteger], take "repeated"
/// arguments to reflect the number of times the given value is referenced
/// by the generated code. The tree IR needs to know the number of references
/// to safely propagate assignments.
@@ -133,7 +133,28 @@
/// The argument must be repeated 3 times.
///
/// Compiles to `typeof x === 'number' && Math.floor(x) === x`
- IsNumberAndFloor,
+ IsInteger,
+
+ /// Returns true if the argument is not an integer.
+ ///
+ /// The argument must be repeated 3 times.
+ ///
+ /// Compiles to `typeof x !== 'number' || Math.floor(x) !== x`
+ IsNotInteger,
+
+ /// Returns true if `x` is an unsigned 32-bit integer.
+ ///
+ /// The argument must be repeated 2 times.
+ ///
+ /// Compiles to `x >>> 0 === x`
+ IsUnsigned32BitInteger,
+
+ /// Returns false if `x` is an unsigned 32-bit integer.
+ ///
+ /// The argument must be repeated 2 times.
+ ///
+ /// Compiles to `x >>> 0 !== x`
+ IsNotUnsigned32BitInteger,
/// Returns true if the argument is a fixed length Array.
///
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 470a96d..8ec5743 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -20,8 +20,11 @@
import '../io/source_information.dart';
import '../js/js.dart' as js show
js,
+ objectLiteral,
+ Expression,
LiteralStatement,
Template,
+ InterpolatedExpression,
isIdentityTemplate;
import '../native/native.dart' show
NativeBehavior;
@@ -691,6 +694,9 @@
assert(!element.isLocal);
assert(!element.isInstanceMember);
assert(isOpen);
+ if (program.isJsInterop(element)) {
+ return buildInvokeJsInteropMember(element, arguments);
+ }
return addPrimitive(
new ir.InvokeStatic(element, selector, arguments, sourceInformation));
}
@@ -1401,8 +1407,8 @@
Selector selector = new Selector.setter(
new Name(variableElement.name, variableElement.library));
List<ir.Primitive> value = <ir.Primitive>[currentValue];
- // Note the order of the comparisons below. It can be the case that an
- // element isError and isMalformed.
+ // Note the comparison below. It can be the case that an element isError
+ // and isMalformed.
if (Elements.isError(variableElement)) {
bodyBuilder.buildStaticNoSuchMethod(selector, value);
} else {
@@ -2066,6 +2072,86 @@
buildReturn(value: value, sourceInformation: source);
}
+ static _isNotNull(ir.Primitive value) =>
+ !(value is ir.Constant && value.value.isNull);
+
+ /// Builds a call to a resolved js-interop element.
+ ir.Primitive buildInvokeJsInteropMember(FunctionElement element,
+ List<ir.Primitive> arguments) {
+ program.addNativeMethod(element);
+ String target = program.getJsInteropTargetPath(element);
+ // Strip off trailing arguments that were not specified.
+ // TODO(jacobr,sigmund): assert that the trailing arguments are all null.
+ // TODO(jacobr): rewrite named arguments to an object literal matching
+ // the factory constructor case.
+ var inputs = arguments.where(_isNotNull).toList();
+
+ var behavior = new NativeBehavior()..sideEffects.setAllSideEffects();
+ DartType type = element.isConstructor ?
+ element.enclosingClass.thisType : element.type.returnType;
+ // Native behavior effects here are similar to native/behavior.dart.
+ // The return type is dynamic if we don't trust js-interop type
+ // declarations.
+ behavior.typesReturned.add(
+ program.trustJSInteropTypeAnnotations ? type : const DynamicType());
+
+ // The allocation effects include the declared type if it is native (which
+ // includes js interop types).
+ if (type.element != null && program.isNative(type.element)) {
+ behavior.typesInstantiated.add(type);
+ }
+
+ // It also includes any other JS interop type if we don't trust the
+ // annotation or if is declared too broad.
+ if (!program.trustJSInteropTypeAnnotations || type.isObject ||
+ type.isDynamic) {
+ behavior.typesInstantiated.add(program.jsJavascriptObjectType);
+ }
+
+ String code;
+ if (element.isGetter) {
+ code = target;
+ } else if (element.isSetter) {
+ code = "$target = #";
+ } else {
+ var args = new List.filled(inputs.length, '#').join(',');
+ code = element.isConstructor ? "new $target($args)" : "$target($args)";
+ }
+ return buildForeignCode(js.js.parseForeignJS(code), inputs, behavior);
+ // TODO(sigmund): should we record the source-information here?
+ }
+
+ /// Builds an object literal that results from invoking a factory constructor
+ /// of a js-interop anonymous type.
+ ir.Primitive buildJsInteropObjectLiteral(ConstructorElement constructor,
+ List<ir.Primitive> arguments, {SourceInformation source}) {
+ assert(program.isJsInteropAnonymous(constructor));
+ program.addNativeMethod(constructor);
+ FunctionSignature params = constructor.functionSignature;
+ int i = 0;
+ var filteredArguments = <ir.Primitive>[];
+ var entries = new Map<String, js.Expression>();
+ params.orderedForEachParameter((ParameterElement parameter) {
+ // TODO(jacobr): throw if parameter names do not match names of property
+ // names in the class.
+ assert (parameter.isNamed);
+ ir.Primitive argument = arguments[i++];
+ if (_isNotNull(argument)) {
+ filteredArguments.add(argument);
+ entries[parameter.name] =
+ new js.InterpolatedExpression(filteredArguments.length - 1);
+ }
+ });
+ var code = new js.Template(null, js.objectLiteral(entries));
+ var behavior = new NativeBehavior();
+ if (program.trustJSInteropTypeAnnotations) {
+ behavior.typesReturned.add(constructor.enclosingClass.thisType);
+ }
+
+ // TODO(sigmund): should we record the source-information here?
+ return buildForeignCode(code, filteredArguments, behavior);
+ }
+
/// Create a blocks of [statements] by applying [build] to all reachable
/// statements. The first statement is assumed to be reachable.
// TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses
@@ -2551,6 +2637,13 @@
Selector selector =
new Selector(SelectorKind.CALL, element.memberName, callStructure);
ClassElement cls = element.enclosingClass;
+ if (program.isJsInterop(element)) {
+ if (program.isJsInteropAnonymous(element)) {
+ return buildJsInteropObjectLiteral(element, arguments,
+ source: sourceInformation);
+ }
+ return buildInvokeJsInteropMember(element, arguments);
+ }
if (program.requiresRuntimeTypesFor(cls)) {
InterfaceType interface = type;
Iterable<ir.Primitive> typeArguments =
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 3ae2c1b..629bfac 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
@@ -796,7 +796,10 @@
/// Creates a primitive for the default value of [parameter].
ir.Primitive translateDefaultValue(ParameterElement parameter) {
- if (parameter.initializer == null) {
+ if (parameter.initializer == null ||
+ // TODO(sigmund): JS doesn't support default values, so this should be
+ // reported as an error earlier (Issue #25759).
+ backend.isJsInterop(parameter.functionDeclaration)) {
return irBuilder.buildNullConstant();
} else {
return inlineConstant(parameter.executableContext, parameter.initializer);
@@ -1111,8 +1114,105 @@
}
visitAsyncForIn(ast.AsyncForIn node) {
- // await for is not yet implemented.
- return giveup(node, 'await for');
+ // Translate await for into a loop over a StreamIterator. The source
+ // statement:
+ //
+ // await for (<decl> in <stream>) <body>
+ //
+ // is translated as if it were:
+ //
+ // var iterator = new StreamIterator(<stream>);
+ // try {
+ // while (await iterator.hasNext()) {
+ // <decl> = await iterator.current;
+ // <body>
+ // }
+ // } finally {
+ // await iterator.cancel();
+ // }
+ ir.Primitive stream = visit(node.expression);
+ ir.Primitive dummyTypeArgument = irBuilder.buildNullConstant();
+ ConstructorElement constructor = helpers.streamIteratorConstructor;
+ ir.Primitive iterator = irBuilder.addPrimitive(new ir.InvokeConstructor(
+ constructor.enclosingClass.thisType,
+ constructor,
+ new Selector.callConstructor(constructor.memberName, 1),
+ <ir.Primitive>[stream, dummyTypeArgument],
+ sourceInformationBuilder.buildGeneric(node)));
+
+ ir.Node buildTryBody(IrBuilder builder) {
+ ir.Node buildLoopCondition(IrBuilder builder) {
+ ir.Primitive moveNext = builder.buildDynamicInvocation(
+ iterator,
+ Selectors.moveNext,
+ elements.getMoveNextTypeMask(node),
+ <ir.Primitive>[]);
+ return builder.addPrimitive(new ir.Await(moveNext));
+ }
+
+ ir.Node buildLoopBody(IrBuilder builder) {
+ return withBuilder(builder, () {
+ ir.Primitive current = irBuilder.buildDynamicInvocation(
+ iterator,
+ Selectors.current,
+ elements.getCurrentTypeMask(node),
+ <ir.Primitive>[]);
+ Element variable = elements.getForInVariable(node);
+ if (Elements.isLocal(variable)) {
+ if (node.declaredIdentifier.asVariableDefinitions() != null) {
+ irBuilder.declareLocalVariable(variable);
+ }
+ irBuilder.buildLocalVariableSet(variable, current);
+ } else if (Elements.isError(variable) ||
+ Elements.isMalformed(variable)) {
+ Selector selector =
+ new Selector.setter(new Name(variable.name, variable.library));
+ List<ir.Primitive> args = <ir.Primitive>[current];
+ // Note the comparison below. It can be the case that an element
+ // isError and isMalformed.
+ if (Elements.isError(variable)) {
+ irBuilder.buildStaticNoSuchMethod(selector, args);
+ } else {
+ irBuilder.buildErroneousInvocation(variable, selector, args);
+ }
+ } else if (Elements.isStaticOrTopLevel(variable)) {
+ if (variable.isField) {
+ irBuilder.addPrimitive(new ir.SetStatic(variable, current));
+ } else {
+ irBuilder.buildStaticSetterSet(variable, current);
+ }
+ } else {
+ ir.Primitive receiver = irBuilder.buildThis();
+ ast.Node identifier = node.declaredIdentifier;
+ irBuilder.buildDynamicSet(
+ receiver,
+ elements.getSelector(identifier),
+ elements.getTypeMask(identifier),
+ current);
+ }
+ visit(node.body);
+ });
+ }
+
+ builder.buildWhile(
+ buildCondition: buildLoopCondition,
+ buildBody: buildLoopBody,
+ target: elements.getTargetDefinition(node),
+ closureScope: getClosureScopeForNode(node));
+ }
+
+ ir.Node buildFinallyBody(IrBuilder builder) {
+ ir.Primitive cancellation = builder.buildDynamicInvocation(
+ iterator,
+ Selectors.cancel,
+ backend.dynamicType,
+ <ir.Primitive>[],
+ sourceInformation: sourceInformationBuilder.buildGeneric(node));
+ return builder.addPrimitive(new ir.Await(cancellation));
+ }
+
+ irBuilder.buildTryFinally(new TryStatementInfo(), buildTryBody,
+ buildFinallyBody);
}
visitAwait(ast.Await node) {
@@ -3921,4 +4021,22 @@
void addNativeMethod(FunctionElement function) {
_backend.emitter.nativeEmitter.nativeMethods.add(function);
}
+
+ bool get trustJSInteropTypeAnnotations =>
+ _compiler.trustJSInteropTypeAnnotations;
+
+ bool isNative(ClassElement element) => _backend.isNative(element);
+
+ bool isJsInterop(FunctionElement element) => _backend.isJsInterop(element);
+
+ bool isJsInteropAnonymous(FunctionElement element) =>
+ _backend.jsInteropAnalysis.hasAnonymousAnnotation(element.contextClass);
+
+ String getJsInteropTargetPath(FunctionElement element) {
+ return '${_backend.namer.fixedBackendPath(element)}.'
+ '${_backend.getFixedBackendName(element)}';
+ }
+
+ DartType get jsJavascriptObjectType =>
+ _backend.helpers.jsJavaScriptObjectClass.thisType;
}
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 7cb9260..1562262 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -781,14 +781,21 @@
/// Checks that [index] is a valid index on a given indexable [object].
///
-/// Compiles to the following, with a subset of the conditions in the `if`:
+/// In the simplest form, compiles to the following:
///
-/// if (index < 0 || index >= object.length || object.length === 0)
+/// if (index < 0 || index >= object.length)
/// ThrowIndexOutOfRangeException(object, index);
///
-/// [index] must be an integer, and [object] must refer to null or an indexable
-/// object, and [length] must be the length of [object] at the time of the
-/// check.
+/// In the general form, any of the following conditions can be checked:
+///
+/// Lower bound: `index >= 0`
+/// Upper bound: `index < object.length`
+/// Emptiness: `object.length !== 0`
+/// Integerness: `index >>> 0 === index`
+///
+/// [index] must be an integer unless integerness is checked, and [object] must
+/// refer to null or an indexable object, and [length] must be the length of
+/// [object] at the time of the check.
///
/// Returns [object] so the bounds check can be used to restrict code motion.
/// It is possible to have a bounds check node that performs no checks but
@@ -825,6 +832,9 @@
/// because that corresponds to `object.length - 1` in the error case.
bool get hasEmptinessCheck => checks & EMPTINESS != 0;
+ /// If true, check that `index` is an integer.
+ bool get hasIntegerCheck => checks & INTEGER != 0;
+
/// True if the [length] is needed to perform the check.
bool get lengthUsedInCheck => checks & (UPPER_BOUND | EMPTINESS) != 0;
@@ -833,6 +843,7 @@
static const int UPPER_BOUND = 1 << 0;
static const int LOWER_BOUND = 1 << 1;
static const int EMPTINESS = 1 << 2; // See [hasEmptinessCheck].
+ static const int INTEGER = 1 << 3; // Check if index is an int.
static const int BOTH_BOUNDS = UPPER_BOUND | LOWER_BOUND;
static const int NONE = 0;
@@ -859,17 +870,13 @@
}
String get checkString {
- if (hasUpperBoundCheck && hasLowerBoundCheck) {
- return 'upper-lower-checks';
- } else if (hasUpperBoundCheck) {
- return 'upper-check';
- } else if (hasLowerBoundCheck) {
- return 'lower-check';
- } else if (hasEmptinessCheck) {
- return 'emptiness-check';
- } else {
- return 'no-check';
- }
+ if (hasNoChecks) return 'no-check';
+ return [hasUpperBoundCheck ? 'upper' : null,
+ hasLowerBoundCheck ? 'lower' : null,
+ hasEmptinessCheck ? 'emptiness' : null,
+ hasIntegerCheck ? 'integer' : null,
+ 'check']
+ .where((x) => x != null).join('-');
}
bool get isSafeForElimination => checks == NONE;
diff --git a/pkg/compiler/lib/src/cps_ir/finalize.dart b/pkg/compiler/lib/src/cps_ir/finalize.dart
index 7e3b6e1..dad9e51 100644
--- a/pkg/compiler/lib/src/cps_ir/finalize.dart
+++ b/pkg/compiler/lib/src/cps_ir/finalize.dart
@@ -42,9 +42,14 @@
return cps;
}
Continuation fail = cps.letCont();
- if (node.hasLowerBoundCheck) {
+ Primitive index = node.index.definition;
+ if (node.hasIntegerCheck) {
+ cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.IsNotUnsigned32BitInteger,
+ [index, index]))
+ .invokeContinuation(fail);
+ } else if (node.hasLowerBoundCheck) {
cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.NumLt,
- [node.index.definition, cps.makeZero()]))
+ [index, cps.makeZero()]))
.invokeContinuation(fail);
}
if (node.hasUpperBoundCheck) {
@@ -59,7 +64,7 @@
cps.letPrim(length);
}
cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.NumGe,
- [node.index.definition, length]))
+ [index, length]))
.invokeContinuation(fail);
}
if (node.hasEmptinessCheck) {
@@ -69,7 +74,7 @@
}
cps.insideContinuation(fail).invokeStaticThrower(
helpers.throwIndexOutOfRangeException,
- [node.object.definition, node.index.definition]);
+ [node.object.definition, index]);
node..replaceUsesWith(node.object.definition)..destroy();
return cps;
}
diff --git a/pkg/compiler/lib/src/cps_ir/inline.dart b/pkg/compiler/lib/src/cps_ir/inline.dart
index 87892d3..28ea3d5 100644
--- a/pkg/compiler/lib/src/cps_ir/inline.dart
+++ b/pkg/compiler/lib/src/cps_ir/inline.dart
@@ -374,6 +374,7 @@
Primitive result = cps.invokeMethod(thisParameter, newSelector, node.mask,
arguments, node.callingConvention);
result.type = typeSystem.getInvokeReturnType(node.selector, node.mask);
+ returnContinuation.parameters.single.type = result.type;
cps.invokeContinuation(returnContinuation, <Primitive>[result]);
return new FunctionDefinition(target, thisParameter, parameters,
returnContinuation,
@@ -394,6 +395,7 @@
// AST node, targets that are asynchronous or generator functions, or
// targets containing a try statement.
if (!target.hasNode) return null;
+ if (backend.isJsInterop(target)) return null;
if (target.asyncMarker != AsyncMarker.SYNC) return null;
// V8 does not optimize functions containing a try statement. Inlining
// code containing a try statement will make the optimizable calling code
@@ -596,6 +598,7 @@
// These should be handled by operator specialization.
return true;
}
+ if (target == backend.helpers.stringInterpolationHelper) return true;
return false;
}
}
diff --git a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
index ea8bb43..2042320 100644
--- a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
@@ -450,6 +450,13 @@
return interceptedTypes.containsMask(t.nonNullable(), classWorld);
}
+ @override
+ bool isDefinitelySelfInterceptor(TypeMask t, {bool allowNull: false}) {
+ assert(allowNull != null);
+ if (!allowNull && t.isNullable) return false;
+ return areDisjoint(t, interceptorType);
+ }
+
/// Given a class from the interceptor hierarchy, returns a [TypeMask]
/// matching all values with that interceptor (or a subtype thereof).
@override
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index fe35b1f..a9a99fa 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -1420,16 +1420,24 @@
/// Returns a CPS fragment whose context is the branch where no error
/// was thrown.
Primitive makeBoundsCheck(CpsFragment cps,
- Primitive list,
- Primitive index,
- [int checkKind = BoundsCheck.BOTH_BOUNDS]) {
+ Primitive list,
+ Primitive index,
+ [int checkKind = BoundsCheck.BOTH_BOUNDS | BoundsCheck.INTEGER]) {
if (compiler.trustPrimitives) {
return cps.letPrim(new BoundsCheck.noCheck(list, cps.sourceInformation));
} else {
GetLength length = cps.letPrim(new GetLength(list));
list = cps.refine(list, typeSystem.nonNullType);
- return cps.letPrim(new BoundsCheck(list, index, length, checkKind,
- cps.sourceInformation));
+ BoundsCheck check = cps.letPrim(new BoundsCheck(list, index, length,
+ checkKind, cps.sourceInformation));
+ if (check.hasIntegerCheck) {
+ if (typeSystem.isDefinitelyInt(index.type)) {
+ check.checks &= ~BoundsCheck.INTEGER;
+ } else {
+ cps.refine(index, typeSystem.uint32Type);
+ }
+ }
+ return check;
}
}
@@ -1468,8 +1476,6 @@
case '[]':
Primitive index = node.dartArgument(0);
- // TODO(asgerf): Consider inserting a guard and specialize anyway.
- if (!lattice.isDefinitelyInt(getValue(index))) return null;
CpsFragment cps = new CpsFragment(node.sourceInformation);
receiver = makeBoundsCheck(cps, receiver, index);
GetIndex get = cps.letPrim(new GetIndex(receiver, index));
@@ -1485,7 +1491,6 @@
}
Primitive index = node.dartArgument(0);
Primitive value = node.dartArgument(1);
- if (!lattice.isDefinitelyInt(getValue(index))) return null;
CpsFragment cps = new CpsFragment(node.sourceInformation);
receiver = makeBoundsCheck(cps, receiver, index);
cps.letPrim(new SetIndex(receiver, index, value));
@@ -2043,10 +2048,24 @@
/// Specialize calls to internal static methods.
specializeInternalMethodCall(InvokeStatic node) {
if (node.target == backend.helpers.stringInterpolationHelper) {
- AbstractConstantValue value = getValue(node.arguments[0].definition);
+ Primitive argument = node.arguments[0].definition;
+ AbstractConstantValue value = getValue(argument);
if (lattice.isDefinitelyString(value)) {
- node.replaceUsesWith(node.arguments[0].definition);
+ node.replaceUsesWith(argument);
return new CpsFragment();
+ } else if (typeSystem.isDefinitelySelfInterceptor(value.type)) {
+ TypeMask toStringReturn = typeSystem.getInvokeReturnType(
+ Selectors.toString_, value.type);
+ if (typeSystem.isDefinitelyString(toStringReturn)) {
+ CpsFragment cps = new CpsFragment(node.sourceInformation);
+ Primitive invoke = cps.invokeMethod(argument,
+ Selectors.toString_,
+ value.type,
+ [cps.makeZero()],
+ CallingConvention.DummyIntercepted);
+ node.replaceUsesWith(invoke);
+ return cps;
+ }
}
} else if (node.target == compiler.identicalFunction) {
if (node.arguments.length == 2) {
@@ -2245,7 +2264,7 @@
return unaryBuiltinOperator(BuiltinOperator.IsNumber);
}
return new ApplyBuiltinOperator(
- BuiltinOperator.IsNumberAndFloor,
+ BuiltinOperator.IsInteger,
<Primitive>[prim, prim, prim],
node.sourceInformation);
}
@@ -2321,7 +2340,8 @@
// The [BoundsChecker] pass does not try to eliminate checks that could be
// eliminated by constant folding.
if (node.hasNoChecks) return;
- int index = lattice.intValue(getValue(node.index.definition));
+ Primitive indexPrim = node.index.definition;
+ int index = lattice.intValue(getValue(indexPrim));
int length = node.length == null
? null
: lattice.intValue(getValue(node.length.definition));
@@ -2334,6 +2354,9 @@
if (length != null && length > 0) {
node.checks &= ~BoundsCheck.EMPTINESS;
}
+ if (typeSystem.isDefinitelyInt(indexPrim.type)) {
+ node.checks &= ~BoundsCheck.INTEGER;
+ }
if (!node.lengthUsedInCheck && node.length != null) {
node..length.unlink()..length = null;
}
@@ -2888,8 +2911,11 @@
case BuiltinOperator.IsFalsy:
case BuiltinOperator.IsNumber:
case BuiltinOperator.IsNotNumber:
+ case BuiltinOperator.IsNotInteger:
case BuiltinOperator.IsFloor:
- case BuiltinOperator.IsNumberAndFloor:
+ case BuiltinOperator.IsInteger:
+ case BuiltinOperator.IsUnsigned32BitInteger:
+ case BuiltinOperator.IsNotUnsigned32BitInteger:
setValue(node, nonConstant(typeSystem.boolType));
break;
diff --git a/pkg/compiler/lib/src/cps_ir/update_refinements.dart b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
index 3500521..5ce47a2 100644
--- a/pkg/compiler/lib/src/cps_ir/update_refinements.dart
+++ b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
@@ -73,6 +73,14 @@
});
}
+ visitBoundsCheck(BoundsCheck node) {
+ super.visitBoundsCheck(node);
+ if (node.hasIntegerCheck &&
+ typeSystem.isDefinitelyInt(node.index.definition.type)) {
+ node.checks &= ~BoundsCheck.INTEGER;
+ }
+ }
+
processReference(Reference ref) {
refine(ref);
}
diff --git a/pkg/compiler/lib/src/diagnostics/source_span.dart b/pkg/compiler/lib/src/diagnostics/source_span.dart
index 95c3c75..25bdc6c 100644
--- a/pkg/compiler/lib/src/diagnostics/source_span.dart
+++ b/pkg/compiler/lib/src/diagnostics/source_span.dart
@@ -20,7 +20,7 @@
factory SourceSpan.fromNode(Uri uri, Node node) {
return new SourceSpan.fromTokens(
- uri, node.getBeginToken(), node.getEndToken());
+ uri, node.getBeginToken(), node.getPrefixEndToken());
}
factory SourceSpan.fromTokens(Uri uri, Token begin, Token end) {
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 3f0d70c..121a882 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -2115,14 +2115,7 @@
if (span != null && hasNode) {
FunctionExpression functionExpression = node.asFunctionExpression();
if (functionExpression != null) {
- Token begin = functionExpression.getBeginToken();
- Token end;
- if (functionExpression.parameters != null) {
- end = functionExpression.parameters.getEndToken();
- } else {
- end = functionExpression.name.getEndToken();
- }
- span = new SourceSpan.fromTokens(span.uri, begin, end);
+ span = new SourceSpan.fromNode(span.uri, functionExpression);
}
}
return span;
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index faa4de3..14d1f6e 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -2577,6 +2577,7 @@
@override
bool enableCodegenWithErrorsIfSupported(Spannable node) {
if (compiler.useCpsIr) {
+ // TODO(25747): Support code generation with compile-time errors.
reporter.reportHintMessage(
node,
MessageKind.GENERIC,
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index eb1e699..1d2549d 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -1123,8 +1123,14 @@
return js.js('typeof # !== "number"', args);
case BuiltinOperator.IsFloor:
return js.js('Math.floor(#) === #', args);
- case BuiltinOperator.IsNumberAndFloor:
+ case BuiltinOperator.IsInteger:
return js.js('typeof # === "number" && Math.floor(#) === #', args);
+ case BuiltinOperator.IsNotInteger:
+ return js.js('typeof # !== "number" || Math.floor(#) !== #', args);
+ case BuiltinOperator.IsUnsigned32BitInteger:
+ return js.js('# >>> 0 === #', args);
+ case BuiltinOperator.IsNotUnsigned32BitInteger:
+ return js.js('# >>> 0 !== #', args);
case BuiltinOperator.IsFixedLengthJSArray:
// TODO(sra): Remove boolify (i.e. !!).
return js.js(r'!!#.fixed$length', args);
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index d06a002..85fd583 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -7535,7 +7535,10 @@
TypeMask mask = elements.getIteratorTypeMask(node);
ClassWorld classWorld = compiler.world;
- if (mask != null && mask.satisfies(helpers.jsIndexableClass, classWorld)) {
+ if (mask != null &&
+ mask.satisfies(helpers.jsIndexableClass, classWorld) &&
+ // String is indexable but not iterable.
+ !mask.satisfies(helpers.jsStringClass, classWorld)) {
return buildSyncForInIndexable(node, mask);
}
buildSyncForInIterator(node);
diff --git a/pkg/compiler/lib/src/tree/nodes.dart b/pkg/compiler/lib/src/tree/nodes.dart
index 04d46f5..e95497b 100644
--- a/pkg/compiler/lib/src/tree/nodes.dart
+++ b/pkg/compiler/lib/src/tree/nodes.dart
@@ -147,6 +147,12 @@
Token getBeginToken();
+ /// Returns the token that ends the 'prefix' of this node.
+ ///
+ /// For instance the end of the parameters in a [FunctionExpression] or the
+ /// last token before the start of a class body for a [ClassNode].
+ Token getPrefixEndToken() => getEndToken();
+
Token getEndToken();
Assert asAssert() => null;
@@ -263,6 +269,25 @@
Token getBeginToken() => beginToken;
+ @override
+ Token getPrefixEndToken() {
+ Token token;
+ if (interfaces != null) {
+ token = interfaces.getEndToken();
+ }
+ if (token == null && superclass != null) {
+ token = superclass.getEndToken();
+ }
+ if (token == null && typeParameters != null) {
+ token == typeParameters.getEndToken();
+ }
+ if (token == null) {
+ token = name.getEndToken();
+ }
+ assert(invariant(beginToken, token != null));
+ return token;
+ }
+
Token getEndToken() => endToken;
}
@@ -738,6 +763,10 @@
visitChildren(Visitor visitor) => function.accept(visitor);
Token getBeginToken() => function.getBeginToken();
+
+ @override
+ Token getPrefixEndToken() => function.getPrefixEndToken();
+
Token getEndToken() => function.getEndToken();
}
@@ -826,6 +855,11 @@
return firstBeginToken(name, parameters);
}
+ @override
+ Token getPrefixEndToken() {
+ return parameters != null ? parameters.getEndToken() : name.getEndToken();
+ }
+
Token getEndToken() {
Token token = (body == null) ? null : body.getEndToken();
token = (token == null) ? parameters.getEndToken() : token;
@@ -1300,7 +1334,10 @@
Token getBeginToken() => typeName.getBeginToken();
- Token getEndToken() => typeName.getEndToken();
+ Token getEndToken() {
+ if (typeArguments != null) return typeArguments.getEndToken();
+ return typeName.getEndToken();
+ }
}
class TypeVariable extends Node {
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
index b4f6dd8..dd44f1d 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
@@ -353,7 +353,8 @@
case BuiltinOperator.IsNumber:
case BuiltinOperator.IsNotNumber:
case BuiltinOperator.IsFloor:
- case BuiltinOperator.IsNumberAndFloor:
+ case BuiltinOperator.IsInteger:
+ case BuiltinOperator.IsNotInteger:
case BuiltinOperator.Identical:
return true;
default:
@@ -373,6 +374,12 @@
case BuiltinOperator.LooseNeq: return BuiltinOperator.LooseEq;
case BuiltinOperator.IsNumber: return BuiltinOperator.IsNotNumber;
case BuiltinOperator.IsNotNumber: return BuiltinOperator.IsNumber;
+ case BuiltinOperator.IsInteger: return BuiltinOperator.IsNotInteger;
+ case BuiltinOperator.IsNotInteger: return BuiltinOperator.IsInteger;
+ case BuiltinOperator.IsUnsigned32BitInteger:
+ return BuiltinOperator.IsNotUnsigned32BitInteger;
+ case BuiltinOperator.IsNotUnsigned32BitInteger:
+ return BuiltinOperator.IsUnsigned32BitInteger;
// Because of NaN, these do not have a negated form.
case BuiltinOperator.NumLt:
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
index 3785f78..8840c8e 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
@@ -265,6 +265,12 @@
return node;
}
+ Expression visitAwait(Await node) {
+ super.visitAwait(node);
+ ++impureCounter;
+ return node;
+ }
+
Expression visitConditional(Conditional node) {
node.condition = visitExpression(node.condition);
// Visit the branches to detect impure subexpressions, but do not pull
diff --git a/pkg/compiler/lib/src/types/abstract_value_domain.dart b/pkg/compiler/lib/src/types/abstract_value_domain.dart
index 3bf01da..73e8ae4 100644
--- a/pkg/compiler/lib/src/types/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/types/abstract_value_domain.dart
@@ -136,6 +136,8 @@
bool isDefinitelyIntercepted(AbstractValue t, {bool allowNull});
+ bool isDefinitelySelfInterceptor(AbstractValue t, {bool allowNull: false});
+
/// Given a class from the interceptor hierarchy, returns an [AbstractValue]
/// matching all values with that interceptor (or a subtype thereof).
AbstractValue getInterceptorSubtypes(ClassElement class_);
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 94de113..6932f93 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -50,6 +50,10 @@
defines += ["NDEBUG"]
}
+ if (is_ios || is_mac) {
+ defines += ["DART_PRECOMPILER"]
+ }
+
cflags = [
"-Werror",
"-Wall",
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index adf0aa4..197eb32 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -76,17 +76,18 @@
}
-iolib_sources_gypi =
+sdk_io_sources_gypi =
exec_script("../../tools/gypi_to_gn.py",
- [rebase_path("../../sdk/lib/io/iolib_sources.gypi")],
+ [rebase_path("../../sdk/lib/io/io_sources.gypi")],
"scope",
- ["../../sdk/lib/io/iolib_sources.gypi"])
-iolib_sources = rebase_path(iolib_sources_gypi.sources, ".", "../../sdk/lib/io")
+ ["../../sdk/lib/io/io_sources.gypi"])
+sdk_io_sources =
+ rebase_path(sdk_io_sources_gypi.sources, ".", "../../sdk/lib/io")
gen_library_src_path("generate_io_cc_file") {
name = "io"
kind = "source"
- sources = ["../../sdk/lib/io/io.dart"] + iolib_sources
+ sources = ["../../sdk/lib/io/io.dart"] + sdk_io_sources
output = "$target_gen_dir/io_gen.cc"
}
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index f271fbd..cb4b63e 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -62,7 +62,7 @@
'../../sdk/lib/io/io.dart',
],
'includes': [
- '../../sdk/lib/io/iolib_sources.gypi',
+ '../../sdk/lib/io/io_sources.gypi',
],
'actions': [
{
@@ -545,6 +545,9 @@
{
'target_name': 'generate_bootstrap_resources_cc_file',
'type': 'none',
+ 'dependencies': [
+ 'bin/zlib.gyp:zlib_dart',
+ ],
'toolsets':['host'],
'includes': [
'vmservice/vmservice_sources.gypi',
@@ -575,6 +578,40 @@
]
},
{
+ # dart_product binary.
+ 'target_name': 'dart_product',
+ 'type': 'executable',
+ 'dependencies': [
+ 'libdart',
+ 'libdart_builtin',
+ 'libdart_io',
+ ],
+ 'include_dirs': [
+ '..',
+ '../../third_party/', # Zlib
+ ],
+ 'defines': [
+ 'DART_PRODUCT_BINARY',
+ ],
+ 'sources': [
+ 'main.cc',
+ 'builtin_common.cc',
+ 'builtin_natives.cc',
+ 'builtin_nolib.cc',
+ 'builtin.h',
+ 'io_natives.h',
+ 'snapshot_empty.cc',
+ 'observatory_assets_empty.cc',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'link_settings': {
+ 'libraries': [ '-lws2_32.lib', '-lRpcrt4.lib', '-lwinmm.lib' ],
+ },
+ }],
+ ],
+ },
+ {
# dart binary with a snapshot of corelibs built in.
'target_name': 'dart',
'type': 'executable',
diff --git a/runtime/bin/extensions_android.cc b/runtime/bin/extensions_android.cc
index 0c79bff..e33c195 100644
--- a/runtime/bin/extensions_android.cc
+++ b/runtime/bin/extensions_android.cc
@@ -13,7 +13,8 @@
namespace bin {
const char* kPrecompiledLibraryName = "libprecompiled.so";
-const char* kPrecompiledSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledInstructionsSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledDataSymbolName = "_kDataSnapshot";
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return dlopen(library_file, RTLD_LAZY);
diff --git a/runtime/bin/extensions_linux.cc b/runtime/bin/extensions_linux.cc
index e172f0d..54a88a4 100644
--- a/runtime/bin/extensions_linux.cc
+++ b/runtime/bin/extensions_linux.cc
@@ -13,7 +13,8 @@
namespace bin {
const char* kPrecompiledLibraryName = "libprecompiled.so";
-const char* kPrecompiledSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledInstructionsSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledDataSymbolName = "_kDataSnapshot";
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return dlopen(library_file, RTLD_LAZY);
diff --git a/runtime/bin/extensions_macos.cc b/runtime/bin/extensions_macos.cc
index e248a47..0edb6b5 100644
--- a/runtime/bin/extensions_macos.cc
+++ b/runtime/bin/extensions_macos.cc
@@ -13,7 +13,8 @@
namespace bin {
const char* kPrecompiledLibraryName = "libprecompiled.dylib";
-const char* kPrecompiledSymbolName = "kInstructionsSnapshot";
+const char* kPrecompiledInstructionsSymbolName = "kInstructionsSnapshot";
+const char* kPrecompiledDataSymbolName = "kDataSnapshot";
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return dlopen(library_file, RTLD_LAZY);
diff --git a/runtime/bin/extensions_win.cc b/runtime/bin/extensions_win.cc
index d3b49f2..224bcdf 100644
--- a/runtime/bin/extensions_win.cc
+++ b/runtime/bin/extensions_win.cc
@@ -14,7 +14,8 @@
namespace bin {
const char* kPrecompiledLibraryName = "precompiled.dll";
-const char* kPrecompiledSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledInstructionsSymbolName = "_kInstructionsSnapshot";
+const char* kPrecompiledDataSymbolName = "_kDataSnapshot";
void* Extensions::LoadExtensionLibrary(const char* library_file) {
SetLastError(0);
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index d783c85..f1f7e2c 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -435,7 +435,11 @@
if (Dart_IsError(source)) {
return source;
}
- return Dart_LoadLibrary(resolved_script_uri, source, 0, 0);
+ if (IsSnapshottingForPrecompilation()) {
+ return Dart_LoadScript(resolved_script_uri, source, 0, 0);
+ } else {
+ return Dart_LoadLibrary(resolved_script_uri, source, 0, 0);
+ }
}
@@ -1028,6 +1032,7 @@
char* error = Dart_Initialize(
NULL,
NULL,
+ NULL,
CreateServiceIsolate,
NULL,
NULL,
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 6be11f0..e5e60dc 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -99,7 +99,8 @@
extern const char* kPrecompiledLibraryName;
-extern const char* kPrecompiledSymbolName;
+extern const char* kPrecompiledInstructionsSymbolName;
+extern const char* kPrecompiledDataSymbolName;
static const char* kPrecompiledVmIsolateName = "precompiled.vmisolate";
static const char* kPrecompiledIsolateName = "precompiled.isolate";
static const char* kPrecompiledInstructionsName = "precompiled.S";
@@ -407,12 +408,10 @@
static bool ProcessRunFullSnapshotOption(
const char* filename, CommandLineOptions* vm_options) {
- // Ensure that we are not running 'dart_no_snapshot'.
- if (isolate_snapshot_buffer == NULL) {
- Log::PrintErr("Full Application snapshots cannot be run with"
- " dart_no_snapshot\n");
- return false;
- }
+#ifndef DART_PRODUCT_BINARY
+ Log::PrintErr("Full Application snapshots can only be be run with"
+ " dart_product\n");
+#endif
return ProcessSnapshotOptionHelper(filename, &run_full_snapshot);
}
@@ -742,8 +741,15 @@
char** error,
int* exit_code) {
ASSERT(script_uri != NULL);
+#if defined(DART_PRODUCT_BINARY)
+ if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
+ // No service isolate support.
+ return NULL;
+ }
+#endif // defined(DART_PRODUCT_BINARY)
+
if (run_full_snapshot &&
- !strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME)) {
+ (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0)) {
// We do not create a service isolate when running a full application
// snapshot.
return NULL;
@@ -777,6 +783,9 @@
Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler);
CHECK_RESULT(result);
+#if defined(DART_PRODUCT_BINARY)
+ ASSERT(!Dart_IsServiceIsolate(isolate));
+#else
if (Dart_IsServiceIsolate(isolate)) {
// If this is the service isolate, load embedder specific bits and return.
if (!VmService::Setup(vm_service_server_ip,
@@ -793,6 +802,7 @@
Dart_ExitIsolate();
return isolate;
}
+#endif // defined(DART_PRODUCT_BINARY)
// Prepare builtin and other core libraries for use to resolve URIs.
// Set up various closures, e.g: printing, timers etc.
@@ -1109,15 +1119,19 @@
void* file = DartUtils::OpenFile(qualified_filename, false);
if (file == NULL) {
- ErrorExit(kErrorExitCode,
- "Error: Unable to open file %s for reading snapshot\n",
- qualified_filename);
+ fprintf(stderr,
+ "Error: Unable to open file %s for reading snapshot\n",
+ qualified_filename);
+ fflush(stderr);
+ Platform::Exit(kErrorExitCode);
}
intptr_t len = -1;
DartUtils::ReadFile(buffer, &len, file);
if (*buffer == NULL || len == -1) {
- ErrorExit(kErrorExitCode,
- "Error: Unable to read snapshot file %s\n", qualified_filename);
+ fprintf(stderr,
+ "Error: Unable to read snapshot file %s\n", qualified_filename);
+ fflush(stderr);
+ Platform::Exit(kErrorExitCode);
}
DartUtils::CloseFile(file);
if (concat != NULL) {
@@ -1268,6 +1282,7 @@
reinterpret_cast<IsolateData*>(Dart_IsolateData(isolate));
result = Dart_LibraryImportLibrary(
isolate_data->builtin_lib(), root_lib, Dart_Null());
+#ifndef DART_PRODUCT_BINARY
if (is_noopt || gen_precompiled_snapshot) {
// Load the embedder's portion of the VM service's Dart code so it will
// be included in the precompiled snapshot.
@@ -1279,6 +1294,7 @@
exit(kErrorExitCode);
}
}
+#endif // !DART_PRODUCT_BINARY
if (compile_all) {
result = Dart_CompileAll();
@@ -1382,12 +1398,14 @@
// Keep handling messages until the last active receive port is closed.
result = Dart_RunLoop();
- CHECK_RESULT(result);
-
// Generate a full snapshot after execution if specified.
if (generate_full_snapshot_after_run) {
- GenerateFullSnapshot();
+ if (!Dart_IsCompilationError(result) &&
+ !Dart_IsVMRestartRequest(result)) {
+ GenerateFullSnapshot();
+ }
}
+ CHECK_RESULT(result);
}
}
@@ -1536,7 +1554,9 @@
Platform::Exit(kErrorExitCode);
}
- if (generate_script_snapshot || generate_full_snapshot_after_run) {
+ if (generate_script_snapshot ||
+ generate_full_snapshot_after_run ||
+ run_full_snapshot) {
vm_options.AddArgument("--load_deferred_eagerly");
}
@@ -1553,15 +1573,21 @@
EventHandler::Start();
const uint8_t* instructions_snapshot = NULL;
+ const uint8_t* data_snapshot = NULL;
if (run_precompiled_snapshot) {
instructions_snapshot = reinterpret_cast<const uint8_t*>(
- LoadLibrarySymbol(kPrecompiledLibraryName, kPrecompiledSymbolName));
+ LoadLibrarySymbol(kPrecompiledLibraryName,
+ kPrecompiledInstructionsSymbolName));
+ data_snapshot = reinterpret_cast<const uint8_t*>(
+ LoadLibrarySymbol(kPrecompiledLibraryName,
+ kPrecompiledDataSymbolName));
ReadSnapshotFile(precompiled_snapshot_directory,
kPrecompiledVmIsolateName,
&vm_isolate_snapshot_buffer);
ReadSnapshotFile(precompiled_snapshot_directory,
kPrecompiledIsolateName,
&isolate_snapshot_buffer);
+
} else if (run_full_snapshot) {
char* vm_snapshot_fname;
char* isolate_snapshot_fname;
@@ -1579,7 +1605,7 @@
// Initialize the Dart VM.
char* error = Dart_Initialize(
- vm_isolate_snapshot_buffer, instructions_snapshot,
+ vm_isolate_snapshot_buffer, instructions_snapshot, data_snapshot,
CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
DartUtils::OpenFile,
DartUtils::ReadFile,
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 1917b46..60fb2b5 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -188,9 +188,9 @@
bool runInShell,
ProcessStartMode mode) : super() {
if (!connectedResourceHandler) {
- registerExtension('__getProcesses',
+ registerExtension('ext.dart.io.getProcesses',
_ProcessResourceInfo.getStartedProcesses);
- registerExtension('__getProcessById',
+ registerExtension('ext.dart.io.getProcessById',
_ProcessResourceInfo.getProcessInfoMapById);
connectedResourceHandler = true;
}
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index bfb597b..ec9479a 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -106,7 +106,7 @@
dart_argv);
ASSERT(set_vm_flags_success);
const char* err_msg = Dart::InitOnce(dart::bin::vm_isolate_snapshot_buffer,
- NULL,
+ NULL, NULL,
NULL, NULL,
dart::bin::DartUtils::OpenFile,
dart::bin::DartUtils::ReadFile,
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
index fa1f7f1..d7735af 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket.cc
@@ -12,6 +12,7 @@
#include <openssl/bio.h>
#include <openssl/err.h>
+#include <openssl/pkcs12.h>
#include <openssl/safestack.h>
#include <openssl/ssl.h>
#include <openssl/tls1.h>
@@ -381,11 +382,11 @@
// BIO is allocated. Leaving the scope cleans up the BIO and the buffer that
// was used to create it.
//
-// Do not make Dart_ API calls while in a MemBIOScope.
-// Do not call Dart_PropagateError while in a MemBIOScope.
-class MemBIOScope {
+// Do not make Dart_ API calls while in a ScopedMemBIO.
+// Do not call Dart_PropagateError while in a ScopedMemBIO.
+class ScopedMemBIO {
public:
- explicit MemBIOScope(Dart_Handle object) {
+ explicit ScopedMemBIO(Dart_Handle object) {
if (!Dart_IsTypedData(object) && !Dart_IsList(object)) {
Dart_ThrowException(DartUtils::NewDartArgumentError(
"Argument is not a List<int>"));
@@ -418,7 +419,7 @@
is_typed_data_ = is_typed_data;
}
- ~MemBIOScope() {
+ ~ScopedMemBIO() {
ASSERT(bio_ != NULL);
if (is_typed_data_) {
BIO_free(bio_);
@@ -441,10 +442,120 @@
bool is_typed_data_;
DISALLOW_ALLOCATION();
- DISALLOW_COPY_AND_ASSIGN(MemBIOScope);
+ DISALLOW_COPY_AND_ASSIGN(ScopedMemBIO);
};
+template<typename T, void (*free_func)(T*)>
+class ScopedSSLType {
+ public:
+ explicit ScopedSSLType(T* obj) : obj_(obj) {}
+
+ ~ScopedSSLType() {
+ if (obj_ != NULL) {
+ free_func(obj_);
+ }
+ }
+
+ T* get() { return obj_; }
+ const T* get() const { return obj_; }
+
+ T* release() {
+ T* result = obj_;
+ obj_ = NULL;
+ return result;
+ }
+
+ private:
+ T* obj_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_COPY_AND_ASSIGN(ScopedSSLType);
+};
+
+template<typename T, typename E, void (*func)(E*)>
+class ScopedSSLStackType {
+ public:
+ explicit ScopedSSLStackType(T* obj) : obj_(obj) {}
+
+ ~ScopedSSLStackType() {
+ if (obj_ != NULL) {
+ sk_pop_free(reinterpret_cast<_STACK*>(obj_),
+ reinterpret_cast<void (*)(void *)>(func));
+ }
+ }
+
+ T* get() { return obj_; }
+ const T* get() const { return obj_; }
+
+ T* release() {
+ T* result = obj_;
+ obj_ = NULL;
+ return result;
+ }
+
+ private:
+ T* obj_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_COPY_AND_ASSIGN(ScopedSSLStackType);
+};
+
+typedef ScopedSSLType<PKCS12, PKCS12_free> ScopedPKCS12;
+typedef ScopedSSLType<X509, X509_free> ScopedX509;
+
+typedef ScopedSSLStackType<STACK_OF(X509), X509, X509_free> ScopedX509Stack;
+typedef ScopedSSLStackType<STACK_OF(X509_NAME), X509_NAME, X509_NAME_free>
+ ScopedX509NAMEStack;
+
+
+// We try reading data as PKCS12 only if reading as PEM was unsuccessful and
+// if there is no indication that the data is malformed PEM. We assume the data
+// is malformed PEM if it contains the start line, i.e. a line with ----- BEGIN.
+static bool TryPKCS12(bool pem_success) {
+ uint32_t last_error = ERR_peek_last_error();
+ return !pem_success &&
+ (ERR_GET_LIB(last_error) == ERR_LIB_PEM) &&
+ (ERR_GET_REASON(last_error) == PEM_R_NO_START_LINE);
+}
+
+
+static EVP_PKEY* GetPrivateKeyPKCS12(BIO* bio, const char* password) {
+ ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+ if (p12.get() == NULL) {
+ return NULL;
+ }
+
+ EVP_PKEY* key = NULL;
+ X509 *cert = NULL;
+ STACK_OF(X509) *ca_certs = NULL;
+ int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
+ if (status == 0) {
+ return NULL;
+ }
+
+ // We only care about the private key.
+ ScopedX509 delete_cert(cert);
+ ScopedX509Stack delete_ca_certs(ca_certs);
+ return key;
+}
+
+
+static EVP_PKEY* GetPrivateKey(BIO* bio, const char* password) {
+ EVP_PKEY *key = PEM_read_bio_PrivateKey(
+ bio, NULL, PasswordCallback, const_cast<char*>(password));
+ if (TryPKCS12(key != NULL)) {
+ // Reset the bio, and clear the error from trying to read as PEM.
+ ERR_clear_error();
+ BIO_reset(bio);
+
+ // Try to decode as PKCS12
+ key = GetPrivateKeyPKCS12(bio, password);
+ }
+ return key;
+}
+
+
void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
Dart_NativeArguments args) {
SSL_CTX* context = GetSecurityContext(args);
@@ -467,9 +578,8 @@
int status;
{
- MemBIOScope bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
- EVP_PKEY *key = PEM_read_bio_PrivateKey(
- bio.bio(), NULL, PasswordCallback, const_cast<char*>(password));
+ ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+ EVP_PKEY *key = GetPrivateKey(bio.bio(), password);
status = SSL_CTX_use_PrivateKey(context, key);
}
@@ -480,7 +590,52 @@
}
-static int SetTrustedCertificatesBytes(SSL_CTX* context, BIO* bio) {
+static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, BIO* bio) {
+ ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+ if (p12.get() == NULL) {
+ return NULL;
+ }
+
+ EVP_PKEY* key = NULL;
+ X509 *cert = NULL;
+ STACK_OF(X509) *ca_certs = NULL;
+ // There should be no private keys in this file, so we hardcode the password
+ // to "".
+ // TODO(zra): Allow passing a password anyway.
+ int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs);
+ if (status == 0) {
+ return status;
+ }
+
+ ScopedX509Stack cert_stack(ca_certs);
+
+ // There should be no private key.
+ if (key != NULL) {
+ X509_free(cert);
+ return 0;
+ }
+
+ X509_STORE* store = SSL_CTX_get_cert_store(context);
+ status = X509_STORE_add_cert(store, cert);
+ if (status == 0) {
+ X509_free(cert);
+ return status;
+ }
+
+ X509* ca;
+ while ((ca = sk_X509_shift(cert_stack.get())) != NULL) {
+ status = X509_STORE_add_cert(store, ca);
+ if (status == 0) {
+ X509_free(ca);
+ return status;
+ }
+ }
+
+ return status;
+}
+
+
+static int SetTrustedCertificatesBytesPEM(SSL_CTX* context, BIO* bio) {
X509_STORE* store = SSL_CTX_get_cert_store(context);
int status = 0;
@@ -493,13 +648,13 @@
}
}
+ // If bio does not contain PEM data, the first call to PEM_read_bio_X509 will
+ // return NULL, and the while-loop will exit while status is still 0.
uint32_t err = ERR_peek_last_error();
- if ((ERR_GET_LIB(err) == ERR_LIB_PEM) &&
- (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
- // Reached the end of the buffer.
- ERR_clear_error();
- } else {
- // Some real error happened.
+ if ((ERR_GET_LIB(err) != ERR_LIB_PEM) ||
+ (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) {
+ // If bio contains data that is trying to be PEM but is malformed, then
+ // this case will be triggered.
status = 0;
}
@@ -507,12 +662,26 @@
}
+static int SetTrustedCertificatesBytes(SSL_CTX* context, BIO* bio) {
+ int status = SetTrustedCertificatesBytesPEM(context, bio);
+ if (TryPKCS12(status != 0)) {
+ ERR_clear_error();
+ BIO_reset(bio);
+ status = SetTrustedCertificatesBytesPKCS12(context, bio);
+ } else if (status != 0) {
+ // The PEM file was successfully parsed.
+ ERR_clear_error();
+ }
+ return status;
+}
+
+
void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
Dart_NativeArguments args) {
SSL_CTX* context = GetSecurityContext(args);
int status;
{
- MemBIOScope bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+ ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
status = SetTrustedCertificatesBytes(context, bio.bio());
}
CheckStatus(status,
@@ -539,34 +708,78 @@
}
-static int UseChainBytes(SSL_CTX* context, BIO* bio) {
- int status = 0;
- X509* x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
- if (x509 == NULL) {
+static int UseChainBytesPKCS12(SSL_CTX* context, BIO* bio) {
+ ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+ if (p12.get() == NULL) {
+ return NULL;
+ }
+
+ EVP_PKEY* key = NULL;
+ X509 *cert = NULL;
+ STACK_OF(X509) *ca_certs = NULL;
+ // There should be no private keys in this file, so we hardcode the password
+ // to "".
+ // TODO(zra): Allow passing a password anyway.
+ int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs);
+ if (status == 0) {
+ return status;
+ }
+
+ ScopedX509 x509(cert);
+ ScopedX509Stack certs(ca_certs);
+
+ // There should be no private key.
+ if (key != NULL) {
return 0;
}
- status = SSL_CTX_use_certificate(context, x509);
+ status = SSL_CTX_use_certificate(context, x509.get());
if (ERR_peek_error() != 0) {
// Key/certificate mismatch doesn't imply status is 0.
status = 0;
}
if (status == 0) {
- X509_free(x509);
return status;
}
SSL_CTX_clear_chain_certs(context);
- while (true) {
- X509* ca = PEM_read_bio_X509(bio, NULL, NULL, NULL);
- if (ca == NULL) {
- break;
- }
+ X509* ca;
+ while ((ca = sk_X509_shift(certs.get())) != NULL) {
status = SSL_CTX_add0_chain_cert(context, ca);
if (status == 0) {
X509_free(ca);
- X509_free(x509);
+ return status;
+ }
+ }
+
+ return status;
+}
+
+
+static int UseChainBytesPEM(SSL_CTX* context, BIO* bio) {
+ int status = 0;
+ ScopedX509 x509(PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL));
+ if (x509.get() == NULL) {
+ return 0;
+ }
+
+ status = SSL_CTX_use_certificate(context, x509.get());
+ if (ERR_peek_error() != 0) {
+ // Key/certificate mismatch doesn't imply status is 0.
+ status = 0;
+ }
+ if (status == 0) {
+ return status;
+ }
+
+ SSL_CTX_clear_chain_certs(context);
+
+ X509* ca;
+ while ((ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
+ status = SSL_CTX_add0_chain_cert(context, ca);
+ if (status == 0) {
+ X509_free(ca);
return status;
}
// Note that we must not free `ca` if it was successfully added to the
@@ -574,17 +787,30 @@
// count is increased by SSL_CTX_use_certificate.
}
+ // If bio does not contain PEM data, the first call to PEM_read_bio_X509 will
+ // return NULL, and the while-loop will exit while status is still 0.
uint32_t err = ERR_peek_last_error();
- if ((ERR_GET_LIB(err) == ERR_LIB_PEM) &&
- (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
- // Reached the end of the buffer.
- ERR_clear_error();
- } else {
- // Some real error happened.
+ if ((ERR_GET_LIB(err) != ERR_LIB_PEM) ||
+ (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) {
+ // If bio contains data that is trying to be PEM but is malformed, then
+ // this case will be triggered.
status = 0;
}
- X509_free(x509);
+ return status;
+}
+
+
+static int UseChainBytes(SSL_CTX* context, BIO* bio) {
+ int status = UseChainBytesPEM(context, bio);
+ if (TryPKCS12(status != 0)) {
+ ERR_clear_error();
+ BIO_reset(bio);
+ status = UseChainBytesPKCS12(context, bio);
+ } else if (status != 0) {
+ // The PEM file was successfully read.
+ ERR_clear_error();
+ }
return status;
}
@@ -594,7 +820,7 @@
SSL_CTX* context = GetSecurityContext(args);
int status;
{
- MemBIOScope bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+ ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
status = UseChainBytes(context, bio.bio());
}
CheckStatus(status,
@@ -603,36 +829,122 @@
}
-static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio) {
- STACK_OF(X509_NAME)* result = sk_X509_NAME_new_null();
- if (result == NULL) {
+static STACK_OF(X509_NAME)* GetCertificateNamesPKCS12(BIO* bio) {
+ ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+ if (p12.get() == NULL) {
+ return NULL;
+ }
+
+ ScopedX509NAMEStack result(sk_X509_NAME_new_null());
+ if (result.get() == NULL) {
+ return NULL;
+ }
+
+ EVP_PKEY* key = NULL;
+ X509 *cert = NULL;
+ STACK_OF(X509) *ca_certs = NULL;
+ // There should be no private keys in this file, so we hardcode the password
+ // to "".
+ // TODO(zra): Allow passing a password anyway.
+ int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs);
+ if (status == 0) {
+ return NULL;
+ }
+
+ ScopedX509 x509(cert);
+ ScopedX509Stack certs(ca_certs);
+
+ // There should be no private key.
+ if (key != NULL) {
+ return NULL;
+ }
+
+ X509_NAME* x509_name = X509_get_subject_name(x509.get());
+ if (x509_name == NULL) {
+ return NULL;
+ }
+
+ x509_name = X509_NAME_dup(x509_name);
+ if (x509_name == NULL) {
+ return NULL;
+ }
+
+ sk_X509_NAME_push(result.get(), x509_name);
+
+ while (true) {
+ ScopedX509 ca(sk_X509_shift(certs.get()));
+ if (ca.get() == NULL) {
+ break;
+ }
+
+ X509_NAME* x509_name = X509_get_subject_name(ca.get());
+ if (x509_name == NULL) {
+ return NULL;
+ }
+
+ x509_name = X509_NAME_dup(x509_name);
+ if (x509_name == NULL) {
+ return NULL;
+ }
+
+ sk_X509_NAME_push(result.get(), x509_name);
+ }
+
+ return result.release();
+}
+
+
+static STACK_OF(X509_NAME)* GetCertificateNamesPEM(BIO* bio) {
+ ScopedX509NAMEStack result(sk_X509_NAME_new_null());
+ if (result.get() == NULL) {
return NULL;
}
while (true) {
- X509* x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
- if (x509 == NULL) {
+ ScopedX509 x509(PEM_read_bio_X509(bio, NULL, NULL, NULL));
+ if (x509.get() == NULL) {
break;
}
- X509_NAME* x509_name = X509_get_subject_name(x509);
+ X509_NAME* x509_name = X509_get_subject_name(x509.get());
if (x509_name == NULL) {
- sk_X509_NAME_pop_free(result, X509_NAME_free);
- X509_free(x509);
return NULL;
}
// Duplicate the name to put it on the stack.
x509_name = X509_NAME_dup(x509_name);
if (x509_name == NULL) {
- sk_X509_NAME_pop_free(result, X509_NAME_free);
- X509_free(x509);
return NULL;
}
- sk_X509_NAME_push(result, x509_name);
- X509_free(x509);
+ sk_X509_NAME_push(result.get(), x509_name);
}
+ if (sk_X509_NAME_num(result.get()) == 0) {
+ // The data was not PEM.
+ return NULL;
+ }
+
+ uint32_t err = ERR_peek_last_error();
+ if ((ERR_GET_LIB(err) != ERR_LIB_PEM) ||
+ (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) {
+ // The data was trying to be PEM, but was malformed.
+ return NULL;
+ }
+
+ return result.release();
+}
+
+
+static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio) {
+ STACK_OF(X509_NAME)* result = GetCertificateNamesPEM(bio);
+ if (TryPKCS12(result != NULL)) {
+ ERR_clear_error();
+ BIO_reset(bio);
+ result = GetCertificateNamesPKCS12(bio);
+ } else if (result != NULL) {
+ // The PEM file was successfully parsed.
+ ERR_clear_error();
+ }
return result;
}
@@ -643,7 +955,7 @@
STACK_OF(X509_NAME)* certificate_names;
{
- MemBIOScope bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+ ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
certificate_names = GetCertificateNames(bio.bio());
}
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index 29adef4..bd5eda3 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -116,7 +116,6 @@
bool in_handshake_;
bool is_server_;
char* hostname_;
- X509_VERIFY_PARAM* certificate_checking_parameters_;
static bool isBufferEncrypted(int i) {
return static_cast<BufferIndex>(i) >= kFirstEncrypted;
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 7de16a9..09904b4 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -932,9 +932,9 @@
eventPort = new RawReceivePort(multiplex);
}
if (!connectedResourceHandler) {
- registerExtension('__getOpenSockets',
+ registerExtension('ext.dart.io.getOpenSockets',
_SocketResourceInfo.getOpenSockets);
- registerExtension('__getSocketByID',
+ registerExtension('ext.dart.io.getSocketByID',
_SocketResourceInfo.getSocketInfoMapByID);
connectedResourceHandler = true;
diff --git a/runtime/bin/zlib.gyp b/runtime/bin/zlib.gyp
index 6f2f913..98555f9f 100644
--- a/runtime/bin/zlib.gyp
+++ b/runtime/bin/zlib.gyp
@@ -20,7 +20,6 @@
'zlib_path': '../../third_party/zlib',
},
# Added by Dart. We do not indent, so diffs with the original are clearer.
- 'conditions': [[ 'dart_io_support==1', {
'targets': [
{
'target_name': 'zlib_dart', # Added by Dart (the _dart postfix)
@@ -72,5 +71,4 @@
],
},
],
- }]],
}
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index abc92eb..77d1289 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -797,6 +797,7 @@
DART_EXPORT char* Dart_Initialize(
const uint8_t* vm_isolate_snapshot,
const uint8_t* instructions_snapshot,
+ const uint8_t* data_snapshot,
Dart_IsolateCreateCallback create,
Dart_IsolateInterruptCallback interrupt,
Dart_IsolateUnhandledExceptionCallback unhandled_exception,
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index 224d532..11e307a 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -40,9 +40,13 @@
class _SyncIterator implements Iterator {
bool isYieldEach; // Set by generated code for the yield* statement.
Iterator yieldEachIterator;
- var current; // Set by generated code for the yield and yield* statement.
+ var _current; // Set by generated code for the yield and yield* statement.
SyncGeneratorCallback moveNextFn;
+ get current => yieldEachIterator != null
+ ? yieldEachIterator.current
+ : _current;
+
_SyncIterator(this.moveNextFn);
bool moveNext() {
@@ -52,7 +56,6 @@
while(true) {
if (yieldEachIterator != null) {
if (yieldEachIterator.moveNext()) {
- current = yieldEachIterator.current;
return true;
}
yieldEachIterator = null;
@@ -60,13 +63,14 @@
isYieldEach = false;
if (!moveNextFn(this)) {
moveNextFn = null;
- current = null;
+ _current = null;
return false;
}
if (isYieldEach) {
// Spec mandates: it is a dynamic error if the class of [the object
// returned by yield*] does not implement Iterable.
- yieldEachIterator = (current as Iterable).iterator;
+ yieldEachIterator = (_current as Iterable).iterator;
+ _current = null;
continue;
}
return true;
diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart
index af505ff..f7b45f0 100644
--- a/runtime/lib/developer.dart
+++ b/runtime/lib/developer.dart
@@ -67,7 +67,8 @@
List<String> parameterKeys,
List<String> parameterValues,
SendPort replyPort,
- Object id) {
+ Object id,
+ bool trace_service) {
var parameters = {};
for (var i = 0; i < parameterKeys.length; i++) {
parameters[parameterKeys[i]] = parameterValues[i];
@@ -80,14 +81,14 @@
response = new ServiceExtensionResponse.error(
ServiceExtensionResponse.kExtensionError,
errorDetails);
- _postResponse(replyPort, id, response);
+ _postResponse(replyPort, id, response, trace_service);
return;
}
if (response is! Future) {
response = new ServiceExtensionResponse.error(
ServiceExtensionResponse.kExtensionError,
"Extension handler must return a Future");
- _postResponse(replyPort, id, response);
+ _postResponse(replyPort, id, response, trace_service);
return;
}
response.catchError((e, st) {
@@ -104,7 +105,7 @@
ServiceExtensionResponse.kExtensionError,
"Extension handler must complete to a ServiceExtensionResponse");
}
- _postResponse(replyPort, id, response);
+ _postResponse(replyPort, id, response, trace_service);
}).catchError((e, st) {
// We do not expect any errors to occur in the .then or .catchError blocks
// but, suppress them just in case.
@@ -114,9 +115,13 @@
// This code is only invoked by _runExtension.
_postResponse(SendPort replyPort,
Object id,
- ServiceExtensionResponse response) {
+ ServiceExtensionResponse response,
+ bool trace_service) {
assert(replyPort != null);
if (id == null) {
+ if (trace_service) {
+ print("vm-service: posting no response for request");
+ }
// No id -> no response.
replyPort.send(null);
return;
@@ -125,8 +130,14 @@
StringBuffer sb = new StringBuffer();
sb.write('{"jsonrpc":"2.0",');
if (response._isError()) {
+ if (trace_service) {
+ print("vm-service: posting error response for request $id");
+ }
sb.write('"error":');
} else {
+ if (trace_service) {
+ print("vm-service: posting response for request $id");
+ }
sb.write('"result":');
}
sb.write('${response._toString()},');
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index dd7acd8..785950b 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -10,17 +10,11 @@
namespace dart {
-DECLARE_FLAG(bool, abort_on_assertion_errors);
-
// Allocate and throw a new AssertionError.
// Arg0: index of the first token of the failed assertion.
// Arg1: index of the first token after the failed assertion.
// Return value: none, throws an exception.
DEFINE_NATIVE_ENTRY(AssertionError_throwNew, 2) {
- if (FLAG_abort_on_assertion_errors) {
- Exceptions::PrintStackTraceAndAbort("an assertion failure");
- }
-
// No need to type check the arguments. This function can only be called
// internally from the VM.
const TokenPosition assertion_start =
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 59a61ec..0165ed9 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -362,18 +362,3 @@
return msg_buf.toString();
}
}
-
-class _JavascriptIntegerOverflowError extends Error {
- final Object _value;
-
- _JavascriptIntegerOverflowError(this._value);
- String toString() => "Javascript Integer Overflow: $_value";
-}
-
-class _JavascriptCompatibilityError extends Error {
- final String _msg;
-
- _JavascriptCompatibilityError(this._msg);
- String toString() => "Javascript Compatibility Error: $_msg";
-}
-
diff --git a/runtime/lib/identical.cc b/runtime/lib/identical.cc
index 6440726..4b24219 100644
--- a/runtime/lib/identical.cc
+++ b/runtime/lib/identical.cc
@@ -9,45 +9,10 @@
namespace dart {
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
-
DEFINE_NATIVE_ENTRY(Identical_comparison, 2) {
GET_NATIVE_ARGUMENT(Instance, a, arguments->NativeArgAt(0));
GET_NATIVE_ARGUMENT(Instance, b, arguments->NativeArgAt(1));
const bool is_identical = a.IsIdenticalTo(b);
- if (FLAG_warn_on_javascript_compatibility) {
- if (!is_identical) {
- if (a.IsString()) {
- if (String::Cast(a).Equals(b)) {
- Report::JSWarningFromNative(
- true, // Identical_comparison is static.
- "strings that are equal are also identical");
- }
- } else if (a.IsInteger()) {
- if (b.IsDouble()) {
- const int64_t a_value = Integer::Cast(a).AsInt64Value();
- const double b_value = Double::Cast(b).value();
- if (a_value == floor(b_value)) {
- Report::JSWarningFromNative(
- true, // Identical_comparison is static.
- "integer value and integral double value that are equal "
- "are also identical");
- }
- }
- } else if (a.IsDouble()) {
- if (b.IsInteger()) {
- const double a_value = Double::Cast(a).value();
- const int64_t b_value = Integer::Cast(b).AsInt64Value();
- if (floor(a_value) == b_value) {
- Report::JSWarningFromNative(
- true, // Identical_comparison is static.
- "integral double value and integer value that are equal "
- "are also identical");
- }
- }
- }
- }
- }
return Bool::Get(is_identical).raw();
}
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index 8deeee4..9478fcc 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -251,17 +251,15 @@
}
-// Passing true for 'silent' prevents throwing JavascriptIntegerOverflow.
static RawInteger* ShiftOperationHelper(Token::Kind kind,
const Integer& value,
- const Smi& amount,
- const bool silent = false) {
+ const Smi& amount) {
if (amount.Value() < 0) {
Exceptions::ThrowArgumentError(amount);
}
if (value.IsSmi()) {
const Smi& smi_value = Smi::Cast(value);
- return smi_value.ShiftOp(kind, amount, Heap::kNew, silent);
+ return smi_value.ShiftOp(kind, amount, Heap::kNew);
}
if (value.IsMint()) {
const int64_t mint_value = value.AsInt64Value();
@@ -273,11 +271,11 @@
if ((count + shift_count) < Mint::kBits) {
switch (kind) {
case Token::kSHL:
- return Integer::New(mint_value << shift_count, Heap::kNew, silent);
+ return Integer::New(mint_value << shift_count, Heap::kNew);
case Token::kSHR:
shift_count =
(-shift_count > Mint::kBits) ? Mint::kBits : -shift_count;
- return Integer::New(mint_value >> shift_count, Heap::kNew, silent);
+ return Integer::New(mint_value >> shift_count, Heap::kNew);
default:
UNIMPLEMENTED();
}
@@ -307,7 +305,7 @@
}
const Smi& smi_shift_count = Smi::Cast(shift_count);
const Integer& shift_result = Integer::Handle(
- ShiftOperationHelper(Token::kSHL, value, smi_shift_count, true));
+ ShiftOperationHelper(Token::kSHL, value, smi_shift_count));
const Integer& result =
Integer::Handle(shift_result.BitOp(Token::kBIT_AND, mask));
return result.AsValidInteger();
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index 667174c..4f0b852 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -116,6 +116,7 @@
// _state[_kSTATE_HI] = state >> 32;
// This is a native to prevent 64-bit operations in Dart, which
// fail with --throw_on_javascript_int_overflow.
+ // TODO(regis): Implement in Dart and remove Random_nextState in math.cc.
void _nextState() native "Random_nextState";
int nextInt(int max) {
@@ -160,6 +161,7 @@
// This is a native to prevent 64-bit operations in Dart, which
// fail with --throw_on_javascript_int_overflow.
+ // TODO(regis): Implement here in Dart and remove native in math.cc.
static Uint32List _setupSeed(int seed) native "Random_setupSeed";
// Get a seed from the VM's random number provider.
static Uint32List _initialSeed() native "Random_initialSeed";
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index b7d95b1..e2ded52 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -2086,7 +2086,7 @@
DEFINE_NATIVE_ENTRY(TypeMirror_subtypeTest, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
- return Bool::Get(a.IsSubtypeOf(b, NULL)).raw();
+ return Bool::Get(a.IsSubtypeOf(b, NULL, NULL, Heap::kNew)).raw();
}
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index cc64a06..95f2661 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -17,7 +17,6 @@
namespace dart {
DECLARE_FLAG(bool, trace_type_checks);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
// Helper function in stacktrace.cc.
void _printCurrentStacktrace();
@@ -121,40 +120,6 @@
}
-static void WarnOnJSIntegralNumTypeTest(
- const Instance& instance,
- const TypeArguments& instantiator_type_arguments,
- const AbstractType& type) {
- const bool instance_is_int = instance.IsInteger();
- const bool instance_is_double = instance.IsDouble();
- if (!(instance_is_int || instance_is_double)) {
- return;
- }
- AbstractType& instantiated_type = AbstractType::Handle(type.raw());
- if (!type.IsInstantiated()) {
- instantiated_type = type.InstantiateFrom(instantiator_type_arguments, NULL);
- }
- if (instance_is_double) {
- if (instantiated_type.IsIntType()) {
- const double value = Double::Cast(instance).value();
- if (floor(value) == value) {
- Report::JSWarningFromNative(
- false, // Object_instanceOf and Object_as are not static calls.
- "integral value of type 'double' is also considered to be "
- "of type 'int'");
- }
- }
- } else {
- ASSERT(instance_is_int);
- if (instantiated_type.IsDoubleType()) {
- Report::JSWarningFromNative(
- false, // Object_instanceOf and Object_as are not static calls.
- "integer value is also considered to be of type 'double'");
- }
- }
-}
-
-
DEFINE_NATIVE_ENTRY(Object_instanceOf, 4) {
const Instance& instance =
Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
@@ -166,12 +131,6 @@
ASSERT(type.IsFinalized());
ASSERT(!type.IsMalformed());
ASSERT(!type.IsMalbounded());
-
- // Check for javascript compatibility.
- if (FLAG_warn_on_javascript_compatibility) {
- WarnOnJSIntegralNumTypeTest(instance, instantiator_type_arguments, type);
- }
-
Error& bound_error = Error::Handle(zone, Error::null());
const bool is_instance_of = instance.IsInstanceOf(type,
instantiator_type_arguments,
@@ -278,12 +237,6 @@
if (instance.IsNull()) {
return instance.raw();
}
-
- // Check for javascript compatibility.
- if (FLAG_warn_on_javascript_compatibility) {
- WarnOnJSIntegralNumTypeTest(instance, instantiator_type_arguments, type);
- }
-
const bool is_instance_of = instance.IsInstanceOf(type,
instantiator_type_arguments,
&bound_error);
@@ -312,7 +265,8 @@
if (!type.IsInstantiated()) {
// Instantiate type before reporting the error.
const AbstractType& instantiated_type = AbstractType::Handle(
- type.InstantiateFrom(instantiator_type_arguments, NULL));
+ type.InstantiateFrom(instantiator_type_arguments, NULL,
+ NULL, NULL, Heap::kNew));
// Note that instantiated_type may be malformed.
type_name = instantiated_type.UserVisibleName();
} else {
diff --git a/runtime/lib/timeline.cc b/runtime/lib/timeline.cc
index 51319d7..ddc2f5a 100644
--- a/runtime/lib/timeline.cc
+++ b/runtime/lib/timeline.cc
@@ -16,9 +16,7 @@
// Native implementations for the dart:developer library.
DEFINE_NATIVE_ENTRY(Timeline_getIsolateNum, 0) {
- return Integer::New(static_cast<int64_t>(isolate->main_port()),
- Heap::kOld,
- true);
+ return Integer::New(static_cast<int64_t>(isolate->main_port()), Heap::kOld);
}
@@ -35,7 +33,7 @@
DEFINE_NATIVE_ENTRY(Timeline_getTraceClock, 0) {
- return Integer::New(OS::GetCurrentMonotonicMicros(), Heap::kNew, true);
+ return Integer::New(OS::GetCurrentMonotonicMicros(), Heap::kNew);
}
diff --git a/runtime/observatory/lib/object_graph.dart b/runtime/observatory/lib/object_graph.dart
index e70570e..8b491e8 100644
--- a/runtime/observatory/lib/object_graph.dart
+++ b/runtime/observatory/lib/object_graph.dart
@@ -8,8 +8,6 @@
import 'dart:collection';
import 'dart:typed_data';
-import 'package:logging/logging.dart';
-
class _JenkinsSmiHash {
static int combine(int hash, int value) {
hash = 0x1fffffff & (hash + value);
@@ -499,7 +497,7 @@
if (childId != null) {
succs[edge] = childId;
edge++;
- } else {
+ } else {
// Reference into VM isolate's heap.
}
stream.readUnsigned();
@@ -519,7 +517,6 @@
void _dfs() {
var N = _N;
- var E = _E;
var firstSuccs = _firstSuccs;
var succs = _succs;
@@ -531,7 +528,6 @@
var parent = new Uint32List(N + 1);
var dfsNumber = 0;
- var dfsCount = 0;
var stackTop = 0;
var root = 1;
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 21305e1..6be5e88 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -122,6 +122,8 @@
}
}).catchError((e, stack) {
Logger.root.severe('VMPage visit error: $e');
+ // Reroute to vm-connect.
+ app.locationManager.go(app.locationManager.makeLink('/vm-connect'));
});
}
}
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 06f91e7..3692d6a 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -1826,7 +1826,8 @@
if (event.asyncContinuation == null) {
console.print("No async continuation at this location");
} else {
- return isolate.asyncStepOver()[Isolate.kFirstResume];
+ List<Future> asyncStepFutures = await isolate.asyncStepOver();
+ return asyncStepFutures[Isolate.kFirstResume];
}
} else {
console.print('The program is already running');
diff --git a/runtime/observatory/lib/src/elements/timeline_page.dart b/runtime/observatory/lib/src/elements/timeline_page.dart
index 04a7376..b7a5462 100644
--- a/runtime/observatory/lib/src/elements/timeline_page.dart
+++ b/runtime/observatory/lib/src/elements/timeline_page.dart
@@ -57,14 +57,14 @@
}
Future recordOn() async {
- return app.vm.invokeRpc('_setVMTimelineFlag', {
- '_record': 'all',
+ return app.vm.invokeRpc('_setVMTimelineFlags', {
+ 'recordedStreams': ['all'],
});
}
Future recordOff() async {
- return app.vm.invokeRpc('_setVMTimelineFlag', {
- '_record': 'none',
+ return app.vm.invokeRpc('_setVMTimelineFlags', {
+ 'recordedStreams': [],
});
}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index bbf1c34..bd76e67 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1590,11 +1590,13 @@
/// result[kSecondResume] completes after the second resume. Tests should
/// wait on this future to avoid confusing the pause event at the
/// state-machine switch with the pause event after the state-machine switch.
- List<Future> asyncStepOver() {
- Completer firstResume = new Completer();
- Completer secondResume = new Completer();
- var subscription;
+ Future<List<Future>> asyncStepOver() async {
+ final Completer firstResume = new Completer();
+ final Completer secondResume = new Completer();
+ final List<Future> result = [firstResume.future, secondResume.future];
+ StreamSubscription subscription;
+ // Inner error handling function.
handleError(error) {
if (subscription != null) {
subscription.cancel();
@@ -1611,35 +1613,56 @@
} else {
Instance continuation = pauseEvent.asyncContinuation;
assert(continuation.isClosure);
- addBreakOnActivation(continuation).then((Breakpoint continuationBpt) {
- vm.getEventStream(VM.kDebugStream).then((stream) {
- var onResume = firstResume;
- subscription = stream.listen((ServiceEvent event) {
- if ((event.kind == ServiceEvent.kPauseBreakpoint) &&
- (event.breakpoint == continuationBpt)) {
- // We are stopped before state-machine dispatch; step-over to
- // reach user code.
- removeBreakpoint(continuationBpt).then((_) {
- onResume = secondResume;
- stepOver().catchError(handleError);
- });
- } else if (event.kind == ServiceEvent.kResume) {
- if (onResume == secondResume) {
- subscription.cancel();
- subscription = null;
- }
- if (onResume != null) {
- onResume.complete(this);
- onResume = null;
- }
- }
- });
- resume().catchError(handleError);
- }).catchError(handleError);
- }).catchError(handleError);
- }
- return [firstResume.future, secondResume.future];
+ // Add breakpoint at continuation.
+ Breakpoint continuationBpt;
+ try {
+ continuationBpt = await addBreakOnActivation(continuation);
+ } catch (e) {
+ handleError(e);
+ return result;
+ }
+
+ // Subscribe to the debugger event stream.
+ Stream stream;
+ try {
+ stream = await vm.getEventStream(VM.kDebugStream);
+ } catch (e) {
+ handleError(e);
+ return result;
+ }
+
+ Completer onResume = firstResume;
+ subscription = stream.listen((ServiceEvent event) async {
+ if ((event.kind == ServiceEvent.kPauseBreakpoint) &&
+ (event.breakpoint == continuationBpt)) {
+ // We are stopped before state-machine dispatch:
+ // 1) Remove the continuation breakpoint.
+ // 2) step over.
+ // reach user code.
+ await removeBreakpoint(continuationBpt);
+ onResume = secondResume;
+ stepOver().catchError(handleError);
+ } else if (event.kind == ServiceEvent.kResume) {
+ // We've resumed.
+ if (onResume == secondResume) {
+ // This is our second resume, cancel our subscription to the debug
+ // stream.
+ subscription.cancel();
+ subscription = null;
+ }
+ // Complete onResume and clear it.
+ if (onResume != null) {
+ onResume.complete(this);
+ onResume = null;
+ }
+ }
+ });
+
+ // Call resume, which will eventually cause us to hit continuationBpt.
+ resume().catchError(handleError);
+ }
+ return result;
}
Future setName(String newName) {
@@ -2416,7 +2439,7 @@
elements = map['elements'];
associations = map['associations'];
if (map['bytes'] != null) {
- var bytes = BASE64.decode(map['bytes']);
+ Uint8List bytes = BASE64.decode(map['bytes']);
switch (map['kind']) {
case "Uint8ClampedList":
typedElements = bytes.buffer.asUint8ClampedList(); break;
@@ -3634,7 +3657,7 @@
@observable bool hasDisassembly = false;
- void _processDisassembly(List<String> disassembly){
+ void _processDisassembly(List disassembly) {
assert(disassembly != null);
instructions.clear();
instructionsByAddressOffset = new List(endAddress - startAddress);
diff --git a/runtime/observatory/tests/service/async_next_test.dart b/runtime/observatory/tests/service/async_next_test.dart
index f3c64d9..dbdc19b 100644
--- a/runtime/observatory/tests/service/async_next_test.dart
+++ b/runtime/observatory/tests/service/async_next_test.dart
@@ -26,7 +26,8 @@
asyncNext(Isolate isolate) async {
print('asyncNext');
- return isolate.asyncStepOver()[Isolate.kSecondResume];
+ List asyncStepFutures = await isolate.asyncStepOver();
+ return asyncStepFutures[Isolate.kSecondResume];
}
var tests = [
diff --git a/runtime/observatory/tests/service/developer_extension_test.dart b/runtime/observatory/tests/service/developer_extension_test.dart
index e29686b..b4bafac 100644
--- a/runtime/observatory/tests/service/developer_extension_test.dart
+++ b/runtime/observatory/tests/service/developer_extension_test.dart
@@ -16,7 +16,7 @@
Map paremeters) {
print('Invoked extension: $method');
switch (method) {
- case '__delay':
+ case 'ext..delay':
Completer c = new Completer();
new Timer(new Duration(seconds: 1), () {
c.complete(new ServiceExtensionResponse.result(JSON.encode({
@@ -26,23 +26,23 @@
})));
});
return c.future;
- case '__error':
+ case 'ext..error':
return new Future.value(
new ServiceExtensionResponse.error(
- ServiceExtensionResponse.kExtensionErrorMin,
+ ServiceExtensionResponse.extensionErrorMin,
'My error detail.'));
- case '__exception':
+ case 'ext..exception':
throw "I always throw!";
- case '__success':
+ case 'ext..success':
return new Future.value(
new ServiceExtensionResponse.result(JSON.encode({
'type': '_extensionType',
'method': method,
'parameters': paremeters,
})));
- case '__null':
+ case 'ext..null':
return null;
- case '__nullFuture':
+ case 'ext..nullFuture':
return new Future.value(null);
}
}
@@ -54,25 +54,25 @@
}
void test() {
- registerExtension('__delay', Handler);
+ registerExtension('ext..delay', Handler);
debugger();
postEvent('ALPHA', {
'cat': 'dog'
});
debugger();
- registerExtension('__error', Handler);
- registerExtension('__exception', Handler);
- registerExtension('__null', Handler);
- registerExtension('__nullFuture', Handler);
- registerExtension('__success', Handler);
+ registerExtension('ext..error', Handler);
+ registerExtension('ext..exception', Handler);
+ registerExtension('ext..null', Handler);
+ registerExtension('ext..nullFuture', Handler);
+ registerExtension('ext..success', Handler);
bool exceptionThrown = false;
try {
- registerExtension('__delay', Handler);
+ registerExtension('ext..delay', Handler);
} catch (e) {
exceptionThrown = true;
}
expect(exceptionThrown, isTrue);
- registerExtension('__languageError', LanguageErrorHandler);
+ registerExtension('ext..languageError', LanguageErrorHandler);
}
var tests = [
@@ -80,7 +80,7 @@
(Isolate isolate) async {
await isolate.load();
expect(isolate.extensionRPCs.length, 1);
- expect(isolate.extensionRPCs[0], equals('__delay'));
+ expect(isolate.extensionRPCs[0], equals('ext..delay'));
},
resumeIsolateAndAwaitEvent(Isolate.kExtensionStream, (ServiceEvent event) {
expect(event.kind, equals(ServiceEvent.kExtension));
@@ -92,65 +92,65 @@
resumeIsolateAndAwaitEvent(VM.kIsolateStream, (ServiceEvent event) {
// Check that we received an event when '__error' was registered.
expect(event.kind, equals(ServiceEvent.kServiceExtensionAdded));
- expect(event.extensionRPC, equals('__error'));
+ expect(event.extensionRPC, equals('ext..error'));
}),
// Initial.
(Isolate isolate) async {
var result;
- result = await isolate.invokeRpcNoUpgrade('__delay', {});
+ result = await isolate.invokeRpcNoUpgrade('ext..delay', {});
expect(result['type'], equals('_delayedType'));
- expect(result['method'], equals('__delay'));
+ expect(result['method'], equals('ext..delay'));
expect(result['parameters']['isolateId'], isNotNull);
try {
- await isolate.invokeRpcNoUpgrade('__error', {});
+ await isolate.invokeRpcNoUpgrade('ext..error', {});
} on ServerRpcException catch (e, st) {
- expect(e.code, equals(ServiceExtensionResponse.kExtensionErrorMin));
+ expect(e.code, equals(ServiceExtensionResponse.extensionErrorMin));
expect(e.message, equals('My error detail.'));
}
try {
- await isolate.invokeRpcNoUpgrade('__exception', {});
+ await isolate.invokeRpcNoUpgrade('ext..exception', {});
} on ServerRpcException catch (e, st) {
- expect(e.code, equals(ServiceExtensionResponse.kExtensionError));
+ expect(e.code, equals(ServiceExtensionResponse.extensionError));
expect(e.message.startsWith('I always throw!\n'), isTrue);
}
try {
- await isolate.invokeRpcNoUpgrade('__null', {});
+ await isolate.invokeRpcNoUpgrade('ext..null', {});
} on ServerRpcException catch (e, st) {
- expect(e.code, equals(ServiceExtensionResponse.kExtensionError));
+ expect(e.code, equals(ServiceExtensionResponse.extensionError));
expect(e.message, equals('Extension handler must return a Future'));
}
try {
- await isolate.invokeRpcNoUpgrade('__nullFuture', {});
+ await isolate.invokeRpcNoUpgrade('ext..nullFuture', {});
} on ServerRpcException catch (e, st) {
- expect(e.code, equals(ServiceExtensionResponse.kExtensionError));
+ expect(e.code, equals(ServiceExtensionResponse.extensionError));
expect(e.message, equals('Extension handler must complete to a '
'ServiceExtensionResponse'));
}
- result = await isolate.invokeRpcNoUpgrade('__success',
+ result = await isolate.invokeRpcNoUpgrade('ext..success',
{'apple': 'banana'});
expect(result['type'], equals('_extensionType'));
- expect(result['method'], equals('__success'));
+ expect(result['method'], equals('ext..success'));
expect(result['parameters']['isolateId'], isNotNull);
expect(result['parameters']['apple'], equals('banana'));
try {
- result = await isolate.invokeRpcNoUpgrade('__languageError', {});
+ result = await isolate.invokeRpcNoUpgrade('ext..languageError', {});
} on ServerRpcException catch (e, st) {
- expect(e.code, equals(ServiceExtensionResponse.kExtensionError));
+ expect(e.code, equals(ServiceExtensionResponse.extensionError));
expect(e.message, stringContainsInOrder([
- 'Error in extension `__languageError`:',
+ 'Error in extension `ext..languageError`:',
'developer_extension_test.dart',
'semicolon expected']));
}
-
},
];
-main(args) async => runIsolateTests(args, tests, testeeConcurrent:test);
+main(args) async => runIsolateTests(args, tests, testeeConcurrent:test,
+ trace_compiler: true);
diff --git a/runtime/observatory/tests/service/file_service_test.dart b/runtime/observatory/tests/service/file_service_test.dart
index 22b5827..25500c6 100644
--- a/runtime/observatory/tests/service/file_service_test.dart
+++ b/runtime/observatory/tests/service/file_service_test.dart
@@ -64,20 +64,21 @@
var result = JSON.encode({'type' : 'foobar'});
return new Future.value(new ServiceExtensionResponse.result(result));
}
- registerExtension('__cleanup', cleanup);
- registerExtension('__setup', setup);
+ registerExtension('ext.dart.io.cleanup', cleanup);
+ registerExtension('ext.dart.io.setup', setup);
}
var fileTests = [
(Isolate isolate) async {
- await isolate.invokeRpcNoUpgrade('__setup', {});
+ await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {});
try {
- var result = await isolate.invokeRpcNoUpgrade('__getOpenFiles', {});
+ var result =
+ await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenFiles', {});
expect(result['type'], equals('_openfiles'));
expect(result['data'].length, equals(2));
var writing = await isolate.invokeRpcNoUpgrade(
- '__getFileByID', { 'id' : result['data'][0]['id'] });
+ 'ext.dart.io.getFileByID', { 'id' : result['data'][0]['id'] });
expect(writing['totalRead'], equals(0));
expect(writing['readCount'], equals(0));
@@ -87,7 +88,7 @@
expect(writing['lastRead'], equals(0));
var reading = await isolate.invokeRpcNoUpgrade(
- '__getFileByID', { 'id' : result['data'][1]['id'] });
+ 'ext.dart.io.getFileByID', { 'id' : result['data'][1]['id'] });
expect(reading['totalRead'], equals(5));
expect(reading['readCount'], equals(5));
@@ -97,7 +98,7 @@
expect(reading['lastRead'], greaterThan(0));
} finally {
- await isolate.invokeRpcNoUpgrade('__cleanup', {});
+ await isolate.invokeRpcNoUpgrade('ext.dart.io.cleanup', {});
}
},
];
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index 2fc74f4..a98c535 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -448,7 +448,7 @@
expect(result['offset'], isNull);
expect(result['count'], isNull);
expect(result['bytes'], equals('AwIB'));
- var bytes = BASE64.decode(result['bytes']);
+ Uint8List bytes = BASE64.decode(result['bytes']);
expect(bytes.buffer.asUint8List().toString(), equals('[3, 2, 1]'));
},
@@ -474,7 +474,7 @@
expect(result['offset'], isNull);
expect(result['count'], equals(2));
expect(result['bytes'], equals('AwI='));
- var bytes = BASE64.decode(result['bytes']);
+ Uint8List bytes = BASE64.decode(result['bytes']);
expect(bytes.buffer.asUint8List().toString(), equals('[3, 2]'));
},
@@ -501,7 +501,7 @@
expect(result['offset'], equals(2));
expect(result['count'], equals(1));
expect(result['bytes'], equals('AQ=='));
- var bytes = BASE64.decode(result['bytes']);
+ Uint8List bytes = BASE64.decode(result['bytes']);
expect(bytes.buffer.asUint8List().toString(), equals('[1]'));
},
@@ -551,7 +551,7 @@
expect(result['offset'], isNull);
expect(result['count'], isNull);
expect(result['bytes'], equals('AwAAAAAAAAACAAAAAAAAAAEAAAAAAAAA'));
- var bytes = BASE64.decode(result['bytes']);
+ Uint8List bytes = BASE64.decode(result['bytes']);
expect(bytes.buffer.asUint64List().toString(), equals('[3, 2, 1]'));
},
@@ -577,7 +577,7 @@
expect(result['offset'], isNull);
expect(result['count'], equals(2));
expect(result['bytes'], equals('AwAAAAAAAAACAAAAAAAAAA=='));
- var bytes = BASE64.decode(result['bytes']);
+ Uint8List bytes = BASE64.decode(result['bytes']);
expect(bytes.buffer.asUint64List().toString(), equals('[3, 2]'));
},
@@ -604,7 +604,7 @@
expect(result['offset'], equals(2));
expect(result['count'], equals(1));
expect(result['bytes'], equals('AQAAAAAAAAA='));
- var bytes = BASE64.decode(result['bytes']);
+ Uint8List bytes = BASE64.decode(result['bytes']);
expect(bytes.buffer.asUint64List().toString(), equals('[1]'));
},
diff --git a/runtime/observatory/tests/service/process_service_test.dart b/runtime/observatory/tests/service/process_service_test.dart
index 956cc77..ee529c9 100644
--- a/runtime/observatory/tests/service/process_service_test.dart
+++ b/runtime/observatory/tests/service/process_service_test.dart
@@ -73,31 +73,32 @@
return process3.exitCode.then((int exit) => returnValue);
}
- registerExtension('__cleanup', cleanup);
- registerExtension('__setup', setup);
- registerExtension('__closeStdin', closeStdin);
+ registerExtension('ext.dart.io.cleanup', cleanup);
+ registerExtension('ext.dart.io.setup', setup);
+ registerExtension('ext.dart.io.closeStdin', closeStdin);
}
var processTests = [
// Initial.
(Isolate isolate) async {
- var setup = await isolate.invokeRpcNoUpgrade('__setup', {});
+ var setup = await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {});
try {
- var all = await isolate.invokeRpcNoUpgrade('__getProcesses', {});
+ var all =
+ await isolate.invokeRpcNoUpgrade('ext.dart.io.getProcesses', {});
expect(all['type'], equals('_startedprocesses'));
expect(all['data'].length, equals(3));
var first = await isolate.invokeRpcNoUpgrade(
- '__getProcessById', { 'id' : all['data'][0]['id'] });
+ 'ext.dart.io.getProcessById', { 'id' : all['data'][0]['id'] });
expect(first['name'], io.Platform.executable);
expect(first['pid'], equals(setup['pids'][0]));
expect(first['arguments'].contains('foobar'), isFalse);
expect(first['startedAt'], greaterThan(0));
var second = await isolate.invokeRpcNoUpgrade(
- '__getProcessById', { 'id' : all['data'][1]['id'] });
+ 'ext.dart.io.getProcessById', { 'id' : all['data'][1]['id'] });
expect(second['name'], io.Platform.executable);
expect(second['pid'], equals(setup['pids'][1]));
expect(second['arguments'].contains('foobar'), isTrue);
@@ -106,19 +107,19 @@
expect(second['startedAt'], greaterThanOrEqualTo(first['startedAt']));
var third = await isolate.invokeRpcNoUpgrade(
- '__getProcessById', { 'id' : all['data'][2]['id'] });
+ 'ext.dart.io.getProcessById', { 'id' : all['data'][2]['id'] });
expect(third['name'], io.Platform.executable);
expect(third['pid'], equals(setup['pids'][2]));
expect(third['pid'] != first['pid'], isTrue);
expect(third['pid'] != second['pid'], isTrue);
expect(third['startedAt'], greaterThanOrEqualTo(second['startedAt']));
- await isolate.invokeRpcNoUpgrade('__closeStdin', {});
- all = await isolate.invokeRpcNoUpgrade('__getProcesses', {});
+ await isolate.invokeRpcNoUpgrade('ext.dart.io.closeStdin', {});
+ all = await isolate.invokeRpcNoUpgrade('ext.dart.io.getProcesses', {});
expect(all['type'], equals('_startedprocesses'));
expect(all['data'].length, equals(2));
} finally {
- await isolate.invokeRpcNoUpgrade('__cleanup', {});
+ await isolate.invokeRpcNoUpgrade('ext.dart.io.cleanup', {});
}
},
];
diff --git a/runtime/observatory/tests/service/smart_next_test.dart b/runtime/observatory/tests/service/smart_next_test.dart
index aeb819f..34bac34 100644
--- a/runtime/observatory/tests/service/smart_next_test.dart
+++ b/runtime/observatory/tests/service/smart_next_test.dart
@@ -47,7 +47,8 @@
smartNext(Isolate isolate) async {
if (isolate.pauseEvent.atAsyncJump) {
print("next-async");
- return isolate.asyncStepOver()[Isolate.kSecondResume];
+ List asyncStepFutures = await isolate.asyncStepOver();
+ return asyncStepFutures[Isolate.kSecondResume];
} else {
print("next-sync");
return stepOverAwaitingResume(isolate);
diff --git a/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart b/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
index 20a9b76..38e415b 100644
--- a/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
+++ b/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
@@ -54,13 +54,14 @@
var tests = [
// Initial.
(Isolate isolate) async {
- var result = await isolate.invokeRpcNoUpgrade('__getOpenSockets', {});
+ var result =
+ await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenSockets', {});
expect(result['type'], equals('_opensockets'));
// We expect only one socket to be open, the server socket create at the
// end of test.
expect(result['data'].length, equals(1));
var server = await isolate.invokeRpcNoUpgrade(
- '__getSocketByID', { 'id' : result['data'][0]['id'] });
+ 'ext.dart.io.getSocketByID', { 'id' : result['data'][0]['id'] });
expect(server['listening'], isTrue);
expect(server['lastRead'], equals(0));
expect(server['totalRead'], equals(0));
diff --git a/runtime/observatory/tests/service/tcp_socket_service_test.dart b/runtime/observatory/tests/service/tcp_socket_service_test.dart
index c80cad5..646b5f6 100644
--- a/runtime/observatory/tests/service/tcp_socket_service_test.dart
+++ b/runtime/observatory/tests/service/tcp_socket_service_test.dart
@@ -30,7 +30,8 @@
var tcpTests = [
// Initial.
(Isolate isolate) async {
- var result = await isolate.invokeRpcNoUpgrade('__getOpenSockets', {});
+ var result =
+ await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenSockets', {});
expect(result['type'], equals('_opensockets'));
// We expect 3 sockets to be open (in this order):
// The server socket accepting connections, on port X
@@ -48,7 +49,7 @@
expect(result['data'][2]['name'].startsWith('127.0.0.1:'), isTrue);
var listening = await isolate.invokeRpcNoUpgrade(
- '__getSocketByID', { 'id' : result['data'][0]['id'] });
+ 'ext.dart.io.getSocketByID', { 'id' : result['data'][0]['id'] });
expect(listening['id'], equals(result['data'][0]['id']));
expect(listening['listening'], isTrue);
expect(listening['socketType'], equals('TCP'));
@@ -64,11 +65,11 @@
expect(listening['remotePort'], equals('NA'));
var client = await isolate.invokeRpcNoUpgrade(
- '__getSocketByID', { 'id' : result['data'][1]['id'] });
+ 'ext.dart.io.getSocketByID', { 'id' : result['data'][1]['id'] });
expect(client['id'], equals(result['data'][1]['id']));
var server = await isolate.invokeRpcNoUpgrade(
- '__getSocketByID', { 'id' : result['data'][2]['id'] });
+ 'ext.dart.io.getSocketByID', { 'id' : result['data'][2]['id'] });
expect(server['id'], equals(result['data'][2]['id']));
// We expect the client to be connected on the port and
@@ -115,10 +116,10 @@
}
var secondClient = await isolate.invokeRpcNoUpgrade(
- '__getSocketByID', { 'id' : result['data'][3]['id'] });
+ 'ext.dart.io.getSocketByID', { 'id' : result['data'][3]['id'] });
expect(secondClient['id'], equals(result['data'][3]['id']));
var secondServer = await isolate.invokeRpcNoUpgrade(
- '__getSocketByID', { 'id' : result['data'][4]['id'] });
+ 'ext.dart.io.getSocketByID', { 'id' : result['data'][4]['id'] });
expect(secondServer['id'], equals(result['data'][4]['id']));
// We expect the client to be connected on the port and
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 1adcd66..1920369 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -29,7 +29,8 @@
Future<int> launch(bool pause_on_start,
bool pause_on_exit,
bool pause_on_unhandled_exceptions,
- bool trace_service) {
+ bool trace_service,
+ bool trace_compiler) {
assert(pause_on_start != null);
assert(pause_on_exit != null);
assert(trace_service != null);
@@ -40,6 +41,10 @@
var fullArgs = [];
if (trace_service) {
fullArgs.add('--trace-service');
+ fullArgs.add('--trace-service-verbose');
+ }
+ if (trace_compiler) {
+ fullArgs.add('--trace-compiler');
}
if (pause_on_start) {
fullArgs.add('--pause-isolates-on-start');
@@ -119,6 +124,7 @@
bool pause_on_start: false,
bool pause_on_exit: false,
bool trace_service: false,
+ bool trace_compiler: false,
bool verbose_vm: false,
bool pause_on_unhandled_exceptions: false}) async {
assert(!pause_on_start || testeeBefore == null);
@@ -142,7 +148,8 @@
} else {
var process = new _TestLauncher();
process.launch(pause_on_start, pause_on_exit,
- pause_on_unhandled_exceptions, trace_service).then((port) {
+ pause_on_unhandled_exceptions,
+ trace_service, trace_compiler).then((port) {
if (mainArgs.contains("--gdb")) {
port = 8181;
}
@@ -190,6 +197,7 @@
bool pause_on_start: false,
bool pause_on_exit: false,
bool trace_service: false,
+ bool trace_compiler: false,
bool verbose_vm: false,
bool pause_on_unhandled_exceptions: false}) {
assert(!pause_on_start || testeeBefore == null);
@@ -210,7 +218,8 @@
} else {
var process = new _TestLauncher();
process.launch(pause_on_start, pause_on_exit,
- pause_on_unhandled_exceptions, trace_service).then((port) {
+ pause_on_unhandled_exceptions,
+ trace_service, trace_compiler).then((port) {
if (mainArgs.contains("--gdb")) {
port = 8181;
}
@@ -400,6 +409,7 @@
bool pause_on_start: false,
bool pause_on_exit: false,
bool trace_service: false,
+ bool trace_compiler: false,
bool verbose_vm: false,
bool pause_on_unhandled_exceptions: false}) async {
if (mainArgs.contains(_TESTEE_MODE_FLAG)) {
@@ -421,7 +431,7 @@
process.launch(pause_on_start,
pause_on_exit,
pause_on_unhandled_exceptions,
- trace_service).then((port) async {
+ trace_service, trace_compiler).then((port) async {
if (mainArgs.contains("--gdb")) {
port = 8181;
}
diff --git a/runtime/observatory/tests/service/udp_socket_service_test.dart b/runtime/observatory/tests/service/udp_socket_service_test.dart
index 49ff5e4..6a6a0e0 100644
--- a/runtime/observatory/tests/service/udp_socket_service_test.dart
+++ b/runtime/observatory/tests/service/udp_socket_service_test.dart
@@ -25,7 +25,8 @@
var udpTests = [
// Initial.
(Isolate isolate) async {
- var result = await isolate.invokeRpcNoUpgrade('__getOpenSockets', {});
+ var result =
+ await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenSockets', {});
expect(result['type'], equals('_opensockets'));
// We expect 2 sockets to be open (in this order):
// The server socket accepting connections, on port X
@@ -38,7 +39,7 @@
expect(result['data'][1]['name'].startsWith('127.0.0.1:'), isTrue);
var server = await isolate.invokeRpcNoUpgrade(
- '__getSocketByID', { 'id' : result['data'][0]['id'] });
+ 'ext.dart.io.getSocketByID', { 'id' : result['data'][0]['id'] });
expect(server['id'], equals(result['data'][0]['id']));
expect(server['remotePort'], equals('NA'));
expect(server['remoteHost'], equals('NA'));
@@ -58,7 +59,7 @@
expect(server['readCount'], greaterThanOrEqualTo(1));
var client = await isolate.invokeRpcNoUpgrade(
- '__getSocketByID', { 'id' : result['data'][1]['id'] });
+ 'ext.dart.io.getSocketByID', { 'id' : result['data'][1]['id'] });
expect(client['id'], equals(result['data'][1]['id']));
expect(client['remotePort'], equals('NA'));
expect(client['remoteHost'], equals('NA'));
diff --git a/runtime/observatory/tests/service/vm_timeline_flags_test.dart b/runtime/observatory/tests/service/vm_timeline_flags_test.dart
new file mode 100644
index 0000000..6e8994e
--- /dev/null
+++ b/runtime/observatory/tests/service/vm_timeline_flags_test.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'dart:developer';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+primeDartTimeline() {
+ while (true) {
+ Timeline.startSync('apple');
+ Timeline.finishSync();
+ debugger();
+ }
+}
+
+bool isDart(Map event) => event['cat'] == 'Dart';
+bool isMetaData(Map event) => event['ph'] == 'M';
+bool isNotMetaData(Map event) => !isMetaData(event);
+bool isNotDartAndMetaData(Map event) => !isDart(event) && !isMetaData(event);
+
+List<Map> filterEvents(List<Map> events, filter) {
+ return events.where(filter).toList();
+}
+
+int dartEventCount;
+
+var tests = [
+ hasStoppedAtBreakpoint,
+ (Isolate isolate) async {
+ // Get the flags.
+ Map flags = await isolate.vm.invokeRpcNoUpgrade('_getVMTimelineFlags', {});
+ expect(flags['type'], 'TimelineFlags');
+ // Confirm that 'Dart' is available.
+ expect(flags['availableStreams'].contains('Dart'), isTrue);
+ // Confirm that nothing is being recorded.
+ expect(flags['recordedStreams'].length, equals(0));
+ },
+ (Isolate isolate) async {
+ // Get the timeline.
+ Map result = await isolate.vm.invokeRpcNoUpgrade('_getVMTimeline', {});
+ expect(result['type'], equals('_Timeline'));
+ expect(result['traceEvents'], new isInstanceOf<List>());
+ // Confirm that it as no non-meta data events.
+ expect(filterEvents(result['traceEvents'], isNotMetaData).length, 0);
+ },
+ (Isolate isolate) async {
+ // Enable the Dart category.
+ await isolate.vm.invokeRpcNoUpgrade('_setVMTimelineFlags', {
+ "recordedStreams": ["Dart"]
+ });
+ },
+ (Isolate isolate) async {
+ // Get the flags.
+ Map flags = await isolate.vm.invokeRpcNoUpgrade('_getVMTimelineFlags', {});
+ expect(flags['type'], 'TimelineFlags');
+ // Confirm that only Dart is being recorded.
+ expect(flags['recordedStreams'].length, equals(1));
+ expect(flags['recordedStreams'].contains('Dart'), isTrue);
+ },
+ resumeIsolate,
+ (Isolate isolate) async {
+ // Get the timeline.
+ Map result = await isolate.vm.invokeRpcNoUpgrade('_getVMTimeline', {});
+ expect(result['type'], equals('_Timeline'));
+ expect(result['traceEvents'], new isInstanceOf<List>());
+ // Confirm that Dart events are added.
+ expect(filterEvents(result['traceEvents'], isDart).length, greaterThan(0));
+ // Confirm that zero non-Dart events are added.
+ expect(
+ filterEvents(result['traceEvents'], isNotDartAndMetaData).length,
+ equals(0));
+ },
+ hasStoppedAtBreakpoint,
+ (Isolate isolate) async {
+ // Disable the Dart category.
+ await isolate.vm.invokeRpcNoUpgrade('_setVMTimelineFlags', {
+ "recordedStreams": []
+ });
+ // Grab the timeline and remember the number of Dart events.
+ Map result = await isolate.vm.invokeRpcNoUpgrade('_getVMTimeline', {});
+ expect(result['type'], equals('_Timeline'));
+ expect(result['traceEvents'], new isInstanceOf<List>());
+ dartEventCount = filterEvents(result['traceEvents'], isDart).length;
+ },
+ (Isolate isolate) async {
+ // Get the flags.
+ Map flags = await isolate.vm.invokeRpcNoUpgrade('_getVMTimelineFlags', {});
+ expect(flags['type'], 'TimelineFlags');
+ // Confirm that 'Dart' is not being recorded.
+ expect(flags['recordedStreams'].length, equals(0));
+ },
+ resumeIsolate,
+ (Isolate isolate) async {
+ // Grab the timeline and verify that we haven't added any new Dart events.
+ Map result = await isolate.vm.invokeRpcNoUpgrade('_getVMTimeline', {});
+ expect(result['type'], equals('_Timeline'));
+ expect(result['traceEvents'], new isInstanceOf<List>());
+ expect(filterEvents(result['traceEvents'], isDart).length, dartEventCount);
+ // Confirm that zero non-Dart events are added.
+ expect(
+ filterEvents(result['traceEvents'], isNotDartAndMetaData).length,
+ equals(0));
+ },
+];
+
+main(args) async => runIsolateTests(args,
+ tests,
+ testeeConcurrent: primeDartTimeline);
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index f626ee9..e8a5074 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -20,6 +20,8 @@
namespace dart {
+DECLARE_FLAG(bool, background_compilation);
+
Benchmark* Benchmark::first_ = NULL;
Benchmark* Benchmark::tail_ = NULL;
const char* Benchmark::executable_ = NULL;
@@ -338,7 +340,10 @@
}
Timer timer(true, "Compile all of dart2js benchmark");
timer.Start();
+ const bool old_flag = FLAG_background_compilation;
+ FLAG_background_compilation = false;
Dart_Handle result = Dart_CompileAll();
+ FLAG_background_compilation = old_flag;
EXPECT_VALID(result);
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
@@ -373,7 +378,10 @@
stats->EnableBenchmark();
Timer timer(true, "Compile all of dart2js benchmark");
timer.Start();
+ const bool old_flag = FLAG_background_compilation;
+ FLAG_background_compilation = false;
Dart_Handle result = Dart_CompileAll();
+ FLAG_background_compilation = old_flag;
EXPECT_VALID(result);
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index c9105ae..3296bcc 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -144,6 +144,7 @@
void ClassTable::RegisterAt(intptr_t index, const Class& cls) {
+ ASSERT(Thread::Current()->IsMutatorThread());
ASSERT(index != kIllegalCid);
ASSERT(index >= kNumPredefinedCids);
if (index >= capacity_) {
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index bf7508a..4f5b2a1 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -40,6 +40,10 @@
DEFINE_FLAG(int, regexp_optimization_counter_threshold, 1000,
"RegExp's usage-counter value before it is optimized, -1 means never");
DEFINE_FLAG(charp, optimization_filter, NULL, "Optimize only named function");
+// TODO(srdjan): Remove this flag once background compilation of regular
+// expressions is possible.
+DEFINE_FLAG(bool, regexp_opt_in_background, false,
+ "Optimize reg-exp functions in background");
DEFINE_FLAG(int, reoptimization_counter_threshold, 4000,
"Counter threshold before a function gets reoptimized.");
DEFINE_FLAG(bool, stop_on_excessive_deoptimization, false,
@@ -61,8 +65,9 @@
DECLARE_FLAG(int, max_deoptimization_counter_threshold);
DECLARE_FLAG(bool, enable_inlining_annotations);
DECLARE_FLAG(bool, trace_compiler);
+DECLARE_FLAG(bool, trace_field_guards);
+DECLARE_FLAG(bool, trace_optimization);
DECLARE_FLAG(bool, trace_optimizing_compiler);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
DECLARE_FLAG(int, max_polymorphic_checks);
DECLARE_FLAG(bool, precompilation);
@@ -318,7 +323,8 @@
// Instantiate type before printing.
Error& bound_error = Error::Handle();
const AbstractType& instantiated_type = AbstractType::Handle(
- type.InstantiateFrom(instantiator_type_arguments, &bound_error));
+ type.InstantiateFrom(instantiator_type_arguments, &bound_error,
+ NULL, NULL, Heap::kOld));
OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n",
message,
String::Handle(instance_type.Name()).ToCString(),
@@ -418,7 +424,8 @@
if (!test_type.IsInstantiated()) {
Error& bound_error = Error::Handle();
test_type = type.InstantiateFrom(instantiator_type_arguments,
- &bound_error);
+ &bound_error,
+ NULL, NULL, Heap::kNew);
ASSERT(bound_error.IsNull()); // Malbounded types are not optimized.
}
OS::PrintErr(" Updated test cache %p ix: %" Pd " with "
@@ -533,7 +540,8 @@
if (!dst_type.IsInstantiated()) {
// Instantiate dst_type before reporting the error.
const AbstractType& instantiated_dst_type = AbstractType::Handle(
- dst_type.InstantiateFrom(instantiator_type_arguments, NULL));
+ dst_type.InstantiateFrom(instantiator_type_arguments, NULL,
+ NULL, NULL, Heap::kNew));
// Note that instantiated_dst_type may be malbounded.
dst_type_name = instantiated_dst_type.UserVisibleName();
dst_type_lib =
@@ -885,18 +893,6 @@
const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
GrowableArray<const Instance*> args(1);
args.Add(&receiver);
- if (FLAG_warn_on_javascript_compatibility) {
- if (receiver.IsDouble() &&
- String::Handle(ic_data.target_name()).Equals(Symbols::toString())) {
- const double value = Double::Cast(receiver).value();
- if (floor(value) == value) {
- Report::JSWarningFromIC(ic_data,
- "string representation of an integral value "
- "of type 'double' has no decimal mark and "
- "no fractional part");
- }
- }
- }
const Function& result =
Function::Handle(InlineCacheMissHandler(args, ic_data));
arguments.SetReturn(result);
@@ -1491,6 +1487,20 @@
if (CanOptimizeFunction(function, thread)) {
if (FLAG_background_compilation) {
+ Field& field = Field::Handle(zone, isolate->GetDeoptimizingBoxedField());
+ while (!field.IsNull()) {
+ if (FLAG_trace_optimization || FLAG_trace_field_guards) {
+ THR_Print("Lazy disabling unboxing of %s\n", field.ToCString());
+ }
+ field.set_is_unboxing_candidate(false);
+ field.DeoptimizeDependentCode();
+ // Get next field.
+ field = isolate->GetDeoptimizingBoxedField();
+ }
+ }
+ // TODO(srdjan): Fix background compilation of regular expressions.
+ if (FLAG_background_compilation &&
+ (!function.IsIrregexpFunction() || FLAG_regexp_opt_in_background)) {
if (FLAG_enable_inlining_annotations) {
FATAL("Cannot enable inlining annotations and background compilation");
}
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 5b67de0..4d88bae 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -25,6 +25,7 @@
#include "vm/flow_graph_compiler.h"
#include "vm/flow_graph_inliner.h"
#include "vm/flow_graph_optimizer.h"
+#include "vm/flow_graph_range_analysis.h"
#include "vm/flow_graph_type_propagator.h"
#include "vm/il_printer.h"
#include "vm/longjump.h"
@@ -518,18 +519,8 @@
}
// Register code with the classes it depends on because of CHA and
- // fields it depends on because of store guards.
- // 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();
- }
+ // fields it depends on because of store guards, unless we cannot
+ // deopt.
for (intptr_t i = 0;
i < thread()->cha()->leaf_classes().length();
++i) {
@@ -584,7 +575,7 @@
// longjmp from the ARM or MIPS assemblers. In all other paths through this
// while loop, done is set to true. use_far_branches is always false on ia32
// and x64.
- bool done = false;
+ volatile bool done = false;
// volatile because the variable may be clobbered by a longjmp.
volatile bool use_far_branches = false;
const bool use_speculative_inlining = false;
@@ -615,8 +606,8 @@
// 'Freeze' ICData in background compilation so that it does not
// change while compiling.
- const bool clone_descriptors = Compiler::IsBackgroundCompilation();
- function.RestoreICDataMap(ic_data_array, clone_descriptors);
+ const bool clone_ic_data = Compiler::IsBackgroundCompilation();
+ function.RestoreICDataMap(ic_data_array, clone_ic_data);
if (Compiler::IsBackgroundCompilation() &&
(function.ic_data_array() == Array::null())) {
@@ -895,7 +886,8 @@
// We have to perform range analysis after LICM because it
// optimistically moves CheckSmi through phis into loop preheaders
// making some phis smi.
- optimizer.InferIntRanges();
+ RangeAnalysis range_analysis(flow_graph);
+ range_analysis.Analyze();
DEBUG_ASSERT(flow_graph->VerifyUseLists());
}
@@ -1325,8 +1317,11 @@
// Optimization must happen in non-mutator/Dart thread if background
// compilation is on. OSR compilation still occurs in the main thread.
+ // TODO(Srdjan): Remove assert allowance for regular expression functions
+ // once they can be compiled in background.
ASSERT((osr_id != kNoOSRDeoptId) || !FLAG_background_compilation ||
- !thread->IsMutatorThread());
+ !thread->IsMutatorThread() ||
+ function.IsIrregexpFunction());
CompilationPipeline* pipeline =
CompilationPipeline::New(thread->zone(), function);
return CompileFunctionHelper(pipeline,
@@ -1531,6 +1526,9 @@
void Compiler::AbortBackgroundCompilation(intptr_t deopt_id) {
+ if (FLAG_trace_compiler) {
+ THR_Print("ABORT background compilation.");
+ }
ASSERT(Compiler::IsBackgroundCompilation());
Thread::Current()->long_jump_base()->Jump(
deopt_id, Object::background_compilation_error());
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc
index 8ce260b..2e85c3d 100644
--- a/runtime/vm/coverage.cc
+++ b/runtime/vm/coverage.cc
@@ -89,7 +89,7 @@
// Print the hit counts for all IC datas.
ZoneGrowableArray<const ICData*>* ic_data_array =
new(zone) ZoneGrowableArray<const ICData*>();
- function.RestoreICDataMap(ic_data_array, false /* clone descriptors */);
+ function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
const PcDescriptors& descriptors = PcDescriptors::Handle(
zone, code.pc_descriptors());
diff --git a/runtime/vm/cpuid.h b/runtime/vm/cpuid.h
index b9d193a..b33812e 100644
--- a/runtime/vm/cpuid.h
+++ b/runtime/vm/cpuid.h
@@ -26,14 +26,14 @@
static const char* field(CpuInfoIndices idx) { return NULL; }
#endif
- static bool sse2() { return sse2_; }
- static bool sse41() { return sse41_; }
-
+ private:
// Caller must free the result of id_string and brand_string.
static const char* id_string();
static const char* brand_string();
- private:
+ static bool sse2() { return sse2_; }
+ static bool sse41() { return sse41_; }
+
static bool sse2_;
static bool sse41_;
static const char* id_string_;
diff --git a/runtime/vm/cpuinfo.h b/runtime/vm/cpuinfo.h
index cd1247e..95b6ec3 100644
--- a/runtime/vm/cpuinfo.h
+++ b/runtime/vm/cpuinfo.h
@@ -45,16 +45,10 @@
// Returns true if the cpuinfo field contains the string.
static bool FieldContains(CpuInfoIndices idx, const char* search_string);
- static bool FieldContainsByString(
- const char* field, const char* search_string);
// Returns true if the cpuinfo field [field] exists and is non-empty.
static bool HasField(const char* field);
- // Returns the field. Caller is responsible for freeing the result.
- static const char* ExtractField(CpuInfoIndices idx);
- static const char* ExtractFieldByString(const char* field);
-
// Returns the field describing the CPU model. Caller is responsible for
// freeing the result.
static const char* GetCpuModel() {
@@ -66,6 +60,9 @@
}
private:
+ // Returns the field. Caller is responsible for freeing the result.
+ static const char* ExtractField(CpuInfoIndices idx);
+
// The method to use to acquire info about the CPU.
static CpuInfoMethod method_;
diff --git a/runtime/vm/cpuinfo_android.cc b/runtime/vm/cpuinfo_android.cc
index e4e4826..1e4229c 100644
--- a/runtime/vm/cpuinfo_android.cc
+++ b/runtime/vm/cpuinfo_android.cc
@@ -52,25 +52,12 @@
}
-bool CpuInfo::FieldContainsByString(const char* field,
- const char* search_string) {
- ASSERT(method_ != kCpuInfoDefault);
- return ProcCpuInfo::FieldContains(field, search_string);
-}
-
-
const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
ASSERT(method_ != kCpuInfoDefault);
return ProcCpuInfo::ExtractField(FieldName(idx));
}
-const char* CpuInfo::ExtractFieldByString(const char* field) {
- ASSERT(method_ != kCpuInfoDefault);
- return ProcCpuInfo::ExtractField(field);
-}
-
-
bool CpuInfo::HasField(const char* field) {
ASSERT(method_ != kCpuInfoDefault);
return ProcCpuInfo::HasField(field);
diff --git a/runtime/vm/cpuinfo_linux.cc b/runtime/vm/cpuinfo_linux.cc
index e58bac1..8d76233 100644
--- a/runtime/vm/cpuinfo_linux.cc
+++ b/runtime/vm/cpuinfo_linux.cc
@@ -67,7 +67,10 @@
bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
if (method_ == kCpuInfoCpuId) {
- return strstr(CpuId::field(idx), search_string);
+ const char* field = CpuId::field(idx);
+ bool contains = (strstr(field, search_string) != NULL);
+ free(const_cast<char*>(field));
+ return contains;
} else {
ASSERT(method_ == kCpuInfoSystem);
return ProcCpuInfo::FieldContains(FieldName(idx), search_string);
@@ -75,23 +78,6 @@
}
-bool CpuInfo::FieldContainsByString(const char* field,
- const char* search_string) {
- if (method_ == kCpuInfoCpuId) {
- for (int i = 0; i < kCpuInfoMax; i++) {
- if (strcmp(field, fields_[i]) == 0) {
- return FieldContains(static_cast<CpuInfoIndices>(i), search_string);
- }
- }
- UNIMPLEMENTED();
- return false;
- } else {
- ASSERT(method_ == kCpuInfoSystem);
- return ProcCpuInfo::FieldContains(field, search_string);
- }
-}
-
-
const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
if (method_ == kCpuInfoCpuId) {
return CpuId::field(idx);
@@ -102,22 +88,6 @@
}
-const char* CpuInfo::ExtractFieldByString(const char* field) {
- if (method_ == kCpuInfoCpuId) {
- for (int i = 0; i < kCpuInfoMax; i++) {
- if (strcmp(field, fields_[i]) == 0) {
- return ExtractField(static_cast<CpuInfoIndices>(i));
- }
- }
- UNIMPLEMENTED();
- return NULL;
- } else {
- ASSERT(method_ == kCpuInfoSystem);
- return ProcCpuInfo::ExtractField(field);
- }
-}
-
-
bool CpuInfo::HasField(const char* field) {
if (method_ == kCpuInfoCpuId) {
return (strcmp(field, fields_[kCpuInfoProcessor]) == 0) ||
diff --git a/runtime/vm/cpuinfo_macos.cc b/runtime/vm/cpuinfo_macos.cc
index 6352391..eef06d9 100644
--- a/runtime/vm/cpuinfo_macos.cc
+++ b/runtime/vm/cpuinfo_macos.cc
@@ -31,10 +31,10 @@
void CpuInfo::Cleanup() {}
-bool CpuInfo::FieldContainsByString(const char* field,
- const char* search_string) {
+bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
ASSERT(method_ != kCpuInfoDefault);
ASSERT(search_string != NULL);
+ const char* field = FieldName(idx);
char dest[1024];
size_t dest_len = 1024;
@@ -48,14 +48,9 @@
}
-bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
+const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
ASSERT(method_ != kCpuInfoDefault);
- return FieldContainsByString(FieldName(idx), search_string);
-}
-
-
-const char* CpuInfo::ExtractFieldByString(const char* field) {
- ASSERT(method_ != kCpuInfoDefault);
+ const char* field = FieldName(idx);
ASSERT(field != NULL);
size_t result_len;
@@ -65,7 +60,7 @@
return 0;
}
- char* result = new char[result_len];
+ char* result = reinterpret_cast<char*>(malloc(result_len));
if (sysctlbyname(field, result, &result_len, NULL, 0) != 0) {
UNREACHABLE();
return 0;
@@ -75,12 +70,6 @@
}
-const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
- ASSERT(method_ != kCpuInfoDefault);
- return ExtractFieldByString(FieldName(idx));
-}
-
-
bool CpuInfo::HasField(const char* field) {
ASSERT(method_ != kCpuInfoDefault);
ASSERT(field != NULL);
diff --git a/runtime/vm/cpuinfo_test.cc b/runtime/vm/cpuinfo_test.cc
index 860c407..0b6113b 100644
--- a/runtime/vm/cpuinfo_test.cc
+++ b/runtime/vm/cpuinfo_test.cc
@@ -12,6 +12,8 @@
UNIT_TEST_CASE(GetCpuModelTest) {
const char* cpumodel = CpuInfo::GetCpuModel();
EXPECT_NE(strlen(cpumodel), 0UL);
+ // caller is responsible for deleting the returned cpumodel string.
+ free(const_cast<char*>(cpumodel));
}
} // namespace dart
diff --git a/runtime/vm/cpuinfo_win.cc b/runtime/vm/cpuinfo_win.cc
index b648566..1570af7 100644
--- a/runtime/vm/cpuinfo_win.cc
+++ b/runtime/vm/cpuinfo_win.cc
@@ -43,37 +43,12 @@
}
-bool CpuInfo::FieldContainsByString(const char* field,
- const char* search_string) {
- ASSERT(method_ != kCpuInfoDefault);
- for (int i = 0; i < kCpuInfoMax; i++) {
- if (strcmp(field, fields_[i]) == 0) {
- return FieldContains(static_cast<CpuInfoIndices>(i), search_string);
- }
- }
- UNIMPLEMENTED();
- return false;
-}
-
-
const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
ASSERT(method_ != kCpuInfoDefault);
return CpuId::field(idx);
}
-const char* CpuInfo::ExtractFieldByString(const char* field) {
- ASSERT(method_ != kCpuInfoDefault);
- for (int i = 0; i < kCpuInfoMax; i++) {
- if (strcmp(field, fields_[i]) == 0) {
- return ExtractField(static_cast<CpuInfoIndices>(i));
- }
- }
- UNIMPLEMENTED();
- return NULL;
-}
-
-
bool CpuInfo::HasField(const char* field) {
ASSERT(method_ != kCpuInfoDefault);
return (strcmp(field, fields_[kCpuInfoProcessor]) == 0) ||
diff --git a/runtime/vm/custom_isolate_test.cc b/runtime/vm/custom_isolate_test.cc
index 8f7796d..d720f70 100644
--- a/runtime/vm/custom_isolate_test.cc
+++ b/runtime/vm/custom_isolate_test.cc
@@ -16,6 +16,8 @@
namespace dart {
+DECLARE_FLAG(bool, trace_shutdown);
+
static void native_echo(Dart_NativeArguments args);
static void CustomIsolateImpl_start(Dart_NativeArguments args);
static Dart_NativeFunction NativeLookup(Dart_Handle name,
@@ -210,6 +212,7 @@
OS::Print("<< Shutting down isolate(%p)\n", isolate());
event_queue->RemoveEventsForIsolate(isolate());
Dart_SetMessageNotifyCallback(NULL);
+ Dart_ExitScope();
Dart_ShutdownIsolate();
} else {
Dart_ExitScope();
@@ -315,6 +318,8 @@
UNIT_TEST_CASE(CustomIsolates) {
+ bool saved_flag = FLAG_trace_shutdown;
+ FLAG_trace_shutdown = true;
FLAG_verify_handles = true;
FLAG_verify_on_transition = true;
event_queue = new EventQueue();
@@ -354,6 +359,7 @@
delete event_queue;
event_queue = NULL;
+ FLAG_trace_shutdown = saved_flag;
}
} // namespace dart
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index bace9af..5e563eb 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -42,12 +42,15 @@
DEFINE_FLAG(bool, keep_code, false,
"Keep deoptimized code for profiling.");
DEFINE_FLAG(bool, shutdown, true, "Do a clean shutdown of the VM");
+DEFINE_FLAG(bool, trace_shutdown, false, "Trace VM shutdown on stderr");
Isolate* Dart::vm_isolate_ = NULL;
+int64_t Dart::start_time_ = 0;
ThreadPool* Dart::thread_pool_ = NULL;
DebugInfo* Dart::pprof_symbol_generator_ = NULL;
ReadOnlyHandles* Dart::predefined_handles_ = NULL;
const uint8_t* Dart::instructions_snapshot_buffer_ = NULL;
+const uint8_t* Dart::data_snapshot_buffer_ = NULL;
// Structure for managing read-only global handles allocation used for
// creating global read-only handles that are pre created and initialized
@@ -75,6 +78,7 @@
const char* Dart::InitOnce(const uint8_t* vm_isolate_snapshot,
const uint8_t* instructions_snapshot,
+ const uint8_t* data_snapshot,
Dart_IsolateCreateCallback create,
Dart_IsolateShutdownCallback shutdown,
Dart_FileOpenCallback file_open,
@@ -133,6 +137,7 @@
Dart_IsolateFlags api_flags;
vm_flags.CopyTo(&api_flags);
vm_isolate_ = Isolate::Init("vm-isolate", api_flags, is_vm_isolate);
+ start_time_ = vm_isolate_->start_time();
vm_isolate_->set_compilation_allowed(!precompiled);
// Verify assumptions about executing in the VM isolate.
ASSERT(vm_isolate_ == Isolate::Current());
@@ -155,6 +160,8 @@
if (vm_isolate_snapshot != NULL) {
if (instructions_snapshot != NULL) {
vm_isolate_->SetupInstructionsSnapshotPage(instructions_snapshot);
+ ASSERT(data_snapshot != NULL);
+ vm_isolate_->SetupDataSnapshotPage(data_snapshot);
}
const Snapshot* snapshot = Snapshot::SetupFromBuffer(vm_isolate_snapshot);
if (snapshot == NULL) {
@@ -164,6 +171,7 @@
VmIsolateSnapshotReader reader(snapshot->content(),
snapshot->length(),
instructions_snapshot,
+ data_snapshot,
T);
const Error& error = Error::Handle(reader.ReadVmIsolateSnapshot());
if (!error.IsNull()) {
@@ -234,8 +242,17 @@
return "VM already terminated.";
}
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Starting shutdown\n",
+ timestamp());
+ }
+
if (FLAG_profiler) {
// Shut down profiling.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down profiling\n",
+ timestamp());
+ }
Profiler::Shutdown();
}
@@ -243,6 +260,10 @@
{
// Set the VM isolate as current isolate when shutting down
// Metrics so that we can use a StackZone.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Entering vm isolate\n",
+ timestamp());
+ }
bool result = Thread::EnterIsolate(vm_isolate_);
ASSERT(result);
Metric::Cleanup();
@@ -251,19 +272,39 @@
if (FLAG_shutdown) {
// Disable the creation of new isolates.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling isolate creation\n",
+ timestamp());
+ }
Isolate::DisableIsolateCreation();
// Send the OOB Kill message to all remaining application isolates.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Killing all app isolates\n",
+ timestamp());
+ }
Isolate::KillAllIsolates(Isolate::kInternalKillMsg);
// Shutdown the service isolate.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down service isolate\n",
+ timestamp());
+ }
ServiceIsolate::Shutdown();
// Wait for all application isolates and the service isolate to shutdown
// before shutting down the thread pool.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Waiting for isolate shutdown\n",
+ timestamp());
+ }
WaitForIsolateShutdown();
// Shutdown the thread pool. On return, all thread pool threads have exited.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting thread pool\n",
+ timestamp());
+ }
delete thread_pool_;
thread_pool_ = NULL;
@@ -273,9 +314,17 @@
// 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.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling OS Thread creation\n",
+ timestamp());
+ }
OSThread::DisableOSThreadCreation();
// Set the VM isolate as current isolate.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Cleaning up vm isolate\n",
+ timestamp());
+ }
bool result = Thread::EnterIsolate(vm_isolate_);
ASSERT(result);
@@ -292,18 +341,41 @@
OSThread* os_thread = OSThread::Current();
OSThread::SetCurrent(NULL);
delete os_thread;
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleted os_thread\n",
+ timestamp());
+ }
} else {
// Shutdown the service isolate.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down service isolate\n",
+ timestamp());
+ }
ServiceIsolate::Shutdown();
// Disable thread creation.
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Disabling OS Thread creation\n",
+ timestamp());
+ }
OSThread::DisableOSThreadCreation();
}
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting code observers\n",
+ timestamp());
+ }
CodeObservers::DeleteAll();
if (FLAG_support_timeline) {
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down timeline\n",
+ timestamp());
+ }
Timeline::Shutdown();
}
+ if (FLAG_trace_shutdown) {
+ OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Done\n", timestamp());
+ }
return NULL;
}
@@ -360,6 +432,7 @@
IsolateSnapshotReader reader(snapshot->content(),
snapshot->length(),
Dart::instructions_snapshot_buffer(),
+ Dart::data_snapshot_buffer(),
T);
const Error& error = Error::Handle(reader.ReadFullSnapshot());
if (!error.IsNull()) {
@@ -466,6 +539,12 @@
}
+int64_t Dart::timestamp() {
+ return ((OS::GetCurrentTimeMicros() - Dart::start_time_) /
+ kMillisecondsPerSecond);
+}
+
+
uword Dart::AllocateReadOnlyHandle() {
ASSERT(Isolate::Current() == Dart::vm_isolate());
ASSERT(predefined_handles_ != NULL);
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index 412eef2..aa43e12 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -23,6 +23,7 @@
static const char* InitOnce(
const uint8_t* vm_isolate_snapshot,
const uint8_t* instructions_snapshot,
+ const uint8_t* data_snapshot,
Dart_IsolateCreateCallback create,
Dart_IsolateShutdownCallback shutdown,
Dart_FileOpenCallback file_open,
@@ -43,6 +44,10 @@
static Isolate* vm_isolate() { return vm_isolate_; }
static ThreadPool* thread_pool() { return thread_pool_; }
+ // Returns a timestamp for use in debugging output in milliseconds
+ // since start time.
+ static int64_t timestamp();
+
static void set_pprof_symbol_generator(DebugInfo* value) {
pprof_symbol_generator_ = value;
}
@@ -64,14 +69,23 @@
return instructions_snapshot_buffer_ != NULL;
}
+ static const uint8_t* data_snapshot_buffer() {
+ return data_snapshot_buffer_;
+ }
+ static void set_data_snapshot_buffer(const uint8_t* buffer) {
+ data_snapshot_buffer_ = buffer;
+ }
+
private:
static void WaitForIsolateShutdown();
static Isolate* vm_isolate_;
+ static int64_t start_time_;
static ThreadPool* thread_pool_;
static DebugInfo* pprof_symbol_generator_;
static ReadOnlyHandles* predefined_handles_;
static const uint8_t* instructions_snapshot_buffer_;
+ static const uint8_t* data_snapshot_buffer_;
};
} // namespace dart
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index a826afe..dad463e 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -150,7 +150,9 @@
if (obj_class.IsSubtypeOf(Object::null_type_arguments(),
list_class,
Object::null_type_arguments(),
- &malformed_type_error)) {
+ &malformed_type_error,
+ NULL,
+ Heap::kNew)) {
ASSERT(malformed_type_error.IsNull()); // Type is a raw List.
return instance.raw();
}
@@ -170,7 +172,9 @@
if (obj_class.IsSubtypeOf(Object::null_type_arguments(),
map_class,
Object::null_type_arguments(),
- &malformed_type_error)) {
+ &malformed_type_error,
+ NULL,
+ Heap::kNew)) {
ASSERT(malformed_type_error.IsNull()); // Type is a raw Map.
return instance.raw();
}
@@ -1134,6 +1138,7 @@
DART_EXPORT char* Dart_Initialize(
const uint8_t* vm_isolate_snapshot,
const uint8_t* instructions_snapshot,
+ const uint8_t* data_snapshot,
Dart_IsolateCreateCallback create,
Dart_IsolateInterruptCallback interrupt,
Dart_IsolateUnhandledExceptionCallback unhandled,
@@ -1157,6 +1162,7 @@
}
const char* err_msg = Dart::InitOnce(vm_isolate_snapshot,
instructions_snapshot,
+ data_snapshot,
create, shutdown,
file_open, file_read, file_write,
file_close, entropy_source,
@@ -2016,7 +2022,9 @@
bool is_future = obj_class.IsSubtypeOf(Object::null_type_arguments(),
future_class,
Object::null_type_arguments(),
- &malformed_type_error);
+ &malformed_type_error,
+ NULL,
+ Heap::kNew);
ASSERT(malformed_type_error.IsNull()); // Type is a raw Future.
return is_future;
}
@@ -3798,7 +3806,8 @@
// type arguments of the type argument.
Error& bound_error = Error::Handle();
redirect_type ^= redirect_type.InstantiateFrom(type_arguments,
- &bound_error);
+ &bound_error,
+ NULL, NULL, Heap::kNew);
if (!bound_error.IsNull()) {
return Api::NewHandle(T, bound_error.raw());
}
@@ -5131,6 +5140,10 @@
NoHeapGrowthControlScope no_growth_control;
const Snapshot* snapshot = Snapshot::SetupFromBuffer(buffer);
+ if (snapshot == NULL) {
+ return Api::NewError("%s expects parameter 'buffer' to be a script type"
+ " snapshot with a valid length.", CURRENT_FUNC);
+ }
if (!snapshot->IsScriptSnapshot()) {
return Api::NewError("%s expects parameter 'buffer' to be a script type"
" snapshot.", CURRENT_FUNC);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index a35bf99..8e7d698 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -2819,6 +2819,7 @@
&peer,
0,
WeakPersistentHandlePeerFinalizer);
+ Dart_ExitScope();
Dart_ShutdownIsolate();
EXPECT(peer == 42);
}
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index fdfd262..85faf11 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -14,6 +14,7 @@
DECLARE_FLAG(bool, background_compilation);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, use_osr);
+DECLARE_FLAG(bool, trace_shutdown);
#ifndef PRODUCT
@@ -1513,6 +1514,8 @@
TEST_CASE(Debug_InterruptIsolate) {
+ bool saved_flag = FLAG_trace_shutdown;
+ FLAG_trace_shutdown = true;
sync = new Monitor();
Dart_SetIsolateEventHandler(&TestInterruptIsolate);
EXPECT(interrupt_isolate_id == ILLEGAL_ISOLATE_ID);
@@ -1522,6 +1525,7 @@
// Wait for the test isolate to be created.
{
+ OS::PrintErr("Waiting for isolate to be created\n");
MonitorLocker ml(sync);
while (interrupt_isolate_id == ILLEGAL_ISOLATE_ID) {
ml.Wait();
@@ -1535,6 +1539,7 @@
// Wait for the test isolate to be interrupted.
{
+ OS::PrintErr("Waiting for isolate to be interrupted\n");
MonitorLocker ml(sync);
while (!isolate_interrupted || !pause_event_handled) {
ml.Wait();
@@ -1545,12 +1550,15 @@
// Wait for the test isolate to shutdown.
{
+ OS::PrintErr("Waiting for isolate to be shut down\n");
MonitorLocker ml(sync);
while (interrupt_isolate_id != ILLEGAL_ISOLATE_ID) {
ml.Wait();
}
}
EXPECT(interrupt_isolate_id == ILLEGAL_ISOLATE_ID);
+ OS::PrintErr("Complete\n");
+ FLAG_trace_shutdown = saved_flag;
}
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 369d099..800a802 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -19,8 +19,6 @@
namespace dart {
-DEFINE_FLAG(bool, abort_on_assertion_errors, false,
- "Abort on assertion and typecheck failures");
DEFINE_FLAG(bool, print_stacktrace_at_throw, false,
"Prints a stack trace everytime a throw occurs.");
@@ -459,7 +457,7 @@
// Type errors in the core library may be difficult to diagnose.
// Print type error information before throwing the error when debugging.
- if (FLAG_print_stacktrace_at_throw || FLAG_abort_on_assertion_errors) {
+ if (FLAG_print_stacktrace_at_throw) {
if (!error_msg.IsNull()) {
OS::Print("%s\n", error_msg.ToCString());
}
@@ -475,10 +473,6 @@
}
}
- if (FLAG_abort_on_assertion_errors) {
- PrintStackTraceAndAbort("a type error");
- }
-
// Throw TypeError or CastError instance.
Exceptions::ThrowByType(exception_type, args);
UNREACHABLE();
@@ -633,14 +627,6 @@
library = Library::IsolateLibrary();
class_name = &Symbols::IsolateSpawnException();
break;
- case kJavascriptIntegerOverflowError:
- library = Library::CoreLibrary();
- class_name = &Symbols::JavascriptIntegerOverflowError();
- break;
- case kJavascriptCompatibilityError:
- library = Library::CoreLibrary();
- class_name = &Symbols::JavascriptCompatibilityError();
- break;
case kAssertion:
library = Library::CoreLibrary();
class_name = &Symbols::AssertionError();
@@ -678,22 +664,4 @@
}
-// Throw JavascriptCompatibilityError exception.
-void Exceptions::ThrowJavascriptCompatibilityError(const char* msg) {
- const Array& exc_args = Array::Handle(Array::New(1));
- const String& msg_str = String::Handle(String::New(msg));
- exc_args.SetAt(0, msg_str);
- Exceptions::ThrowByType(Exceptions::kJavascriptCompatibilityError, exc_args);
-}
-
-
-void Exceptions::PrintStackTraceAndAbort(const char* reason) {
- const Instance& stacktrace = Instance::Handle(CurrentStacktrace());
-
- OS::PrintErr("\n\n\nAborting due to %s. Stacktrace:\n%s\n",
- reason,
- stacktrace.ToCString());
- OS::Abort();
-}
-
} // namespace dart
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index ada7606..86e3261 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -61,8 +61,6 @@
kOutOfMemory,
kNullThrown,
kIsolateSpawn,
- kJavascriptIntegerOverflowError,
- kJavascriptCompatibilityError,
kAssertion,
kCast,
kType,
@@ -81,14 +79,11 @@
const Integer& argument_value,
intptr_t expected_from,
intptr_t expected_to);
- static void ThrowJavascriptCompatibilityError(const char* msg);
// Returns a RawInstance if the exception is successfully created,
// otherwise returns a RawError.
static RawObject* Create(ExceptionType type, const Array& arguments);
- static void PrintStackTraceAndAbort(const char* reason);
-
private:
DISALLOW_COPY_AND_ASSIGN(Exceptions);
};
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index 49f81ff..1f97a72 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -44,7 +44,6 @@
loop_headers_(NULL),
loop_invariant_loads_(NULL),
guarded_fields_(parsed_function.guarded_fields()),
- deoptimize_dependent_code_(),
deferred_prefixes_(parsed_function.deferred_prefixes()),
captured_parameters_(new(zone()) BitVector(zone(), variable_count())),
inlining_id_(-1) {
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index 970a7a0..9841716 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -285,10 +285,6 @@
return guarded_fields_;
}
- GrowableArray<const Field*>& deoptimize_dependent_code() {
- return deoptimize_dependent_code_;
- }
-
ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes() const {
return deferred_prefixes_;
}
@@ -373,7 +369,6 @@
ZoneGrowableArray<BlockEntryInstr*>* loop_headers_;
ZoneGrowableArray<BitVector*>* loop_invariant_loads_;
ZoneGrowableArray<const Field*>* guarded_fields_;
- GrowableArray<const Field*> deoptimize_dependent_code_;
ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes_;
DirectChainedHashMap<ConstantPoolTrait> constant_instr_pool_;
BitVector* captured_parameters_;
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 63bdb24..458557d 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -41,7 +41,6 @@
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, profile_vm);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
DECLARE_FLAG(bool, use_field_guards);
// Quick access to the locally defined zone() method.
@@ -1594,30 +1593,6 @@
}
-bool FlowGraphBuilder::WarnOnJSIntegralNumTypeTest(
- AstNode* node, const AbstractType& type) const {
- if (!(node->IsLiteralNode() && (type.IsIntType() || type.IsDoubleType()))) {
- return false;
- }
- const Instance& instance = node->AsLiteralNode()->literal();
- if (type.IsIntType()) {
- if (instance.IsDouble()) {
- const Double& double_instance = Double::Cast(instance);
- double value = double_instance.value();
- if (floor(value) == value) {
- return true;
- }
- }
- } else {
- ASSERT(type.IsDoubleType());
- if (instance.IsInteger()) {
- return true;
- }
- }
- return false;
-}
-
-
void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
ASSERT(Token::IsTypeTestOperator(node->kind()));
const AbstractType& type = node->right()->AsTypeNode()->type();
@@ -1638,41 +1613,39 @@
node->left()->Visit(&for_left_value);
Append(for_left_value);
- if (!FLAG_warn_on_javascript_compatibility) {
- if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType() ||
- type.IsSmiType() || type.IsStringType()) {
- String& method_name = String::ZoneHandle(Z);
- if (type.IsNumberType()) {
- method_name = Symbols::_instanceOfNum().raw();
- } else if (type.IsIntType()) {
- method_name = Symbols::_instanceOfInt().raw();
- } else if (type.IsDoubleType()) {
- method_name = Symbols::_instanceOfDouble().raw();
- } else if (type.IsSmiType()) {
- method_name = Symbols::_instanceOfSmi().raw();
- } else if (type.IsStringType()) {
- method_name = Symbols::_instanceOfString().raw();
- }
- ASSERT(!method_name.IsNull());
- PushArgumentInstr* push_left = PushArgument(for_left_value.value());
- ZoneGrowableArray<PushArgumentInstr*>* arguments =
- new(Z) ZoneGrowableArray<PushArgumentInstr*>(2);
- arguments->Add(push_left);
- const Bool& negate = Bool::Get(node->kind() == Token::kISNOT);
- Value* negate_arg = Bind(new(Z) ConstantInstr(negate));
- arguments->Add(PushArgument(negate_arg));
- const intptr_t kNumArgsChecked = 1;
- InstanceCallInstr* call = new(Z) InstanceCallInstr(
- node->token_pos(),
- Library::PrivateCoreLibName(method_name),
- node->kind(),
- arguments,
- Object::null_array(), // No argument names.
- kNumArgsChecked,
- owner()->ic_data_array());
- ReturnDefinition(call);
- return;
+ if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType() ||
+ type.IsSmiType() || type.IsStringType()) {
+ String& method_name = String::ZoneHandle(Z);
+ if (type.IsNumberType()) {
+ method_name = Symbols::_instanceOfNum().raw();
+ } else if (type.IsIntType()) {
+ method_name = Symbols::_instanceOfInt().raw();
+ } else if (type.IsDoubleType()) {
+ method_name = Symbols::_instanceOfDouble().raw();
+ } else if (type.IsSmiType()) {
+ method_name = Symbols::_instanceOfSmi().raw();
+ } else if (type.IsStringType()) {
+ method_name = Symbols::_instanceOfString().raw();
}
+ ASSERT(!method_name.IsNull());
+ PushArgumentInstr* push_left = PushArgument(for_left_value.value());
+ ZoneGrowableArray<PushArgumentInstr*>* arguments =
+ new(Z) ZoneGrowableArray<PushArgumentInstr*>(2);
+ arguments->Add(push_left);
+ const Bool& negate = Bool::Get(node->kind() == Token::kISNOT);
+ Value* negate_arg = Bind(new(Z) ConstantInstr(negate));
+ arguments->Add(PushArgument(negate_arg));
+ const intptr_t kNumArgsChecked = 1;
+ InstanceCallInstr* call = new(Z) InstanceCallInstr(
+ node->token_pos(),
+ Library::PrivateCoreLibName(method_name),
+ node->kind(),
+ arguments,
+ Object::null_array(), // No argument names.
+ kNumArgsChecked,
+ owner()->ic_data_array());
+ ReturnDefinition(call);
+ return;
}
PushArgumentInstr* push_left = PushArgument(for_left_value.value());
@@ -1719,13 +1692,8 @@
for_value.value(),
type,
dst_name)) {
- // Check for javascript compatibility.
- // Do not skip type check if javascript compatibility warning is required.
- if (!FLAG_warn_on_javascript_compatibility ||
- !owner()->WarnOnJSIntegralNumTypeTest(node->left(), type)) {
- ReturnValue(for_value.value());
- return;
- }
+ ReturnValue(for_value.value());
+ return;
}
PushArgumentInstr* push_left = PushArgument(for_value.value());
PushArgumentInstr* push_type_args = NULL;
@@ -4442,8 +4410,23 @@
*method_arguments,
temp,
is_super_invocation);
- const Function& no_such_method_func = Function::ZoneHandle(Z,
- Resolver::ResolveDynamicAnyArgs(target_class, Symbols::NoSuchMethod()));
+ // Make sure we resolve to a compatible noSuchMethod, otherwise call
+ // noSuchMethod of class Object.
+ const int kNumArguments = 2;
+ ArgumentsDescriptor args_desc(
+ Array::ZoneHandle(Z, ArgumentsDescriptor::New(kNumArguments)));
+ Function& no_such_method_func = Function::ZoneHandle(Z,
+ Resolver::ResolveDynamicForReceiverClass(target_class,
+ Symbols::NoSuchMethod(),
+ args_desc));
+ if (no_such_method_func.IsNull()) {
+ const Class& object_class =
+ Class::ZoneHandle(Z, isolate()->object_store()->object_class());
+ no_such_method_func =
+ Resolver::ResolveDynamicForReceiverClass(object_class,
+ Symbols::NoSuchMethod(),
+ args_desc);
+ }
// We are guaranteed to find noSuchMethod of class Object.
ASSERT(!no_such_method_func.IsNull());
ZoneGrowableArray<PushArgumentInstr*>* push_arguments =
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 6dc14ce..27062d6 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -113,11 +113,6 @@
return ic_data_array_;
}
- // Return true if a Javascript compatibility warning should be emitted at
- // runtime for this type test.
- bool WarnOnJSIntegralNumTypeTest(AstNode* node,
- const AbstractType& type) const;
-
void Bailout(const char* reason) const;
intptr_t AllocateBlockId() { return ++last_used_block_id_; }
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 15851e6..ef109ac 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -55,7 +55,6 @@
DECLARE_FLAG(charp, deoptimize_filter);
DECLARE_FLAG(bool, emit_edge_counters);
DECLARE_FLAG(bool, fields_may_be_reset);
-DECLARE_FLAG(bool, guess_icdata_cid);
DECLARE_FLAG(bool, ic_range_profiling);
DECLARE_FLAG(bool, intrinsify);
DECLARE_FLAG(bool, load_deferred_eagerly);
@@ -68,7 +67,6 @@
DECLARE_FLAG(bool, use_field_guards);
DECLARE_FLAG(bool, use_cha_deopt);
DECLARE_FLAG(bool, use_osr);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
DECLARE_FLAG(bool, print_stop_message);
DECLARE_FLAG(bool, lazy_dispatchers);
DECLARE_FLAG(bool, interpret_irregexp);
@@ -1098,7 +1096,7 @@
// Reading from a mutable double box requires allocating a fresh double.
if (load_node.field().guarded_cid() == kDynamicCid) {
GenerateInlinedGetter(load_node.field().Offset());
- return true;
+ return !FLAG_use_field_guards;
}
return false;
}
@@ -1113,7 +1111,7 @@
*sequence_node.NodeAt(0)->AsStoreInstanceFieldNode();
if (store_node.field().guarded_cid() == kDynamicCid) {
GenerateInlinedSetter(store_node.field().Offset());
- return true;
+ return !FLAG_use_field_guards;
}
}
}
@@ -1173,12 +1171,7 @@
return;
}
- if (is_optimizing() &&
- // Do not make the instance call megamorphic if the callee needs to decode
- // the calling code sequence to lookup the ic data and verify if a JS
- // warning has already been issued or not.
- (!FLAG_warn_on_javascript_compatibility ||
- !ic_data.MayCheckForJSWarning())) {
+ if (is_optimizing()) {
EmitMegamorphicInstanceCall(ic_data, argument_count,
deopt_id, token_pos, locs);
return;
@@ -1213,12 +1206,7 @@
ic_data.IsNull() ? ArgumentsDescriptor::New(argument_count,
argument_names)
: ic_data.arguments_descriptor());
- // Proper reporting of Javascript incompatibilities requires icdata and
- // may therefore prevent the optimization of some static calls.
- if (is_optimizing() &&
- !(FLAG_warn_on_javascript_compatibility &&
- (MethodRecognizer::RecognizeKind(function) ==
- MethodRecognizer::kObjectIdentical))) {
+ if (is_optimizing()) {
EmitOptimizedStaticCall(function, arguments_descriptor,
argument_count, deopt_id, token_pos, locs);
} else {
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 8cec8d7..f2fd49d 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -69,6 +69,7 @@
// Quick access to the current zone.
#define Z (zone())
+#define I (isolate())
#define TRACE_INLINING(statement) \
do { \
@@ -705,8 +706,8 @@
// Load IC data for the callee.
ZoneGrowableArray<const ICData*>* ic_data_array =
new(Z) ZoneGrowableArray<const ICData*>();
- const bool clone_descriptors = Compiler::IsBackgroundCompilation();
- function.RestoreICDataMap(ic_data_array, clone_descriptors);
+ const bool clone_ic_data = Compiler::IsBackgroundCompilation();
+ function.RestoreICDataMap(ic_data_array, clone_ic_data);
if (Compiler::IsBackgroundCompilation() &&
(function.ic_data_array() == Array::null())) {
Compiler::AbortBackgroundCompilation(Thread::kNoDeoptId);
@@ -1520,13 +1521,15 @@
new(Z) RedefinitionInstr(new(Z) Value(receiver));
redefinition->set_ssa_temp_index(
owner_->caller_graph()->alloc_ssa_temp_index());
- if (optimizer.TryInlineRecognizedMethod(receiver_cid,
- target,
- call_,
- redefinition,
- call_->instance_call()->token_pos(),
- *call_->instance_call()->ic_data(),
- &entry, &last)) {
+ if (FlowGraphInliner::TryInlineRecognizedMethod(
+ owner_->caller_graph(),
+ receiver_cid,
+ target,
+ call_,
+ redefinition,
+ call_->instance_call()->token_pos(),
+ *call_->instance_call()->ic_data(),
+ &entry, &last)) {
// Create a graph fragment.
redefinition->InsertAfter(entry);
InlineExitCollector* exit_collector =
@@ -1948,4 +1951,1107 @@
}
+static bool ShouldInlineSimd() {
+ return FlowGraphCompiler::SupportsUnboxedSimd128();
+}
+
+
+static bool CanUnboxDouble() {
+ return FlowGraphCompiler::SupportsUnboxedDoubles();
+}
+
+
+static bool ShouldInlineInt64ArrayOps() {
+#if defined(TARGET_ARCH_X64)
+ return true;
+#else
+ return false;
+#endif
+}
+
+
+static bool CanUnboxInt32() {
+ // Int32/Uint32 can be unboxed if it fits into a smi or the platform
+ // supports unboxed mints.
+ return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints();
+}
+
+
+// Quick access to the current one.
+#undef Z
+#define Z (flow_graph->zone())
+
+static intptr_t PrepareInlineIndexedOp(FlowGraph* flow_graph,
+ Instruction* call,
+ intptr_t array_cid,
+ Definition** array,
+ Definition* index,
+ Instruction** cursor) {
+ // Insert index smi check.
+ *cursor = flow_graph->AppendTo(
+ *cursor,
+ new(Z) CheckSmiInstr(new(Z) Value(index),
+ call->deopt_id(),
+ call->token_pos()),
+ call->env(),
+ FlowGraph::kEffect);
+
+ // Insert array length load and bounds check.
+ LoadFieldInstr* length =
+ new(Z) LoadFieldInstr(
+ new(Z) Value(*array),
+ CheckArrayBoundInstr::LengthOffsetFor(array_cid),
+ Type::ZoneHandle(Z, Type::SmiType()),
+ call->token_pos());
+ length->set_is_immutable(
+ CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid));
+ length->set_result_cid(kSmiCid);
+ length->set_recognized_kind(
+ LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
+ *cursor = flow_graph->AppendTo(*cursor,
+ length,
+ NULL,
+ FlowGraph::kValue);
+
+ *cursor = flow_graph->AppendTo(*cursor,
+ new(Z) CheckArrayBoundInstr(
+ new(Z) Value(length),
+ new(Z) Value(index),
+ call->deopt_id()),
+ call->env(),
+ FlowGraph::kEffect);
+
+ if (array_cid == kGrowableObjectArrayCid) {
+ // Insert data elements load.
+ LoadFieldInstr* elements =
+ new(Z) LoadFieldInstr(
+ new(Z) Value(*array),
+ GrowableObjectArray::data_offset(),
+ Object::dynamic_type(),
+ call->token_pos());
+ elements->set_result_cid(kArrayCid);
+ *cursor = flow_graph->AppendTo(*cursor,
+ elements,
+ NULL,
+ FlowGraph::kValue);
+ // Load from the data from backing store which is a fixed-length array.
+ *array = elements;
+ array_cid = kArrayCid;
+ } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ LoadUntaggedInstr* elements =
+ new(Z) LoadUntaggedInstr(new(Z) Value(*array),
+ ExternalTypedData::data_offset());
+ *cursor = flow_graph->AppendTo(*cursor,
+ elements,
+ NULL,
+ FlowGraph::kValue);
+ *array = elements;
+ }
+ return array_cid;
+}
+
+
+static intptr_t MethodKindToCid(MethodRecognizer::Kind kind) {
+ switch (kind) {
+ case MethodRecognizer::kImmutableArrayGetIndexed:
+ return kImmutableArrayCid;
+
+ case MethodRecognizer::kObjectArrayGetIndexed:
+ case MethodRecognizer::kObjectArraySetIndexed:
+ return kArrayCid;
+
+ case MethodRecognizer::kGrowableArrayGetIndexed:
+ case MethodRecognizer::kGrowableArraySetIndexed:
+ return kGrowableObjectArrayCid;
+
+ case MethodRecognizer::kFloat32ArrayGetIndexed:
+ case MethodRecognizer::kFloat32ArraySetIndexed:
+ return kTypedDataFloat32ArrayCid;
+
+ case MethodRecognizer::kFloat64ArrayGetIndexed:
+ case MethodRecognizer::kFloat64ArraySetIndexed:
+ return kTypedDataFloat64ArrayCid;
+
+ case MethodRecognizer::kInt8ArrayGetIndexed:
+ case MethodRecognizer::kInt8ArraySetIndexed:
+ return kTypedDataInt8ArrayCid;
+
+ case MethodRecognizer::kUint8ArrayGetIndexed:
+ case MethodRecognizer::kUint8ArraySetIndexed:
+ return kTypedDataUint8ArrayCid;
+
+ case MethodRecognizer::kUint8ClampedArrayGetIndexed:
+ case MethodRecognizer::kUint8ClampedArraySetIndexed:
+ return kTypedDataUint8ClampedArrayCid;
+
+ case MethodRecognizer::kExternalUint8ArrayGetIndexed:
+ case MethodRecognizer::kExternalUint8ArraySetIndexed:
+ return kExternalTypedDataUint8ArrayCid;
+
+ case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
+ case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
+ return kExternalTypedDataUint8ClampedArrayCid;
+
+ case MethodRecognizer::kInt16ArrayGetIndexed:
+ case MethodRecognizer::kInt16ArraySetIndexed:
+ return kTypedDataInt16ArrayCid;
+
+ case MethodRecognizer::kUint16ArrayGetIndexed:
+ case MethodRecognizer::kUint16ArraySetIndexed:
+ return kTypedDataUint16ArrayCid;
+
+ case MethodRecognizer::kInt32ArrayGetIndexed:
+ case MethodRecognizer::kInt32ArraySetIndexed:
+ return kTypedDataInt32ArrayCid;
+
+ case MethodRecognizer::kUint32ArrayGetIndexed:
+ case MethodRecognizer::kUint32ArraySetIndexed:
+ return kTypedDataUint32ArrayCid;
+
+ case MethodRecognizer::kInt64ArrayGetIndexed:
+ case MethodRecognizer::kInt64ArraySetIndexed:
+ return kTypedDataInt64ArrayCid;
+
+ case MethodRecognizer::kFloat32x4ArrayGetIndexed:
+ case MethodRecognizer::kFloat32x4ArraySetIndexed:
+ return kTypedDataFloat32x4ArrayCid;
+
+ case MethodRecognizer::kInt32x4ArrayGetIndexed:
+ case MethodRecognizer::kInt32x4ArraySetIndexed:
+ return kTypedDataInt32x4ArrayCid;
+
+ case MethodRecognizer::kFloat64x2ArrayGetIndexed:
+ case MethodRecognizer::kFloat64x2ArraySetIndexed:
+ return kTypedDataFloat64x2ArrayCid;
+
+ default:
+ break;
+ }
+ return kIllegalCid;
+}
+
+
+static Instruction* GetCheckClass(FlowGraph* flow_graph,
+ Definition* to_check,
+ const ICData& unary_checks,
+ intptr_t deopt_id,
+ TokenPosition token_pos) {
+ if ((unary_checks.NumberOfUsedChecks() == 1) &&
+ unary_checks.HasReceiverClassId(kSmiCid)) {
+ return new(Z) CheckSmiInstr(new(Z) Value(to_check),
+ deopt_id,
+ token_pos);
+ }
+ return new(Z) CheckClassInstr(
+ new(Z) Value(to_check), deopt_id, unary_checks, token_pos);
+}
+
+
+static bool InlineGetIndexed(FlowGraph* flow_graph,
+ MethodRecognizer::Kind kind,
+ Instruction* call,
+ Definition* receiver,
+ TargetEntryInstr** entry,
+ Definition** last) {
+ intptr_t array_cid = MethodKindToCid(kind);
+ ASSERT(array_cid != kIllegalCid);
+
+ Definition* array = receiver;
+ Definition* index = call->ArgumentAt(1);
+ *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+ call->GetBlock()->try_index());
+ (*entry)->InheritDeoptTarget(Z, call);
+ Instruction* cursor = *entry;
+
+ array_cid = PrepareInlineIndexedOp(flow_graph,
+ call,
+ array_cid,
+ &array,
+ index,
+ &cursor);
+
+ intptr_t deopt_id = Thread::kNoDeoptId;
+ if ((array_cid == kTypedDataInt32ArrayCid) ||
+ (array_cid == kTypedDataUint32ArrayCid)) {
+ // Deoptimization may be needed if result does not always fit in a Smi.
+ deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id();
+ }
+
+ // Array load and return.
+ intptr_t index_scale = Instance::ElementSizeFor(array_cid);
+ *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
+ new(Z) Value(index),
+ index_scale,
+ array_cid,
+ deopt_id,
+ call->token_pos());
+ cursor = flow_graph->AppendTo(
+ cursor,
+ *last,
+ deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
+ FlowGraph::kValue);
+
+ if (array_cid == kTypedDataFloat32ArrayCid) {
+ *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id);
+ flow_graph->AppendTo(cursor,
+ *last,
+ deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
+ FlowGraph::kValue);
+ }
+ return true;
+}
+
+
+static bool InlineSetIndexed(FlowGraph* flow_graph,
+ MethodRecognizer::Kind kind,
+ const Function& target,
+ Instruction* call,
+ Definition* receiver,
+ TokenPosition token_pos,
+ const ICData& value_check,
+ TargetEntryInstr** entry,
+ Definition** last) {
+ intptr_t array_cid = MethodKindToCid(kind);
+ ASSERT(array_cid != kIllegalCid);
+
+ Definition* array = receiver;
+ Definition* index = call->ArgumentAt(1);
+ Definition* stored_value = call->ArgumentAt(2);
+
+ *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+ call->GetBlock()->try_index());
+ (*entry)->InheritDeoptTarget(Z, call);
+ Instruction* cursor = *entry;
+ if (flow_graph->isolate()->flags().type_checks()) {
+ // Only type check for the value. A type check for the index is not
+ // needed here because we insert a deoptimizing smi-check for the case
+ // the index is not a smi.
+ const AbstractType& value_type =
+ AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2));
+ Definition* type_args = NULL;
+ switch (array_cid) {
+ case kArrayCid:
+ case kGrowableObjectArrayCid: {
+ const Class& instantiator_class = Class::Handle(Z, target.Owner());
+ intptr_t type_arguments_field_offset =
+ instantiator_class.type_arguments_field_offset();
+ LoadFieldInstr* load_type_args =
+ new(Z) LoadFieldInstr(new(Z) Value(array),
+ type_arguments_field_offset,
+ Type::ZoneHandle(Z), // No type.
+ call->token_pos());
+ cursor = flow_graph->AppendTo(cursor,
+ load_type_args,
+ NULL,
+ FlowGraph::kValue);
+
+ type_args = load_type_args;
+ break;
+ }
+ case kTypedDataInt8ArrayCid:
+ case kTypedDataUint8ArrayCid:
+ case kTypedDataUint8ClampedArrayCid:
+ case kExternalTypedDataUint8ArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid:
+ case kTypedDataInt32ArrayCid:
+ case kTypedDataUint32ArrayCid:
+ case kTypedDataInt64ArrayCid:
+ ASSERT(value_type.IsIntType());
+ // Fall through.
+ case kTypedDataFloat32ArrayCid:
+ case kTypedDataFloat64ArrayCid: {
+ type_args = flow_graph->constant_null();
+ ASSERT((array_cid != kTypedDataFloat32ArrayCid &&
+ array_cid != kTypedDataFloat64ArrayCid) ||
+ value_type.IsDoubleType());
+ ASSERT(value_type.IsInstantiated());
+ break;
+ }
+ case kTypedDataFloat32x4ArrayCid: {
+ type_args = flow_graph->constant_null();
+ ASSERT((array_cid != kTypedDataFloat32x4ArrayCid) ||
+ value_type.IsFloat32x4Type());
+ ASSERT(value_type.IsInstantiated());
+ break;
+ }
+ case kTypedDataFloat64x2ArrayCid: {
+ type_args = flow_graph->constant_null();
+ ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) ||
+ value_type.IsFloat64x2Type());
+ ASSERT(value_type.IsInstantiated());
+ break;
+ }
+ default:
+ // TODO(fschneider): Add support for other array types.
+ UNREACHABLE();
+ }
+ AssertAssignableInstr* assert_value =
+ new(Z) AssertAssignableInstr(token_pos,
+ new(Z) Value(stored_value),
+ new(Z) Value(type_args),
+ value_type,
+ Symbols::Value(),
+ call->deopt_id());
+ cursor = flow_graph->AppendTo(cursor,
+ assert_value,
+ call->env(),
+ FlowGraph::kValue);
+ }
+
+ array_cid = PrepareInlineIndexedOp(flow_graph,
+ call,
+ array_cid,
+ &array,
+ index,
+ &cursor);
+
+ // Check if store barrier is needed. Byte arrays don't need a store barrier.
+ StoreBarrierType needs_store_barrier =
+ (RawObject::IsTypedDataClassId(array_cid) ||
+ RawObject::IsTypedDataViewClassId(array_cid) ||
+ RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier
+ : kEmitStoreBarrier;
+
+ // No need to class check stores to Int32 and Uint32 arrays because
+ // we insert unboxing instructions below which include a class check.
+ if ((array_cid != kTypedDataUint32ArrayCid) &&
+ (array_cid != kTypedDataInt32ArrayCid) &&
+ !value_check.IsNull()) {
+ // No store barrier needed because checked value is a smi, an unboxed mint,
+ // an unboxed double, an unboxed Float32x4, or unboxed Int32x4.
+ needs_store_barrier = kNoStoreBarrier;
+ Instruction* check = GetCheckClass(flow_graph,
+ stored_value,
+ value_check,
+ call->deopt_id(),
+ call->token_pos());
+ cursor = flow_graph->AppendTo(cursor,
+ check,
+ call->env(),
+ FlowGraph::kEffect);
+ }
+
+ if (array_cid == kTypedDataFloat32ArrayCid) {
+ stored_value =
+ new(Z) DoubleToFloatInstr(
+ new(Z) Value(stored_value), call->deopt_id());
+ cursor = flow_graph->AppendTo(cursor,
+ stored_value,
+ NULL,
+ FlowGraph::kValue);
+ } else if (array_cid == kTypedDataInt32ArrayCid) {
+ stored_value = new(Z) UnboxInt32Instr(
+ UnboxInt32Instr::kTruncate,
+ new(Z) Value(stored_value),
+ call->deopt_id());
+ cursor = flow_graph->AppendTo(cursor,
+ stored_value,
+ call->env(),
+ FlowGraph::kValue);
+ } else if (array_cid == kTypedDataUint32ArrayCid) {
+ stored_value = new(Z) UnboxUint32Instr(
+ new(Z) Value(stored_value),
+ call->deopt_id());
+ ASSERT(stored_value->AsUnboxInteger()->is_truncating());
+ cursor = flow_graph->AppendTo(cursor,
+ stored_value,
+ call->env(),
+ FlowGraph::kValue);
+ }
+
+ const intptr_t index_scale = Instance::ElementSizeFor(array_cid);
+ *last = new(Z) StoreIndexedInstr(new(Z) Value(array),
+ new(Z) Value(index),
+ new(Z) Value(stored_value),
+ needs_store_barrier,
+ index_scale,
+ array_cid,
+ call->deopt_id(),
+ call->token_pos());
+ flow_graph->AppendTo(cursor,
+ *last,
+ call->env(),
+ FlowGraph::kEffect);
+ return true;
+}
+
+
+static bool InlineDoubleOp(FlowGraph* flow_graph,
+ Token::Kind op_kind,
+ Instruction* call,
+ TargetEntryInstr** entry,
+ Definition** last) {
+ Definition* left = call->ArgumentAt(0);
+ Definition* right = call->ArgumentAt(1);
+
+ *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+ call->GetBlock()->try_index());
+ (*entry)->InheritDeoptTarget(Z, call);
+ // Arguments are checked. No need for class check.
+ BinaryDoubleOpInstr* double_bin_op =
+ new(Z) BinaryDoubleOpInstr(op_kind,
+ new(Z) Value(left),
+ new(Z) Value(right),
+ call->deopt_id(), call->token_pos());
+ flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
+ *last = double_bin_op;
+
+ return true;
+}
+
+
+static intptr_t PrepareInlineByteArrayBaseOp(
+ FlowGraph* flow_graph,
+ Instruction* call,
+ intptr_t array_cid,
+ intptr_t view_cid,
+ Definition** array,
+ Definition* byte_index,
+ Instruction** cursor) {
+ // Insert byte_index smi check.
+ *cursor = flow_graph->AppendTo(*cursor,
+ new(Z) CheckSmiInstr(
+ new(Z) Value(byte_index),
+ call->deopt_id(),
+ call->token_pos()),
+ call->env(),
+ FlowGraph::kEffect);
+
+ LoadFieldInstr* length =
+ new(Z) LoadFieldInstr(
+ new(Z) Value(*array),
+ CheckArrayBoundInstr::LengthOffsetFor(array_cid),
+ Type::ZoneHandle(Z, Type::SmiType()),
+ call->token_pos());
+ length->set_is_immutable(true);
+ length->set_result_cid(kSmiCid);
+ length->set_recognized_kind(
+ LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
+ *cursor = flow_graph->AppendTo(*cursor,
+ length,
+ NULL,
+ FlowGraph::kValue);
+
+ intptr_t element_size = Instance::ElementSizeFor(array_cid);
+ ConstantInstr* bytes_per_element =
+ flow_graph->GetConstant(Smi::Handle(Z, Smi::New(element_size)));
+ BinarySmiOpInstr* len_in_bytes =
+ new(Z) BinarySmiOpInstr(Token::kMUL,
+ new(Z) Value(length),
+ new(Z) Value(bytes_per_element),
+ call->deopt_id());
+ *cursor = flow_graph->AppendTo(*cursor, len_in_bytes, call->env(),
+ FlowGraph::kValue);
+
+ // adjusted_length = len_in_bytes - (element_size - 1).
+ Definition* adjusted_length = len_in_bytes;
+ intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1;
+ if (adjustment > 0) {
+ ConstantInstr* length_adjustment =
+ flow_graph->GetConstant(Smi::Handle(Z, Smi::New(adjustment)));
+ adjusted_length =
+ new(Z) BinarySmiOpInstr(Token::kSUB,
+ new(Z) Value(len_in_bytes),
+ new(Z) Value(length_adjustment),
+ call->deopt_id());
+ *cursor = flow_graph->AppendTo(*cursor, adjusted_length, call->env(),
+ FlowGraph::kValue);
+ }
+
+ // Check adjusted_length > 0.
+ ConstantInstr* zero =
+ flow_graph->GetConstant(Smi::Handle(Z, Smi::New(0)));
+ *cursor = flow_graph->AppendTo(*cursor,
+ new(Z) CheckArrayBoundInstr(
+ new(Z) Value(adjusted_length),
+ new(Z) Value(zero),
+ call->deopt_id()),
+ call->env(),
+ FlowGraph::kEffect);
+ // Check 0 <= byte_index < adjusted_length.
+ *cursor = flow_graph->AppendTo(*cursor,
+ new(Z) CheckArrayBoundInstr(
+ new(Z) Value(adjusted_length),
+ new(Z) Value(byte_index),
+ call->deopt_id()),
+ call->env(),
+ FlowGraph::kEffect);
+
+ if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ LoadUntaggedInstr* elements =
+ new(Z) LoadUntaggedInstr(new(Z) Value(*array),
+ ExternalTypedData::data_offset());
+ *cursor = flow_graph->AppendTo(*cursor,
+ elements,
+ NULL,
+ FlowGraph::kValue);
+ *array = elements;
+ }
+ return array_cid;
+}
+
+
+static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph,
+ Instruction* call,
+ Definition* receiver,
+ intptr_t array_cid,
+ intptr_t view_cid,
+ TargetEntryInstr** entry,
+ Definition** last) {
+ ASSERT(array_cid != kIllegalCid);
+ Definition* array = receiver;
+ Definition* index = call->ArgumentAt(1);
+ *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+ call->GetBlock()->try_index());
+ (*entry)->InheritDeoptTarget(Z, call);
+ Instruction* cursor = *entry;
+
+ array_cid = PrepareInlineByteArrayBaseOp(flow_graph,
+ call,
+ array_cid,
+ view_cid,
+ &array,
+ index,
+ &cursor);
+
+ intptr_t deopt_id = Thread::kNoDeoptId;
+ if ((array_cid == kTypedDataInt32ArrayCid) ||
+ (array_cid == kTypedDataUint32ArrayCid)) {
+ // Deoptimization may be needed if result does not always fit in a Smi.
+ deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id();
+ }
+
+ *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
+ new(Z) Value(index),
+ 1,
+ view_cid,
+ deopt_id,
+ call->token_pos());
+ cursor = flow_graph->AppendTo(
+ cursor,
+ *last,
+ deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
+ FlowGraph::kValue);
+
+ if (view_cid == kTypedDataFloat32ArrayCid) {
+ *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id);
+ flow_graph->AppendTo(cursor,
+ *last,
+ deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
+ FlowGraph::kValue);
+ }
+ return true;
+}
+
+
+static bool InlineByteArrayBaseStore(FlowGraph* flow_graph,
+ const Function& target,
+ Instruction* call,
+ Definition* receiver,
+ intptr_t array_cid,
+ intptr_t view_cid,
+ TargetEntryInstr** entry,
+ Definition** last) {
+ ASSERT(array_cid != kIllegalCid);
+ Definition* array = receiver;
+ Definition* index = call->ArgumentAt(1);
+ *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+ call->GetBlock()->try_index());
+ (*entry)->InheritDeoptTarget(Z, call);
+ Instruction* cursor = *entry;
+
+ array_cid = PrepareInlineByteArrayBaseOp(flow_graph,
+ call,
+ array_cid,
+ view_cid,
+ &array,
+ index,
+ &cursor);
+
+ // Extract the instance call so we can use the function_name in the stored
+ // value check ICData.
+ InstanceCallInstr* i_call = NULL;
+ if (call->IsPolymorphicInstanceCall()) {
+ i_call = call->AsPolymorphicInstanceCall()->instance_call();
+ } else {
+ ASSERT(call->IsInstanceCall());
+ i_call = call->AsInstanceCall();
+ }
+ ASSERT(i_call != NULL);
+ ICData& value_check = ICData::ZoneHandle(Z);
+ switch (view_cid) {
+ case kTypedDataInt8ArrayCid:
+ case kTypedDataUint8ArrayCid:
+ case kTypedDataUint8ClampedArrayCid:
+ case kExternalTypedDataUint8ArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid: {
+ // Check that value is always smi.
+ value_check = ICData::New(flow_graph->function(),
+ i_call->function_name(),
+ Object::empty_array(), // Dummy args. descr.
+ Thread::kNoDeoptId,
+ 1);
+ value_check.AddReceiverCheck(kSmiCid, target);
+ break;
+ }
+ case kTypedDataInt32ArrayCid:
+ case kTypedDataUint32ArrayCid:
+ // On 64-bit platforms assume that stored value is always a smi.
+ if (kSmiBits >= 32) {
+ value_check = ICData::New(flow_graph->function(),
+ i_call->function_name(),
+ Object::empty_array(), // Dummy args. descr.
+ Thread::kNoDeoptId,
+ 1);
+ value_check.AddReceiverCheck(kSmiCid, target);
+ }
+ break;
+ case kTypedDataFloat32ArrayCid:
+ case kTypedDataFloat64ArrayCid: {
+ // Check that value is always double.
+ value_check = ICData::New(flow_graph->function(),
+ i_call->function_name(),
+ Object::empty_array(), // Dummy args. descr.
+ Thread::kNoDeoptId,
+ 1);
+ value_check.AddReceiverCheck(kDoubleCid, target);
+ break;
+ }
+ case kTypedDataInt32x4ArrayCid: {
+ // Check that value is always Int32x4.
+ value_check = ICData::New(flow_graph->function(),
+ i_call->function_name(),
+ Object::empty_array(), // Dummy args. descr.
+ Thread::kNoDeoptId,
+ 1);
+ value_check.AddReceiverCheck(kInt32x4Cid, target);
+ break;
+ }
+ case kTypedDataFloat32x4ArrayCid: {
+ // Check that value is always Float32x4.
+ value_check = ICData::New(flow_graph->function(),
+ i_call->function_name(),
+ Object::empty_array(), // Dummy args. descr.
+ Thread::kNoDeoptId,
+ 1);
+ value_check.AddReceiverCheck(kFloat32x4Cid, target);
+ break;
+ }
+ default:
+ // Array cids are already checked in the caller.
+ UNREACHABLE();
+ }
+
+ Definition* stored_value = call->ArgumentAt(2);
+ if (!value_check.IsNull()) {
+ Instruction* check = GetCheckClass(flow_graph,
+ stored_value,
+ value_check,
+ call->deopt_id(),
+ call->token_pos());
+ cursor = flow_graph->AppendTo(cursor,
+ check,
+ call->env(),
+ FlowGraph::kEffect);
+ }
+
+ if (view_cid == kTypedDataFloat32ArrayCid) {
+ stored_value = new(Z) DoubleToFloatInstr(
+ new(Z) Value(stored_value), call->deopt_id());
+ cursor = flow_graph->AppendTo(cursor,
+ stored_value,
+ NULL,
+ FlowGraph::kValue);
+ } else if (view_cid == kTypedDataInt32ArrayCid) {
+ stored_value = new(Z) UnboxInt32Instr(
+ UnboxInt32Instr::kTruncate,
+ new(Z) Value(stored_value),
+ call->deopt_id());
+ cursor = flow_graph->AppendTo(cursor,
+ stored_value,
+ call->env(),
+ FlowGraph::kValue);
+ } else if (view_cid == kTypedDataUint32ArrayCid) {
+ stored_value = new(Z) UnboxUint32Instr(
+ new(Z) Value(stored_value),
+ call->deopt_id());
+ ASSERT(stored_value->AsUnboxInteger()->is_truncating());
+ cursor = flow_graph->AppendTo(cursor,
+ stored_value,
+ call->env(),
+ FlowGraph::kValue);
+ }
+
+ StoreBarrierType needs_store_barrier = kNoStoreBarrier;
+ *last = new(Z) StoreIndexedInstr(new(Z) Value(array),
+ new(Z) Value(index),
+ new(Z) Value(stored_value),
+ needs_store_barrier,
+ 1, // Index scale
+ view_cid,
+ call->deopt_id(),
+ call->token_pos());
+
+ flow_graph->AppendTo(cursor,
+ *last,
+ call->deopt_id() != Thread::kNoDeoptId ?
+ call->env() : NULL,
+ FlowGraph::kEffect);
+ return true;
+}
+
+
+
+// Returns the LoadIndexedInstr.
+static Definition* PrepareInlineStringIndexOp(
+ FlowGraph* flow_graph,
+ Instruction* call,
+ intptr_t cid,
+ Definition* str,
+ Definition* index,
+ Instruction* cursor) {
+
+ cursor = flow_graph->AppendTo(cursor,
+ new(Z) CheckSmiInstr(
+ new(Z) Value(index),
+ call->deopt_id(),
+ call->token_pos()),
+ call->env(),
+ FlowGraph::kEffect);
+
+ // Load the length of the string.
+ // Treat length loads as mutable (i.e. affected by side effects) to avoid
+ // hoisting them since we can't hoist the preceding class-check. This
+ // is because of externalization of strings that affects their class-id.
+ LoadFieldInstr* length = new(Z) LoadFieldInstr(
+ new(Z) Value(str),
+ String::length_offset(),
+ Type::ZoneHandle(Z, Type::SmiType()),
+ str->token_pos());
+ length->set_result_cid(kSmiCid);
+ length->set_recognized_kind(MethodRecognizer::kStringBaseLength);
+
+ cursor = flow_graph->AppendTo(cursor, length, NULL, FlowGraph::kValue);
+ // Bounds check.
+ cursor = flow_graph->AppendTo(cursor,
+ new(Z) CheckArrayBoundInstr(
+ new(Z) Value(length),
+ new(Z) Value(index),
+ call->deopt_id()),
+ call->env(),
+ FlowGraph::kEffect);
+
+ LoadIndexedInstr* load_indexed = new(Z) LoadIndexedInstr(
+ new(Z) Value(str),
+ new(Z) Value(index),
+ Instance::ElementSizeFor(cid),
+ cid,
+ Thread::kNoDeoptId,
+ call->token_pos());
+
+ cursor = flow_graph->AppendTo(cursor, load_indexed, NULL, FlowGraph::kValue);
+ ASSERT(cursor == load_indexed);
+ return load_indexed;
+}
+
+
+static bool InlineStringBaseCharAt(
+ FlowGraph* flow_graph,
+ Instruction* call,
+ intptr_t cid,
+ TargetEntryInstr** entry,
+ Definition** last) {
+ // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp.
+ if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) {
+ return false;
+ }
+ Definition* str = call->ArgumentAt(0);
+ Definition* index = call->ArgumentAt(1);
+
+ *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+ call->GetBlock()->try_index());
+ (*entry)->InheritDeoptTarget(Z, call);
+
+ *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry);
+
+ StringFromCharCodeInstr* char_at = new(Z) StringFromCharCodeInstr(
+ new(Z) Value(*last), cid);
+
+ flow_graph->AppendTo(*last, char_at, NULL, FlowGraph::kValue);
+ *last = char_at;
+
+ return true;
+}
+
+
+static bool InlineStringCodeUnitAt(
+ FlowGraph* flow_graph,
+ Instruction* call,
+ intptr_t cid,
+ TargetEntryInstr** entry,
+ Definition** last) {
+ // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp.
+ if (RawObject::IsExternalStringClassId(cid)) {
+ return false;
+ }
+
+ Definition* str = call->ArgumentAt(0);
+ Definition* index = call->ArgumentAt(1);
+
+ *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
+ call->GetBlock()->try_index());
+ (*entry)->InheritDeoptTarget(Z, call);
+
+ *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry);
+
+ return true;
+}
+
+
+bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph,
+ intptr_t receiver_cid,
+ const Function& target,
+ Instruction* call,
+ Definition* receiver,
+ TokenPosition token_pos,
+ const ICData& ic_data,
+ TargetEntryInstr** entry,
+ Definition** last) {
+ ICData& value_check = ICData::ZoneHandle(Z);
+ MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
+ switch (kind) {
+ // Recognized [] operators.
+ case MethodRecognizer::kImmutableArrayGetIndexed:
+ case MethodRecognizer::kObjectArrayGetIndexed:
+ case MethodRecognizer::kGrowableArrayGetIndexed:
+ case MethodRecognizer::kInt8ArrayGetIndexed:
+ case MethodRecognizer::kUint8ArrayGetIndexed:
+ case MethodRecognizer::kUint8ClampedArrayGetIndexed:
+ case MethodRecognizer::kExternalUint8ArrayGetIndexed:
+ case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
+ case MethodRecognizer::kInt16ArrayGetIndexed:
+ case MethodRecognizer::kUint16ArrayGetIndexed:
+ return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
+ case MethodRecognizer::kFloat32ArrayGetIndexed:
+ case MethodRecognizer::kFloat64ArrayGetIndexed:
+ if (!CanUnboxDouble()) {
+ return false;
+ }
+ return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
+ case MethodRecognizer::kFloat32x4ArrayGetIndexed:
+ case MethodRecognizer::kFloat64x2ArrayGetIndexed:
+ if (!ShouldInlineSimd()) {
+ return false;
+ }
+ return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
+ case MethodRecognizer::kInt32ArrayGetIndexed:
+ case MethodRecognizer::kUint32ArrayGetIndexed:
+ if (!CanUnboxInt32()) return false;
+ return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
+
+ case MethodRecognizer::kInt64ArrayGetIndexed:
+ if (!ShouldInlineInt64ArrayOps()) {
+ return false;
+ }
+ return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
+ // Recognized []= operators.
+ case MethodRecognizer::kObjectArraySetIndexed:
+ case MethodRecognizer::kGrowableArraySetIndexed:
+ return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+ token_pos, value_check, entry, last);
+ case MethodRecognizer::kInt8ArraySetIndexed:
+ case MethodRecognizer::kUint8ArraySetIndexed:
+ case MethodRecognizer::kUint8ClampedArraySetIndexed:
+ case MethodRecognizer::kExternalUint8ArraySetIndexed:
+ case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
+ case MethodRecognizer::kInt16ArraySetIndexed:
+ case MethodRecognizer::kUint16ArraySetIndexed:
+ // Optimistically assume Smi.
+ if (ic_data.HasDeoptReason(ICData::kDeoptCheckSmi)) {
+ // Optimistic assumption failed at least once.
+ return false;
+ }
+ value_check = ic_data.AsUnaryClassChecksForCid(kSmiCid, target);
+ return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+ token_pos, value_check, entry, last);
+ case MethodRecognizer::kInt32ArraySetIndexed:
+ case MethodRecognizer::kUint32ArraySetIndexed: {
+ // Value check not needed for Int32 and Uint32 arrays because they
+ // implicitly contain unboxing instructions which check for right type.
+ ICData& value_check = ICData::Handle();
+ return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+ token_pos, value_check, entry, last);
+ }
+ case MethodRecognizer::kInt64ArraySetIndexed:
+ if (!ShouldInlineInt64ArrayOps()) {
+ return false;
+ }
+ return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+ token_pos, value_check, entry, last);
+ case MethodRecognizer::kFloat32ArraySetIndexed:
+ case MethodRecognizer::kFloat64ArraySetIndexed:
+ if (!CanUnboxDouble()) {
+ return false;
+ }
+ value_check = ic_data.AsUnaryClassChecksForCid(kDoubleCid, target);
+ return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+ token_pos, value_check, entry, last);
+ case MethodRecognizer::kFloat32x4ArraySetIndexed:
+ if (!ShouldInlineSimd()) {
+ return false;
+ }
+ value_check = ic_data.AsUnaryClassChecksForCid(kFloat32x4Cid, target);
+
+ return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+ token_pos, value_check, entry, last);
+ case MethodRecognizer::kFloat64x2ArraySetIndexed:
+ if (!ShouldInlineSimd()) {
+ return false;
+ }
+ value_check = ic_data.AsUnaryClassChecksForCid(kFloat64x2Cid, target);
+ return InlineSetIndexed(flow_graph, kind, target, call, receiver,
+ token_pos, value_check, entry, last);
+ case MethodRecognizer::kByteArrayBaseGetInt8:
+ return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+ kTypedDataInt8ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseGetUint8:
+ return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+ kTypedDataUint8ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseGetInt16:
+ return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+ kTypedDataInt16ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseGetUint16:
+ return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+ kTypedDataUint16ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseGetInt32:
+ if (!CanUnboxInt32()) {
+ return false;
+ }
+ return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+ kTypedDataInt32ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseGetUint32:
+ if (!CanUnboxInt32()) {
+ return false;
+ }
+ return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+ kTypedDataUint32ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseGetFloat32:
+ if (!CanUnboxDouble()) {
+ return false;
+ }
+ return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+ kTypedDataFloat32ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseGetFloat64:
+ if (!CanUnboxDouble()) {
+ return false;
+ }
+ return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+ kTypedDataFloat64ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseGetFloat32x4:
+ if (!ShouldInlineSimd()) {
+ return false;
+ }
+ return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+ kTypedDataFloat32x4ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseGetInt32x4:
+ if (!ShouldInlineSimd()) {
+ return false;
+ }
+ return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
+ kTypedDataInt32x4ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseSetInt8:
+ return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+ receiver_cid, kTypedDataInt8ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseSetUint8:
+ return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+ receiver_cid,
+ kTypedDataUint8ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseSetInt16:
+ return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+ receiver_cid,
+ kTypedDataInt16ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseSetUint16:
+ return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+ receiver_cid,
+ kTypedDataUint16ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseSetInt32:
+ return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+ receiver_cid,
+ kTypedDataInt32ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseSetUint32:
+ return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+ receiver_cid,
+ kTypedDataUint32ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseSetFloat32:
+ if (!CanUnboxDouble()) {
+ return false;
+ }
+ return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+ receiver_cid,
+ kTypedDataFloat32ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseSetFloat64:
+ if (!CanUnboxDouble()) {
+ return false;
+ }
+ return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+ receiver_cid,
+ kTypedDataFloat64ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseSetFloat32x4:
+ if (!ShouldInlineSimd()) {
+ return false;
+ }
+ return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+ receiver_cid,
+ kTypedDataFloat32x4ArrayCid,
+ entry, last);
+ case MethodRecognizer::kByteArrayBaseSetInt32x4:
+ if (!ShouldInlineSimd()) {
+ return false;
+ }
+ return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
+ receiver_cid,
+ kTypedDataInt32x4ArrayCid,
+ entry, last);
+ case MethodRecognizer::kStringBaseCodeUnitAt:
+ return InlineStringCodeUnitAt(
+ flow_graph, call, receiver_cid, entry, last);
+ case MethodRecognizer::kStringBaseCharAt:
+ return InlineStringBaseCharAt(
+ flow_graph, call, receiver_cid, entry, last);
+ case MethodRecognizer::kDoubleAdd:
+ return InlineDoubleOp(flow_graph, Token::kADD, call, entry, last);
+ case MethodRecognizer::kDoubleSub:
+ return InlineDoubleOp(flow_graph, Token::kSUB, call, entry, last);
+ case MethodRecognizer::kDoubleMul:
+ return InlineDoubleOp(flow_graph, Token::kMUL, call, entry, last);
+ case MethodRecognizer::kDoubleDiv:
+ return InlineDoubleOp(flow_graph, Token::kDIV, call, entry, last);
+ default:
+ return false;
+ }
+}
+
+
} // namespace dart
diff --git a/runtime/vm/flow_graph_inliner.h b/runtime/vm/flow_graph_inliner.h
index 6e3ce09..c4d8ca2 100644
--- a/runtime/vm/flow_graph_inliner.h
+++ b/runtime/vm/flow_graph_inliner.h
@@ -10,9 +10,12 @@
namespace dart {
+class Definition;
class Field;
class FlowGraph;
class Function;
+class Instruction;
+class TargetEntryInstr;
class FlowGraphInliner : ValueObject {
public:
@@ -36,6 +39,16 @@
bool trace_inlining() const { return trace_inlining_; }
+ static bool TryInlineRecognizedMethod(FlowGraph* flow_graph,
+ intptr_t receiver_cid,
+ const Function& target,
+ Instruction* call,
+ Definition* receiver,
+ TokenPosition token_pos,
+ const ICData& ic_data,
+ TargetEntryInstr** entry,
+ Definition** last);
+
private:
friend class CallSiteInliner;
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index f10954a..b4c3a2a 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -13,6 +13,7 @@
#include "vm/exceptions.h"
#include "vm/flow_graph_builder.h"
#include "vm/flow_graph_compiler.h"
+#include "vm/flow_graph_inliner.h"
#include "vm/flow_graph_range_analysis.h"
#include "vm/hash_map.h"
#include "vm/il_printer.h"
@@ -49,11 +50,8 @@
DECLARE_FLAG(bool, precompilation);
DECLARE_FLAG(bool, polymorphic_with_deopt);
-DECLARE_FLAG(bool, source_lines);
DECLARE_FLAG(bool, trace_cha);
DECLARE_FLAG(bool, trace_field_guards);
-DECLARE_FLAG(bool, trace_type_check_elimination);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
// Quick access to the current isolate and zone.
#define I (isolate())
@@ -69,13 +67,6 @@
}
-static bool ShouldInlineInt64ArrayOps() {
-#if defined(TARGET_ARCH_X64)
- return true;
-#endif
- return false;
-}
-
static bool CanConvertUnboxedMintToDouble() {
#if defined(TARGET_ARCH_IA32)
return true;
@@ -97,9 +88,10 @@
void FlowGraphOptimizer::PopulateWithICData() {
ASSERT(current_iterator_ == NULL);
- for (intptr_t i = 0; i < block_order_.length(); ++i) {
- BlockEntryInstr* entry = block_order_[i];
- ForwardInstructionIterator it(entry);
+ for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ ForwardInstructionIterator it(block_it.Current());
for (; !it.Done(); it.Advance()) {
Instruction* instr = it.Current();
if (instr->IsInstanceCall()) {
@@ -130,9 +122,10 @@
// e.g., receiver class id, guarded-cid, or by guessing cid-s.
void FlowGraphOptimizer::ApplyClassIds() {
ASSERT(current_iterator_ == NULL);
- for (intptr_t i = 0; i < block_order_.length(); ++i) {
- BlockEntryInstr* entry = block_order_[i];
- ForwardInstructionIterator it(entry);
+ for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ ForwardInstructionIterator it(block_it.Current());
current_iterator_ = ⁢
for (; !it.Done(); it.Advance()) {
Instruction* instr = it.Current();
@@ -172,14 +165,6 @@
// to megamorphic call.
return false;
}
- if (FLAG_warn_on_javascript_compatibility) {
- // Do not make the instance call megamorphic if the callee needs to decode
- // the calling code sequence to lookup the ic data and verify if a warning
- // has already been issued or not.
- if (call->ic_data()->MayCheckForJSWarning()) {
- return false;
- }
- }
GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested());
ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount());
for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) {
@@ -418,28 +403,6 @@
}
-
-// Used by TryMergeDivMod.
-// Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction,
-// and the using instruction. This is an intermediate step before merging.
-void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr,
- intptr_t ix,
- intptr_t cid) {
- const intptr_t index_scale = Instance::ElementSizeFor(cid);
- ConstantInstr* index_instr =
- flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(ix)));
- LoadIndexedInstr* load =
- new(Z) LoadIndexedInstr(new(Z) Value(instr),
- new(Z) Value(index_instr),
- index_scale,
- cid,
- Thread::kNoDeoptId,
- instr->token_pos());
- instr->ReplaceUsesWith(load);
- flow_graph()->InsertAfter(instr, load, NULL, FlowGraph::kValue);
-}
-
-
void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr,
intptr_t index,
Representation rep,
@@ -595,12 +558,13 @@
ASSERT(current_iterator_ == NULL);
GrowableArray<BinarySmiOpInstr*> div_mod_merge;
GrowableArray<MathUnaryInstr*> sin_cos_merge;
- for (intptr_t i = 0; i < block_order_.length(); ++i) {
+ for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
// Merging only per basic-block.
div_mod_merge.Clear();
sin_cos_merge.Clear();
- BlockEntryInstr* entry = block_order_[i];
- ForwardInstructionIterator it(entry);
+ ForwardInstructionIterator it(block_it.Current());
current_iterator_ = ⁢
for (; !it.Done(); it.Advance()) {
if (it.Current()->IsBinarySmiOp()) {
@@ -641,9 +605,13 @@
bool FlowGraphOptimizer::Canonicalize() {
bool changed = false;
- for (intptr_t i = 0; i < block_order_.length(); ++i) {
- BlockEntryInstr* entry = block_order_[i];
- for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
+
+ for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ for (ForwardInstructionIterator it(block_it.Current());
+ !it.Done();
+ it.Advance()) {
Instruction* current = it.Current();
if (current->HasUnmatchedInputRepresentations()) {
// Can't canonicalize this instruction until all conversions for its
@@ -875,8 +843,10 @@
void FlowGraphOptimizer::SelectRepresentations() {
// Conservatively unbox all phis that were proven to be of Double,
// Float32x4, or Int32x4 type.
- for (intptr_t i = 0; i < block_order_.length(); ++i) {
- JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry();
+ for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ JoinEntryInstr* join_entry = block_it.Current()->AsJoinEntry();
if (join_entry != NULL) {
for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
PhiInstr* phi = it.Current();
@@ -886,15 +856,17 @@
}
// Process all instructions and insert conversions where needed.
- GraphEntryInstr* graph_entry = block_order_[0]->AsGraphEntry();
+ GraphEntryInstr* graph_entry = flow_graph_->graph_entry();
// Visit incoming parameters and constants.
for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
InsertConversionsFor((*graph_entry->initial_definitions())[i]);
}
- for (intptr_t i = 0; i < block_order_.length(); ++i) {
- BlockEntryInstr* entry = block_order_[i];
+ for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ BlockEntryInstr* entry = block_it.Current();
JoinEntryInstr* join_entry = entry->AsJoinEntry();
if (join_entry != NULL) {
for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
@@ -1138,93 +1110,6 @@
}
-static bool CanUnboxInt32() {
- // Int32/Uint32 can be unboxed if it fits into a smi or the platform
- // supports unboxed mints.
- return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints();
-}
-
-
-static intptr_t MethodKindToCid(MethodRecognizer::Kind kind) {
- switch (kind) {
- case MethodRecognizer::kImmutableArrayGetIndexed:
- return kImmutableArrayCid;
-
- case MethodRecognizer::kObjectArrayGetIndexed:
- case MethodRecognizer::kObjectArraySetIndexed:
- return kArrayCid;
-
- case MethodRecognizer::kGrowableArrayGetIndexed:
- case MethodRecognizer::kGrowableArraySetIndexed:
- return kGrowableObjectArrayCid;
-
- case MethodRecognizer::kFloat32ArrayGetIndexed:
- case MethodRecognizer::kFloat32ArraySetIndexed:
- return kTypedDataFloat32ArrayCid;
-
- case MethodRecognizer::kFloat64ArrayGetIndexed:
- case MethodRecognizer::kFloat64ArraySetIndexed:
- return kTypedDataFloat64ArrayCid;
-
- case MethodRecognizer::kInt8ArrayGetIndexed:
- case MethodRecognizer::kInt8ArraySetIndexed:
- return kTypedDataInt8ArrayCid;
-
- case MethodRecognizer::kUint8ArrayGetIndexed:
- case MethodRecognizer::kUint8ArraySetIndexed:
- return kTypedDataUint8ArrayCid;
-
- case MethodRecognizer::kUint8ClampedArrayGetIndexed:
- case MethodRecognizer::kUint8ClampedArraySetIndexed:
- return kTypedDataUint8ClampedArrayCid;
-
- case MethodRecognizer::kExternalUint8ArrayGetIndexed:
- case MethodRecognizer::kExternalUint8ArraySetIndexed:
- return kExternalTypedDataUint8ArrayCid;
-
- case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
- case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
- return kExternalTypedDataUint8ClampedArrayCid;
-
- case MethodRecognizer::kInt16ArrayGetIndexed:
- case MethodRecognizer::kInt16ArraySetIndexed:
- return kTypedDataInt16ArrayCid;
-
- case MethodRecognizer::kUint16ArrayGetIndexed:
- case MethodRecognizer::kUint16ArraySetIndexed:
- return kTypedDataUint16ArrayCid;
-
- case MethodRecognizer::kInt32ArrayGetIndexed:
- case MethodRecognizer::kInt32ArraySetIndexed:
- return kTypedDataInt32ArrayCid;
-
- case MethodRecognizer::kUint32ArrayGetIndexed:
- case MethodRecognizer::kUint32ArraySetIndexed:
- return kTypedDataUint32ArrayCid;
-
- case MethodRecognizer::kInt64ArrayGetIndexed:
- case MethodRecognizer::kInt64ArraySetIndexed:
- return kTypedDataInt64ArrayCid;
-
- case MethodRecognizer::kFloat32x4ArrayGetIndexed:
- case MethodRecognizer::kFloat32x4ArraySetIndexed:
- return kTypedDataFloat32x4ArrayCid;
-
- case MethodRecognizer::kInt32x4ArrayGetIndexed:
- case MethodRecognizer::kInt32x4ArraySetIndexed:
- return kTypedDataInt32x4ArrayCid;
-
- case MethodRecognizer::kFloat64x2ArrayGetIndexed:
- case MethodRecognizer::kFloat64x2ArraySetIndexed:
- return kTypedDataFloat64x2ArrayCid;
-
- default:
- break;
- }
- return kIllegalCid;
-}
-
-
bool FlowGraphOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) {
// Check for monomorphic IC data.
if (!call->HasICData()) return false;
@@ -1237,530 +1122,6 @@
}
-bool FlowGraphOptimizer::InlineSetIndexed(
- MethodRecognizer::Kind kind,
- const Function& target,
- Instruction* call,
- Definition* receiver,
- TokenPosition token_pos,
- const ICData& value_check,
- TargetEntryInstr** entry,
- Definition** last) {
- intptr_t array_cid = MethodKindToCid(kind);
- ASSERT(array_cid != kIllegalCid);
-
- Definition* array = receiver;
- Definition* index = call->ArgumentAt(1);
- Definition* stored_value = call->ArgumentAt(2);
-
- *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
- call->GetBlock()->try_index());
- (*entry)->InheritDeoptTarget(Z, call);
- Instruction* cursor = *entry;
- if (I->flags().type_checks()) {
- // Only type check for the value. A type check for the index is not
- // needed here because we insert a deoptimizing smi-check for the case
- // the index is not a smi.
- const AbstractType& value_type =
- AbstractType::ZoneHandle(Z, target.ParameterTypeAt(2));
- Definition* type_args = NULL;
- switch (array_cid) {
- case kArrayCid:
- case kGrowableObjectArrayCid: {
- const Class& instantiator_class = Class::Handle(Z, target.Owner());
- intptr_t type_arguments_field_offset =
- instantiator_class.type_arguments_field_offset();
- LoadFieldInstr* load_type_args =
- new(Z) LoadFieldInstr(new(Z) Value(array),
- type_arguments_field_offset,
- Type::ZoneHandle(Z), // No type.
- call->token_pos());
- cursor = flow_graph()->AppendTo(cursor,
- load_type_args,
- NULL,
- FlowGraph::kValue);
-
- type_args = load_type_args;
- break;
- }
- case kTypedDataInt8ArrayCid:
- case kTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kExternalTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint16ArrayCid:
- case kTypedDataInt32ArrayCid:
- case kTypedDataUint32ArrayCid:
- case kTypedDataInt64ArrayCid:
- ASSERT(value_type.IsIntType());
- // Fall through.
- case kTypedDataFloat32ArrayCid:
- case kTypedDataFloat64ArrayCid: {
- type_args = flow_graph_->constant_null();
- ASSERT((array_cid != kTypedDataFloat32ArrayCid &&
- array_cid != kTypedDataFloat64ArrayCid) ||
- value_type.IsDoubleType());
- ASSERT(value_type.IsInstantiated());
- break;
- }
- case kTypedDataFloat32x4ArrayCid: {
- type_args = flow_graph_->constant_null();
- ASSERT((array_cid != kTypedDataFloat32x4ArrayCid) ||
- value_type.IsFloat32x4Type());
- ASSERT(value_type.IsInstantiated());
- break;
- }
- case kTypedDataFloat64x2ArrayCid: {
- type_args = flow_graph_->constant_null();
- ASSERT((array_cid != kTypedDataFloat64x2ArrayCid) ||
- value_type.IsFloat64x2Type());
- ASSERT(value_type.IsInstantiated());
- break;
- }
- default:
- // TODO(fschneider): Add support for other array types.
- UNREACHABLE();
- }
- AssertAssignableInstr* assert_value =
- new(Z) AssertAssignableInstr(token_pos,
- new(Z) Value(stored_value),
- new(Z) Value(type_args),
- value_type,
- Symbols::Value(),
- call->deopt_id());
- cursor = flow_graph()->AppendTo(cursor,
- assert_value,
- call->env(),
- FlowGraph::kValue);
- }
-
- array_cid = PrepareInlineIndexedOp(call,
- array_cid,
- &array,
- index,
- &cursor);
-
- // Check if store barrier is needed. Byte arrays don't need a store barrier.
- StoreBarrierType needs_store_barrier =
- (RawObject::IsTypedDataClassId(array_cid) ||
- RawObject::IsTypedDataViewClassId(array_cid) ||
- RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier
- : kEmitStoreBarrier;
-
- // No need to class check stores to Int32 and Uint32 arrays because
- // we insert unboxing instructions below which include a class check.
- if ((array_cid != kTypedDataUint32ArrayCid) &&
- (array_cid != kTypedDataInt32ArrayCid) &&
- !value_check.IsNull()) {
- // No store barrier needed because checked value is a smi, an unboxed mint,
- // an unboxed double, an unboxed Float32x4, or unboxed Int32x4.
- needs_store_barrier = kNoStoreBarrier;
- Instruction* check = GetCheckClass(
- stored_value, value_check, call->deopt_id(), call->token_pos());
- cursor = flow_graph()->AppendTo(cursor,
- check,
- call->env(),
- FlowGraph::kEffect);
- }
-
- if (array_cid == kTypedDataFloat32ArrayCid) {
- stored_value =
- new(Z) DoubleToFloatInstr(
- new(Z) Value(stored_value), call->deopt_id());
- cursor = flow_graph()->AppendTo(cursor,
- stored_value,
- NULL,
- FlowGraph::kValue);
- } else if (array_cid == kTypedDataInt32ArrayCid) {
- stored_value = new(Z) UnboxInt32Instr(
- UnboxInt32Instr::kTruncate,
- new(Z) Value(stored_value),
- call->deopt_id());
- cursor = flow_graph()->AppendTo(cursor,
- stored_value,
- call->env(),
- FlowGraph::kValue);
- } else if (array_cid == kTypedDataUint32ArrayCid) {
- stored_value = new(Z) UnboxUint32Instr(
- new(Z) Value(stored_value),
- call->deopt_id());
- ASSERT(stored_value->AsUnboxInteger()->is_truncating());
- cursor = flow_graph()->AppendTo(cursor,
- stored_value,
- call->env(),
- FlowGraph::kValue);
- }
-
- const intptr_t index_scale = Instance::ElementSizeFor(array_cid);
- *last = new(Z) StoreIndexedInstr(new(Z) Value(array),
- new(Z) Value(index),
- new(Z) Value(stored_value),
- needs_store_barrier,
- index_scale,
- array_cid,
- call->deopt_id(),
- call->token_pos());
- flow_graph()->AppendTo(cursor,
- *last,
- call->env(),
- FlowGraph::kEffect);
- return true;
-}
-
-
-bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid,
- const Function& target,
- Instruction* call,
- Definition* receiver,
- TokenPosition token_pos,
- const ICData& ic_data,
- TargetEntryInstr** entry,
- Definition** last) {
- ICData& value_check = ICData::ZoneHandle(Z);
- MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
- switch (kind) {
- // Recognized [] operators.
- case MethodRecognizer::kImmutableArrayGetIndexed:
- case MethodRecognizer::kObjectArrayGetIndexed:
- case MethodRecognizer::kGrowableArrayGetIndexed:
- case MethodRecognizer::kInt8ArrayGetIndexed:
- case MethodRecognizer::kUint8ArrayGetIndexed:
- case MethodRecognizer::kUint8ClampedArrayGetIndexed:
- case MethodRecognizer::kExternalUint8ArrayGetIndexed:
- case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
- case MethodRecognizer::kInt16ArrayGetIndexed:
- case MethodRecognizer::kUint16ArrayGetIndexed:
- return InlineGetIndexed(kind, call, receiver, entry, last);
- case MethodRecognizer::kFloat32ArrayGetIndexed:
- case MethodRecognizer::kFloat64ArrayGetIndexed:
- if (!CanUnboxDouble()) {
- return false;
- }
- return InlineGetIndexed(kind, call, receiver, entry, last);
- case MethodRecognizer::kFloat32x4ArrayGetIndexed:
- case MethodRecognizer::kFloat64x2ArrayGetIndexed:
- if (!ShouldInlineSimd()) {
- return false;
- }
- return InlineGetIndexed(kind, call, receiver, entry, last);
- case MethodRecognizer::kInt32ArrayGetIndexed:
- case MethodRecognizer::kUint32ArrayGetIndexed:
- if (!CanUnboxInt32()) return false;
- return InlineGetIndexed(kind, call, receiver, entry, last);
-
- case MethodRecognizer::kInt64ArrayGetIndexed:
- if (!ShouldInlineInt64ArrayOps()) {
- return false;
- }
- return InlineGetIndexed(kind, call, receiver, entry, last);
- // Recognized []= operators.
- case MethodRecognizer::kObjectArraySetIndexed:
- case MethodRecognizer::kGrowableArraySetIndexed:
- return InlineSetIndexed(kind, target, call, receiver, token_pos,
- value_check, entry, last);
- case MethodRecognizer::kInt8ArraySetIndexed:
- case MethodRecognizer::kUint8ArraySetIndexed:
- case MethodRecognizer::kUint8ClampedArraySetIndexed:
- case MethodRecognizer::kExternalUint8ArraySetIndexed:
- case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
- case MethodRecognizer::kInt16ArraySetIndexed:
- case MethodRecognizer::kUint16ArraySetIndexed:
- // Optimistically assume Smi.
- if (ic_data.HasDeoptReason(ICData::kDeoptCheckSmi)) {
- // Optimistic assumption failed at least once.
- return false;
- }
- value_check = ic_data.AsUnaryClassChecksForCid(kSmiCid, target);
- return InlineSetIndexed(kind, target, call, receiver, token_pos,
- value_check, entry, last);
- case MethodRecognizer::kInt32ArraySetIndexed:
- case MethodRecognizer::kUint32ArraySetIndexed: {
- // Value check not needed for Int32 and Uint32 arrays because they
- // implicitly contain unboxing instructions which check for right type.
- ICData& value_check = ICData::Handle();
- return InlineSetIndexed(kind, target, call, receiver, token_pos,
- value_check, entry, last);
- }
- case MethodRecognizer::kInt64ArraySetIndexed:
- if (!ShouldInlineInt64ArrayOps()) {
- return false;
- }
- return InlineSetIndexed(kind, target, call, receiver, token_pos,
- value_check, entry, last);
- case MethodRecognizer::kFloat32ArraySetIndexed:
- case MethodRecognizer::kFloat64ArraySetIndexed:
- if (!CanUnboxDouble()) {
- return false;
- }
- value_check = ic_data.AsUnaryClassChecksForCid(kDoubleCid, target);
- return InlineSetIndexed(kind, target, call, receiver, token_pos,
- value_check, entry, last);
- case MethodRecognizer::kFloat32x4ArraySetIndexed:
- if (!ShouldInlineSimd()) {
- return false;
- }
- value_check = ic_data.AsUnaryClassChecksForCid(kFloat32x4Cid, target);
-
- return InlineSetIndexed(kind, target, call, receiver, token_pos,
- value_check, entry, last);
- case MethodRecognizer::kFloat64x2ArraySetIndexed:
- if (!ShouldInlineSimd()) {
- return false;
- }
- value_check = ic_data.AsUnaryClassChecksForCid(kFloat64x2Cid, target);
- return InlineSetIndexed(kind, target, call, receiver, token_pos,
- value_check, entry, last);
- case MethodRecognizer::kByteArrayBaseGetInt8:
- return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
- kTypedDataInt8ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseGetUint8:
- return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
- kTypedDataUint8ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseGetInt16:
- return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
- kTypedDataInt16ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseGetUint16:
- return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
- kTypedDataUint16ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseGetInt32:
- if (!CanUnboxInt32()) {
- return false;
- }
- return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
- kTypedDataInt32ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseGetUint32:
- if (!CanUnboxInt32()) {
- return false;
- }
- return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
- kTypedDataUint32ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseGetFloat32:
- if (!CanUnboxDouble()) {
- return false;
- }
- return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
- kTypedDataFloat32ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseGetFloat64:
- if (!CanUnboxDouble()) {
- return false;
- }
- return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
- kTypedDataFloat64ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseGetFloat32x4:
- if (!ShouldInlineSimd()) {
- return false;
- }
- return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
- kTypedDataFloat32x4ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseGetInt32x4:
- if (!ShouldInlineSimd()) {
- return false;
- }
- return InlineByteArrayBaseLoad(call, receiver, receiver_cid,
- kTypedDataInt32x4ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseSetInt8:
- return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
- kTypedDataInt8ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseSetUint8:
- return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
- kTypedDataUint8ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseSetInt16:
- return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
- kTypedDataInt16ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseSetUint16:
- return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
- kTypedDataUint16ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseSetInt32:
- return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
- kTypedDataInt32ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseSetUint32:
- return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
- kTypedDataUint32ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseSetFloat32:
- if (!CanUnboxDouble()) {
- return false;
- }
- return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
- kTypedDataFloat32ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseSetFloat64:
- if (!CanUnboxDouble()) {
- return false;
- }
- return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
- kTypedDataFloat64ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseSetFloat32x4:
- if (!ShouldInlineSimd()) {
- return false;
- }
- return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
- kTypedDataFloat32x4ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kByteArrayBaseSetInt32x4:
- if (!ShouldInlineSimd()) {
- return false;
- }
- return InlineByteArrayBaseStore(target, call, receiver, receiver_cid,
- kTypedDataInt32x4ArrayCid,
- ic_data, entry, last);
- case MethodRecognizer::kStringBaseCodeUnitAt:
- return InlineStringCodeUnitAt(call, receiver_cid, entry, last);
- case MethodRecognizer::kStringBaseCharAt:
- return InlineStringBaseCharAt(call, receiver_cid, entry, last);
- case MethodRecognizer::kDoubleAdd:
- return InlineDoubleOp(Token::kADD, call, entry, last);
- case MethodRecognizer::kDoubleSub:
- return InlineDoubleOp(Token::kSUB, call, entry, last);
- case MethodRecognizer::kDoubleMul:
- return InlineDoubleOp(Token::kMUL, call, entry, last);
- case MethodRecognizer::kDoubleDiv:
- return InlineDoubleOp(Token::kDIV, call, entry, last);
- default:
- return false;
- }
-}
-
-
-intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call,
- intptr_t array_cid,
- Definition** array,
- Definition* index,
- Instruction** cursor) {
- // Insert index smi check.
- *cursor = flow_graph()->AppendTo(
- *cursor,
- new(Z) CheckSmiInstr(new(Z) Value(index),
- call->deopt_id(),
- call->token_pos()),
- call->env(),
- FlowGraph::kEffect);
-
- // Insert array length load and bounds check.
- LoadFieldInstr* length =
- new(Z) LoadFieldInstr(
- new(Z) Value(*array),
- CheckArrayBoundInstr::LengthOffsetFor(array_cid),
- Type::ZoneHandle(Z, Type::SmiType()),
- call->token_pos());
- length->set_is_immutable(
- CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid));
- length->set_result_cid(kSmiCid);
- length->set_recognized_kind(
- LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
- *cursor = flow_graph()->AppendTo(*cursor,
- length,
- NULL,
- FlowGraph::kValue);
-
- *cursor = flow_graph()->AppendTo(*cursor,
- new(Z) CheckArrayBoundInstr(
- new(Z) Value(length),
- new(Z) Value(index),
- call->deopt_id()),
- call->env(),
- FlowGraph::kEffect);
-
- if (array_cid == kGrowableObjectArrayCid) {
- // Insert data elements load.
- LoadFieldInstr* elements =
- new(Z) LoadFieldInstr(
- new(Z) Value(*array),
- GrowableObjectArray::data_offset(),
- Object::dynamic_type(),
- call->token_pos());
- elements->set_result_cid(kArrayCid);
- *cursor = flow_graph()->AppendTo(*cursor,
- elements,
- NULL,
- FlowGraph::kValue);
- // Load from the data from backing store which is a fixed-length array.
- *array = elements;
- array_cid = kArrayCid;
- } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
- LoadUntaggedInstr* elements =
- new(Z) LoadUntaggedInstr(new(Z) Value(*array),
- ExternalTypedData::data_offset());
- *cursor = flow_graph()->AppendTo(*cursor,
- elements,
- NULL,
- FlowGraph::kValue);
- *array = elements;
- }
- return array_cid;
-}
-
-
-bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind,
- Instruction* call,
- Definition* receiver,
- TargetEntryInstr** entry,
- Definition** last) {
- intptr_t array_cid = MethodKindToCid(kind);
- ASSERT(array_cid != kIllegalCid);
-
- Definition* array = receiver;
- Definition* index = call->ArgumentAt(1);
- *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
- call->GetBlock()->try_index());
- (*entry)->InheritDeoptTarget(Z, call);
- Instruction* cursor = *entry;
-
- array_cid = PrepareInlineIndexedOp(call,
- array_cid,
- &array,
- index,
- &cursor);
-
- intptr_t deopt_id = Thread::kNoDeoptId;
- if ((array_cid == kTypedDataInt32ArrayCid) ||
- (array_cid == kTypedDataUint32ArrayCid)) {
- // Deoptimization may be needed if result does not always fit in a Smi.
- deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id();
- }
-
- // Array load and return.
- intptr_t index_scale = Instance::ElementSizeFor(array_cid);
- *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
- new(Z) Value(index),
- index_scale,
- array_cid,
- deopt_id,
- call->token_pos());
- cursor = flow_graph()->AppendTo(
- cursor,
- *last,
- deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
- FlowGraph::kValue);
-
- if (array_cid == kTypedDataFloat32ArrayCid) {
- *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id);
- flow_graph()->AppendTo(cursor,
- *last,
- deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
- FlowGraph::kValue);
- }
- return true;
-}
-
-
// Return true if d is a string of length one (a constant or result from
// from string-from-char-code instruction.
static bool IsLengthOneString(Definition* d) {
@@ -2692,13 +2053,14 @@
TargetEntryInstr* entry;
Definition* last;
- if (!TryInlineRecognizedMethod(receiver_cid,
- target,
- call,
- call->ArgumentAt(0),
- call->token_pos(),
- *call->ic_data(),
- &entry, &last)) {
+ if (!FlowGraphInliner::TryInlineRecognizedMethod(flow_graph_,
+ receiver_cid,
+ target,
+ call,
+ call->ArgumentAt(0),
+ call->token_pos(),
+ *call->ic_data(),
+ &entry, &last)) {
return false;
}
@@ -2726,136 +2088,6 @@
}
-// Returns the LoadIndexedInstr.
-Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp(
- Instruction* call,
- intptr_t cid,
- Definition* str,
- Definition* index,
- Instruction* cursor) {
-
- cursor = flow_graph()->AppendTo(cursor,
- new(Z) CheckSmiInstr(
- new(Z) Value(index),
- call->deopt_id(),
- call->token_pos()),
- call->env(),
- FlowGraph::kEffect);
-
- // Load the length of the string.
- // Treat length loads as mutable (i.e. affected by side effects) to avoid
- // hoisting them since we can't hoist the preceding class-check. This
- // is because of externalization of strings that affects their class-id.
- LoadFieldInstr* length = new(Z) LoadFieldInstr(
- new(Z) Value(str),
- String::length_offset(),
- Type::ZoneHandle(Z, Type::SmiType()),
- str->token_pos());
- length->set_result_cid(kSmiCid);
- length->set_recognized_kind(MethodRecognizer::kStringBaseLength);
-
- cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue);
- // Bounds check.
- cursor = flow_graph()->AppendTo(cursor,
- new(Z) CheckArrayBoundInstr(
- new(Z) Value(length),
- new(Z) Value(index),
- call->deopt_id()),
- call->env(),
- FlowGraph::kEffect);
-
- LoadIndexedInstr* load_indexed = new(Z) LoadIndexedInstr(
- new(Z) Value(str),
- new(Z) Value(index),
- Instance::ElementSizeFor(cid),
- cid,
- Thread::kNoDeoptId,
- call->token_pos());
-
- cursor = flow_graph()->AppendTo(cursor,
- load_indexed,
- NULL,
- FlowGraph::kValue);
- ASSERT(cursor == load_indexed);
- return load_indexed;
-}
-
-
-bool FlowGraphOptimizer::InlineStringCodeUnitAt(
- Instruction* call,
- intptr_t cid,
- TargetEntryInstr** entry,
- Definition** last) {
- // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp.
- if (RawObject::IsExternalStringClassId(cid)) {
- return false;
- }
-
- Definition* str = call->ArgumentAt(0);
- Definition* index = call->ArgumentAt(1);
-
- *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
- call->GetBlock()->try_index());
- (*entry)->InheritDeoptTarget(Z, call);
-
- *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry);
-
- return true;
-}
-
-
-bool FlowGraphOptimizer::InlineStringBaseCharAt(
- Instruction* call,
- intptr_t cid,
- TargetEntryInstr** entry,
- Definition** last) {
- // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp.
- if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) {
- return false;
- }
- Definition* str = call->ArgumentAt(0);
- Definition* index = call->ArgumentAt(1);
-
- *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
- call->GetBlock()->try_index());
- (*entry)->InheritDeoptTarget(Z, call);
-
- *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry);
-
- StringFromCharCodeInstr* char_at = new(Z) StringFromCharCodeInstr(
- new(Z) Value(*last), cid);
-
- flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue);
- *last = char_at;
-
- return true;
-}
-
-
-bool FlowGraphOptimizer::InlineDoubleOp(
- Token::Kind op_kind,
- Instruction* call,
- TargetEntryInstr** entry,
- Definition** last) {
- Definition* left = call->ArgumentAt(0);
- Definition* right = call->ArgumentAt(1);
-
- *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
- call->GetBlock()->try_index());
- (*entry)->InheritDeoptTarget(Z, call);
- // Arguments are checked. No need for class check.
- BinaryDoubleOpInstr* double_bin_op =
- new(Z) BinaryDoubleOpInstr(op_kind,
- new(Z) Value(left),
- new(Z) Value(right),
- call->deopt_id(), call->token_pos());
- flow_graph()->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
- *last = double_bin_op;
-
- return true;
-}
-
-
void FlowGraphOptimizer::ReplaceWithMathCFunction(
InstanceCallInstr* call,
MethodRecognizer::Kind recognized_kind) {
@@ -3545,300 +2777,6 @@
}
-bool FlowGraphOptimizer::InlineByteArrayBaseLoad(Instruction* call,
- Definition* receiver,
- intptr_t array_cid,
- intptr_t view_cid,
- const ICData& ic_data,
- TargetEntryInstr** entry,
- Definition** last) {
- ASSERT(array_cid != kIllegalCid);
- Definition* array = receiver;
- Definition* index = call->ArgumentAt(1);
- *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
- call->GetBlock()->try_index());
- (*entry)->InheritDeoptTarget(Z, call);
- Instruction* cursor = *entry;
-
- array_cid = PrepareInlineByteArrayBaseOp(call,
- array_cid,
- view_cid,
- &array,
- index,
- &cursor);
-
- intptr_t deopt_id = Thread::kNoDeoptId;
- if ((array_cid == kTypedDataInt32ArrayCid) ||
- (array_cid == kTypedDataUint32ArrayCid)) {
- // Deoptimization may be needed if result does not always fit in a Smi.
- deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id();
- }
-
- *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
- new(Z) Value(index),
- 1,
- view_cid,
- deopt_id,
- call->token_pos());
- cursor = flow_graph()->AppendTo(
- cursor,
- *last,
- deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
- FlowGraph::kValue);
-
- if (view_cid == kTypedDataFloat32ArrayCid) {
- *last = new(Z) FloatToDoubleInstr(new(Z) Value(*last), deopt_id);
- flow_graph()->AppendTo(cursor,
- *last,
- deopt_id != Thread::kNoDeoptId ? call->env() : NULL,
- FlowGraph::kValue);
- }
- return true;
-}
-
-
-bool FlowGraphOptimizer::InlineByteArrayBaseStore(const Function& target,
- Instruction* call,
- Definition* receiver,
- intptr_t array_cid,
- intptr_t view_cid,
- const ICData& ic_data,
- TargetEntryInstr** entry,
- Definition** last) {
- ASSERT(array_cid != kIllegalCid);
- Definition* array = receiver;
- Definition* index = call->ArgumentAt(1);
- *entry = new(Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
- call->GetBlock()->try_index());
- (*entry)->InheritDeoptTarget(Z, call);
- Instruction* cursor = *entry;
-
- array_cid = PrepareInlineByteArrayBaseOp(call,
- array_cid,
- view_cid,
- &array,
- index,
- &cursor);
-
- // Extract the instance call so we can use the function_name in the stored
- // value check ICData.
- InstanceCallInstr* i_call = NULL;
- if (call->IsPolymorphicInstanceCall()) {
- i_call = call->AsPolymorphicInstanceCall()->instance_call();
- } else {
- ASSERT(call->IsInstanceCall());
- i_call = call->AsInstanceCall();
- }
- ASSERT(i_call != NULL);
- ICData& value_check = ICData::ZoneHandle(Z);
- switch (view_cid) {
- case kTypedDataInt8ArrayCid:
- case kTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kExternalTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint16ArrayCid: {
- // Check that value is always smi.
- value_check = ICData::New(flow_graph_->function(),
- i_call->function_name(),
- Object::empty_array(), // Dummy args. descr.
- Thread::kNoDeoptId,
- 1);
- value_check.AddReceiverCheck(kSmiCid, target);
- break;
- }
- case kTypedDataInt32ArrayCid:
- case kTypedDataUint32ArrayCid:
- // On 64-bit platforms assume that stored value is always a smi.
- if (kSmiBits >= 32) {
- value_check = ICData::New(flow_graph_->function(),
- i_call->function_name(),
- Object::empty_array(), // Dummy args. descr.
- Thread::kNoDeoptId,
- 1);
- value_check.AddReceiverCheck(kSmiCid, target);
- }
- break;
- case kTypedDataFloat32ArrayCid:
- case kTypedDataFloat64ArrayCid: {
- // Check that value is always double.
- value_check = ICData::New(flow_graph_->function(),
- i_call->function_name(),
- Object::empty_array(), // Dummy args. descr.
- Thread::kNoDeoptId,
- 1);
- value_check.AddReceiverCheck(kDoubleCid, target);
- break;
- }
- case kTypedDataInt32x4ArrayCid: {
- // Check that value is always Int32x4.
- value_check = ICData::New(flow_graph_->function(),
- i_call->function_name(),
- Object::empty_array(), // Dummy args. descr.
- Thread::kNoDeoptId,
- 1);
- value_check.AddReceiverCheck(kInt32x4Cid, target);
- break;
- }
- case kTypedDataFloat32x4ArrayCid: {
- // Check that value is always Float32x4.
- value_check = ICData::New(flow_graph_->function(),
- i_call->function_name(),
- Object::empty_array(), // Dummy args. descr.
- Thread::kNoDeoptId,
- 1);
- value_check.AddReceiverCheck(kFloat32x4Cid, target);
- break;
- }
- default:
- // Array cids are already checked in the caller.
- UNREACHABLE();
- }
-
- Definition* stored_value = call->ArgumentAt(2);
- if (!value_check.IsNull()) {
- AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(),
- call);
- }
-
- if (view_cid == kTypedDataFloat32ArrayCid) {
- stored_value = new(Z) DoubleToFloatInstr(
- new(Z) Value(stored_value), call->deopt_id());
- cursor = flow_graph()->AppendTo(cursor,
- stored_value,
- NULL,
- FlowGraph::kValue);
- } else if (view_cid == kTypedDataInt32ArrayCid) {
- stored_value = new(Z) UnboxInt32Instr(
- UnboxInt32Instr::kTruncate,
- new(Z) Value(stored_value),
- call->deopt_id());
- cursor = flow_graph()->AppendTo(cursor,
- stored_value,
- call->env(),
- FlowGraph::kValue);
- } else if (view_cid == kTypedDataUint32ArrayCid) {
- stored_value = new(Z) UnboxUint32Instr(
- new(Z) Value(stored_value),
- call->deopt_id());
- ASSERT(stored_value->AsUnboxInteger()->is_truncating());
- cursor = flow_graph()->AppendTo(cursor,
- stored_value,
- call->env(),
- FlowGraph::kValue);
- }
-
- StoreBarrierType needs_store_barrier = kNoStoreBarrier;
- *last = new(Z) StoreIndexedInstr(new(Z) Value(array),
- new(Z) Value(index),
- new(Z) Value(stored_value),
- needs_store_barrier,
- 1, // Index scale
- view_cid,
- call->deopt_id(),
- call->token_pos());
-
- flow_graph()->AppendTo(cursor,
- *last,
- call->deopt_id() != Thread::kNoDeoptId ?
- call->env() : NULL,
- FlowGraph::kEffect);
- return true;
-}
-
-
-
-intptr_t FlowGraphOptimizer::PrepareInlineByteArrayBaseOp(
- Instruction* call,
- intptr_t array_cid,
- intptr_t view_cid,
- Definition** array,
- Definition* byte_index,
- Instruction** cursor) {
- // Insert byte_index smi check.
- *cursor = flow_graph()->AppendTo(*cursor,
- new(Z) CheckSmiInstr(
- new(Z) Value(byte_index),
- call->deopt_id(),
- call->token_pos()),
- call->env(),
- FlowGraph::kEffect);
-
- LoadFieldInstr* length =
- new(Z) LoadFieldInstr(
- new(Z) Value(*array),
- CheckArrayBoundInstr::LengthOffsetFor(array_cid),
- Type::ZoneHandle(Z, Type::SmiType()),
- call->token_pos());
- length->set_is_immutable(true);
- length->set_result_cid(kSmiCid);
- length->set_recognized_kind(
- LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
- *cursor = flow_graph()->AppendTo(*cursor,
- length,
- NULL,
- FlowGraph::kValue);
-
- intptr_t element_size = Instance::ElementSizeFor(array_cid);
- ConstantInstr* bytes_per_element =
- flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(element_size)));
- BinarySmiOpInstr* len_in_bytes =
- new(Z) BinarySmiOpInstr(Token::kMUL,
- new(Z) Value(length),
- new(Z) Value(bytes_per_element),
- call->deopt_id());
- *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(),
- FlowGraph::kValue);
-
- // adjusted_length = len_in_bytes - (element_size - 1).
- Definition* adjusted_length = len_in_bytes;
- intptr_t adjustment = Instance::ElementSizeFor(view_cid) - 1;
- if (adjustment > 0) {
- ConstantInstr* length_adjustment =
- flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(adjustment)));
- adjusted_length =
- new(Z) BinarySmiOpInstr(Token::kSUB,
- new(Z) Value(len_in_bytes),
- new(Z) Value(length_adjustment),
- call->deopt_id());
- *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(),
- FlowGraph::kValue);
- }
-
- // Check adjusted_length > 0.
- ConstantInstr* zero =
- flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(0)));
- *cursor = flow_graph()->AppendTo(*cursor,
- new(Z) CheckArrayBoundInstr(
- new(Z) Value(adjusted_length),
- new(Z) Value(zero),
- call->deopt_id()),
- call->env(),
- FlowGraph::kEffect);
- // Check 0 <= byte_index < adjusted_length.
- *cursor = flow_graph()->AppendTo(*cursor,
- new(Z) CheckArrayBoundInstr(
- new(Z) Value(adjusted_length),
- new(Z) Value(byte_index),
- call->deopt_id()),
- call->env(),
- FlowGraph::kEffect);
-
- if (RawObject::IsExternalTypedDataClassId(array_cid)) {
- LoadUntaggedInstr* elements =
- new(Z) LoadUntaggedInstr(new(Z) Value(*array),
- ExternalTypedData::data_offset());
- *cursor = flow_graph()->AppendTo(*cursor,
- elements,
- NULL,
- FlowGraph::kValue);
- *array = elements;
- }
- return array_cid;
-}
-
-
// If type tests specified by 'ic_data' do not depend on type arguments,
// return mapping cid->result in 'results' (i : cid; i + 1: result).
// If all tests yield the same result, return it otherwise return Bool::null.
@@ -4044,15 +2982,6 @@
}
const ICData& unary_checks =
ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
- if (FLAG_warn_on_javascript_compatibility &&
- !unary_checks.IssuedJSWarning() &&
- (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) {
- // No warning was reported yet for this type check, either because it has
- // not been executed yet, or because no problematic combinations of instance
- // type and test type have been encountered so far. A warning may still be
- // reported, so do not replace the instance call.
- return;
- }
if ((unary_checks.NumberOfChecks() > 0) &&
(unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
ZoneGrowableArray<intptr_t>* results =
@@ -4134,15 +3063,6 @@
ASSERT(!type.IsMalformedOrMalbounded());
const ICData& unary_checks =
ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
- if (FLAG_warn_on_javascript_compatibility &&
- !unary_checks.IssuedJSWarning() &&
- (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) {
- // No warning was reported yet for this type check, either because it has
- // not been executed yet, or because no problematic combinations of instance
- // type and test type have been encountered so far. A warning may still be
- // reported, so do not replace the instance call.
- return;
- }
if ((unary_checks.NumberOfChecks() > 0) &&
(unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
ZoneGrowableArray<intptr_t>* results =
@@ -4643,6 +3563,15 @@
}
}
if (!unboxed_field) {
+ // TODO(srdjan): Instead of aborting pass this field to the mutator thread
+ // so that it can:
+ // - set it to unboxed
+ // - deoptimize dependent code.
+ if (Compiler::IsBackgroundCompilation()) {
+ isolate()->AddDeoptimizingBoxedField(field);
+ Compiler::AbortBackgroundCompilation(Thread::kNoDeoptId);
+ UNREACHABLE();
+ }
if (FLAG_trace_optimization || FLAG_trace_field_guards) {
THR_Print("Disabling unboxing of %s\n", field.ToCString());
if (!setter.IsNull()) {
@@ -4653,14 +3582,7 @@
}
}
field.set_is_unboxing_candidate(false);
- if (Compiler::IsBackgroundCompilation()) {
- // Delay deoptimization of dependent code to the code installation time.
- // The invalidation of the background compilation result occurs only
- // when the deoptimization is triggered at code installation.
- flow_graph()->deoptimize_dependent_code().Add(&field);
- } else {
- field.DeoptimizeDependentCode();
- }
+ field.DeoptimizeDependentCode();
} else {
FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field);
}
@@ -4890,7 +3812,7 @@
continue;
}
- if (FLAG_trace_smi_widening) {
+ if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
THR_Print("analysing candidate: %s\n", op->ToCString());
}
worklist.Clear();
@@ -4902,14 +3824,14 @@
for (intptr_t j = 0; j < worklist.definitions().length(); j++) {
Definition* defn = worklist.definitions()[j];
- if (FLAG_trace_smi_widening) {
+ if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
THR_Print("> %s\n", defn->ToCString());
}
if (defn->IsBinarySmiOp() &&
BenefitsFromWidening(defn->AsBinarySmiOp())) {
gain++;
- if (FLAG_trace_smi_widening) {
+ if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
THR_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString());
}
}
@@ -4927,7 +3849,7 @@
} else if (input->IsBinaryMintOp()) {
// Mint operation produces untagged result. We avoid tagging.
gain++;
- if (FLAG_trace_smi_widening) {
+ if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString());
}
} else if (defn_loop == loops[input->GetBlock()->preorder_number()] &&
@@ -4938,7 +3860,7 @@
// known to be smi have to be checked and this check can be
// coalesced with untagging. Start coalescing them.
gain--;
- if (FLAG_trace_smi_widening) {
+ if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
THR_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString());
}
}
@@ -4955,7 +3877,7 @@
// very little compared to the cost of the return/call itself.
if (!instr->IsReturn() && !instr->IsPushArgument()) {
gain--;
- if (FLAG_trace_smi_widening) {
+ if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
THR_Print("v [%" Pd "] (u) %s\n",
gain,
use->instruction()->ToCString());
@@ -4973,14 +3895,14 @@
// Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost
// sign extension operation.
gain++;
- if (FLAG_trace_smi_widening) {
+ if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
THR_Print("^ [%" Pd "] (u) %s\n",
gain,
use->instruction()->ToCString());
}
} else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) {
gain--;
- if (FLAG_trace_smi_widening) {
+ if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
THR_Print("v [%" Pd "] (u) %s\n",
gain,
use->instruction()->ToCString());
@@ -4991,7 +3913,7 @@
processed->AddAll(worklist.contains_vector());
- if (FLAG_trace_smi_widening) {
+ if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
THR_Print("~ %s gain %" Pd "\n", op->ToCString(), gain);
}
@@ -5028,19 +3950,16 @@
}
#endif
-void FlowGraphOptimizer::InferIntRanges() {
- RangeAnalysis range_analysis(flow_graph_);
- range_analysis.Analyze();
-}
-
void FlowGraphOptimizer::EliminateEnvironments() {
// After this pass we can no longer perform LICM and hoist instructions
// that can deoptimize.
flow_graph_->disallow_licm();
- for (intptr_t i = 0; i < block_order_.length(); ++i) {
- BlockEntryInstr* block = block_order_[i];
+ for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ BlockEntryInstr* block = block_it.Current();
block->RemoveEnvironment();
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
Instruction* current = it.Current();
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 9bbcbdf..79abf12 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -54,21 +54,6 @@
void WidenSmiToInt32();
- void InferIntRanges();
-
- void SelectIntegerInstructions();
-
- void AnalyzeTryCatch();
-
- bool TryInlineRecognizedMethod(intptr_t receiver_cid,
- const Function& target,
- Instruction* call,
- Definition* receiver,
- TokenPosition token_pos,
- const ICData& ic_data,
- TargetEntryInstr** entry,
- Definition** last);
-
// Remove environments from the instructions which do not deoptimize.
void EliminateEnvironments();
@@ -93,24 +78,6 @@
void SpecializePolymorphicInstanceCall(PolymorphicInstanceCallInstr* call);
bool TryReplaceWithIndexedOp(InstanceCallInstr* call);
- bool InlineSetIndexed(MethodRecognizer::Kind kind,
- const Function& target,
- Instruction* call,
- Definition* receiver,
- TokenPosition token_pos,
- const ICData& value_check,
- TargetEntryInstr** entry,
- Definition** last);
- bool InlineGetIndexed(MethodRecognizer::Kind kind,
- Instruction* call,
- Definition* receiver,
- TargetEntryInstr** entry,
- Definition** last);
- intptr_t PrepareInlineIndexedOp(Instruction* call,
- intptr_t array_cid,
- Definition** array,
- Definition* index,
- Instruction** cursor);
bool TryReplaceWithBinaryOp(InstanceCallInstr* call, Token::Kind op_kind);
@@ -144,51 +111,6 @@
bool TryReplaceInstanceCallWithInline(InstanceCallInstr* call);
- Definition* PrepareInlineStringIndexOp(Instruction* call,
- intptr_t cid,
- Definition* str,
- Definition* index,
- Instruction* cursor);
-
- bool InlineStringCodeUnitAt(Instruction* call,
- intptr_t cid,
- TargetEntryInstr** entry,
- Definition** last);
-
- bool InlineStringBaseCharAt(Instruction* call,
- intptr_t cid,
- TargetEntryInstr** entry,
- Definition** last);
-
- bool InlineDoubleOp(Token::Kind op_kind,
- Instruction* call,
- TargetEntryInstr** entry,
- Definition** last);
-
- bool InlineByteArrayBaseLoad(Instruction* call,
- Definition* receiver,
- intptr_t array_cid,
- intptr_t view_cid,
- const ICData& ic_data,
- TargetEntryInstr** entry,
- Definition** last);
-
- bool InlineByteArrayBaseStore(const Function& target,
- Instruction* call,
- Definition* receiver,
- intptr_t array_cid,
- intptr_t view_cid,
- const ICData& ic_data,
- TargetEntryInstr** entry,
- Definition** last);
-
- intptr_t PrepareInlineByteArrayBaseOp(Instruction* call,
- intptr_t array_cid,
- intptr_t view_cid,
- Definition** array,
- Definition* index,
- Instruction** cursor);
-
// Insert a check of 'to_check' determined by 'unary_checks'. If the
// check fails it will deoptimize to 'deopt_id' using the deoptimization
// environment 'deopt_environment'. The check is inserted immediately
@@ -256,7 +178,6 @@
void TryMergeTruncDivMod(GrowableArray<BinarySmiOpInstr*>* merge_candidates);
void TryMergeMathUnary(GrowableArray<MathUnaryInstr*>* merge_candidates);
- void AppendLoadIndexedForMerged(Definition* instr, intptr_t ix, intptr_t cid);
void AppendExtractNthOutputForMerged(Definition* instr, intptr_t ix,
Representation rep, intptr_t cid);
bool TryStringLengthOneEquality(InstanceCallInstr* call, Token::Kind op_kind);
diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h
index 950223c..cfc1b54 100644
--- a/runtime/vm/heap.h
+++ b/runtime/vm/heap.h
@@ -246,8 +246,8 @@
bool ShouldPretenure(intptr_t class_id) const;
- void SetupInstructionsSnapshotPage(void* pointer, uword size) {
- old_space_.SetupInstructionsSnapshotPage(pointer, size);
+ void SetupExternalPage(void* pointer, uword size, bool is_executable) {
+ old_space_.SetupExternalPage(pointer, size, is_executable);
}
private:
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index be7171a..20b1e09 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -43,7 +43,6 @@
"Don't optimize away static field initialization");
DECLARE_FLAG(bool, eliminate_type_checks);
DECLARE_FLAG(bool, trace_optimization);
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
Definition::Definition(intptr_t deopt_id)
: Instruction(deopt_id),
@@ -1323,11 +1322,6 @@
bool BinarySmiOpInstr::CanDeoptimize() const {
- if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits > 32)) {
- // If Smi's are bigger than 32-bits, then the instruction could deoptimize
- // if the result is too big.
- return true;
- }
switch (op_kind()) {
case Token::kBIT_AND:
case Token::kBIT_OR:
@@ -2055,19 +2049,25 @@
const TypeArguments& instantiator_type_args =
TypeArguments::Cast(constant_type_args->value());
Error& bound_error = Error::Handle();
- const AbstractType& new_dst_type = AbstractType::Handle(
+ AbstractType& new_dst_type = AbstractType::Handle(
dst_type().InstantiateFrom(
instantiator_type_args, &bound_error, NULL, NULL, Heap::kOld));
- // If dst_type is instantiated to dynamic or Object, skip the test.
- if (!new_dst_type.IsMalformedOrMalbounded() && bound_error.IsNull() &&
- (new_dst_type.IsDynamicType() || new_dst_type.IsObjectType())) {
+ if (new_dst_type.IsMalformedOrMalbounded() || !bound_error.IsNull()) {
+ return this;
+ }
+ if (new_dst_type.IsTypeRef()) {
+ new_dst_type = TypeRef::Cast(new_dst_type).type();
+ }
+ new_dst_type = new_dst_type.Canonicalize();
+ set_dst_type(new_dst_type);
+
+ if (new_dst_type.IsDynamicType() ||
+ new_dst_type.IsObjectType() ||
+ (FLAG_eliminate_type_checks &&
+ value()->Type()->IsAssignableTo(new_dst_type))) {
return value()->definition();
}
- set_dst_type(AbstractType::ZoneHandle(new_dst_type.Canonicalize()));
- if (FLAG_eliminate_type_checks &&
- value()->Type()->IsAssignableTo(dst_type())) {
- return value()->definition();
- }
+
ConstantInstr* null_constant = flow_graph->constant_null();
instantiator_type_arguments()->BindTo(null_constant);
}
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index f4664dc..8677ac9 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -17,8 +17,6 @@
namespace dart {
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
-
class BitVector;
class BlockEntryInstr;
class BoxIntegerInstr;
@@ -2643,6 +2641,7 @@
dst_type_(AbstractType::ZoneHandle(dst_type.raw())),
dst_name_(dst_name) {
ASSERT(!dst_type.IsNull());
+ ASSERT(!dst_type.IsTypeRef());
ASSERT(!dst_name.IsNull());
SetInputAt(0, value);
SetInputAt(1, instantiator_type_arguments);
@@ -2658,6 +2657,7 @@
virtual TokenPosition token_pos() const { return token_pos_; }
const AbstractType& dst_type() const { return dst_type_; }
void set_dst_type(const AbstractType& dst_type) {
+ ASSERT(!dst_type.IsTypeRef());
dst_type_ = dst_type.raw();
}
const String& dst_name() const { return dst_name_; }
@@ -6829,7 +6829,7 @@
}
virtual bool CanDeoptimize() const {
- return FLAG_throw_on_javascript_int_overflow;
+ return false;
}
virtual CompileType ComputeType() const;
@@ -7089,8 +7089,7 @@
}
virtual bool CanDeoptimize() const {
- return FLAG_throw_on_javascript_int_overflow
- || (can_overflow() && ((op_kind() == Token::kADD) ||
+ return (can_overflow() && ((op_kind() == Token::kADD) ||
(op_kind() == Token::kSUB)))
|| (op_kind() == Token::kMUL); // Deopt if inputs are not int32.
}
@@ -7125,8 +7124,7 @@
}
virtual bool CanDeoptimize() const {
- return FLAG_throw_on_javascript_int_overflow
- || has_shift_count_check()
+ return has_shift_count_check()
|| (can_overflow() && (op_kind() == Token::kSHL));
}
@@ -8177,7 +8175,7 @@
class FlowGraphVisitor : public ValueObject {
public:
explicit FlowGraphVisitor(const GrowableArray<BlockEntryInstr*>& block_order)
- : block_order_(block_order), current_iterator_(NULL) { }
+ : current_iterator_(NULL), block_order_(block_order) { }
virtual ~FlowGraphVisitor() { }
ForwardInstructionIterator* current_iterator() const {
@@ -8198,10 +8196,10 @@
#undef DECLARE_VISIT_INSTRUCTION
protected:
- const GrowableArray<BlockEntryInstr*>& block_order_;
ForwardInstructionIterator* current_iterator_;
private:
+ const GrowableArray<BlockEntryInstr*>& block_order_;
DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor);
};
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index a86906a..93619bc 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -2883,10 +2883,15 @@
const Register value = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
- ASSERT(FLAG_allow_absolute_addresses);
- __ LoadImmediate(IP, flags_address);
- __ LoadImmediate(value, Isolate::kOsrRequest);
- __ str(value, Address(IP));
+ if (FLAG_allow_absolute_addresses) {
+ __ LoadImmediate(IP, flags_address);
+ __ LoadImmediate(value, Isolate::kOsrRequest);
+ __ str(value, Address(IP));
+ } else {
+ __ LoadIsolate(IP);
+ __ LoadImmediate(value, Isolate::kOsrRequest);
+ __ str(value, Address(IP, Isolate::stack_overflow_flags_offset()));
+ }
}
__ Comment("CheckStackOverflowSlowPath");
__ Bind(entry_label());
@@ -6069,27 +6074,6 @@
}
-static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
- Label* overflow,
- Register result_lo,
- Register result_hi) {
- // Compare upper half.
- Label check_lower;
- __ CompareImmediate(result_hi, 0x00200000);
- __ b(overflow, GT);
- __ b(&check_lower, NE);
-
- __ CompareImmediate(result_lo, 0);
- __ b(overflow, HI);
-
- __ Bind(&check_lower);
- __ CompareImmediate(result_hi, -0x00200000);
- __ b(overflow, LT);
- // Anything in the lower part would make the number bigger than the lower
- // bound, so we are done.
-}
-
-
LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@@ -6167,9 +6151,6 @@
default:
UNREACHABLE();
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
- }
}
@@ -6315,10 +6296,6 @@
UNREACHABLE();
}
}
-
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
- }
}
@@ -6345,17 +6322,8 @@
PairLocation* out_pair = locs()->out(0).AsPairLocation();
Register out_lo = out_pair->At(0).reg();
Register out_hi = out_pair->At(1).reg();
-
- Label* deopt = NULL;
-
- if (FLAG_throw_on_javascript_int_overflow) {
- deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
- }
__ mvn(out_lo, Operand(left_lo));
__ mvn(out_hi, Operand(left_hi));
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
- }
}
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index e8bd759..0627f74 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -2593,10 +2593,15 @@
const Register value = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
- ASSERT(FLAG_allow_absolute_addresses);
- __ LoadImmediate(TMP, flags_address);
- __ LoadImmediate(value, Isolate::kOsrRequest);
- __ str(value, Address(TMP));
+ if (FLAG_allow_absolute_addresses) {
+ __ LoadImmediate(TMP, flags_address);
+ __ LoadImmediate(value, Isolate::kOsrRequest);
+ __ str(value, Address(TMP));
+ } else {
+ __ LoadIsolate(TMP);
+ __ LoadImmediate(value, Isolate::kOsrRequest);
+ __ str(value, Address(TMP, Isolate::stack_overflow_flags_offset()));
+ }
}
__ Comment("CheckStackOverflowSlowPath");
__ Bind(entry_label());
@@ -2667,20 +2672,6 @@
}
-static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler,
- Range* range,
- Label* overflow,
- Register result) {
- if (!RangeUtils::IsWithin(range, -0x20000000000000LL, 0x20000000000000LL)) {
- ASSERT(overflow != NULL);
- __ LoadImmediate(TMP, 0x20000000000000LL);
- __ add(TMP2, result, Operand(TMP));
- __ cmp(TMP2, Operand(TMP, LSL, 1));
- __ b(overflow, HI);
- }
-}
-
-
static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
BinarySmiOpInstr* shift_left) {
const LocationSummary& locs = *shift_left->locs();
@@ -2704,9 +2695,6 @@
}
// Shift for result now we know there is no overflow.
__ LslImmediate(result, left, value);
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
- }
return;
}
@@ -2736,9 +2724,6 @@
__ SmiUntag(TMP, right);
__ lslv(result, left, TMP);
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
- }
return;
}
@@ -2783,9 +2768,6 @@
// Shift for result now we know there is no overflow.
__ lslv(result, left, TMP);
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
- }
}
@@ -2921,9 +2903,6 @@
UNREACHABLE();
break;
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
- }
return;
}
@@ -3066,9 +3045,6 @@
UNREACHABLE();
break;
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
- }
}
@@ -4527,9 +4503,6 @@
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
__ subs(result, ZR, Operand(value));
__ b(deopt, VS);
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, value);
- }
break;
}
case Token::kBIT_NOT:
@@ -4645,9 +4618,6 @@
__ CompareImmediate(result, 0xC000000000000000);
__ b(&do_call, MI);
__ SmiTag(result);
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), &do_call, result);
- }
__ b(&done);
__ Bind(&do_call);
__ Push(value_obj);
@@ -4695,9 +4665,6 @@
__ CompareImmediate(result, 0xC000000000000000);
__ b(deopt, MI);
__ SmiTag(result);
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
- }
}
@@ -5011,9 +4978,6 @@
__ add(TMP, result_mod, Operand(right));
__ csel(result_mod, TMP, TMP2, GE);
__ Bind(&done);
- // FLAG_throw_on_javascript_int_overflow: not needed.
- // Note that the result of an integer division/modulo of two
- // in-range arguments, cannot create out-of-range result.
return;
}
if (kind() == MergedMathInstr::kSinCos) {
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index f067afe..8933848 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -25,7 +25,6 @@
DECLARE_FLAG(bool, emit_edge_counters);
DECLARE_FLAG(int, optimization_counter_threshold);
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
DECLARE_FLAG(bool, use_osr);
// Generic summary for call instructions that have all arguments pushed
@@ -441,27 +440,6 @@
}
-static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
- Label* overflow,
- Register result_lo,
- Register result_hi) {
- // Compare upper half.
- Label check_lower;
- __ cmpl(result_hi, Immediate(0x00200000));
- __ j(GREATER, overflow);
- __ j(NOT_EQUAL, &check_lower);
-
- __ cmpl(result_lo, Immediate(0));
- __ j(ABOVE, overflow);
-
- __ Bind(&check_lower);
- __ cmpl(result_hi, Immediate(-0x00200000));
- __ j(LESS, overflow);
- // Anything in the lower part would make the number bigger than the lower
- // bound, so we are done.
-}
-
-
static Condition TokenKindToMintCondition(Token::Kind kind) {
switch (kind) {
case Token::kEQ: return EQUAL;
@@ -6035,9 +6013,6 @@
default:
UNREACHABLE();
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
- }
}
@@ -6237,9 +6212,6 @@
}
__ Bind(&done);
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
- }
}
@@ -6252,9 +6224,6 @@
summary->set_in(0, Location::Pair(Location::RequiresRegister(),
Location::RequiresRegister()));
summary->set_out(0, Location::SameAsFirstInput());
- if (FLAG_throw_on_javascript_int_overflow) {
- summary->set_temp(0, Location::RequiresRegister());
- }
return summary;
}
@@ -6269,18 +6238,8 @@
Register out_hi = out_pair->At(1).reg();
ASSERT(out_lo == left_lo);
ASSERT(out_hi == left_hi);
-
- Label* deopt = NULL;
- if (FLAG_throw_on_javascript_int_overflow) {
- deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
- }
-
__ notl(left_lo);
__ notl(left_hi);
-
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
- }
}
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 064bd6e..93e720c 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -2711,10 +2711,15 @@
Register value = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
- ASSERT(FLAG_allow_absolute_addresses);
- __ LoadImmediate(TMP, flags_address);
- __ LoadImmediate(value, Isolate::kOsrRequest);
- __ sw(value, Address(TMP));
+ if (FLAG_allow_absolute_addresses) {
+ __ LoadImmediate(TMP, flags_address);
+ __ LoadImmediate(value, Isolate::kOsrRequest);
+ __ sw(value, Address(TMP));
+ } else {
+ __ LoadIsolate(TMP);
+ __ LoadImmediate(value, Isolate::kOsrRequest);
+ __ sw(value, Address(TMP, Isolate::stack_overflow_flags_offset()));
+ }
}
__ Comment("CheckStackOverflowSlowPath");
__ Bind(entry_label());
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 1f840fd..2fdf93e 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -26,7 +26,6 @@
DECLARE_FLAG(bool, allow_absolute_addresses);
DECLARE_FLAG(bool, emit_edge_counters);
DECLARE_FLAG(int, optimization_counter_threshold);
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
DECLARE_FLAG(bool, use_osr);
DECLARE_FLAG(bool, precompilation);
@@ -2613,9 +2612,14 @@
Register temp = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
- ASSERT(FLAG_allow_absolute_addresses);
- __ LoadImmediate(temp, Immediate(flags_address));
- __ movq(Address(temp, 0), Immediate(Isolate::kOsrRequest));
+ if (FLAG_allow_absolute_addresses) {
+ __ LoadImmediate(temp, Immediate(flags_address));
+ __ movq(Address(temp, 0), Immediate(Isolate::kOsrRequest));
+ } else {
+ __ LoadIsolate(TMP);
+ __ movq(Address(TMP, Isolate::stack_overflow_flags_offset()),
+ Immediate(Isolate::kOsrRequest));
+ }
}
__ Comment("CheckStackOverflowSlowPath");
__ Bind(entry_label());
@@ -2687,22 +2691,6 @@
}
-static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler,
- Range* range,
- Label* overflow,
- Register result) {
- if (!RangeUtils::IsWithin(range, -0x20000000000000LL, 0x20000000000000LL)) {
- ASSERT(overflow != NULL);
- // TODO(zra): This can be tightened to one compare/branch using:
- // overflow = (result + 2^52) > 2^53 with an unsigned comparison.
- __ CompareImmediate(result, Immediate(-0x20000000000000LL));
- __ j(LESS, overflow);
- __ CompareImmediate(result, Immediate(0x20000000000000LL));
- __ j(GREATER, overflow);
- }
-}
-
-
static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
BinarySmiOpInstr* shift_left) {
const LocationSummary& locs = *shift_left->locs();
@@ -2730,9 +2718,6 @@
}
// Shift for result now we know there is no overflow.
__ shlq(left, Immediate(value));
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
- }
return;
}
@@ -2761,9 +2746,6 @@
__ SmiUntag(right);
__ shlq(left, right);
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
- }
return;
}
@@ -2813,9 +2795,6 @@
// Shift for result now we know there is no overflow.
__ shlq(left, right);
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
- }
}
@@ -2996,9 +2975,6 @@
UNREACHABLE();
break;
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
- }
return;
} // locs()->in(1).IsConstant().
@@ -3041,9 +3017,6 @@
UNREACHABLE();
break;
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
- }
return;
} // locs()->in(1).IsStackSlot().
@@ -3240,9 +3213,6 @@
UNREACHABLE();
break;
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
- }
}
@@ -4732,9 +4702,6 @@
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
__ negq(value);
__ j(OVERFLOW, deopt);
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, value);
- }
break;
}
case Token::kBIT_NOT:
@@ -4938,9 +4905,6 @@
__ shlq(temp, Immediate(1));
__ j(OVERFLOW, &do_call, Assembler::kNearJump);
__ SmiTag(result);
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), &do_call, result);
- }
__ jmp(&done);
__ Bind(&do_call);
ASSERT(instance_call()->HasICData());
@@ -4988,9 +4952,6 @@
__ shlq(temp, Immediate(1));
__ j(OVERFLOW, deopt);
__ SmiTag(result);
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
- }
}
@@ -5423,7 +5384,6 @@
__ SmiTag(RAX);
__ SmiTag(RDX);
- // FLAG_throw_on_javascript_int_overflow: not needed.
// Note that the result of an integer division/modulo of two
// in-range arguments, cannot create out-of-range result.
return;
@@ -5728,10 +5688,6 @@
}
EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt);
-
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, out);
- }
}
@@ -5752,17 +5708,7 @@
const Register left = locs()->in(0).reg();
const Register out = locs()->out(0).reg();
ASSERT(out == left);
-
- Label* deopt = NULL;
- if (FLAG_throw_on_javascript_int_overflow) {
- deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
- }
-
__ notq(left);
-
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, out);
- }
}
@@ -5859,9 +5805,6 @@
UNREACHABLE();
}
}
- if (FLAG_throw_on_javascript_int_overflow) {
- EmitJavascriptOverflowCheck(compiler, range(), deopt, out);
- }
}
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 69c723d..193dba4 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -21,7 +21,6 @@
namespace dart {
DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible");
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
DECLARE_FLAG(bool, code_comments);
DECLARE_FLAG(bool, print_flow_graph);
DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -201,15 +200,10 @@
default:
break;
}
- // Integer intrinsics are in the core library, but we don't want to
- // intrinsify when Smi > 32 bits if we are looking for javascript integer
- // overflow.
- if (!(FLAG_throw_on_javascript_int_overflow && (Smi::kBits >= 32))) {
- switch (function.recognized_kind()) {
- CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE)
- default:
- break;
- }
+ switch (function.recognized_kind()) {
+ CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE)
+ default:
+ break;
}
#undef EMIT_INTRINSIC
}
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 3214d5f..32b50e8 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -52,6 +52,7 @@
DECLARE_FLAG(bool, print_metrics);
DECLARE_FLAG(bool, timing);
DECLARE_FLAG(bool, trace_service);
+DECLARE_FLAG(bool, trace_service_verbose);
DEFINE_FLAG(bool, trace_isolates, false,
"Trace isolate creation and shut down.");
@@ -764,6 +765,8 @@
#define REUSABLE_HANDLE_INITIALIZERS(object) \
object##_handle_(NULL),
+// TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with
+// that shared monitor.
Isolate::Isolate(const Dart_IsolateFlags& api_flags)
: stack_limit_(0),
store_buffer_(new StoreBuffer()),
@@ -831,6 +834,8 @@
cha_invalidation_gen_(kInvalidGen),
field_invalidation_gen_(kInvalidGen),
prefix_invalidation_gen_(kInvalidGen),
+ boxed_field_list_monitor_(new Monitor()),
+ boxed_field_list_(GrowableObjectArray::null()),
spawn_count_monitor_(new Monitor()),
spawn_count_(0) {
flags_.CopyFrom(api_flags);
@@ -868,6 +873,8 @@
object_id_ring_ = NULL;
delete pause_loop_monitor_;
pause_loop_monitor_ = NULL;
+ delete boxed_field_list_monitor_;
+ boxed_field_list_monitor_ = NULL;
ASSERT(spawn_count_ == 0);
delete spawn_count_monitor_;
if (compiler_stats_ != NULL) {
@@ -901,12 +908,7 @@
#ifndef PRODUCT
// Initialize Timeline streams.
-#define ISOLATE_TIMELINE_STREAM_INIT(name, enabled_by_default) \
- result->stream_##name##_.Init(#name, \
- enabled_by_default, \
- Timeline::Stream##name##EnabledFlag());
- ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT);
-#undef ISOLATE_TIMELINE_STREAM_INIT
+ Timeline::SetupIsolateStreams(result);
#endif // !PRODUCT
Heap::Init(result,
@@ -1011,11 +1013,29 @@
snapshot.instructions_size());
}
#endif
- heap_->SetupInstructionsSnapshotPage(snapshot.instructions_start(),
- snapshot.instructions_size());
+ heap_->SetupExternalPage(snapshot.instructions_start(),
+ snapshot.instructions_size(),
+ /* is_executable = */ true);
}
+void Isolate::SetupDataSnapshotPage(const uint8_t* data_snapshot_buffer) {
+ DataSnapshot snapshot(data_snapshot_buffer);
+#if defined(DEBUG)
+ if (FLAG_trace_isolates) {
+ OS::Print("Precompiled rodata are at [0x%" Px ", 0x%" Px ")\n",
+ reinterpret_cast<uword>(snapshot.data_start()),
+ reinterpret_cast<uword>(snapshot.data_start()) +
+ snapshot.data_size());
+ }
+#endif
+ heap_->SetupExternalPage(snapshot.data_start(),
+ snapshot.data_size(),
+ /* is_executable = */ false);
+}
+
+
+
void Isolate::set_debugger_name(const char* name) {
free(debugger_name_);
debugger_name_ = strdup(name);
@@ -1518,6 +1538,10 @@
stack_limit_ = saved_stack_limit_;
}
}
+ if (FLAG_trace_service && FLAG_trace_service_verbose) {
+ OS::Print("[+%" Pd64 "ms] Isolate %s deferring OOB interrupts\n",
+ Dart::timestamp(), name());
+ }
}
@@ -1532,6 +1556,10 @@
stack_limit_ |= deferred_interrupts_;
deferred_interrupts_ = 0;
}
+ if (FLAG_trace_service && FLAG_trace_service_verbose) {
+ OS::Print("[+%" Pd64 "ms] Isolate %s restoring OOB interrupts\n",
+ Dart::timestamp(), name());
+ }
}
@@ -1846,6 +1874,12 @@
visitor->VisitPointer(
reinterpret_cast<RawObject**>(®istered_service_extension_handlers_));
+ // Visit the boxed_field_list.
+ // 'boxed_field_list_' access via mutator and background compilation threads
+ // is guarded with a monitor. This means that we can visit it only
+ // when at safepoint or the boxed_field_list_monitor_ lock has been taken.
+ visitor->VisitPointer(reinterpret_cast<RawObject**>(&boxed_field_list_));
+
// Visit objects in the debugger.
if (FLAG_support_debugger) {
debugger()->VisitObjectPointers(visitor);
@@ -2050,6 +2084,31 @@
}
+void Isolate::AddDeoptimizingBoxedField(const Field& field) {
+ MonitorLocker ml(boxed_field_list_monitor_);
+ if (boxed_field_list_ == GrowableObjectArray::null()) {
+ boxed_field_list_ = GrowableObjectArray::New(Heap::kOld);
+ }
+ const GrowableObjectArray& array =
+ GrowableObjectArray::Handle(boxed_field_list_);
+ array.Add(field, Heap::kOld);
+}
+
+
+RawField* Isolate::GetDeoptimizingBoxedField() {
+ MonitorLocker ml(boxed_field_list_monitor_);
+ if (boxed_field_list_ == GrowableObjectArray::null()) {
+ return Field::null();
+ }
+ const GrowableObjectArray& array =
+ GrowableObjectArray::Handle(boxed_field_list_);
+ if (array.Length() == 0) {
+ return Field::null();
+ }
+ return Field::RawCast(array.RemoveLast());
+}
+
+
RawObject* Isolate::InvokePendingServiceExtensionCalls() {
if (!FLAG_support_service) {
return Object::null();
@@ -2067,7 +2126,7 @@
ASSERT(!run_extension.IsNull());
const Array& arguments =
- Array::Handle(Array::New(kPendingEntrySize, Heap::kNew));
+ Array::Handle(Array::New(kPendingEntrySize + 1, Heap::kNew));
Object& result = Object::Handle();
String& method_name = String::Handle();
Instance& closure = Instance::Handle();
@@ -2094,8 +2153,19 @@
arguments.SetAt(kPendingReplyPortIndex, reply_port);
id ^= calls.At(i + kPendingIdIndex);
arguments.SetAt(kPendingIdIndex, id);
+ arguments.SetAt(kPendingEntrySize, Bool::Get(FLAG_trace_service));
+ if (FLAG_trace_service) {
+ OS::Print(
+ "[+%" Pd64 "ms] Isolate %s invoking _runExtension for %s\n",
+ Dart::timestamp(), name(), method_name.ToCString());
+ }
result = DartEntry::InvokeFunction(run_extension, arguments);
+ if (FLAG_trace_service) {
+ OS::Print(
+ "[+%" Pd64 "ms] Isolate %s : _runExtension complete for %s\n",
+ Dart::timestamp(), name(), method_name.ToCString());
+ }
if (result.IsError()) {
if (result.IsUnwindError()) {
// Propagate the unwind error. Remaining service extension calls
@@ -2133,6 +2203,11 @@
const Array& parameter_values,
const Instance& reply_port,
const Instance& id) {
+ if (FLAG_trace_service) {
+ OS::Print(
+ "[+%" Pd64 "ms] Isolate %s ENQUEUING request for extension %s\n",
+ Dart::timestamp(), name(), method_name.ToCString());
+ }
GrowableObjectArray& calls =
GrowableObjectArray::Handle(pending_service_extension_calls());
if (calls.IsNull()) {
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index f2a0cc3..15c2562 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -53,6 +53,7 @@
class RawObject;
class RawInteger;
class RawError;
+class RawField;
class RawFloat32x4;
class RawInt32x4;
class RawUserTag;
@@ -239,6 +240,8 @@
void SetupInstructionsSnapshotPage(
const uint8_t* instructions_snapshot_buffer);
+ void SetupDataSnapshotPage(
+ const uint8_t* instructions_snapshot_buffer);
// Returns true if any of the interrupts specified by 'interrupt_bits' are
// currently scheduled for this isolate, but leaves them unchanged.
@@ -274,6 +277,9 @@
uword stack_overflow_flags_address() const {
return reinterpret_cast<uword>(&stack_overflow_flags_);
}
+ static intptr_t stack_overflow_flags_offset() {
+ return OFFSET_OF(Isolate, stack_overflow_flags_);
+ }
int32_t IncrementAndGetStackOverflowCount() {
return ++stack_overflow_count_;
@@ -642,6 +648,12 @@
void ResetPrefixInvalidationGen() { prefix_invalidation_gen_ = kInvalidGen; }
uint32_t prefix_invalidation_gen() const { return prefix_invalidation_gen_; }
+ // Used by background compiler which field became boxed and must trigger
+ // deoptimization in the mutator thread.
+ void AddDeoptimizingBoxedField(const Field& field);
+ // Returns Field::null() if none available in the list.
+ RawField* GetDeoptimizingBoxedField();
+
RawObject* InvokePendingServiceExtensionCalls();
void AppendServiceExtensionCall(const Instance& closure,
const String& method_name,
@@ -844,6 +856,11 @@
uint32_t field_invalidation_gen_;
uint32_t prefix_invalidation_gen_;
+ // Protect access to boxed_field_list_.
+ Monitor* boxed_field_list_monitor_;
+ // List of fields that became boxed and that trigger deoptimization.
+ RawGrowableObjectArray* boxed_field_list_;
+
// This guards spawn_count_. An isolate cannot complete shutdown and be
// destroyed while there are child isolates in the midst of a spawn.
Monitor* spawn_count_monitor_;
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index b64d6e6..94928ab 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -79,9 +79,9 @@
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
const char* isolate_name = isolate->name();
- OS::Print("Isolate %s processing service request %s\n",
- isolate_name, method_);
setup_time_micros_ = OS::GetCurrentTimeMicros();
+ OS::Print("[+%" Pd64 "ms] Isolate %s processing service request %s\n",
+ Dart::timestamp(), isolate_name, method_);
}
buffer_.Printf("{\"jsonrpc\":\"2.0\", \"result\":");
}
@@ -172,10 +172,6 @@
Dart_Port port = reply_port();
ASSERT(port != ILLEGAL_PORT);
set_reply_port(ILLEGAL_PORT); // Prevent double replies.
- int64_t process_delta_micros = 0;
- if (FLAG_trace_service) {
- process_delta_micros = OS::GetCurrentTimeMicros() - setup_time_micros_;
- }
ASSERT(seq_ != NULL);
if (seq_->IsString()) {
const String& str = String::Cast(*seq_);
@@ -206,12 +202,15 @@
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
const char* isolate_name = isolate->name();
+ int64_t total_time = OS::GetCurrentTimeMicros() - setup_time_micros_;
if (result) {
- OS::Print("Isolate %s processed service request %s in %" Pd64" us.\n",
- isolate_name, method_, process_delta_micros);
+ OS::Print("[+%" Pd64 "ms] Isolate %s processed service request %s "
+ "(%" Pd64 "us)\n",
+ Dart::timestamp(), isolate_name, method_, total_time);
} else {
- OS::Print("Isolate %s FAILED to post response for service request %s.\n",
- isolate_name, method_);
+ OS::Print("[+%" Pd64 "ms] Isolate %s processed service request %s "
+ "(%" Pd64 "us) FAILED\n",
+ Dart::timestamp(), isolate_name, method_, total_time);
}
}
}
diff --git a/runtime/vm/log.cc b/runtime/vm/log.cc
index b7f6589..91be51d 100644
--- a/runtime/vm/log.cc
+++ b/runtime/vm/log.cc
@@ -141,16 +141,26 @@
void Log::TerminateString() {
+ if (this == NoOpLog()) {
+ return;
+ }
buffer_.Add('\0');
}
void Log::EnableManualFlush() {
+ if (this == NoOpLog()) {
+ return;
+ }
manual_flush_++;
}
void Log::DisableManualFlush() {
+ if (this == NoOpLog()) {
+ return;
+ }
+
manual_flush_--;
ASSERT(manual_flush_ >= 0);
if (manual_flush_ == 0) {
diff --git a/runtime/vm/longjump.cc b/runtime/vm/longjump.cc
index ef141c9..13e0133 100644
--- a/runtime/vm/longjump.cc
+++ b/runtime/vm/longjump.cc
@@ -29,7 +29,10 @@
uword jumpbuf_addr = Isolate::GetCurrentStackPointer();
#if defined(USING_SIMULATOR)
Simulator* sim = Simulator::Current();
- uword top_exit_frame_info = sim->top_exit_frame_info();
+ // When using simulator, only mutator thread should refer to Simulator
+ // since there can be only one per isolate.
+ uword top_exit_frame_info = thread->IsMutatorThread() ?
+ sim->top_exit_frame_info() : 0;
#else
uword top_exit_frame_info = thread->top_exit_frame_info();
#endif
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index febf565..c85afa2 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -56,9 +56,6 @@
DEFINE_FLAG(bool, show_internal_names, false,
"Show names of internal classes (e.g. \"OneByteString\") in error messages "
"instead of showing the corresponding interface names (e.g. \"String\")");
-DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false,
- "Throw an exception when the result of an integer calculation will not "
- "fit into a javascript integer.");
DEFINE_FLAG(bool, trace_cha, false, "Trace CHA operations");
DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids.");
DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
@@ -915,9 +912,12 @@
if (!obj->IsFreeListElement()) {
ASSERT(obj->IsVMHeapObject());
if (obj->IsMarked()) {
- // Precompiled instructions are loaded pre-marked.
+ // Precompiled objects are loaded pre-marked.
ASSERT(Dart::IsRunningPrecompiledCode());
- ASSERT(obj->IsInstructions());
+ ASSERT(obj->IsInstructions() ||
+ obj->IsPcDescriptors() ||
+ obj->IsStackmap() ||
+ obj->IsOneByteString());
} else {
obj->SetMarkBitUnsynchronized();
}
@@ -3690,13 +3690,13 @@
}
if (other.IsFunctionClass()) {
// Check if type S has a call() method.
- Function& function =
- Function::Handle(zone, thsi.LookupDynamicFunction(Symbols::Call()));
+ Function& function = Function::Handle(zone,
+ thsi.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
if (function.IsNull()) {
// Walk up the super_class chain.
Class& cls = Class::Handle(zone, thsi.SuperClass());
while (!cls.IsNull() && function.IsNull()) {
- function = cls.LookupDynamicFunction(Symbols::Call());
+ function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
cls = cls.SuperClass();
}
}
@@ -3819,6 +3819,12 @@
}
+RawFunction* Class::LookupDynamicFunctionAllowAbstract(
+ const String& name) const {
+ return LookupFunction(name, kInstanceAllowAbstract);
+}
+
+
RawFunction* Class::LookupDynamicFunctionAllowPrivate(
const String& name) const {
return LookupFunctionAllowPrivate(name, kInstance);
@@ -3891,8 +3897,8 @@
RawFunction* Class::CheckFunctionType(const Function& func, MemberKind kind) {
- if (kind == kInstance) {
- if (func.IsDynamicFunction()) {
+ if ((kind == kInstance) || (kind == kInstanceAllowAbstract)) {
+ if (func.IsDynamicFunction(kind == kInstanceAllowAbstract)) {
return func.raw();
}
} else if (kind == kStatic) {
@@ -6030,26 +6036,29 @@
AbstractType& other_res_type = AbstractType::Handle(other.result_type());
if (!other_res_type.IsInstantiated()) {
other_res_type = other_res_type.InstantiateFrom(other_type_arguments,
- bound_error);
+ bound_error,
+ NULL, NULL, space);
ASSERT((bound_error == NULL) || bound_error->IsNull());
}
if (!other_res_type.IsDynamicType() && !other_res_type.IsVoidType()) {
AbstractType& res_type = AbstractType::Handle(result_type());
if (!res_type.IsInstantiated()) {
- res_type = res_type.InstantiateFrom(type_arguments, bound_error);
+ res_type = res_type.InstantiateFrom(type_arguments, bound_error,
+ NULL, NULL, space);
ASSERT((bound_error == NULL) || bound_error->IsNull());
}
if (res_type.IsVoidType()) {
return false;
}
if (test_kind == kIsSubtypeOf) {
- if (!res_type.IsSubtypeOf(other_res_type, bound_error) &&
- !other_res_type.IsSubtypeOf(res_type, bound_error)) {
+ if (!res_type.IsSubtypeOf(other_res_type, bound_error, NULL, space) &&
+ !other_res_type.IsSubtypeOf(res_type, bound_error, NULL, space)) {
return false;
}
} else {
ASSERT(test_kind == kIsMoreSpecificThan);
- if (!res_type.IsMoreSpecificThan(other_res_type, bound_error)) {
+ if (!res_type.IsMoreSpecificThan(other_res_type, bound_error,
+ NULL, space)) {
return false;
}
}
@@ -6418,7 +6427,8 @@
if (instantiate &&
param_type.IsFinalized() &&
!param_type.IsInstantiated()) {
- param_type = param_type.InstantiateFrom(instantiator, NULL);
+ param_type = param_type.InstantiateFrom(instantiator, NULL,
+ NULL, NULL, Heap::kNew);
}
name = param_type.BuildName(name_visibility);
pieces->Add(name);
@@ -6445,7 +6455,8 @@
if (instantiate &&
param_type.IsFinalized() &&
!param_type.IsInstantiated()) {
- param_type = param_type.InstantiateFrom(instantiator, NULL);
+ param_type = param_type.InstantiateFrom(instantiator, NULL,
+ NULL, NULL, Heap::kNew);
}
ASSERT(!param_type.IsNull());
name = param_type.BuildName(name_visibility);
@@ -6543,7 +6554,8 @@
pieces.Add(Symbols::RParenArrow());
AbstractType& res_type = AbstractType::Handle(zone, result_type());
if (instantiate && res_type.IsFinalized() && !res_type.IsInstantiated()) {
- res_type = res_type.InstantiateFrom(instantiator, NULL);
+ res_type = res_type.InstantiateFrom(instantiator, NULL,
+ NULL, NULL, Heap::kNew);
}
name = res_type.BuildName(name_visibility);
pieces.Add(name);
@@ -6775,7 +6787,7 @@
void Function::RestoreICDataMap(
ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data,
- bool clone_descriptors) const {
+ bool clone_ic_data) const {
ASSERT(deopt_id_to_ic_data->is_empty());
Zone* zone = Thread::Current()->zone();
const Array& saved_ic_data = Array::Handle(zone, ic_data_array());
@@ -6795,9 +6807,9 @@
for (intptr_t i = 1; i < saved_length; i++) {
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);
+ if (clone_ic_data) {
+ const ICData& original_ic_data = ICData::Handle(zone, ic_data.raw());
+ ic_data = ICData::Clone(ic_data);
ic_data.SetOriginal(original_ic_data);
}
(*deopt_id_to_ic_data)[ic_data.deopt_id()] = &ic_data;
@@ -11675,7 +11687,6 @@
void ICData::set_owner(const Function& value) const {
- ASSERT(!value.IsNull());
StorePointer(&raw_ptr()->owner_, reinterpret_cast<RawObject*>(value.raw()));
}
@@ -11739,35 +11750,6 @@
}
-bool ICData::IssuedJSWarning() const {
- return IssuedJSWarningBit::decode(raw_ptr()->state_bits_);
-}
-
-
-void ICData::SetIssuedJSWarning() const {
- StoreNonPointer(&raw_ptr()->state_bits_,
- IssuedJSWarningBit::update(true, raw_ptr()->state_bits_));
-}
-
-
-bool ICData::MayCheckForJSWarning() const {
- const String& name = String::Handle(target_name());
- // Warning issued from native code.
- // Calling sequence is decoded to obtain ic data in order to check if a
- // warning has already been issued.
- if (name.Equals(Library::PrivateCoreLibName(Symbols::_instanceOf())) ||
- name.Equals(Library::PrivateCoreLibName(Symbols::_as()))) {
- return true;
- }
- // Warning issued in ic miss handler.
- // No decoding necessary, so allow optimization if warning already issued.
- if (name.Equals(Symbols::toString()) && !IssuedJSWarning()) {
- return true;
- }
- return false;
-}
-
-
void ICData::set_state_bits(uint32_t bits) const {
StoreNonPointer(&raw_ptr()->state_bits_, bits);
}
@@ -12326,7 +12308,7 @@
}
-RawICData* ICData::CloneDescriptor(const ICData& from) {
+RawICData* ICData::Clone(const ICData& from) {
Zone* zone = Thread::Current()->zone();
const ICData& result = ICData::Handle(ICData::NewDescriptor(
zone,
@@ -12335,8 +12317,17 @@
Array::Handle(zone, from.arguments_descriptor()),
from.deopt_id(),
from.NumArgsTested()));
- // Preserve entry array.
- result.set_ic_data_array(Array::Handle(zone, from.ic_data()));
+ // Clone entry array.
+ const Array& from_array = Array::Handle(zone, from.ic_data());
+ const intptr_t len = from_array.Length();
+ const Array& cloned_array =
+ Array::Handle(zone, Array::New(len, Heap::kOld));
+ Object& obj = Object::Handle(zone);
+ for (intptr_t i = 0; i < len; i++) {
+ obj = from_array.At(i);
+ cloned_array.SetAt(i, obj);
+ }
+ result.set_ic_data_array(cloned_array);
// Copy deoptimization reasons.
result.SetDeoptReasons(from.DeoptReasons());
return result.raw();
@@ -14205,6 +14196,7 @@
Error* bound_error) const {
ASSERT(other.IsFinalized());
ASSERT(!other.IsDynamicType());
+ ASSERT(!other.IsTypeRef()); // Must be dereferenced at compile time.
ASSERT(!other.IsMalformed());
ASSERT(!other.IsMalbounded());
if (other.IsVoidType()) {
@@ -14220,12 +14212,16 @@
TypeArguments& other_type_arguments = TypeArguments::Handle(zone);
// Note that we may encounter a bound error in checked mode.
if (!other.IsInstantiated()) {
- const AbstractType& instantiated_other = AbstractType::Handle(
- zone, other.InstantiateFrom(other_instantiator, bound_error));
+ AbstractType& instantiated_other = AbstractType::Handle(
+ zone, other.InstantiateFrom(other_instantiator, bound_error,
+ NULL, NULL, Heap::kOld));
if ((bound_error != NULL) && !bound_error->IsNull()) {
ASSERT(Isolate::Current()->flags().type_checks());
return false;
}
+ if (instantiated_other.IsTypeRef()) {
+ instantiated_other = TypeRef::Cast(instantiated_other).type();
+ }
if (instantiated_other.IsDynamicType() ||
instantiated_other.IsObjectType() ||
instantiated_other.IsDartFunctionType()) {
@@ -14273,7 +14269,8 @@
AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
// Note that we may encounter a bound error in checked mode.
if (!other.IsInstantiated()) {
- instantiated_other = other.InstantiateFrom(other_instantiator, bound_error);
+ instantiated_other = other.InstantiateFrom(other_instantiator, bound_error,
+ NULL, NULL, Heap::kOld);
if ((bound_error != NULL) && !bound_error->IsNull()) {
ASSERT(Isolate::Current()->flags().type_checks());
return false;
@@ -14289,13 +14286,13 @@
const bool other_is_dart_function = instantiated_other.IsDartFunctionType();
if (other_is_dart_function || instantiated_other.IsFunctionType()) {
// Check if this instance understands a call() method of a compatible type.
- Function& call =
- Function::Handle(zone, cls.LookupDynamicFunction(Symbols::Call()));
+ Function& call = Function::Handle(zone,
+ cls.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
if (call.IsNull()) {
// Walk up the super_class chain.
Class& super_cls = Class::Handle(zone, cls.SuperClass());
while (!super_cls.IsNull() && call.IsNull()) {
- call = super_cls.LookupDynamicFunction(Symbols::Call());
+ call = super_cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
super_cls = super_cls.SuperClass();
}
}
@@ -15027,7 +15024,7 @@
}
// The current bound_trail cannot be used, because operands are swapped and
// the test is different anyway (more specific vs. subtype).
- if (bound.IsMoreSpecificThan(other, bound_error, NULL)) {
+ if (bound.IsMoreSpecificThan(other, bound_error, NULL, space)) {
return true;
}
return false; // TODO(regis): We should return "maybe after instantiation".
@@ -15056,13 +15053,13 @@
space);
}
// Check if type S has a call() method of function type T.
- Function& function =
- Function::Handle(zone, type_cls.LookupDynamicFunction(Symbols::Call()));
+ Function& function = Function::Handle(zone,
+ type_cls.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
if (function.IsNull()) {
// Walk up the super_class chain.
Class& cls = Class::Handle(zone, type_cls.SuperClass());
while (!cls.IsNull() && function.IsNull()) {
- function = cls.LookupDynamicFunction(Symbols::Call());
+ function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
cls = cls.SuperClass();
}
}
@@ -16728,7 +16725,8 @@
(!type_param.CheckBound(instantiated_bounded_type,
instantiated_upper_bound,
bound_error,
- bound_trail) &&
+ bound_trail,
+ space) &&
bound_error->IsNull())) {
// We cannot determine yet whether the bounded_type is below the
// upper_bound, because one or both of them is still being finalized or
@@ -16905,16 +16903,6 @@
}
-// Throw JavascriptIntegerOverflow exception.
-static void ThrowJavascriptIntegerOverflow(const Integer& i) {
- const Array& exc_args = Array::Handle(Array::New(1));
- const String& i_str = String::Handle(String::New(i.ToCString()));
- exc_args.SetAt(0, i_str);
- Exceptions::ThrowByType(Exceptions::kJavascriptIntegerOverflowError,
- exc_args);
-}
-
-
RawInteger* Integer::New(const String& str, Heap::Space space) {
// We are not supposed to have integers represented as two byte strings.
ASSERT(str.IsOneByteString());
@@ -16924,19 +16912,12 @@
Bigint::NewFromCString(str.ToCString(), space));
ASSERT(!big.FitsIntoSmi());
ASSERT(!big.FitsIntoInt64());
- if (FLAG_throw_on_javascript_int_overflow) {
- ThrowJavascriptIntegerOverflow(big);
- }
return big.raw();
}
return Integer::New(value, space);
}
-// This is called from LiteralToken::New() in the parser, so we can't
-// raise an exception for javascript overflow here. Instead we do it in
-// Parser::CurrentIntegerLiteral(), which is the point in the parser where
-// integer literals escape, so we can call Parser::ErrorMsg().
RawInteger* Integer::NewCanonical(const String& str) {
// We are not supposed to have integers represented as two byte strings.
ASSERT(str.IsOneByteString());
@@ -16954,16 +16935,8 @@
}
-RawInteger* Integer::New(int64_t value, Heap::Space space, const bool silent) {
+RawInteger* Integer::New(int64_t value, Heap::Space space) {
const bool is_smi = Smi::IsValid(value);
- if (!silent &&
- FLAG_throw_on_javascript_int_overflow &&
- !Utils::IsJavascriptInt(value)) {
- const Integer& i = is_smi ?
- Integer::Handle(Smi::New(static_cast<intptr_t>(value))) :
- Integer::Handle(Mint::New(value, space));
- ThrowJavascriptIntegerOverflow(i);
- }
if (is_smi) {
return Smi::New(static_cast<intptr_t>(value));
}
@@ -16973,10 +16946,6 @@
RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) {
if (value > static_cast<uint64_t>(Mint::kMaxValue)) {
- if (FLAG_throw_on_javascript_int_overflow) {
- const Integer &i = Integer::Handle(Bigint::NewFromUint64(value, space));
- ThrowJavascriptIntegerOverflow(i);
- }
return Bigint::NewFromUint64(value, space);
} else {
return Integer::New(value, space);
@@ -17040,31 +17009,7 @@
}
-// Returns true if the signed Integer does not fit into a
-// Javascript integer.
-bool Integer::CheckJavascriptIntegerOverflow() const {
- // Always overflow if the value doesn't fit into an int64_t.
- int64_t value = 1ULL << 63;
- if (IsSmi()) {
- value = AsInt64Value();
- } else if (IsMint()) {
- Mint& mint = Mint::Handle();
- mint ^= raw();
- value = mint.value();
- } else {
- if (Bigint::Cast(*this).FitsIntoInt64()) {
- value = AsInt64Value();
- }
- }
- return !Utils::IsJavascriptInt(value);
-}
-
-
RawInteger* Integer::AsValidInteger() const {
- if (FLAG_throw_on_javascript_int_overflow &&
- CheckJavascriptIntegerOverflow()) {
- ThrowJavascriptIntegerOverflow(*this);
- }
if (IsSmi()) return raw();
if (IsMint()) {
Mint& mint = Mint::Handle();
@@ -17234,8 +17179,7 @@
// TODO(srdjan): Clarify handling of negative right operand in a shift op.
RawInteger* Smi::ShiftOp(Token::Kind kind,
const Smi& other,
- Heap::Space space,
- const bool silent) const {
+ Heap::Space space) const {
intptr_t result = 0;
const intptr_t left_value = Value();
const intptr_t right_value = other.Value();
@@ -17252,7 +17196,7 @@
return Bigint::NewFromShiftedInt64(left_value, right_value, space);
} else {
int64_t left_64 = left_value;
- return Integer::New(left_64 << right_value, space, silent);
+ return Integer::New(left_64 << right_value, space);
}
}
}
@@ -17709,8 +17653,10 @@
--used;
}
if (used > 0) {
- if ((used & 1) != 0) {
- // Set leading zero for 64-bit processing of digit pairs.
+ if (((used & 1) != 0) && (digits.GetUint32(used << 2) != 0)) {
+ // Set leading zero for 64-bit processing of digit pairs if not set.
+ // The check above ensures that we avoid a write access to a possibly
+ // reused digits array that could be marked read only.
digits.SetUint32(used << 2, 0);
}
result.set_digits(digits);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 34440a1..ebd93ae 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1132,8 +1132,8 @@
const Class& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const {
+ TrailPtr bound_trail,
+ Heap::Space space) const {
return TypeTest(kIsSubtypeOf,
type_arguments,
other,
@@ -1148,8 +1148,8 @@
const Class& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const {
+ TrailPtr bound_trail,
+ Heap::Space space) const {
return TypeTest(kIsMoreSpecificThan,
type_arguments,
other,
@@ -1186,6 +1186,7 @@
RawFunction* ImplicitClosureFunctionFromIndex(intptr_t idx) const;
RawFunction* LookupDynamicFunction(const String& name) const;
+ RawFunction* LookupDynamicFunctionAllowAbstract(const String& name) const;
RawFunction* LookupDynamicFunctionAllowPrivate(const String& name) const;
RawFunction* LookupStaticFunction(const String& name) const;
RawFunction* LookupStaticFunctionAllowPrivate(const String& name) const;
@@ -1373,6 +1374,7 @@
kAny = 0,
kStatic,
kInstance,
+ kInstanceAllowAbstract,
kConstructor,
kFactory,
};
@@ -1582,8 +1584,8 @@
intptr_t from_index,
intptr_t len,
Error* bound_error,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const {
+ TrailPtr bound_trail,
+ Heap::Space space) const {
return TypeTest(kIsSubtypeOf, other, from_index, len,
bound_error, bound_trail, space);
}
@@ -1594,8 +1596,8 @@
intptr_t from_index,
intptr_t len,
Error* bound_error,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const {
+ TrailPtr bound_trail,
+ Heap::Space space) const {
return TypeTest(kIsMoreSpecificThan, other, from_index, len,
bound_error, bound_trail, space);
}
@@ -1653,9 +1655,9 @@
RawTypeArguments* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr instantiation_trail = NULL,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const;
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
+ Heap::Space space) const;
// Runtime instantiation with canonicalization. Not to be used during type
// finalization at compile time.
@@ -1839,13 +1841,6 @@
bool HasDeoptReason(ICData::DeoptReasonId reason) const;
void AddDeoptReason(ICData::DeoptReasonId reason) const;
- bool IssuedJSWarning() const;
- void SetIssuedJSWarning() const;
-
- // Return true if the target function of this IC data may check for (and
- // possibly issue) a Javascript compatibility warning.
- bool MayCheckForJSWarning() const;
-
intptr_t NumberOfChecks() const;
// Discounts any checks with usage of zero.
@@ -1946,11 +1941,8 @@
intptr_t num_args_tested);
static RawICData* NewFrom(const ICData& from, intptr_t num_args_tested);
- // Generates a new ICData with descriptor data copied (shallow clone).
- // Entry array of the result is the same as in 'from'. Once entry array is
- // created, it can only change the 'count', all other properties are invariant
- // (target, cids, number of checks).
- static RawICData* CloneDescriptor(const ICData& from);
+ // Generates a new ICData with descriptor and data array copied (deep clone).
+ static RawICData* Clone(const ICData& from);
static intptr_t TestEntryLengthFor(intptr_t num_args);
@@ -2034,7 +2026,7 @@
}
}
- // It is only meaningful to interptret range feedback stored in the ICData
+ // It is only meaningful to interpret range feedback stored in the ICData
// when all checks are Mint or Smi.
bool HasRangeFeedback() const;
RangeFeedback DecodeRangeFeedbackAt(intptr_t idx) const;
@@ -2073,8 +2065,7 @@
kNumArgsTestedSize = 2,
kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize,
kDeoptReasonSize = kLastRecordedDeoptReason + 1,
- kIssuedJSWarningBit = kDeoptReasonPos + kDeoptReasonSize,
- kRangeFeedbackPos = kIssuedJSWarningBit + 1,
+ kRangeFeedbackPos = kDeoptReasonPos + kDeoptReasonSize,
kRangeFeedbackSize = kBitsPerRangeFeedback * kRangeFeedbackSlots
};
@@ -2086,8 +2077,6 @@
uint32_t,
ICData::kDeoptReasonPos,
ICData::kDeoptReasonSize> {};
- class IssuedJSWarningBit :
- public BitField<uint32_t, bool, kIssuedJSWarningBit, 1> {};
class RangeFeedbackBits : public BitField<uint32_t,
uint32_t,
ICData::kRangeFeedbackPos,
@@ -2315,8 +2304,8 @@
bool IsFactory() const {
return (kind() == RawFunction::kConstructor) && is_static();
}
- bool IsDynamicFunction() const {
- if (is_static() || is_abstract()) {
+ bool IsDynamicFunction(bool allow_abstract = false) const {
+ if (is_static() || (!allow_abstract && is_abstract())) {
return false;
}
switch (kind()) {
@@ -2501,7 +2490,7 @@
const Function& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
- Heap::Space space = Heap::kNew) const {
+ Heap::Space space) const {
return TypeTest(kIsSubtypeOf,
type_arguments,
other,
@@ -2516,7 +2505,7 @@
const Function& other,
const TypeArguments& other_type_arguments,
Error* bound_error,
- Heap::Space space = Heap::kNew) const {
+ Heap::Space space) const {
return TypeTest(kIsMoreSpecificThan,
type_arguments,
other,
@@ -2689,9 +2678,9 @@
const ZoneGrowableArray<const ICData*>& deopt_id_to_ic_data,
const Array& edge_counters_array) const;
// Uses 'ic_data_array' to populate the table 'deopt_id_to_ic_data'. Clone
- // descriptors if 'clone_descriptors' true.
+ // ic_data (array and descriptor) if 'clone_ic_data' is true.
void RestoreICDataMap(ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data,
- bool clone_descriptors) const;
+ bool clone_ic_data) const;
RawArray* ic_data_array() const;
void ClearICDataArray() const;
@@ -5283,9 +5272,9 @@
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr instantiation_trail = NULL,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const;
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
+ Heap::Space space) const;
// Return a clone of this unfinalized type or the type itself if it is
// already finalized. Apply recursively to type arguments, i.e. finalized
@@ -5398,16 +5387,16 @@
// Check the subtype relationship.
bool IsSubtypeOf(const AbstractType& other,
Error* bound_error,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const {
+ TrailPtr bound_trail,
+ Heap::Space space) const {
return TypeTest(kIsSubtypeOf, other, bound_error, bound_trail, space);
}
// Check the 'more specific' relationship.
bool IsMoreSpecificThan(const AbstractType& other,
Error* bound_error,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const {
+ TrailPtr bound_trail,
+ Heap::Space space) const {
return TypeTest(kIsMoreSpecificThan, other,
bound_error, bound_trail, space);
}
@@ -5476,9 +5465,9 @@
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr instantiation_trail = NULL,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const;
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
+ Heap::Space space) const;
virtual RawAbstractType* CloneUnfinalized() const;
virtual RawAbstractType* CloneUninstantiated(
const Class& new_owner,
@@ -5624,9 +5613,9 @@
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* malformed_error,
- TrailPtr instantiation_trail = NULL,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const;
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
+ Heap::Space space) const;
virtual RawAbstractType* CloneUnfinalized() const;
virtual RawAbstractType* CloneUninstantiated(
const Class& new_owner,
@@ -5701,9 +5690,9 @@
virtual RawTypeRef* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr instantiation_trail = NULL,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const;
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
+ Heap::Space space) const;
virtual RawTypeRef* CloneUninstantiated(
const Class& new_owner,
TrailPtr trail = NULL) const;
@@ -5763,8 +5752,8 @@
bool CheckBound(const AbstractType& bounded_type,
const AbstractType& upper_bound,
Error* bound_error,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const;
+ TrailPtr bound_trail,
+ Heap::Space space) const;
virtual TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
virtual bool IsInstantiated(TrailPtr trail = NULL) const {
return false;
@@ -5774,9 +5763,9 @@
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr instantiation_trail = NULL,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const;
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
+ Heap::Space space) const;
virtual RawAbstractType* CloneUnfinalized() const;
virtual RawAbstractType* CloneUninstantiated(
const Class& new_owner, TrailPtr trail = NULL) const;
@@ -5860,9 +5849,9 @@
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr instantiation_trail = NULL,
- TrailPtr bound_trail = NULL,
- Heap::Space space = Heap::kNew) const;
+ TrailPtr instantiation_trail,
+ TrailPtr bound_trail,
+ Heap::Space space) const;
virtual RawAbstractType* CloneUnfinalized() const;
virtual RawAbstractType* CloneUninstantiated(
const Class& new_owner, TrailPtr trail = NULL) const;
@@ -5965,10 +5954,7 @@
// Returns a canonical Integer object allocated in the old gen space.
static RawInteger* NewCanonical(const String& str);
- // Do not throw JavascriptIntegerOverflow if 'silent' is true.
- static RawInteger* New(int64_t value,
- Heap::Space space = Heap::kNew,
- const bool silent = false);
+ static RawInteger* New(int64_t value, Heap::Space space = Heap::kNew);
virtual bool OperatorEquals(const Instance& other) const {
return Equals(other);
@@ -6006,9 +5992,6 @@
const Integer& other,
Heap::Space space = Heap::kNew) const;
- // Returns true if the Integer does not fit in a Javascript integer.
- bool CheckJavascriptIntegerOverflow() const;
-
private:
OBJECT_IMPLEMENTATION(Integer, Number);
friend class Class;
@@ -6065,8 +6048,7 @@
RawInteger* ShiftOp(Token::Kind kind,
const Smi& other,
- Heap::Space space = Heap::kNew,
- const bool silent = false) const;
+ Heap::Space space = Heap::kNew) const;
void operator=(RawSmi* value) {
raw_ = value;
@@ -6597,6 +6579,7 @@
friend class ExternalTwoByteString;
// So that SkippedCodeFunctions can print a debug string from a NoHandleScope.
friend class SkippedCodeFunctions;
+ friend class RawOneByteString;
};
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index caea245..ff0fa53 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -59,7 +59,7 @@
ASSERT(result != NULL);
result->memory_ = memory;
result->next_ = NULL;
- result->executable_ = is_executable;
+ result->type_ = type;
return result;
}
@@ -132,7 +132,7 @@
void HeapPage::WriteProtect(bool read_only) {
VirtualMemory::Protection prot;
if (read_only) {
- if (executable_) {
+ if (type_ == kExecutable) {
prot = VirtualMemory::kReadExecute;
} else {
prot = VirtualMemory::kReadOnly;
@@ -665,7 +665,9 @@
AbandonBumpAllocation();
}
for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
- if ((it.page()->type() != HeapPage::kExecutable) || include_code_pages) {
+ HeapPage::PageType page_type = it.page()->type();
+ if ((page_type != HeapPage::kReadOnlyData) &&
+ ((page_type != HeapPage::kExecutable) || include_code_pages)) {
it.page()->WriteProtect(read_only);
}
}
@@ -1071,7 +1073,9 @@
}
-void PageSpace::SetupInstructionsSnapshotPage(void* pointer, uword size) {
+void PageSpace::SetupExternalPage(void* pointer,
+ uword size,
+ bool is_executable) {
// Setup a HeapPage so precompiled Instructions can be traversed.
// Instructions are contiguous at [pointer, pointer + size). HeapPage
// expects to find objects at [memory->start() + ObjectStartOffset,
@@ -1080,23 +1084,31 @@
pointer = reinterpret_cast<void*>(reinterpret_cast<uword>(pointer) - offset);
size += offset;
- ASSERT(Utils::IsAligned(pointer, OS::PreferredCodeAlignment()));
-
- VirtualMemory* memory = VirtualMemory::ForInstructionsSnapshot(pointer, size);
+ VirtualMemory* memory = VirtualMemory::ForExternalPage(pointer, size);
ASSERT(memory != NULL);
HeapPage* page = reinterpret_cast<HeapPage*>(malloc(sizeof(HeapPage)));
page->memory_ = memory;
page->next_ = NULL;
page->object_end_ = memory->end();
- page->executable_ = true;
MutexLocker ml(pages_lock_);
- if (exec_pages_ == NULL) {
- exec_pages_ = page;
+ HeapPage** first, **tail;
+ if (is_executable) {
+ ASSERT(Utils::IsAligned(pointer, OS::PreferredCodeAlignment()));
+ page->type_ = HeapPage::kExecutable;
+ first = &exec_pages_;
+ tail = &exec_pages_tail_;
} else {
- exec_pages_tail_->set_next(page);
+ page->type_ = HeapPage::kReadOnlyData;
+ first = &pages_;
+ tail = &pages_tail_;
}
- exec_pages_tail_ = page;
+ if (*first == NULL) {
+ *first = page;
+ } else {
+ (*tail)->set_next(page);
+ }
+ (*tail) = page;
}
diff --git a/runtime/vm/pages.h b/runtime/vm/pages.h
index 17d1674..008b7cd 100644
--- a/runtime/vm/pages.h
+++ b/runtime/vm/pages.h
@@ -31,6 +31,7 @@
enum PageType {
kData = 0,
kExecutable,
+ kReadOnlyData,
kNumPageTypes
};
@@ -49,7 +50,7 @@
}
PageType type() const {
- return executable_ ? kExecutable : kData;
+ return type_;
}
void VisitObjects(ObjectVisitor* visitor) const;
@@ -80,7 +81,7 @@
VirtualMemory* memory_;
HeapPage* next_;
uword object_end_;
- bool executable_;
+ PageType type_;
friend class PageSpace;
@@ -346,7 +347,7 @@
static intptr_t top_offset() { return OFFSET_OF(PageSpace, bump_top_); }
static intptr_t end_offset() { return OFFSET_OF(PageSpace, bump_end_); }
- void SetupInstructionsSnapshotPage(void* pointer, uword size);
+ void SetupExternalPage(void* pointer, uword size, bool is_executable);
private:
// Ids for time and data records in Heap::GCStats.
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 2449f9d..048c184 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -59,8 +59,6 @@
DECLARE_FLAG(bool, lazy_dispatchers);
DECLARE_FLAG(bool, load_deferred_eagerly);
DECLARE_FLAG(bool, profile_vm);
-DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
-DECLARE_FLAG(bool, warn_on_javascript_compatibility);
// Quick access to the current thread, isolate and zone.
#define T (thread())
@@ -423,6 +421,7 @@
if (unregister_pending_function_) {
const GrowableObjectArray& pending_functions =
GrowableObjectArray::Handle(T->pending_functions());
+ ASSERT(!pending_functions.IsNull());
ASSERT(pending_functions.Length() > 0);
ASSERT(pending_functions.At(pending_functions.Length() - 1) ==
current_function().raw());
@@ -537,14 +536,6 @@
literal_token_ ^= tokens_iterator_.CurrentToken();
ASSERT(literal_token_.kind() == Token::kINTEGER);
RawInteger* ri = Integer::RawCast(literal_token_.value());
- if (FLAG_throw_on_javascript_int_overflow) {
- const Integer& i = Integer::Handle(Z, ri);
- if (i.CheckJavascriptIntegerOverflow()) {
- ReportError(TokenPos(),
- "Integer literal does not fit in a Javascript integer: %s.",
- i.ToCString());
- }
- }
return ri;
}
@@ -2961,6 +2952,7 @@
void Parser::CheckRecursiveInvocation() {
const GrowableObjectArray& pending_functions =
GrowableObjectArray::Handle(Z, T->pending_functions());
+ ASSERT(!pending_functions.IsNull());
for (int i = 0; i < pending_functions.Length(); i++) {
if (pending_functions.At(i) == current_function().raw()) {
const String& fname =
@@ -2969,7 +2961,7 @@
}
}
ASSERT(!unregister_pending_function_);
- pending_functions.Add(current_function());
+ pending_functions.Add(current_function(), Heap::kOld);
unregister_pending_function_ = true;
}
@@ -9803,7 +9795,8 @@
AstNode* store_current =
new(Z) InstanceSetterNode(TokenPosition::kNoSource,
iterator,
- String::ZoneHandle(Symbols::Current().raw()),
+ Library::PrivateCoreLibName(
+ Symbols::_current()),
expr);
yield->AddNode(store_current);
if (is_yield_each) {
@@ -11114,36 +11107,32 @@
(cls.library() == Library::CoreLibrary()) &&
(func.name() == Symbols::Identical().raw())) {
// This is the predefined toplevel function identical(a,b).
- // Create a comparison node instead of a static call to the function, unless
- // javascript warnings are desired and identical is not invoked from a patch
- // source.
- if (!FLAG_warn_on_javascript_compatibility || is_patch_source()) {
- ASSERT(num_arguments == 2);
+ // Create a comparison node instead of a static call to the function.
+ 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)));
- }
+ // 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),
- arguments->NodeAt(1));
}
+ return new(Z) ComparisonNode(ident_pos,
+ Token::kEQ_STRICT,
+ arguments->NodeAt(0),
+ arguments->NodeAt(1));
}
return new(Z) StaticCallNode(ident_pos, func, arguments);
}
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 30fb890..65b6166 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -22,6 +22,7 @@
#include "vm/flow_graph_compiler.h"
#include "vm/flow_graph_inliner.h"
#include "vm/flow_graph_optimizer.h"
+#include "vm/flow_graph_range_analysis.h"
#include "vm/flow_graph_type_propagator.h"
#include "vm/hash_table.h"
#include "vm/il_printer.h"
@@ -347,10 +348,6 @@
{ "dart:core", "_CastError", "_CastError._create" },
{ "dart:core", "_InternalError", "_InternalError." },
{ "dart:core", "_InvocationMirror", "_allocateInvocationMirror" },
- { "dart:core", "_JavascriptCompatibilityError",
- "_JavascriptCompatibilityError." },
- { "dart:core", "_JavascriptIntegerOverflowError",
- "_JavascriptIntegerOverflowError." },
{ "dart:core", "_TypeError", "_TypeError._create" },
{ "dart:isolate", "IsolateSpawnException", "IsolateSpawnException." },
{ "dart:isolate", "::", "_getIsolateScheduleImmediateClosure" },
@@ -1917,7 +1914,8 @@
// We have to perform range analysis after LICM because it
// optimistically moves CheckSmi through phis into loop preheaders
// making some phis smi.
- optimizer.InferIntRanges();
+ RangeAnalysis range_analysis(flow_graph);
+ range_analysis.Analyze();
DEBUG_ASSERT(flow_graph->VerifyUseLists());
}
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index c7c44a2..a262edf 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -436,6 +436,15 @@
bool IsString() {
return IsStringClassId(GetClassId());
}
+ bool IsStackmap() {
+ return ((GetClassId() == kStackmapCid));
+ }
+ bool IsPcDescriptors() {
+ return ((GetClassId() == kPcDescriptorsCid));
+ }
+ bool IsOneByteString() {
+ return ((GetClassId() == kOneByteStringCid));
+ }
intptr_t Size() const {
uword tags = ptr()->tags_;
@@ -1428,14 +1437,17 @@
RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
RawObject** from() {
- return reinterpret_cast<RawObject**>(&ptr()->owner_);
+ return reinterpret_cast<RawObject**>(&ptr()->ic_data_);
}
- RawObject* owner_; // Parent/calling function or original IC of cloned IC.
+ RawArray* ic_data_; // Contains class-ids, target and count.
RawString* target_name_; // Name of target function.
RawArray* args_descriptor_; // Arguments descriptor.
- RawArray* ic_data_; // Contains class-ids, target and count.
+ RawObject** to_precompiled_snapshot() {
+ return reinterpret_cast<RawObject**>(&ptr()->args_descriptor_);
+ }
+ RawObject* owner_; // Parent/calling function or original IC of cloned IC.
RawObject** to() {
- return reinterpret_cast<RawObject**>(&ptr()->ic_data_);
+ return reinterpret_cast<RawObject**>(&ptr()->owner_);
}
int32_t deopt_id_; // Deoptimization id corresponding to this IC.
uint32_t state_bits_; // Number of arguments tested in IC, deopt reasons,
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 1a617ba..405c2e4 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1477,7 +1477,11 @@
ASSERT(reader->snapshot_code());
ASSERT(kind == Snapshot::kFull);
+#ifdef DEBUG
intptr_t full_tags = static_cast<uword>(reader->Read<intptr_t>());
+#else
+ intptr_t full_tags = 0; // unused in release mode
+#endif
intptr_t offset = reader->Read<int32_t>();
Instructions& result =
Instructions::ZoneHandle(reader->zone(),
@@ -1499,6 +1503,7 @@
writer->WriteVMIsolateObject(kInstructionsCid);
writer->WriteTags(writer->GetObjectTags(this));
+#ifdef DEBUG
// Instructions will be written pre-marked and in the VM heap. Write out
// the tags we expect to find when reading the snapshot for a sanity check
// that our offsets/alignment didn't get out of sync.
@@ -1506,6 +1511,7 @@
written_tags = RawObject::VMHeapObjectTag::update(true, written_tags);
written_tags = RawObject::MarkBit::update(true, written_tags);
writer->Write<intptr_t>(written_tags);
+#endif
writer->Write<int32_t>(writer->GetInstructionsId(this));
}
@@ -1643,19 +1649,11 @@
ASSERT(reader->snapshot_code());
ASSERT(kind == Snapshot::kFull);
- const int32_t length = reader->Read<int32_t>();
- PcDescriptors& result =
- PcDescriptors::ZoneHandle(reader->zone(),
- NEW_OBJECT_WITH_LEN(PcDescriptors, length));
+ intptr_t offset = reader->Read<int32_t>();
+ PcDescriptors& result = PcDescriptors::ZoneHandle(reader->zone());
+ result ^= reader->GetObjectAt(offset);
reader->AddBackRef(object_id, &result, kIsDeserialized);
- if (result.Length() > 0) {
- NoSafepointScope no_safepoint;
- intptr_t len = result.Length();
- uint8_t* data = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
- reader->ReadBytes(data, len);
- }
-
return result.raw();
}
@@ -1671,12 +1669,8 @@
writer->WriteInlinedObjectHeader(object_id);
writer->WriteIndexedObject(kPcDescriptorsCid);
writer->WriteTags(writer->GetObjectTags(this));
- writer->Write<int32_t>(ptr()->length_);
- if (ptr()->length_ > 0) {
- intptr_t len = ptr()->length_;
- uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
- writer->WriteBytes(data, len);
- }
+
+ writer->Write<int32_t>(writer->GetObjectId(this));
}
@@ -1733,22 +1727,11 @@
ASSERT(reader->snapshot_code());
ASSERT(kind == Snapshot::kFull);
- const int32_t length = reader->Read<int32_t>();
- Stackmap& result =
- Stackmap::ZoneHandle(reader->zone(),
- reader->NewStackmap(length));
+ intptr_t offset = reader->Read<int32_t>();
+ Stackmap& result = Stackmap::ZoneHandle(reader->zone());
+ result ^= reader->GetObjectAt(offset);
reader->AddBackRef(object_id, &result, kIsDeserialized);
- result.SetRegisterBitCount(reader->Read<int32_t>());
- result.SetPcOffset(reader->Read<uint32_t>());
-
- if (length > 0) {
- NoSafepointScope no_safepoint;
- intptr_t len = (result.Length() + 7) / 8;
- uint8_t* data = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
- reader->ReadBytes(data, len);
- }
-
return result.raw();
}
@@ -1765,14 +1748,7 @@
writer->WriteIndexedObject(kStackmapCid);
writer->WriteTags(writer->GetObjectTags(this));
- writer->Write<int32_t>(ptr()->length_);
- writer->Write<int32_t>(ptr()->register_bit_count_);
- writer->Write<uint32_t>(ptr()->pc_offset_);
- if (ptr()->length_ > 0) {
- intptr_t len = (ptr()->length_ + 7) / 8;
- uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
- writer->WriteBytes(data, len);
- }
+ writer->Write<int32_t>(writer->GetObjectId(this));
}
@@ -2021,8 +1997,11 @@
result.set_state_bits(reader->Read<uint32_t>());
// Set all the object fields.
+ RawObject** toobj = reader->snapshot_code()
+ ? result.raw()->to_precompiled_snapshot()
+ : result.raw()->to();
READ_OBJECT_FIELDS(result,
- result.raw()->from(), result.raw()->to(),
+ result.raw()->from(), toobj,
kAsReference);
return result.raw();
@@ -2047,8 +2026,12 @@
writer->Write<uint32_t>(ptr()->state_bits_);
// Write out all the object pointer fields.
+ // In precompiled snapshots, omit the owner field. The owner field may
+ // refer to a function which was always inlined and no longer needed.
SnapshotWriterVisitor visitor(writer, kAsReference);
- visitor.VisitPointers(from(), to());
+ RawObject** toobj = writer->snapshot_code() ? to_precompiled_snapshot()
+ : to();
+ visitor.VisitPointers(from(), toobj);
}
@@ -2572,6 +2555,14 @@
intptr_t tags,
Snapshot::Kind kind,
bool as_reference) {
+ if (reader->snapshot_code()) {
+ ASSERT(kind == Snapshot::kFull);
+ intptr_t offset = reader->Read<int32_t>();
+ String& result = String::ZoneHandle(reader->zone());
+ result ^= reader->GetObjectAt(offset);
+ reader->AddBackRef(object_id, &result, kIsDeserialized);
+ return raw(result);
+ }
// Read the length so that we can determine instance size to allocate.
ASSERT(reader != NULL);
intptr_t len = reader->ReadSmiValue();
@@ -2679,6 +2670,22 @@
intptr_t object_id,
Snapshot::Kind kind,
bool as_reference) {
+ if (writer->snapshot_code()) {
+ ASSERT(writer->snapshot_code());
+ ASSERT(kind == Snapshot::kFull);
+ // Assert that hash is computed.
+ if (ptr()->hash_ == NULL) {
+ ptr()->hash_ = Smi::New(String::Hash(ptr()->data(),
+ Smi::Value(ptr()->length_)));
+ }
+ ASSERT(ptr()->hash_ != NULL);
+ // Write out the serialization header value for this object.
+ writer->WriteInlinedObjectHeader(object_id);
+ writer->WriteIndexedObject(kOneByteStringCid);
+ writer->WriteTags(writer->GetObjectTags(this));
+ writer->Write<int32_t>(writer->GetObjectId(this));
+ return;
+ }
StringWriteTo(writer,
object_id,
kind,
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 6ac5782..7cf9710 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -5272,9 +5272,9 @@
// TODO(zerny): Share these arrays between all irregexp functions.
fn.set_num_fixed_parameters(kParamCount);
fn.set_parameter_types(Array::Handle(zone, Array::New(kParamCount,
- Heap::kOld)));
+ Heap::kOld)));
fn.set_parameter_names(Array::Handle(zone, Array::New(kParamCount,
- Heap::kOld)));
+ Heap::kOld)));
fn.SetParameterTypeAt(RegExpMacroAssembler::kParamRegExpIndex,
Object::dynamic_type());
fn.SetParameterNameAt(RegExpMacroAssembler::kParamRegExpIndex,
diff --git a/runtime/vm/report.cc b/runtime/vm/report.cc
index 42a47d9..21bbdc8 100644
--- a/runtime/vm/report.cc
+++ b/runtime/vm/report.cc
@@ -14,15 +14,9 @@
namespace dart {
-DEFINE_FLAG(int, stacktrace_depth_on_warning, 5,
- "Maximal number of stack frames to print after a runtime warning.");
DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings.");
-DEFINE_FLAG(bool, warn_on_javascript_compatibility, false,
- "Warn on incompatibilities between vm and dart2js.");
DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors.");
-DECLARE_FLAG(bool, always_megamorphic_calls);
-
RawString* Report::PrependSnippet(Kind kind,
const Script& script,
TokenPosition token_pos,
@@ -31,7 +25,6 @@
const char* message_header;
switch (kind) {
case kWarning: message_header = "warning"; break;
- case kJSWarning: message_header = "javascript compatibility warning"; break;
case kError: message_header = "error"; break;
case kMalformedType: message_header = "malformed type"; break;
case kMalboundedType: message_header = "malbounded type"; break;
@@ -159,17 +152,6 @@
const String& snippet_msg = String::Handle(
PrependSnippet(kind, script, token_pos, report_after_token, msg));
OS::Print("%s", snippet_msg.ToCString());
- if (kind == kJSWarning) {
- TraceJSWarning(script, token_pos, msg);
- // Do not print stacktrace if we have not executed Dart code yet.
- if (Thread::Current()->top_exit_frame_info() != 0) {
- const Stacktrace& stacktrace =
- Stacktrace::Handle(Exceptions::CurrentStacktrace());
- intptr_t idx = 0;
- OS::Print("%s", stacktrace.ToCStringInternal(
- &idx, FLAG_stacktrace_depth_on_warning));
- }
- }
return;
}
}
@@ -179,96 +161,9 @@
script, token_pos, report_after_token,
kind, Heap::kNew,
format, args));
- if (kind == kJSWarning) {
- Exceptions::ThrowJavascriptCompatibilityError(error.ToErrorCString());
- UNREACHABLE();
- }
LongJump(error);
UNREACHABLE();
}
-
-void Report::JSWarningFromNative(bool is_static_native, const char* msg) {
- DartFrameIterator iterator;
- iterator.NextFrame(); // Skip native call.
- StackFrame* caller_frame = iterator.NextFrame();
- ASSERT(caller_frame != NULL);
- const Code& caller_code = Code::Handle(caller_frame->LookupDartCode());
- ASSERT(!caller_code.IsNull());
- const uword caller_pc = caller_frame->pc();
- ICData& ic_data = ICData::Handle();
- if (is_static_native) {
- // Assume an unoptimized static call. Optimization was prevented.
- CodePatcher::GetUnoptimizedStaticCallAt(caller_pc, caller_code, &ic_data);
- } else {
- if (FLAG_always_megamorphic_calls) {
- Report::JSWarningFromFrame(caller_frame, msg);
- return;
- } else {
- // Assume an instance call.
- CodePatcher::GetInstanceCallAt(caller_pc, caller_code, &ic_data);
- }
- }
- ASSERT(!ic_data.IsNull());
- // Report warning only if not already reported at this location.
- if (!ic_data.IssuedJSWarning()) {
- ic_data.SetIssuedJSWarning();
- Report::JSWarningFromFrame(caller_frame, msg);
- }
-}
-
-
-void Report::JSWarningFromIC(const ICData& ic_data, const char* msg) {
- DartFrameIterator iterator;
- StackFrame* caller_frame = iterator.NextFrame();
- ASSERT(caller_frame != NULL);
- // Report warning only if not already reported at this location.
- if (!ic_data.IssuedJSWarning()) {
- ic_data.SetIssuedJSWarning();
- JSWarningFromFrame(caller_frame, msg);
- }
-}
-
-
-void Report::JSWarningFromFrame(StackFrame* caller_frame, const char* msg) {
- ASSERT(caller_frame != NULL);
- ASSERT(FLAG_warn_on_javascript_compatibility);
- if (FLAG_silent_warnings) return;
- Zone* zone = Thread::Current()->zone();
- const Code& caller_code = Code::Handle(zone,
- caller_frame->LookupDartCode());
- ASSERT(!caller_code.IsNull());
- const uword caller_pc = caller_frame->pc();
- const TokenPosition token_pos = caller_code.GetTokenIndexOfPC(caller_pc);
- const Function& caller = Function::Handle(zone, caller_code.function());
- const Script& script = Script::Handle(zone, caller.script());
- MessageF(kJSWarning, script, token_pos, Report::AtLocation, "%s", msg);
-}
-
-
-void Report::TraceJSWarning(const Script& script,
- TokenPosition token_pos,
- const String& message) {
- if (!FLAG_support_service) {
- return;
- }
- const int64_t micros = OS::GetCurrentTimeMicros();
- Isolate* isolate = Isolate::Current();
- TraceBuffer* trace_buffer = isolate->trace_buffer();
- if (trace_buffer == NULL) {
- TraceBuffer::Init(isolate);
- trace_buffer = isolate->trace_buffer();
- }
- JSONStream js;
- {
- JSONObject trace_warning(&js);
- trace_warning.AddProperty("type", "JSCompatibilityWarning");
- trace_warning.AddProperty("script", script);
- trace_warning.AddProperty("tokenPos", token_pos);
- trace_warning.AddProperty("message", message);
- }
- trace_buffer->Trace(micros, js.ToCString(), true); // Already escaped.
-}
-
} // namespace dart
diff --git a/runtime/vm/report.h b/runtime/vm/report.h
index 3cf48ac..f95cb84 100644
--- a/runtime/vm/report.h
+++ b/runtime/vm/report.h
@@ -22,7 +22,6 @@
public:
enum Kind {
kWarning,
- kJSWarning,
kError,
kMalformedType,
kMalboundedType,
@@ -55,23 +54,6 @@
bool report_after_token,
const char* format, va_list args);
- // Support to report Javascript compatibility warnings. Note that a
- // JavascriptCompatibilityError is thrown if --warning_as_error is specified.
- // If a warning is issued by the various JSWarning calls, the warning is also
- // emitted in the trace buffer of the current isolate.
-
- // Report a Javascript compatibility warning at the call site given by
- // ic_data, unless one has already been emitted at that location.
- static void JSWarningFromIC(const ICData& ic_data, const char* msg);
-
- // Report a Javascript compatibility warning at the current native call,
- // unless one has already been emitted at that location.
- static void JSWarningFromNative(bool is_static_native, const char* msg);
-
- // Report a Javascript compatibility warning at the call site given by
- // caller_frame.
- static void JSWarningFromFrame(StackFrame* caller_frame, const char* msg);
-
// Prepend a source snippet to the message.
// A null script means no source and a negative token_pos means no position.
static RawString* PrependSnippet(Kind kind,
@@ -81,11 +63,6 @@
const String& message);
private:
- // Emit a Javascript compatibility warning to the current trace buffer.
- static void TraceJSWarning(const Script& script,
- TokenPosition token_pos,
- const String& message);
-
DISALLOW_COPY_AND_ASSIGN(Report);
};
diff --git a/runtime/vm/report_test.cc b/runtime/vm/report_test.cc
deleted file mode 100644
index d939dd2..0000000
--- a/runtime/vm/report_test.cc
+++ /dev/null
@@ -1,84 +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.
-
-#include "platform/assert.h"
-#include "vm/report.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-#ifndef PRODUCT
-
-TEST_CASE(TraceJSWarning) {
- Zone* zone = thread->zone();
- Isolate* isolate = thread->isolate();
- TraceBuffer::Init(isolate, 3);
- TraceBuffer* trace_buffer = isolate->trace_buffer();
- const String& url = String::Handle(zone, String::New("Plug"));
- const String& source = String::Handle(zone, String::New("240 100"));
- const Script& script = Script::Handle(zone,
- Script::New(url, source, RawScript::kEvaluateTag));
- script.Tokenize(String::Handle(String::New("")));
- {
- const TokenPosition token_pos = TokenPosition(0);
- const char* message = "High Voltage";
- Report::MessageF(Report::kJSWarning,
- script, token_pos, Report::AtLocation, "%s", message);
- {
- JSONStream js;
- trace_buffer->PrintToJSONStream(&js);
- EXPECT_SUBSTRING("{\"type\":\"TraceBuffer\",\"members\":["
- "{\"type\":\"TraceBufferEntry\",\"time\":",
- js.ToCString());
- // Skip time.
- EXPECT_SUBSTRING("\"message\":{\"type\":\"JSCompatibilityWarning\","
- "\"script\":{\"type\":\"@Script\"",
- js.ToCString());
- // Skip object ring id.
- EXPECT_SUBSTRING("\"uri\":\"Plug\","
- "\"_kind\":\"evaluate\"},\"tokenPos\":0,"
- "\"message\":{\"type\":\"@Instance\"",
- js.ToCString());
- // Skip private _OneByteString.
- EXPECT_SUBSTRING("\"valueAsString\":\"High Voltage\"",
- js.ToCString());
- }
- }
- {
- const TokenPosition token_pos = TokenPosition(1);
- const char* message = "Low Voltage";
- Report::MessageF(Report::kJSWarning,
- script, token_pos, Report::AtLocation, "%s", message);
- }
- EXPECT_EQ(2, trace_buffer->Length());
- EXPECT_SUBSTRING("{\"type\":\"JSCompatibilityWarning\",\"script\":{\"type\":"
- "\"@Script\"",
- trace_buffer->At(0)->message);
- // Skip object ring id.
- EXPECT_SUBSTRING("\"uri\":\"Plug\","
- "\"_kind\":\"evaluate\"},\"tokenPos\":0,"
- "\"message\":{\"type\":\"@Instance\"",
- trace_buffer->At(0)->message);
- // Skip private _OneByteString.
- EXPECT_SUBSTRING("\"valueAsString\":\"High Voltage\"",
- trace_buffer->At(0)->message);
-
- EXPECT_SUBSTRING("{\"type\":\"JSCompatibilityWarning\",\"script\":{\"type\":"
- "\"@Script\"",
- trace_buffer->At(1)->message);
- // Skip object ring id.
- EXPECT_SUBSTRING("\"uri\":\"Plug\","
- "\"_kind\":\"evaluate\"},\"tokenPos\":1,"
- "\"message\":{\"type\":\"@Instance\"",
- trace_buffer->At(1)->message);
- // Skip private _OneByteString.
- EXPECT_SUBSTRING("\"valueAsString\":\"Low Voltage\"",
- trace_buffer->At(1)->message);
-
- delete trace_buffer;
-}
-
-#endif // !PRODUCT
-
-} // namespace dart
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index cdfdd288..c8912eb 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -647,7 +647,6 @@
// Returns number of elements in the list. -1 on parse error.
intptr_t ElementCount(const char* value) const {
const char* kJsonWhitespaceChars = " \t\r\n";
-
if (value == NULL) {
return -1;
}
@@ -2408,13 +2407,9 @@
};
-static const EnumListParameter* reports_parameter =
- new EnumListParameter("reports", true, report_enum_names);
-
-
static const MethodParameter* get_source_report_params[] = {
RUNNABLE_ISOLATE_PARAMETER,
- reports_parameter,
+ new EnumListParameter("reports", true, report_enum_names),
new IdParameter("scriptId", false),
new UIntParameter("tokenPos", false),
new UIntParameter("endTokenPos", false),
@@ -2425,6 +2420,8 @@
static bool GetSourceReport(Thread* thread, JSONStream* js) {
const char* reports_str = js->LookupParam("reports");
+ const EnumListParameter* reports_parameter =
+ static_cast<const EnumListParameter*>(get_source_report_params[1]);
const char** reports = reports_parameter->Parse(thread->zone(), reports_str);
intptr_t report_set = 0;
while (*reports != NULL) {
@@ -2860,27 +2857,58 @@
return false;
}
+static const char* const timeline_streams_enum_names[] = {
+ "all",
+#define DEFINE_NAME(name, unused) \
+ #name,
+ISOLATE_TIMELINE_STREAM_LIST(DEFINE_NAME)
+#undef DEFINE_NAME
+ "VM",
+ NULL
+};
-static const MethodParameter* set_vm_timeline_flag_params[] = {
+static const MethodParameter* set_vm_timeline_flags_params[] = {
NO_ISOLATE_PARAMETER,
- new MethodParameter("_record", true),
+ new EnumListParameter("recordedStreams",
+ false,
+ timeline_streams_enum_names),
NULL,
};
-static bool SetVMTimelineFlag(Thread* thread, JSONStream* js) {
+static bool HasStream(const char** recorded_streams, const char* stream) {
+ while (*recorded_streams != NULL) {
+ if ((strstr(*recorded_streams, "all") != NULL) ||
+ (strstr(*recorded_streams, stream) != NULL)) {
+ return true;
+ }
+ recorded_streams++;
+ }
+ return false;
+}
+
+
+static bool SetVMTimelineFlags(Thread* thread, JSONStream* js) {
+ if (!FLAG_support_timeline) {
+ PrintSuccess(js);
+ return true;
+ }
Isolate* isolate = thread->isolate();
ASSERT(isolate != NULL);
StackZone zone(thread);
- bool recording = strcmp(js->LookupParam("_record"), "all") == 0;
- Timeline::SetStreamAPIEnabled(recording);
- Timeline::SetStreamCompilerEnabled(recording);
- Timeline::SetStreamDartEnabled(recording);
- Timeline::SetStreamDebuggerEnabled(recording);
- Timeline::SetStreamEmbedderEnabled(recording);
- Timeline::SetStreamGCEnabled(recording);
- Timeline::SetStreamIsolateEnabled(recording);
+ const EnumListParameter* recorded_streams_param =
+ static_cast<const EnumListParameter*>(set_vm_timeline_flags_params[1]);
+
+ const char* recorded_streams_str = js->LookupParam("recordedStreams");
+ const char** recorded_streams =
+ recorded_streams_param->Parse(thread->zone(), recorded_streams_str);
+
+#define SET_ENABLE_STREAM(name, unused) \
+ Timeline::SetStream##name##Enabled(HasStream(recorded_streams, #name));
+ISOLATE_TIMELINE_STREAM_LIST(SET_ENABLE_STREAM);
+#undef SET_ENABLE_STREAM
+ Timeline::SetVMStreamEnabled(HasStream(recorded_streams, "VM"));
PrintSuccess(js);
@@ -2888,19 +2916,22 @@
}
-static const MethodParameter* get_vm_timeline_flag_params[] = {
+static const MethodParameter* get_vm_timeline_flags_params[] = {
NO_ISOLATE_PARAMETER,
- new MethodParameter("_record", false),
NULL,
};
-static bool GetVMTimelineFlag(Thread* thread, JSONStream* js) {
+static bool GetVMTimelineFlags(Thread* thread, JSONStream* js) {
+ if (!FLAG_support_timeline) {
+ JSONObject obj(js);
+ obj.AddProperty("type", "TimelineFlags");
+ return true;
+ }
Isolate* isolate = thread->isolate();
ASSERT(isolate != NULL);
StackZone zone(thread);
-
- js->PrintError(kFeatureDisabled, "TODO(johnmccutchan)");
+ Timeline::PrintFlagsToJSON(js);
return true;
}
@@ -3918,8 +3949,8 @@
get_vm_metric_list_params },
{ "_getVMTimeline", GetVMTimeline,
get_vm_timeline_params },
- { "_getVMTimelineFlag", GetVMTimelineFlag,
- get_vm_timeline_flag_params },
+ { "_getVMTimelineFlags", GetVMTimelineFlags,
+ get_vm_timeline_flags_params },
{ "pause", Pause,
pause_params },
{ "removeBreakpoint", RemoveBreakpoint,
@@ -3942,8 +3973,8 @@
set_trace_class_allocation_params },
{ "setVMName", SetVMName,
set_vm_name_params },
- { "_setVMTimelineFlag", SetVMTimelineFlag,
- set_vm_timeline_flag_params },
+ { "_setVMTimelineFlags", SetVMTimelineFlags,
+ set_vm_timeline_flags_params },
};
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 2103acd..0ab4ee2 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -2294,7 +2294,7 @@
// sorted list of token positions. Provided only when the when the
// PossibleBreakpoint report has been requested and the range has been
// compiled.
- int possibleBreakpoints[] [optional];
+ int[] possibleBreakpoints [optional];
}
```
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index d80364e..3d6207a 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -30,6 +30,8 @@
DEFINE_FLAG(bool, trace_service, false, "Trace VM service requests.");
DEFINE_FLAG(bool, trace_service_pause_events, false,
"Trace VM service isolate pause events.");
+DEFINE_FLAG(bool, trace_service_verbose, false,
+ "Provide extra service tracing information.");
static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 76292c0..bbfa73b 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -407,7 +407,11 @@
if (Simulator::IsIllegalAddress(last_pc)) {
OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc);
} else {
- Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+ if (FLAG_support_disassembler) {
+ Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+ } else {
+ OS::Print("Disassembler not supported in this mode.\n");
+ }
}
}
char* line = ReadLine("sim> ");
@@ -546,7 +550,11 @@
}
}
if ((start > 0) && (end > start)) {
- Disassembler::Disassemble(start, end);
+ if (FLAG_support_disassembler) {
+ Disassembler::Disassemble(start, end);
+ } else {
+ OS::Print("Disassembler not supported in this mode.\n");
+ }
} else {
OS::Print("disasm [<address> [<number_of_instructions>]]\n");
}
@@ -3603,7 +3611,11 @@
OS::Print("%" Pu64 " ", icount_);
const uword start = reinterpret_cast<uword>(instr);
const uword end = start + Instr::kInstrSize;
- Disassembler::Disassemble(start, end);
+ if (FLAG_support_disassembler) {
+ Disassembler::Disassemble(start, end);
+ } else {
+ OS::Print("Disassembler not supported in this mode.\n");
+ }
}
if (instr->ConditionField() == kSpecialCondition) {
if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 8ab8455..7916d18 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -425,7 +425,11 @@
if (Simulator::IsIllegalAddress(last_pc)) {
OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc);
} else {
- Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+ if (FLAG_support_disassembler) {
+ Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+ } else {
+ OS::Print("Disassembler not supported in this mode.\n");
+ }
}
}
char* line = ReadLine("sim> ");
@@ -597,7 +601,11 @@
}
}
if ((start > 0) && (end > start)) {
- Disassembler::Disassemble(start, end);
+ if (FLAG_support_disassembler) {
+ Disassembler::Disassemble(start, end);
+ } else {
+ OS::Print("Disassembler not supported in this mode.\n");
+ }
} else {
OS::Print("disasm [<address> [<number_of_instructions>]]\n");
}
@@ -3364,7 +3372,11 @@
OS::Print("%" Pu64 " ", icount_);
const uword start = reinterpret_cast<uword>(instr);
const uword end = start + Instr::kInstrSize;
- Disassembler::Disassemble(start, end);
+ if (FLAG_support_disassembler) {
+ Disassembler::Disassemble(start, end);
+ } else {
+ OS::Print("Disassembler not supported in this mode.\n");
+ }
}
if (instr->IsDPImmediateOp()) {
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 5491c6b..2b03da8 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -418,7 +418,11 @@
if (Simulator::IsIllegalAddress(last_pc)) {
OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc);
} else {
- Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+ if (FLAG_support_disassembler) {
+ Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+ } else {
+ OS::Print("Disassembler not supported in this mode.\n");
+ }
}
}
char* line = ReadLine("sim> ");
@@ -556,7 +560,11 @@
}
}
if ((start > 0) && (end > start)) {
- Disassembler::Disassemble(start, end);
+ if (FLAG_support_disassembler) {
+ Disassembler::Disassemble(start, end);
+ } else {
+ OS::Print("Disassembler not supported in this mode.\n");
+ }
} else {
OS::Print("disasm [<address> [<number_of_instructions>]]\n");
}
@@ -1996,7 +2004,11 @@
OS::Print("%" Pu64 " ", icount_);
const uword start = reinterpret_cast<uword>(instr);
const uword end = start + Instr::kInstrSize;
- Disassembler::Disassemble(start, end);
+ if (FLAG_support_disassembler) {
+ Disassembler::Disassemble(start, end);
+ } else {
+ OS::Print("Disassembler not supported in this mode.\n");
+ }
}
switch (instr->OpcodeField()) {
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index bbeef36..340351a 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -177,11 +177,13 @@
const uint8_t* buffer,
intptr_t size,
const uint8_t* instructions_buffer,
+ const uint8_t* data_buffer,
Snapshot::Kind kind,
ZoneGrowableArray<BackRefNode>* backward_refs,
Thread* thread)
: BaseReader(buffer, size),
instructions_buffer_(instructions_buffer),
+ data_buffer_(data_buffer),
kind_(kind),
snapshot_code_(instructions_buffer != NULL),
thread_(thread),
@@ -211,7 +213,8 @@
backward_references_(backward_refs),
instructions_reader_(NULL) {
if (instructions_buffer != NULL) {
- instructions_reader_ = new InstructionsReader(instructions_buffer);
+ instructions_reader_ =
+ new InstructionsReader(instructions_buffer, data_buffer);
}
}
@@ -1133,6 +1136,15 @@
}
+int32_t InstructionsWriter::GetObjectOffsetFor(RawObject* raw_object) {
+ intptr_t heap_size = raw_object->Size();
+ intptr_t offset = next_object_offset_;
+ next_object_offset_ += heap_size;
+ objects_.Add(ObjectData(raw_object));
+ return offset;
+}
+
+
static void EnsureIdentifier(char* label) {
for (char c = *label; c != '\0'; c = *++label) {
if (((c >= 'a') && (c <= 'z')) ||
@@ -1156,10 +1168,16 @@
ASSERT(data.raw_code_ != NULL);
data.code_ = &Code::Handle(Z, data.raw_code_);
}
+ for (intptr_t i = 0; i < objects_.length(); i++) {
+ ObjectData& data = objects_[i];
+ data.obj_ = &Object::Handle(Z, data.raw_obj_);
+ }
stream_.Print(".text\n");
stream_.Print(".globl _kInstructionsSnapshot\n");
- stream_.Print(".balign %" Pd ", 0\n", OS::kMaxPreferredCodeAlignment);
+ // Start snapshot at page boundary.
+ ASSERT(VirtualMemory::PageSize() >= OS::kMaxPreferredCodeAlignment);
+ stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
stream_.Print("_kInstructionsSnapshot:\n");
// This head also provides the gap to make the instructions snapshot
@@ -1241,6 +1259,42 @@
}
}
}
+#if defined(TARGET_OS_LINUX)
+ stream_.Print(".section .rodata\n");
+#elif defined(TARGET_OS_MACOS)
+ stream_.Print(".const\n");
+#else
+ // Unsupported platform.
+ UNREACHABLE();
+#endif
+ stream_.Print(".globl _kDataSnapshot\n");
+ // Start snapshot at page boundary.
+ stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
+ stream_.Print("_kDataSnapshot:\n");
+ WriteWordLiteral(next_object_offset_); // Data length.
+ COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment);
+ stream_.Print(".balign %" Pd ", 0\n", OS::kMaxPreferredCodeAlignment);
+
+ for (intptr_t i = 0; i < objects_.length(); i++) {
+ const Object& obj = *objects_[i].obj_;
+ stream_.Print("Precompiled_Obj_%d:\n", i);
+
+ NoSafepointScope no_safepoint;
+ uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag;
+ uword end = start + obj.raw()->Size();
+
+ // Write object header with the mark and VM heap bits set.
+ uword marked_tags = obj.raw()->ptr()->tags_;
+ marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
+ marked_tags = RawObject::MarkBit::update(true, marked_tags);
+ WriteWordLiteral(marked_tags);
+ start += sizeof(uword);
+ for (uword* cursor = reinterpret_cast<uword*>(start);
+ cursor < reinterpret_cast<uword*>(end);
+ cursor++) {
+ WriteWordLiteral(*cursor);
+ }
+ }
}
@@ -1250,14 +1304,17 @@
RawInstructions* result =
reinterpret_cast<RawInstructions*>(
- reinterpret_cast<uword>(buffer_) + offset + kHeapObjectTag);
+ reinterpret_cast<uword>(instructions_buffer_) +
+ offset + kHeapObjectTag);
+#ifdef DEBUG
uword actual_tags = result->ptr()->tags_;
if (actual_tags != expected_tags) {
FATAL2("Instructions tag mismatch: expected %" Pd ", saw %" Pd,
expected_tags,
actual_tags);
}
+#endif
ASSERT(result->IsMarked());
@@ -1265,6 +1322,18 @@
}
+RawObject* InstructionsReader::GetObjectAt(int32_t offset) {
+ ASSERT(Utils::IsAligned(offset, kWordSize));
+
+ RawObject* result =
+ reinterpret_cast<RawObject*>(
+ reinterpret_cast<uword>(data_buffer_) + offset + kHeapObjectTag);
+ ASSERT(result->IsMarked());
+
+ return result;
+}
+
+
intptr_t SnapshotReader::LookupInternalClass(intptr_t class_header) {
// If the header is an object Id, lookup singleton VM classes or classes
// stored in the object store.
@@ -1489,10 +1558,12 @@
const uint8_t* buffer,
intptr_t size,
const uint8_t* instructions_buffer,
+ const uint8_t* data_buffer,
Thread* thread)
: SnapshotReader(buffer,
size,
instructions_buffer,
+ data_buffer,
Snapshot::kFull,
new ZoneGrowableArray<BackRefNode>(
kNumVmIsolateSnapshotReferences),
@@ -1510,6 +1581,7 @@
}
ResetBackwardReferenceTable();
Dart::set_instructions_snapshot_buffer(instructions_buffer_);
+ Dart::set_data_snapshot_buffer(data_buffer_);
}
@@ -1561,10 +1633,12 @@
IsolateSnapshotReader::IsolateSnapshotReader(const uint8_t* buffer,
intptr_t size,
const uint8_t* instructions_buffer,
+ const uint8_t* data_buffer,
Thread* thread)
: SnapshotReader(buffer,
size,
instructions_buffer,
+ data_buffer,
Snapshot::kFull,
new ZoneGrowableArray<BackRefNode>(
kNumInitialReferencesInFullSnapshot),
@@ -1584,6 +1658,7 @@
: SnapshotReader(buffer,
size,
NULL, /* instructions_buffer */
+ NULL, /* data_buffer */
Snapshot::kScript,
new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
thread) {
@@ -1601,6 +1676,7 @@
: SnapshotReader(buffer,
size,
NULL, /* instructions_buffer */
+ NULL, /* data_buffer */
Snapshot::kMessage,
new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
thread) {
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index b1071d6..978dbd1 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -224,6 +224,34 @@
};
+class DataSnapshot : ValueObject {
+ public:
+ explicit DataSnapshot(const void* raw_memory)
+ : raw_memory_(raw_memory) {
+ ASSERT(Utils::IsAligned(raw_memory, 2 * kWordSize)); // kObjectAlignment
+ }
+
+ void* data_start() {
+ return reinterpret_cast<void*>(
+ reinterpret_cast<uword>(raw_memory_) + kHeaderSize);
+ }
+
+ uword data_size() {
+ uword snapshot_size = *reinterpret_cast<const uword*>(raw_memory_);
+ return snapshot_size - kHeaderSize;
+ }
+
+ // Header: data length and padding for alignment. We use the same alignment
+ // as for code for now.
+ static const intptr_t kHeaderSize = OS::kMaxPreferredCodeAlignment;
+
+ private:
+ const void* raw_memory_; // The symbol kDataSnapshot.
+
+ DISALLOW_COPY_AND_ASSIGN(DataSnapshot);
+};
+
+
class BaseReader {
public:
BaseReader(const uint8_t* buffer, intptr_t size) : stream_(buffer, size) {}
@@ -333,17 +361,22 @@
class InstructionsReader : public ZoneAllocated {
public:
- explicit InstructionsReader(const uint8_t* buffer)
- : buffer_(buffer) {
- ASSERT(buffer != NULL);
- ASSERT(Utils::IsAligned(reinterpret_cast<uword>(buffer),
+ InstructionsReader(const uint8_t* instructions_buffer,
+ const uint8_t* data_buffer)
+ : instructions_buffer_(instructions_buffer),
+ data_buffer_(data_buffer) {
+ ASSERT(instructions_buffer != NULL);
+ ASSERT(data_buffer != NULL);
+ ASSERT(Utils::IsAligned(reinterpret_cast<uword>(instructions_buffer),
OS::PreferredCodeAlignment()));
}
RawInstructions* GetInstructionsAt(int32_t offset, uword expected_tags);
+ RawObject* GetObjectAt(int32_t offset);
private:
- const uint8_t* buffer_;
+ const uint8_t* instructions_buffer_;
+ const uint8_t* data_buffer_;
DISALLOW_COPY_AND_ASSIGN(InstructionsReader);
};
@@ -456,12 +489,18 @@
return instructions_reader_->GetInstructionsAt(offset, expected_tags);
}
+ RawObject* GetObjectAt(int32_t offset) {
+ return instructions_reader_->GetObjectAt(offset);
+ }
+
const uint8_t* instructions_buffer_;
+ const uint8_t* data_buffer_;
protected:
SnapshotReader(const uint8_t* buffer,
intptr_t size,
const uint8_t* instructions_buffer,
+ const uint8_t* data_buffer,
Snapshot::Kind kind,
ZoneGrowableArray<BackRefNode>* backward_references,
Thread* thread);
@@ -608,6 +647,7 @@
VmIsolateSnapshotReader(const uint8_t* buffer,
intptr_t size,
const uint8_t* instructions_buffer,
+ const uint8_t* data_buffer,
Thread* thread);
~VmIsolateSnapshotReader();
@@ -623,6 +663,7 @@
IsolateSnapshotReader(const uint8_t* buffer,
intptr_t size,
const uint8_t* instructions_buffer,
+ const uint8_t* data_buffer,
Thread* thread);
~IsolateSnapshotReader();
@@ -811,8 +852,10 @@
intptr_t initial_size)
: stream_(buffer, alloc, initial_size),
next_offset_(InstructionsSnapshot::kHeaderSize),
+ next_object_offset_(DataSnapshot::kHeaderSize),
binary_size_(0),
- instructions_() {
+ instructions_(),
+ objects_() {
ASSERT(buffer != NULL);
ASSERT(alloc != NULL);
}
@@ -824,6 +867,8 @@
int32_t GetOffsetFor(RawInstructions* instructions);
+ int32_t GetObjectOffsetFor(RawObject* raw_object);
+
void SetInstructionsCode(RawInstructions* insns, RawCode* code) {
for (intptr_t i = 0; i < instructions_.length(); i++) {
if (instructions_[i].raw_insns_ == insns) {
@@ -851,6 +896,16 @@
};
};
+ struct ObjectData {
+ explicit ObjectData(RawObject* raw_obj)
+ : raw_obj_(raw_obj) { }
+
+ union {
+ RawObject* raw_obj_;
+ const Object* obj_;
+ };
+ };
+
void WriteWordLiteral(uword value) {
// Padding is helpful for comparing the .S with --disassemble.
#if defined(ARCH_IS_64_BIT)
@@ -863,8 +918,10 @@
WriteStream stream_;
intptr_t next_offset_;
+ intptr_t next_object_offset_;
intptr_t binary_size_;
GrowableArray<InstructionsData> instructions_;
+ GrowableArray<ObjectData> objects_;
DISALLOW_COPY_AND_ASSIGN(InstructionsWriter);
};
@@ -920,6 +977,10 @@
return instructions_writer_->GetOffsetFor(instructions);
}
+ int32_t GetObjectId(RawObject* raw) {
+ return instructions_writer_->GetObjectOffsetFor(raw);
+ }
+
void SetInstructionsCode(RawInstructions* instructions, RawCode* code) {
return instructions_writer_->SetInstructionsCode(instructions, code);
}
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 210e43f..35d3728 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -1537,6 +1537,7 @@
EXPECT(script_snapshot != NULL);
result = Dart_LoadScriptFromSnapshot(script_snapshot, size);
EXPECT_VALID(result);
+ Dart_ExitScope();
}
FLAG_load_deferred_eagerly = saved_load_deferred_eagerly_mode;
@@ -1657,6 +1658,7 @@
// Invoke the test_b function.
result = Dart_Invoke(lib, NewString("test_b"), 0, NULL);
EXPECT(Dart_IsError(result) == saved_enable_type_checks_mode);
+ Dart_ExitScope();
}
Dart_ShutdownIsolate();
free(full_snapshot);
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 3b9398f..bbd35ab 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -118,7 +118,7 @@
ZoneGrowableArray<const ICData*>* ic_data_array =
new(zone()) ZoneGrowableArray<const ICData*>();
- function.RestoreICDataMap(ic_data_array, false /* clone descriptors */);
+ function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
const PcDescriptors& descriptors = PcDescriptors::Handle(
zone(), code.pc_descriptors());
@@ -150,7 +150,7 @@
ZoneGrowableArray<const ICData*>* ic_data_array =
new(zone()) ZoneGrowableArray<const ICData*>();
- function.RestoreICDataMap(ic_data_array, false /* clone descriptors */);
+ function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
const PcDescriptors& descriptors = PcDescriptors::Handle(
zone(), code.pc_descriptors());
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 6cbbd7a..ec83c5d 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -26,7 +26,6 @@
"Set to true for debugging & verifying the slow paths.");
DECLARE_FLAG(bool, trace_optimized_ic_calls);
DECLARE_FLAG(int, optimization_counter_threshold);
-DECLARE_FLAG(bool, support_debugger);
DECLARE_FLAG(bool, lazy_dispatchers);
// Input parameters:
@@ -1294,10 +1293,6 @@
Label* not_smi_or_overflow,
bool should_update_result_range) {
__ Comment("Fast Smi op");
- if (FLAG_throw_on_javascript_int_overflow) {
- // The overflow check is more complex than implemented below.
- return;
- }
__ ldr(R0, Address(SP, + 0 * kWordSize)); // Right.
__ ldr(R1, Address(SP, + 1 * kWordSize)); // Left.
__ orr(TMP, R0, Operand(R1));
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 3f44fc0..3931825 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1234,10 +1234,6 @@
Label* not_smi_or_overflow,
bool should_update_result_range) {
__ Comment("Fast Smi op");
- if (FLAG_throw_on_javascript_int_overflow) {
- // The overflow check is more complex than implemented below.
- return;
- }
ASSERT(num_args == 2);
__ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right
__ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left.
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index e9033d1..39d6b23 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -34,6 +34,7 @@
V(Other, "other") \
V(Call, "call") \
V(Current, "current") \
+ V(_current, "_current") \
V(MoveNext, "moveNext") \
V(IsYieldEach, "isYieldEach") \
V(Value, "value") \
@@ -307,8 +308,6 @@
V(OutOfMemoryError, "OutOfMemoryError") \
V(NullThrownError, "NullThrownError") \
V(IsolateSpawnException, "IsolateSpawnException") \
- V(JavascriptIntegerOverflowError, "_JavascriptIntegerOverflowError") \
- V(JavascriptCompatibilityError, "_JavascriptCompatibilityError") \
V(BooleanExpression, "boolean expression") \
V(Malformed, "malformed") \
V(Malbounded, "malbounded") \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 0fa2d40..c5c6e70 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -24,6 +24,15 @@
Thread::~Thread() {
// We should cleanly exit any isolate before destruction.
ASSERT(isolate_ == NULL);
+ // There should be no top api scopes at this point.
+ ASSERT(api_top_scope() == NULL);
+ // Delete the resusable api scope if there is one.
+ if (api_reusable_scope_) {
+ delete api_reusable_scope_;
+ api_reusable_scope_ = NULL;
+ }
+ delete thread_lock_;
+ thread_lock_ = NULL;
}
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 8fb0768..be86154 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -27,6 +27,10 @@
DEFINE_FLAG(charp, timeline_dir, NULL,
"Enable all timeline trace streams and output VM global trace "
"into specified directory.");
+DEFINE_FLAG(charp, timeline_streams, NULL,
+ "Comma separated list of timeline streams to record. "
+ "Valid values: all, API, Compiler, Dart, Debugger, Embedder, "
+ "GC, Isolate, and VM.");
// Implementation notes:
//
@@ -70,6 +74,56 @@
// |TimelineEventRecorder::lock_|
//
+
+// Returns a caller freed array of stream names in FLAG_timeline_streams.
+static MallocGrowableArray<char*>* GetEnabledByDefaultTimelineStreams() {
+ MallocGrowableArray<char*>* result = new MallocGrowableArray<char*>();
+ if (FLAG_timeline_streams == NULL) {
+ // Nothing set.
+ return result;
+ }
+ char* save_ptr; // Needed for strtok_r.
+ // strtok modifies arg 1 so we make a copy of it.
+ char* streams = strdup(FLAG_timeline_streams);
+ char* token = strtok_r(streams, ",", &save_ptr);
+ while (token != NULL) {
+ result->Add(strdup(token));
+ token = strtok_r(NULL, ",", &save_ptr);
+ }
+ free(streams);
+ return result;
+}
+
+
+// Frees the result of |GetEnabledByDefaultTimelineStreams|.
+static void FreeEnabledByDefaultTimelineStreams(
+ MallocGrowableArray<char*>* streams) {
+ if (streams == NULL) {
+ return;
+ }
+ for (intptr_t i = 0; i < streams->length(); i++) {
+ free((*streams)[i]);
+ }
+ delete streams;
+}
+
+
+// Returns true if |streams| contains |stream| or "all". Not case sensitive.
+static bool HasStream(MallocGrowableArray<char*>* streams, const char* stream) {
+ if ((FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline) {
+ return true;
+ }
+ for (intptr_t i = 0; i < streams->length(); i++) {
+ const char* checked_stream = (*streams)[i];
+ if ((strstr(checked_stream, "all") != NULL) ||
+ (strstr(checked_stream, stream) != NULL)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
void Timeline::InitOnce() {
ASSERT(recorder_ == NULL);
// Default to ring recorder being enabled.
@@ -82,18 +136,24 @@
} else if (use_ring_recorder) {
recorder_ = new TimelineEventRingRecorder();
}
- vm_stream_.Init("VM", EnableStreamByDefault("VM"), NULL);
+ enabled_streams_ = GetEnabledByDefaultTimelineStreams();
+ vm_stream_.Init("VM", HasStream(enabled_streams_, "VM"), NULL);
vm_api_stream_.Init("API",
- EnableStreamByDefault("API"),
+ HasStream(enabled_streams_, "API"),
&stream_API_enabled_);
// Global overrides.
#define ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT(name, not_used) \
- stream_##name##_enabled_ = EnableStreamByDefault(#name);
+ stream_##name##_enabled_ = HasStream(enabled_streams_, #name);
ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT)
#undef ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT
}
+void Timeline::SetVMStreamEnabled(bool enabled) {
+ vm_stream_.set_enabled(enabled);
+}
+
+
void Timeline::Shutdown() {
ASSERT(recorder_ != NULL);
if (FLAG_timeline_dir != NULL) {
@@ -108,6 +168,10 @@
#undef ISOLATE_TIMELINE_STREAM_DISABLE
delete recorder_;
recorder_ = NULL;
+ if (enabled_streams_ != NULL) {
+ FreeEnabledByDefaultTimelineStreams(enabled_streams_);
+ enabled_streams_ = NULL;
+ }
}
@@ -116,9 +180,17 @@
}
-bool Timeline::EnableStreamByDefault(const char* stream_name) {
- // TODO(johnmccutchan): Allow for command line control over streams.
- return (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline;
+void Timeline::SetupIsolateStreams(Isolate* isolate) {
+ if (!FLAG_support_timeline) {
+ return;
+ }
+#define ISOLATE_TIMELINE_STREAM_INIT(name, enabled_by_default) \
+ isolate->Get##name##Stream()->Init( \
+ #name, \
+ (enabled_by_default || HasStream(enabled_streams_, #name)), \
+ Timeline::Stream##name##EnabledFlag());
+ ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT);
+#undef ISOLATE_TIMELINE_STREAM_INIT
}
@@ -154,6 +226,38 @@
}
+void Timeline::PrintFlagsToJSON(JSONStream* js) {
+ JSONObject obj(js);
+ obj.AddProperty("type", "TimelineFlags");
+ TimelineEventRecorder* recorder = Timeline::recorder();
+ if (recorder == NULL) {
+ obj.AddProperty("recorderName", "null");
+ } else {
+ obj.AddProperty("recorderName", recorder->name());
+ }
+ {
+ JSONArray availableStreams(&obj, "availableStreams");
+#define ADD_STREAM_NAME(name, not_used) \
+ availableStreams.AddValue(#name);
+ISOLATE_TIMELINE_STREAM_LIST(ADD_STREAM_NAME);
+#undef ADD_STREAM_NAME
+ availableStreams.AddValue("VM");
+ }
+ {
+ JSONArray recordedStreams(&obj, "recordedStreams");
+#define ADD_RECORDED_STREAM_NAME(name, not_used) \
+ if (stream_##name##_enabled_) { \
+ recordedStreams.AddValue(#name); \
+ }
+ISOLATE_TIMELINE_STREAM_LIST(ADD_RECORDED_STREAM_NAME);
+#undef ADD_RECORDED_STREAM_NAME
+ if (vm_stream_.enabled()) {
+ recordedStreams.AddValue("VM");
+ }
+ }
+}
+
+
void Timeline::Clear() {
TimelineEventRecorder* recorder = Timeline::recorder();
if (recorder == NULL) {
@@ -167,6 +271,7 @@
TimelineEventRecorder* Timeline::recorder_ = NULL;
TimelineStream Timeline::vm_stream_;
TimelineStream Timeline::vm_api_stream_;
+MallocGrowableArray<char*>* Timeline::enabled_streams_ = NULL;
#define ISOLATE_TIMELINE_STREAM_DEFINE_FLAG(name, enabled_by_default) \
bool Timeline::stream_##name##_enabled_ = enabled_by_default;
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index cf77396..f44fb53 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -46,7 +46,7 @@
// Access the global recorder. Not thread safe.
static TimelineEventRecorder* recorder();
- static bool EnableStreamByDefault(const char* stream_name);
+ static void SetupIsolateStreams(Isolate* isolate);
static TimelineStream* GetVMStream();
@@ -57,6 +57,9 @@
static void Clear();
+ // Print information about streams to JSON.
+ static void PrintFlagsToJSON(JSONStream* json);
+
#define ISOLATE_TIMELINE_STREAM_FLAGS(name, not_used) \
static const bool* Stream##name##EnabledFlag() { \
return &stream_##name##_enabled_; \
@@ -66,11 +69,13 @@
}
ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAGS)
#undef ISOLATE_TIMELINE_STREAM_FLAGS
+ static void SetVMStreamEnabled(bool enabled);
private:
static TimelineEventRecorder* recorder_;
static TimelineStream vm_stream_;
static TimelineStream vm_api_stream_;
+ static MallocGrowableArray<char*>* enabled_streams_;
#define ISOLATE_TIMELINE_STREAM_DECLARE_FLAG(name, not_used) \
static bool stream_##name##_enabled_;
@@ -618,7 +623,7 @@
// Interface method(s) which must be implemented.
virtual void PrintJSON(JSONStream* js, TimelineEventFilter* filter) = 0;
virtual void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) = 0;
-
+ virtual const char* name() const = 0;
int64_t GetNextAsyncId();
void FinishBlock(TimelineEventBlock* block);
@@ -662,6 +667,9 @@
void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter);
+ const char* name() const {
+ return "ring";
+ }
protected:
TimelineEvent* StartEvent();
@@ -693,6 +701,10 @@
// reference to |event| as it may be freed as soon as this function returns.
virtual void StreamEvent(TimelineEvent* event) = 0;
+ const char* name() const {
+ return "streaming";
+ }
+
protected:
TimelineEventBlock* GetNewBlockLocked() {
return NULL;
@@ -717,6 +729,10 @@
void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter);
+ const char* name() const {
+ return "endless";
+ }
+
protected:
TimelineEvent* StartEvent();
void CompleteEvent(TimelineEvent* event);
diff --git a/runtime/vm/timeline_test.cc b/runtime/vm/timeline_test.cc
index 05c4abb..01d0c6a 100644
--- a/runtime/vm/timeline_test.cc
+++ b/runtime/vm/timeline_test.cc
@@ -345,12 +345,12 @@
TimelineTestHelper::FakeThreadEvent(block_1_2, 1, "B2");
TimelineTestHelper::FakeThreadEvent(block_1_2, 1, "B3");
// Sleep to ensure timestamps differ.
- OS::Sleep(1);
+ OS::Sleep(32);
TimelineTestHelper::FakeThreadEvent(block_1_0, 1, "A1");
- OS::Sleep(1);
+ OS::Sleep(32);
TimelineTestHelper::FakeThreadEvent(block_1_1, 1, "C1");
TimelineTestHelper::FakeThreadEvent(block_1_1, 1, "C2");
- OS::Sleep(1);
+ OS::Sleep(32);
// Add events to each block for thread 2.
TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "A");
@@ -455,7 +455,7 @@
// Emit the earlier event into block_1.
TimelineTestHelper::FakeThreadEvent(block_1, 2, "Alpha", &stream);
- OS::Sleep(1);
+ OS::Sleep(32);
// Emit the later event into block_0.
TimelineTestHelper::FakeThreadEvent(block_0, 2, "Beta", &stream);
diff --git a/runtime/vm/virtual_memory.cc b/runtime/vm/virtual_memory.cc
index 1ad6c06..1372545 100644
--- a/runtime/vm/virtual_memory.cc
+++ b/runtime/vm/virtual_memory.cc
@@ -28,8 +28,7 @@
}
-VirtualMemory* VirtualMemory::ForInstructionsSnapshot(void* pointer,
- uword size) {
+VirtualMemory* VirtualMemory::ForExternalPage(void* pointer, uword size) {
// Memory for precompilated instructions was allocated by the embedder, so
// create a VirtualMemory without allocating.
MemoryRegion region(pointer, size);
diff --git a/runtime/vm/virtual_memory.h b/runtime/vm/virtual_memory.h
index 53ba57d..270d3cf 100644
--- a/runtime/vm/virtual_memory.h
+++ b/runtime/vm/virtual_memory.h
@@ -71,7 +71,7 @@
bool embedder_allocated() const { return embedder_allocated_; }
- static VirtualMemory* ForInstructionsSnapshot(void* pointer, uword size);
+ static VirtualMemory* ForExternalPage(void* pointer, uword size);
private:
static VirtualMemory* ReserveInternal(intptr_t size);
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 30df00d..a3d0536 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -376,7 +376,6 @@
'regexp_test.cc',
'report.cc',
'report.h',
- 'report_test.cc',
'resolver.cc',
'resolver.h',
'resolver_test.cc',
diff --git a/sdk/lib/_internal/js_runtime/lib/async_patch.dart b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
index 4d91d79..20cd748 100644
--- a/sdk/lib/_internal/js_runtime/lib/async_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
@@ -255,7 +255,7 @@
/// is done, schedules [asyncBody] again.
///
/// If the async* function wants to do an await it calls this function with
-/// [object] not and [IterationMarker].
+/// [object] not an [IterationMarker].
///
/// If [object] is not a [Future], it is wrapped in a `Future.value`.
/// The [asyncBody] is called on completion of the future (see [asyncHelper].
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 5dae802..b69c6fc 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1495,7 +1495,7 @@
class StreamView<T> extends Stream<T> {
final Stream<T> _stream;
- StreamView(this._stream);
+ const StreamView(Stream<T> stream) : _stream = stream, super._internal();
bool get isBroadcast => _stream.isBroadcast;
diff --git a/sdk/lib/convert/line_splitter.dart b/sdk/lib/convert/line_splitter.dart
index 0af2f2f..b5ec32b 100644
--- a/sdk/lib/convert/line_splitter.dart
+++ b/sdk/lib/convert/line_splitter.dart
@@ -57,6 +57,9 @@
}
return new _LineSplitterSink(sink);
}
+
+ // Override the base-class' bind, to provide a better type.
+ Stream<String> bind(Stream<String> stream) => super.bind(stream);
}
// TODO(floitsch): deal with utf8.
diff --git a/sdk/lib/developer/developer_sources.gypi b/sdk/lib/developer/developer_sources.gypi
index 0c4333a..5bdfe3d 100644
--- a/sdk/lib/developer/developer_sources.gypi
+++ b/sdk/lib/developer/developer_sources.gypi
@@ -5,9 +5,9 @@
{
'sources': [
'developer.dart',
+ # The above file needs to be first if additional parts are added to the lib.
'extension.dart',
'profiler.dart',
'timeline.dart',
- # The above file needs to be first if additional parts are added to the lib.
],
}
diff --git a/sdk/lib/developer/extension.dart b/sdk/lib/developer/extension.dart
index 309dca2..75737f6 100644
--- a/sdk/lib/developer/extension.dart
+++ b/sdk/lib/developer/extension.dart
@@ -4,21 +4,38 @@
part of dart.developer;
+/// A response to a service protocol extension RPC.
+///
+/// If the RPC was successful, use [ServiceExtensionResponse.result], otherwise
+/// use [ServiceExtensionResponse.error].
class ServiceExtensionResponse {
final String _result;
final int _errorCode;
final String _errorDetail;
- ServiceExtensionResponse.result(this._result)
- : _errorCode = null,
+ /// Creates a successful to a service protocol extension RPC.
+ ///
+ /// Requires [result] to be a JSON object encoded as a string. When forming
+ /// the JSON-RPC message [result] will be inlined directly.
+ ServiceExtensionResponse.result(String result)
+ : _result = result,
+ _errorCode = null,
_errorDetail = null {
if (_result is! String) {
throw new ArgumentError.value(_result, "result", "Must be a String");
}
}
- ServiceExtensionResponse.error(this._errorCode, this._errorDetail)
- : _result = null {
+ /// Creates an error response to a service protocol extension RPC.
+ ///
+ /// Requires [errorCode] to be [invalidParams] or between [extensionErrorMin]
+ /// and [extensionErrorMax]. Requires [errorDetail] to be a JSON object
+ /// encoded as a string. When forming the JSON-RPC message [errorDetail] will
+ /// be inlined directly.
+ ServiceExtensionResponse.error(int errorCode, String errorDetail)
+ : _result = null,
+ _errorCode = errorCode,
+ _errorDetail = errorDetail {
_validateErrorCode(_errorCode);
if (_errorDetail is! String) {
throw new ArgumentError.value(_errorDetail,
@@ -28,13 +45,23 @@
}
/// Invalid method parameter(s) error code.
- static const kInvalidParams = -32602;
+ @deprecated static const kInvalidParams = invalidParams;
/// Generic extension error code.
- static const kExtensionError = -32000;
+ @deprecated static const kExtensionError = extensionError;
/// Maximum extension provided error code.
- static const kExtensionErrorMax = -32000;
+ @deprecated static const kExtensionErrorMax = extensionErrorMax;
/// Minimum extension provided error code.
- static const kExtensionErrorMin = -32016;
+ @deprecated static const kExtensionErrorMin = extensionErrorMin;
+
+ /// Invalid method parameter(s) error code.
+ static const invalidParams = -32602;
+ /// Generic extension error code.
+ static const extensionError = -32000;
+ /// Maximum extension provided error code.
+ static const extensionErrorMax = -32000;
+ /// Minimum extension provided error code.
+ static const extensionErrorMin = -32016;
+
static String _errorCodeMessage(int errorCode) {
_validateErrorCode(errorCode);
@@ -48,11 +75,11 @@
if (errorCode is! int) {
throw new ArgumentError.value(errorCode, "errorCode", "Must be an int");
}
- if (errorCode == kInvalidParams) {
+ if (errorCode == invalidParams) {
return;
}
- if ((errorCode >= kExtensionErrorMin) &&
- (errorCode <= kExtensionErrorMax)) {
+ if ((errorCode >= extensionErrorMin) &&
+ (errorCode <= extensionErrorMax)) {
return;
}
throw new ArgumentError.value(errorCode, "errorCode", "Out of range");
@@ -90,14 +117,27 @@
/// Register a [ServiceExtensionHandler] that will be invoked in this isolate
/// for [method]. *NOTE*: Service protocol extensions must be registered
-/// in each isolate and users of extensions must always specify a target
-/// isolate.
+/// in each isolate.
+///
+/// *NOTE*: [method] must begin with 'ext.' and you should use the following
+/// structure to avoid conflicts with other packages: 'ext.package.command'.
+/// That is, immediately following the 'ext.' prefix, should be the registering
+/// package name followed by another period ('.') and then the command name.
+/// For example: 'ext.dart.io.getOpenFiles'.
+///
+/// Because service extensions are isolate specific, clients using extensions
+/// must always include an 'isolateId' parameter with each RPC.
void registerExtension(String method, ServiceExtensionHandler handler) {
if (method is! String) {
throw new ArgumentError.value(method,
'method',
'Must be a String');
}
+ if (!method.startsWith('ext.')) {
+ throw new ArgumentError.value(method,
+ 'method',
+ 'Must begin with ext.');
+ }
if (_lookupExtension(method) != null) {
throw new ArgumentError('Extension already registered: $method');
}
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 8d4c3de..c306d5b 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -26122,8 +26122,12 @@
@DomName('MessageEvent.data')
@DocsEditable()
- Object get data => wrap_jso(_blink.BlinkMessageEvent.instance.data_Getter_(unwrap_jso(this)));
-
+ // TODO(alanknight): This really should be generated by the
+ // _OutputConversion in the systemnative.py script, but that doesn't
+ // use those conversions right now, so do this as a one-off.
+ dynamic get data => convertNativeToDart_SerializedScriptValue(
+ _blink.BlinkMessageEvent.instance.data_Getter_(unwrap_jso(this)));
+
@DomName('MessageEvent.lastEventId')
@DocsEditable()
@Unstable()
@@ -48429,8 +48433,7 @@
return [
"inspect",
(o) {
- host.callMethod("inspect", [o]);
- return o;
+ return host.callMethod("_inspect", [unwrap_jso(o)]);
},
"dir",
window().console.dir,
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 5dd559c..0d0bc9e 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -595,9 +595,9 @@
// We need to make sure that these are always awailable from the
// observatory even if no files (or sockets for the socket ones) are
// open.
- registerExtension('__getOpenFiles',
+ registerExtension('ext.dart.io.getOpenFiles',
_FileResourceInfo.getOpenFiles);
- registerExtension('__getFileByID',
+ registerExtension('ext.dart.io.getFileByID',
_FileResourceInfo.getFileInfoMapByID);
_connectedResourceHandler = true;
}
diff --git a/sdk/lib/io/io_resource_info.dart b/sdk/lib/io/io_resource_info.dart
index 1a18fc9..9267084 100644
--- a/sdk/lib/io/io_resource_info.dart
+++ b/sdk/lib/io/io_resource_info.dart
@@ -112,7 +112,7 @@
}
static Future<ServiceExtensionResponse> getOpenFiles(function, params) {
- assert(function == '__getOpenFiles');
+ assert(function == 'ext.dart.io.getOpenFiles');
var data = {'type': '_openfiles', 'data': getOpenFilesList()};
var json = JSON.encode(data);
return new Future.value(new ServiceExtensionResponse.result(json));
@@ -182,7 +182,7 @@
static Future<ServiceExtensionResponse> getStartedProcesses(
String function, Map<String, String> params) {
- assert(function == '__getProcesses');
+ assert(function == 'ext.dart.io.getProcesses');
var data = {'type': '_startedprocesses', 'data': getStartedProcessesList()};
var json = JSON.encode(data);
return new Future.value(new ServiceExtensionResponse.result(json));
@@ -264,7 +264,7 @@
}
static Future<ServiceExtensionResponse> getOpenSockets(function, params) {
- assert(function == '__getOpenSockets');
+ assert(function == 'ext.dart.io.getOpenSockets');
var data = {'type': '_opensockets', 'data': getOpenSocketsList()};
var json = JSON.encode(data);
return new Future.value(new ServiceExtensionResponse.result(json));
diff --git a/sdk/lib/io/iolib_sources.gypi b/sdk/lib/io/io_sources.gypi
similarity index 91%
rename from sdk/lib/io/iolib_sources.gypi
rename to sdk/lib/io/io_sources.gypi
index ad2110f..10a6bf4 100644
--- a/sdk/lib/io/iolib_sources.gypi
+++ b/sdk/lib/io/io_sources.gypi
@@ -4,6 +4,8 @@
{
'sources': [
+ 'io.dart',
+ # The above file needs to be first if additional parts are added to the lib.
'bytes_builder.dart',
'common.dart',
'crypto.dart',
diff --git a/sdk/lib/io/security_context.dart b/sdk/lib/io/security_context.dart
index 28351b2..7fc7287 100644
--- a/sdk/lib/io/security_context.dart
+++ b/sdk/lib/io/security_context.dart
@@ -46,7 +46,7 @@
*
* A secure connection using this SecurityContext will use this key with
* the server or client certificate to sign and decrypt messages.
- * [keyFile] is a PEM file containing an encrypted
+ * [keyFile] is a PEM or PKCS12 file containing an encrypted
* private key, encrypted with [password]. An unencrypted file can be
* used, but this is not usual.
*/
@@ -62,11 +62,7 @@
/**
* Sets the private key for a server certificate or client certificate.
*
- * A secure connection using this SecurityContext will use this key with
- * the server or client certificate to sign and decrypt messages.
- * [keyBytes] is the contents of a PEM file containing an encrypted
- * private key, encrypted with [password]. An unencrypted file can be
- * used, but this is not usual.
+ * Like [usePrivateKeyBytesSync], but takes the contents of the file.
*/
void usePrivateKeyBytes(List<int> keyBytes, {String password});
@@ -74,8 +70,10 @@
* Sets the set of trusted X509 certificates used by [SecureSocket]
* client connections, when connecting to a secure server.
*
- * [file] is the path to a PEM file containing X509 certificates, usually
- * root certificates from certificate authorities.
+ * [file] is the path to a PEM or PKCS12 file containing X509 certificates,
+ * usually root certificates from certificate authorities. When using a
+ * PKCS12 file, it should not contain a private key, and the password should
+ * be the empty string.
*/
void setTrustedCertificatesSync(String file);
@@ -90,8 +88,7 @@
* Sets the set of trusted X509 certificates used by [SecureSocket]
* client connections, when connecting to a secure server.
*
- * [file] is the contents of a PEM file containing X509 certificates, usually
- * root certificates from certificate authorities.
+ * Like [setTrustedCertificatesSync] but takes the contents of the file.
*/
void setTrustedCertificatesBytes(List<int> certBytes);
@@ -99,10 +96,12 @@
* Sets the chain of X509 certificates served by [SecureServer]
* when making secure connections, including the server certificate.
*
- * [file] is a PEM file containing X509 certificates, starting with
+ * [file] is a PEM or PKCS12 file containing X509 certificates, starting with
* the root authority and intermediate authorities forming the signed
* chain to the server certificate, and ending with the server certificate.
- * The private key for the server certificate is set by [usePrivateKey].
+ * The private key for the server certificate is set by [usePrivateKey]. When
+ * using a PKCS12 file, it should not contain a private key, and the password
+ * should be the empty string.
*/
void useCertificateChainSync(String file);
@@ -117,19 +116,19 @@
* Sets the chain of X509 certificates served by [SecureServer]
* when making secure connections, including the server certificate.
*
- * [chainBytes] is the contents of a PEM file containing X509 certificates,
- * starting with the root authority and intermediate authorities forming the
- * signed chain to the server certificate, and ending with the server
- * certificate. The private key for the server certificate is set by
- * [usePrivateKey].
+ * Like [useCertificateChainSync] but takes the contents of the file.
*/
void useCertificateChainBytes(List<int> chainBytes);
/**
* Sets the list of authority names that a [SecureServer] will advertise
- * as accepted, when requesting a client certificate from a connecting
- * client. [file] is a PEM file containing the accepted signing authority
- * certificates - the authority names are extracted from the certificates.
+ * as accepted when requesting a client certificate from a connecting
+ * client.
+ *
+ * [file] is a PEM or PKCS12 file containing the accepted signing
+ * authority certificates - the authority names are extracted from the
+ * certificates. When using a PKCS12 file, it should not contain a private
+ * key, and the password should be the empty string.
*/
void setClientAuthoritiesSync(String file);
@@ -143,9 +142,9 @@
/**
* Sets the list of authority names that a [SecureServer] will advertise
* as accepted, when requesting a client certificate from a connecting
- * client. [authCertBytes] is the contents of a PEM file containing the
- * accepted signing authority certificates - the authority names are extracted
- * from the certificates.
+ * client.
+ *
+ * Like [setClientAuthoritySync] but takes the contents of the file.
*/
void setClientAuthoritiesBytes(List<int> authCertBytes);
diff --git a/sdk/lib/rules.gni b/sdk/lib/rules.gni
new file mode 100644
index 0000000..93ade221
--- /dev/null
+++ b/sdk/lib/rules.gni
@@ -0,0 +1,44 @@
+# 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.
+
+# This build rule will copy the source for one Dart SDK library.
+#
+# Required arguments:
+# sdk_lib_name
+# The name of a Dart SDK library.
+#
+# Optional arguments:
+# dart_root
+# Path to the Dart SDK source root. Default value is "//dart".
+#
+# The sources will be copied into $root_gen_dir/dart_sdk_libs/$sdk_lib_name/.
+#
+template("dart_sdk_lib_copy") {
+ assert(defined(invoker.sdk_lib_name))
+ if (defined(invoker.dart_root)) {
+ dart_root = rebase_path(invoker.dart_root)
+ } else {
+ dart_root = rebase_path("//dart")
+ }
+ dart_sdk_sdk_lib_path =
+ rebase_path("sdk/lib", "", dart_root)
+ dart_sdk_tools_gypi_to_gn_path =
+ rebase_path("tools/gypi_to_gn.py", "", dart_root)
+ # The name of the SDK library being copied.
+ lib_name = invoker.sdk_lib_name
+ # The path to the libraries source directory.
+ lib_path = rebase_path(lib_name, "", dart_sdk_sdk_lib_path)
+ # The path to the sources gypi.
+ lib_sources_gypi = lib_name + "_sources.gypi"
+ # Get the contents of the gypi file.
+ sdk_lib_sources_gypi =
+ exec_script(dart_sdk_tools_gypi_to_gn_path,
+ [rebase_path(lib_sources_gypi, "", lib_path)],
+ "scope",
+ [rebase_path(lib_sources_gypi, "", lib_path)])
+ copy(target_name) {
+ sources = rebase_path(sdk_lib_sources_gypi.sources, "", lib_path)
+ outputs = [ "$root_gen_dir/dart_sdk_libs/$lib_name/{{source_file_part}}" ]
+ }
+}
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 7a3b561..8ee4e6d 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -9619,12 +9619,6 @@
[ $compiler == dart2js && $cps_ir ]
Language/Types/Interface_Types/subtype_t09: Crash # Pending static: JSArray
LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Timeout
-LibTest/core/Invocation/isAccessor_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
LibTest/core/Invocation/isGetter_A01_t01: RuntimeError # Please triage this failure.
-LibTest/core/Invocation/isGetter_A01_t02: RuntimeError # Please triage this failure.
-LibTest/core/Invocation/isMethod_A01_t02: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
-LibTest/core/Invocation/isSetter_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
LibTest/core/Invocation/isSetter_A01_t02: RuntimeError # Please triage this failure.
-LibTest/core/Invocation/memberName_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
-LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError # Please triage this failure.
-LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # Please triage this failure.
+LibTest/core/Invocation/memberName_A01_t01: RuntimeError # Expect.equals(expected: <Symbol("bar=")>, actual: <Symbol("bar")>) fails.
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status
index 502bd58..eb8f2c5 100644
--- a/tests/co19/co19-dartium.status
+++ b/tests/co19/co19-dartium.status
@@ -462,8 +462,6 @@
LayoutTests/fast/mediastream/RTCPeerConnection-AddRemoveStream_t01: Skip # Issue 22111
LayoutTests/fast/mediastream/RTCPeerConnection-AddRemoveStream_t01: Skip # Passes on Safari, Issue 23475 # co19 issue 11.
LayoutTests/fast/mediastream/getusermedia_t01: Skip # co19 issue 738
-LayoutTests/fast/multicol/balance-short-trailing-empty-block_t01: RuntimeError # co19-roll r801: Please triage this failure.
-LayoutTests/fast/multicol/balance-trailing-border_t01: RuntimeError # co19-roll r801: Please triage this failure.
LayoutTests/fast/multicol/balance-trailing-border_t02: RuntimeError # co19-roll r801: Please triage this failure.
LayoutTests/fast/multicol/balance-unbreakable_t01: Pass, RuntimeError # co19 issue 11.
LayoutTests/fast/multicol/break-after-always-bottom-margin_t01: RuntimeError # co19-roll r801: Please triage this failure.
@@ -507,7 +505,6 @@
LayoutTests/fast/multicol/vertical-rl/image-inside-nested-blocks-with-border_t01: RuntimeError # co19-roll r801: Please triage this failure.
LayoutTests/fast/multicol/widows_t01: Pass, RuntimeError # co19 issue 11.
LayoutTests/fast/multicol/widows_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
-LayoutTests/fast/multicol/widows_t02: RuntimeError # co19-roll r801: Please triage this failure.
LayoutTests/fast/multicol/zeroColumnCount_t01: RuntimeError # co19 issue 11.
LayoutTests/fast/overflow/child-100percent-height-inside-fixed-container-with-overflow-auto_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
LayoutTests/fast/overflow/child-100percent-height-inside-fixed-container-with-overflow-auto_t01: RuntimeError # co19 issue 11.
@@ -702,7 +699,6 @@
LayoutTests/fast/xpath/attr-namespace_t02: RuntimeError # co19-roll r786: Please triage this failure.
LayoutTests/fast/xpath/ensure-null-namespace_t01: RuntimeError # co19-roll r761: Please triage this failure.
LayoutTests/fast/xpath/implicit-node-args_t01: RuntimeError # co19-roll r761: Please triage this failure.
-LayoutTests/fast/xpath/invalid-resolver_t01: RuntimeError # co19-roll r761: Please triage this failure.
LayoutTests/fast/xpath/node-name-case-sensitivity_t01: RuntimeError # co19-roll r761: Please triage this failure.
LayoutTests/fast/xpath/node-name-case-sensitivity_t02: RuntimeError # co19-roll r786: Please triage this failure.
LayoutTests/fast/xpath/position_t01: RuntimeError # co19-roll r761: Please triage this failure.
@@ -731,7 +727,6 @@
LibTest/html/Element/focus_A01_t01: Skip # co19-roll r706. Please triage this failure.
LibTest/html/Element/getAttributeNS_A01_t01: RuntimeError # co19-roll r706. Issue 16395
LibTest/html/Element/getAttributeNS_A01_t02: RuntimeError # Please triage this failure.
-LibTest/html/Element/getClientRects_A01_t02: RuntimeError # co19-roll r706. Issue 16575
LibTest/html/Element/getNamespacedAttributes_A01_t01: RuntimeError # co19-roll r706. Issue 16395
LibTest/html/Element/isContentEditable_A01_t01: RuntimeError # co19-roll r706. Please triage this failure.
LibTest/html/Element/isContentEditable_A02_t01: RuntimeError # co19-roll r706. Please triage this failure.
@@ -763,7 +758,6 @@
LibTest/html/IFrameElement/createShadowRoot_A01_t01: RuntimeError # co19-roll r706. Please triage this failure.
LibTest/html/IFrameElement/enteredView_A01_t01: Skip # co19-roll r706. Please triage this failure.
LibTest/html/IFrameElement/focus_A01_t01: Skip # co19-roll r706. Please triage this failure.
-LibTest/html/IFrameElement/getClientRects_A01_t02: RuntimeError # co19-roll r706. Please triage this failure.
LibTest/html/IFrameElement/getNamespacedAttributes_A01_t01: RuntimeError # co19-roll r706. Please triage this failure.
LibTest/html/IFrameElement/innerHtml_A01_t01: RuntimeError # co19-roll r706. Please triage this failure.
LibTest/html/IFrameElement/isContentEditable_A01_t01: RuntimeError # co19-roll r706. Please triage this failure.
@@ -780,7 +774,6 @@
LibTest/html/Node/nodes_A01_t02: RuntimeError # co19-roll r722: Please triage this failure.
LibTest/html/Node/parent_A01_t01: RuntimeError # co19-roll r722: Please triage this failure.
LibTest/html/Node/previousNode_A01_t01: RuntimeError # co19-roll r722: Please triage this failure.
-LibTest/html/Window/close_A01_t01: RuntimeError # co19-roll r706. Please triage this failure.
LibTest/html/Window/find_A01_t01: RuntimeError # co19-roll r706. Please triage this failure.
LibTest/html/Window/find_A03_t01: RuntimeError # co19-roll r706. Please triage this failure.
LibTest/html/Window/find_A06_t01: RuntimeError # co19-roll r706. Please triage this failure.
@@ -863,12 +856,12 @@
LibTest/isolate/ReceivePort/transform_A01_t02: RuntimeError, OK # Uses Isolate.spawn.
LibTest/isolate/ReceivePort/where_A01_t01: RuntimeError, OK # Uses Isolate.spawn.
LibTest/isolate/ReceivePort/where_A01_t02: RuntimeError, OK # Uses Isolate.spawn.
+LibTest/isolate/ReceivePort/close_A01_t01: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
LibTest/isolate/ReceivePort/asBroadcastStream_A01_t02: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
LibTest/isolate/ReceivePort/asBroadcastStream_A02_t01: RuntimeError # Issue 13921
LibTest/isolate/ReceivePort/asBroadcastStream_A03_t01: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
LibTest/isolate/ReceivePort/asBroadcastStream_A03_t02: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
LibTest/isolate/ReceivePort/asBroadcastStream_A03_t03: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
-LibTest/isolate/ReceivePort/close_A01_t01: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
LibTest/isolate/ReceivePort/close_A02_t01: Pass, RuntimeError # Issue 13921, co19 issue for false pass https://github.com/dart-lang/co19/issues/13
LibTest/isolate/ReceivePort/sendPort_A01_t01: RuntimeError # Issue 13921
LibTest/isolate/SendPort/send_A01_t01: RuntimeError, OK # Uses Isolate.spawn.
@@ -1050,8 +1043,6 @@
WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-009_t01: RuntimeError # Please triage this failure.
WebPlatformTest/webstorage/event_constructor_t01: RuntimeError # co19-roll r761: Please triage this failure.
WebPlatformTest/webstorage/event_constructor_t02: RuntimeError # co19-roll r761: Please triage this failure.
-WebPlatformTest/webstorage/event_local_key_t01: RuntimeError # co19-roll r761: Please triage this failure.
-WebPlatformTest/webstorage/event_session_key_t01: RuntimeError # co19-roll r761: Please triage this failure.
WebPlatformTest/webstorage/storage_local_setitem_quotaexceedederr_t01: Skip # Times out flakily. co19-roll r761: Please triage this failure.
WebPlatformTest/webstorage/storage_session_setitem_quotaexceedederr_t01: Skip # Times out flakily. co19-roll r761: Please triage this failure.
@@ -1130,6 +1121,7 @@
LayoutTests/fast/text/line-break-after-inline-latin1_t01: RuntimeError # co19-roll r786: Please triage this failure.
LayoutTests/fast/url/trivial-segments_t01: RuntimeError # co19-roll r786: Please triage this failure.
LayoutTests/fast/url/trivial_t01: RuntimeError # co19-roll r786: Please triage this failure.
+LayoutTests/fast/xpath/invalid-resolver_t01: RuntimeError # https://github.com/dart-lang/co19/issues/21
LayoutTests/fast/xpath/xpath-result-eventlistener-crash_t01: RuntimeError # co19-roll r761: Please triage this failure.
LibTest/html/Node/ownerDocument_A01_t01: RuntimeError # co19-roll r722: Issue 18251
WebPlatformTest/DOMEvents/approved/Propagation.path.target.removed_t01: RuntimeError # co19-roll r738: Please triage this failure.
@@ -1258,50 +1250,49 @@
LayoutTests/fast/canvas/webgl/viewport-unchanged-upon-resize_t01: RuntimeError # Issue 25653
LayoutTests/fast/canvas/webgl/webgl-depth-texture_t01: RuntimeError # Please triage this failure
-[ $compiler == none && $runtime == dartium && $system != macos ]
-LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/attrib-location-length-limits_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/buffer-bind-test_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/attrib-location-length-limits_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/buffer-bind-test_t01: Pass, RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/buffer-data-array-buffer_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/canvas-test_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/canvas-zero-size_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/compressed-tex-image_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/context-destroyed-crash_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/css-webkit-canvas-repaint_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/css-webkit-canvas_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/context-destroyed-crash_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/css-webkit-canvas-repaint_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/css-webkit-canvas_t01: Pass, RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/draw-arrays-out-of-bounds_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/draw-elements-out-of-bounds_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/error-reporting_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/error-reporting_t01: Pass, RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/framebuffer-bindings-unaffected-on-resize_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/functions-returning-strings_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/get-active-test_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-enable-enum-test_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/framebuffer-test_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/functions-returning-strings_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/get-active-test_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-enable-enum-test_t01: Pass, RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/gl-enum-tests_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-get-calls_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-getshadersource_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-getstring_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-get-calls_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-getshadersource_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-getstring_t01: Pass, RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/gl-teximage_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/gl-uniformmatrix4fv_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/gl-vertex-attrib-zero-issues_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/gl-vertex-attrib_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-vertexattribpointer_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/glsl-conformance_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-vertexattribpointer_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/glsl-conformance_t01: Pass, RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/index-validation-copies-indices_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/index-validation-crash-with-buffer-sub-data_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/index-validation-verifies-too-many-indices_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/index-validation-with-resized-buffer_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/index-validation_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/invalid-UTF-16_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/invalid-UTF-16_t01: Pass, RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/invalid-passed-params_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/null-uniform-location_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/object-deletion-behaviour_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/oes-element-index-uint_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/program-test_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/renderer-and-vendor-strings_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/shader-precision-format_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/renderer-and-vendor-strings_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/shader-precision-format_t01: Pass, RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-array-buffer-view_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgb565_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas-rgba4444_t01: RuntimeError # Issue 22026
@@ -1321,24 +1312,86 @@
LayoutTests/fast/canvas/webgl/tex-sub-image-cube-maps_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/texImageTest_t01: RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/texture-transparent-pixels-initialized_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/uniform-location-length-limits_t01: RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/uniform-location-length-limits_t01: Pass, RuntimeError # Issue 22026
LayoutTests/fast/canvas/webgl/uninitialized-test_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-composite-modes-repaint_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-composite-modes_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-exceptions_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-layer-update_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-specific_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-unprefixed-context-id_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/webgl-viewport-parameters-preserved_t01: RuntimeError # Issue 22026
-LayoutTests/fast/canvas/webgl/gl-object-get-calls_t01: RuntimeError # Issue 20, 22026
-LayoutTests/fast/canvas/webgl/incorrect-context-object-behaviour_t01: RuntimeError # Issue 20, 22026
-LayoutTests/fast/canvas/webgl/null-object-behaviour_t01: RuntimeError # Issue 20, 22026
-LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: RuntimeError # Issue 20, 22026
+LayoutTests/fast/canvas/webgl/webgl-composite-modes-repaint_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-composite-modes_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-exceptions_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-layer-update_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-specific_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-unprefixed-context-id_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/webgl-viewport-parameters-preserved_t01: Pass, RuntimeError # Issue 22026
+LayoutTests/fast/canvas/webgl/gl-object-get-calls_t01: RuntimeError # Pass, Issue 20, 22026
+LayoutTests/fast/canvas/webgl/incorrect-context-object-behaviour_t01: Pass, RuntimeError # Issue 20, 22026
+LayoutTests/fast/canvas/webgl/null-object-behaviour_t01: Pass, RuntimeError # Issue 20, 22026
+LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: Pass, RuntimeError # Issue 20, 22026
LayoutTests/fast/canvas/webgl/context-lost_t01: RuntimeError # Issue 20, 22026
LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Issue 20, 22026
LayoutTests/fast/canvas/webgl/invalid-passed-params_t01: RuntimeError # Issue 20, 22026
LayoutTests/fast/canvas/webgl/tex-input-validation_t01: RuntimeError # Issue 20, 22026
-LayoutTests/fast/canvas/webgl/tex-sub-image-2d-bad-args_t01: RuntimeError # Issue 20, 22026
+LayoutTests/fast/canvas/webgl/tex-sub-image-2d-bad-args_t01: Pass, RuntimeError # Issue 20, 22026
+
+LayoutTests/fast/canvas/alpha_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/canvas/canvas-lineDash-input-sequence_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-replaced-absolutes_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/MarqueeLayoutTest_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/aspect-ratio-inheritance_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/aspect-ratio-parsing-tests_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/auto-min-size_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/background-position-serialize_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-case-insensitivity_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-dynamically-added_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-dynamically-removed_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-mapped-to-webkit-locale_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-multiple_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/content-language-no-content_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/counters/counter-cssText_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/cssText-shorthand_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/csstext-of-content-string_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/ex-unit-with-no-x-height_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/font-shorthand-from-longhands_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/getComputedStyle/computed-style-font_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/getComputedStyle/computed-style-properties_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/getComputedStyle/counterIncrement-without-counter_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/getPropertyValue-columns_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/image-set-setting_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/important-js-override_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/nested-at-rules_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/parse-color-int-or-percent-crash_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/parsing-css-allowed-string-characters_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/parsing-css-nth-child_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/parsing-text-rendering_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/pseudo-valid-unapplied_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/string-quote-binary_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css/transform-origin-parsing_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/background-shorthand-csstext_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/css-selectorText_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/custom/element-names_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/fragment-activation-focuses-target_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/shadow/content-reprojection-fallback-crash_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/shadow/shadow-disable_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/dom/shadow/shadow-root-js-api_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/encoding/css-charset-dom_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/events/overflowchanged-event-raf-timing_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/files/blob-constructor_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/files/file-reader-fffd_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/forms/ValidityState-customError_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/forms/input-value-sanitization_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/forms/validationMessage_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/innerHTML/javascript-url_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/multicol/columns-shorthand-parsing_t02: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-anonymous-table-cell_t01: RuntimeError # Dartium 45 roll. Issue 25754
+WebPlatformTest/html/semantics/forms/textfieldselection/selection_t01: RuntimeError # Dartium 45 roll. Issue 25754
+WebPlatformTest/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-001_t01: RuntimeError # Dartium 45 roll. Issue 25754
+WebPlatformTest/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-002_t01: RuntimeError # Dartium 45 roll. Issue 25754
+WebPlatformTest/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-005_t01: RuntimeError # Dartium 45 roll. Issue 25754
+WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002_t01: RuntimeError # Dartium 45 roll. Issue 25754
+LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-replaced-absolutes_t01: Timeout # Dartium 45 roll. Issue 25754
+LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-anonymous-table-cell_t01: Timeout # Dartium 45 roll. Issue 25754
+LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-table-cell-ignore-height_t01: Timeout # Dartium 45 roll. Issue 25754
+LayoutTests/fast/events/change-overflow-on-overflow-change_t01: Timeout # Dartium 45 roll. Issue 25754
+LayoutTests/fast/loader/onload-policy-ignore-for-frame_t01: Timeout # Dartium 45 roll. Issue 25754
[ $compiler == none && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $system != windows ]
LayoutTests/fast/css/font-face-unicode-range-monospace_t01: RuntimeError # co19-roll r761: Please triage this failure.
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index ae94df1..322d664 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -59,11 +59,13 @@
[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $mode == debug ]
LibTest/core/List/List_class_A01_t02: Pass, Slow
-[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch != x64 && $arch != simarm64) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch != x64 && $arch != simarm64 && $arch != arm64) ]
LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
-[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && $arch == mips ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch == mips) ]
LibTest/core/double/toInt_A01_t01: Fail
+
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch == mips || $arch == arm64) ]
# 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
LibTest/core/List/List_class_A01_t02: Skip # co19 issue 673
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_1.js b/tests/compiler/dart2js/cps_ir/expected/basic_1.js
index 5ae55be..f8384d4 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_1.js
@@ -19,9 +19,9 @@
P.print("()");
P.print("(true)");
P.print("(1)");
- P.print("(" + P.IterableBase_iterableToFullString([1, 2, 3], "[", "]") + ")");
+ P.print("(" + H.S([1, 2, 3]) + ")");
P.print("(" + P.Maps_mapToString(P.LinkedHashMap__makeLiteral(["s", 1])) + ")");
P.print("(1)");
- P.print("(" + P.IterableBase_iterableToFullString(l, "[", "]") + ")");
+ P.print("(" + H.S(l) + ")");
P.print("(" + P.Maps_mapToString(m) + ")");
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_10.js b/tests/compiler/dart2js/cps_ir/expected/basic_10.js
index 104f614..745bc50 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_10.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_10.js
@@ -4,7 +4,7 @@
// }
function() {
- var line = Date.now() < Date.now() ? "true" : "false";
+ var line = H.S(Date.now() < Date.now());
if (typeof dartPrint == "function")
dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_11.js b/tests/compiler/dart2js/cps_ir/expected/basic_11.js
index 5f26f1c..68995ca 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_11.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_11.js
@@ -3,14 +3,13 @@
// main() { foo(); }
function() {
- var line = "" + 42;
if (typeof dartPrint == "function")
- dartPrint(line);
+ dartPrint("42");
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(line);
+ console.log("42");
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(line);
- print(line);
+ throw "Unable to print message: " + String("42");
+ print("42");
}
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_12.js b/tests/compiler/dart2js/cps_ir/expected/basic_12.js
index 084681f..ac9e1d3 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_12.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_12.js
@@ -3,7 +3,7 @@
// main() { print(foo); }
function() {
- var v0 = $.foo, line = v0 === 0 ? 1 / v0 < 0 ? "-0.0" : "" + v0 : "" + v0;
+ var line = H.S($.foo);
if (typeof dartPrint == "function")
dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_13.js b/tests/compiler/dart2js/cps_ir/expected/basic_13.js
index 218ba31..e8db598 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_13.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_13.js
@@ -3,14 +3,13 @@
// main() { foo; }
function() {
- var line = "" + 42;
if (typeof dartPrint == "function")
- dartPrint(line);
+ dartPrint("42");
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(line);
+ console.log("42");
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(line);
- print(line);
+ throw "Unable to print message: " + String("42");
+ print("42");
}
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_14.js b/tests/compiler/dart2js/cps_ir/expected/basic_14.js
index a42876b..068816d 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_14.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_14.js
@@ -3,15 +3,14 @@
// main() { print(foo = 42); }
function() {
- var line = "" + 42;
$.foo = 42;
if (typeof dartPrint == "function")
- dartPrint(line);
+ dartPrint("42");
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(line);
+ console.log("42");
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(line);
- print(line);
+ throw "Unable to print message: " + String("42");
+ print("42");
}
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_15.js b/tests/compiler/dart2js/cps_ir/expected/basic_15.js
index ea86609..92ba7b0 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_15.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_15.js
@@ -3,14 +3,13 @@
// main() { foo = 42; }
function() {
- var line = "" + 42;
if (typeof dartPrint == "function")
- dartPrint(line);
+ dartPrint("42");
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(line);
+ console.log("42");
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(line);
- print(line);
+ throw "Unable to print message: " + String("42");
+ print("42");
}
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_4.js b/tests/compiler/dart2js/cps_ir/expected/basic_4.js
index 68f024f..8ce632a 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_4.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_4.js
@@ -3,15 +3,14 @@
// main() { return foo(); }
function() {
- var line = "" + 42;
if (typeof dartPrint == "function")
- dartPrint(line);
+ dartPrint("42");
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(line);
+ console.log("42");
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(line);
- print(line);
+ throw "Unable to print message: " + String("42");
+ print("42");
}
return 42;
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_9.js b/tests/compiler/dart2js/cps_ir/expected/basic_9.js
index b47ad6a..c23788a 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_9.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_9.js
@@ -5,14 +5,14 @@
// }
function() {
- var res = "Instance of '" + H.Primitives_objectTypeName(V.C$()) + "'";
+ var line = "Instance of '" + H.Primitives_objectTypeName(V.C$()) + "'";
if (typeof dartPrint == "function")
- dartPrint(res);
+ dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(res);
+ console.log(line);
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(res);
- print(res);
+ throw "Unable to print message: " + String(line);
+ print(line);
}
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/closures_5.js b/tests/compiler/dart2js/cps_ir/expected/closures_5.js
index 959b14a..3c61ff5 100644
--- a/tests/compiler/dart2js/cps_ir/expected/closures_5.js
+++ b/tests/compiler/dart2js/cps_ir/expected/closures_5.js
@@ -7,7 +7,7 @@
// }
function() {
- var _captured_x_0 = 122 + 1, line = _captured_x_0 === 0 ? 1 / _captured_x_0 < 0 ? "-0.0" : "" + _captured_x_0 : "" + _captured_x_0;
+ var line = H.S(122 + 1);
if (typeof dartPrint == "function")
dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/closures_7.js b/tests/compiler/dart2js/cps_ir/expected/closures_7.js
index 4a16c92..62f16ad 100644
--- a/tests/compiler/dart2js/cps_ir/expected/closures_7.js
+++ b/tests/compiler/dart2js/cps_ir/expected/closures_7.js
@@ -10,7 +10,7 @@
// }
function() {
- var _captured_x_0 = 122 + 1, line = _captured_x_0 === 0 ? 1 / _captured_x_0 < 0 ? "-0.0" : "" + _captured_x_0 : "" + _captured_x_0;
+ var line = H.S(122 + 1);
if (typeof dartPrint == "function")
dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_1.js b/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_1.js
index 92a1969..9043a3f 100644
--- a/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_1.js
@@ -5,14 +5,13 @@
// }
function() {
- var line = "" + 65;
if (typeof dartPrint == "function")
- dartPrint(line);
+ dartPrint("65");
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(line);
+ console.log("65");
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(line);
- print(line);
+ throw "Unable to print message: " + String("65");
+ print("65");
}
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/constructor_1.js b/tests/compiler/dart2js/cps_ir/expected/constructor_1.js
index 21493c2..6afa3a3 100644
--- a/tests/compiler/dart2js/cps_ir/expected/constructor_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/constructor_1.js
@@ -12,7 +12,7 @@
// }
function() {
- var line = 1 === 0 ? 1 / 1 < 0 ? "-0.0" : "" + 1 : "" + 1;
+ var line = H.S(1);
if (typeof dartPrint == "function")
dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/constructor_11.js b/tests/compiler/dart2js/cps_ir/expected/constructor_11.js
index 9c0d6d0..3221867 100644
--- a/tests/compiler/dart2js/cps_ir/expected/constructor_11.js
+++ b/tests/compiler/dart2js/cps_ir/expected/constructor_11.js
@@ -9,7 +9,7 @@
// }
function() {
- var line = 1 === 0 ? 1 / 1 < 0 ? "-0.0" : "" + 1 : "" + 1;
+ var line = H.S(1);
if (typeof dartPrint == "function")
dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/constructor_13.js b/tests/compiler/dart2js/cps_ir/expected/constructor_13.js
index 074cf69..a95670c 100644
--- a/tests/compiler/dart2js/cps_ir/expected/constructor_13.js
+++ b/tests/compiler/dart2js/cps_ir/expected/constructor_13.js
@@ -9,14 +9,14 @@
// }
function() {
- var res = "Instance of '" + H.Primitives_objectTypeName(new V.Foo(5)) + "'";
+ var line = "Instance of '" + H.Primitives_objectTypeName(new V.Foo(5)) + "'";
if (typeof dartPrint == "function")
- dartPrint(res);
+ dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(res);
+ console.log(line);
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(res);
- print(res);
+ throw "Unable to print message: " + String(line);
+ print(line);
}
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/gvn_1.js b/tests/compiler/dart2js/cps_ir/expected/gvn_1.js
index 1307a74..5e14c5c 100644
--- a/tests/compiler/dart2js/cps_ir/expected/gvn_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/gvn_1.js
@@ -45,7 +45,7 @@
for (; k < 10; sum += i + v0[v1], ++k)
if (v1 < 0 || v1 >= 10)
return H.ioore(v0, v1);
- line = sum === 0 ? 1 / sum < 0 ? "-0.0" : "" + sum : "" + sum;
+ line = H.S(sum);
if (typeof dartPrint == "function")
dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/interceptors_1.js b/tests/compiler/dart2js/cps_ir/expected/interceptors_1.js
index ed58ff0..a8df9d1 100644
--- a/tests/compiler/dart2js/cps_ir/expected/interceptors_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/interceptors_1.js
@@ -7,14 +7,13 @@
// }
function() {
- var line = "" + 4;
if (typeof dartPrint == "function")
- dartPrint(line);
+ dartPrint("4");
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(line);
+ console.log("4");
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(line);
- print(line);
+ throw "Unable to print message: " + String("4");
+ print("4");
}
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators_4.js b/tests/compiler/dart2js/cps_ir/expected/operators_4.js
index 837c082..65acae6 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators_4.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators_4.js
@@ -6,16 +6,12 @@
function() {
var v0 = $.x + 1, line;
$.x = v0;
- L0: {
- if (v0 > 10) {
- $.x = v0 = $.x + 1;
- if (v0 > 10) {
- line = "true";
- break L0;
- }
- }
- line = "false";
- }
+ if (v0 > 10) {
+ $.x = v0 = $.x + 1;
+ v0 = v0 > 10;
+ } else
+ v0 = false;
+ line = H.S(v0);
if (typeof dartPrint == "function")
dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators_5.js b/tests/compiler/dart2js/cps_ir/expected/operators_5.js
index d2986cc..df02418 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators_5.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators_5.js
@@ -6,16 +6,13 @@
function() {
var v0 = $.x + 1, line;
$.x = v0;
- L0: {
- if (!(v0 > 10)) {
- $.x = v0 = $.x + 1;
- if (!(v0 > 10)) {
- line = "false";
- break L0;
- }
- }
- line = "true";
+ if (v0 > 10)
+ v0 = true;
+ else {
+ $.x = v0 = $.x + 1;
+ v0 = v0 > 10;
}
+ line = H.S(v0);
if (typeof dartPrint == "function")
dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators_7.js b/tests/compiler/dart2js/cps_ir/expected/operators_7.js
index b81aaa9..9b278bf 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators_7.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators_7.js
@@ -10,15 +10,14 @@
// }
function() {
- var line = "" + 6;
V.Foo$();
if (typeof dartPrint == "function")
- dartPrint(line);
+ dartPrint("6");
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(line);
+ console.log("6");
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(line);
- print(line);
+ throw "Unable to print message: " + String("6");
+ print("6");
}
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators_8.js b/tests/compiler/dart2js/cps_ir/expected/operators_8.js
index 3f1c27e..908c5f3 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators_8.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators_8.js
@@ -6,16 +6,16 @@
// }
function() {
- var list = [1, 2, 3], res;
+ var list = [1, 2, 3], line;
list[1] = 6;
- res = P.IterableBase_iterableToFullString(list, "[", "]");
+ line = H.S(list);
if (typeof dartPrint == "function")
- dartPrint(res);
+ dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
- console.log(res);
+ console.log(line);
else if (!(typeof window == "object")) {
if (!(typeof print == "function"))
- throw "Unable to print message: " + String(res);
- print(res);
+ throw "Unable to print message: " + String(line);
+ print(line);
}
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js b/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js
index 21c1d71..1b8c351 100644
--- a/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js
+++ b/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js
@@ -5,13 +5,16 @@
// // This example illustrates a case we wish to do better in terms of inlining and
// // code generation.
// //
-// // Today this function is compiled without inlining Wrapper.[], JSArray.[] and
-// // Wrapper.[]= because:
+// // Naively this function would be compiled without inlining Wrapper.[],
+// // JSArray.[] and Wrapper.[]= because:
// // JSArray.[] is too big (14 nodes)
// // Wrapper.[] is too big if we force inlining of JSArray (15 nodes)
// // Wrapper.[]= is even bigger (46 nodes)
// //
-// // See #25478 for ideas on how to make this better.
+// // We now do specialization of [] and []= by adding guards and injecting builtin
+// // operators. This made it possible to inline []. We still don't see []= inlined
+// // yet, that might require that we improve the inlining counting heuristics a
+// // bit.
// @NoInline()
// test(data, x) {
// data[x + 1] = data[x];
@@ -33,5 +36,8 @@
// }
function(data, x) {
- data.$indexSet(0, J.$add$ns(x, 1), C.JSArray_methods.$index(data.arr, x));
+ var v0 = J.$add$ns(x, 1), v1 = data.arr;
+ if (x >>> 0 !== x || x >= v1.length)
+ return H.ioore(v1, x);
+ data.$indexSet(0, v0, v1[x]);
}
diff --git a/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js b/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js
index a3a2ae0..211aec6 100644
--- a/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js
+++ b/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js
@@ -27,7 +27,7 @@
function() {
var a = V.nextNumber();
- if (!(typeof a === "number" && Math.floor(a) === a))
+ if (typeof a !== "number" || Math.floor(a) !== a)
throw H.wrapException("error 1");
a += 5;
V.action(a);
diff --git a/tests/compiler/dart2js/cps_ir/expected/supercall_3.js b/tests/compiler/dart2js/cps_ir/expected/supercall_3.js
index ffc1752..f45afaf 100644
--- a/tests/compiler/dart2js/cps_ir/expected/supercall_3.js
+++ b/tests/compiler/dart2js/cps_ir/expected/supercall_3.js
@@ -10,7 +10,7 @@
// }
function() {
- var line = "" + (10 + V.Sub$().field);
+ var line = H.S(10 + V.Sub$().field);
if (typeof dartPrint == "function")
dartPrint(line);
else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart b/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart
index 084bc34..8150653 100644
--- a/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart
+++ b/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart
@@ -4,13 +4,16 @@
// This example illustrates a case we wish to do better in terms of inlining and
// code generation.
//
-// Today this function is compiled without inlining Wrapper.[], JSArray.[] and
-// Wrapper.[]= because:
+// Naively this function would be compiled without inlining Wrapper.[],
+// JSArray.[] and Wrapper.[]= because:
// JSArray.[] is too big (14 nodes)
// Wrapper.[] is too big if we force inlining of JSArray (15 nodes)
// Wrapper.[]= is even bigger (46 nodes)
//
-// See #25478 for ideas on how to make this better.
+// We now do specialization of [] and []= by adding guards and injecting builtin
+// operators. This made it possible to inline []. We still don't see []= inlined
+// yet, that might require that we improve the inlining counting heuristics a
+// bit.
@NoInline()
test(data, x) {
data[x + 1] = data[x];
diff --git a/tests/compiler/dart2js/diagnostic_helper.dart b/tests/compiler/dart2js/diagnostic_helper.dart
index 26dac30..c9b19e1 100644
--- a/tests/compiler/dart2js/diagnostic_helper.dart
+++ b/tests/compiler/dart2js/diagnostic_helper.dart
@@ -25,7 +25,7 @@
CollectedMessage(
this.message, this.uri, this.begin, this.end, this.text, this.kind);
- MessageKind get messageKind => message.kind;
+ MessageKind get messageKind => message?.kind;
String toString() {
return '${message != null ? message.kind : ''}'
diff --git a/tests/compiler/dart2js/message_span_test.dart b/tests/compiler/dart2js/message_span_test.dart
new file mode 100644
index 0000000..655b814
--- /dev/null
+++ b/tests/compiler/dart2js/message_span_test.dart
@@ -0,0 +1,182 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/diagnostics/messages.dart';
+import 'package:compiler/src/io/source_file.dart';
+import 'package:expect/expect.dart';
+import 'memory_compiler.dart';
+import 'memory_source_file_helper.dart';
+
+const List<Test> TESTS = const <Test>[
+ const Test('''
+class A { A(b); }
+class B extends A {
+ a() {}
+
+ lot() {}
+
+ of() {}
+
+ var members;
+}
+main() => new B();''',
+ const {
+ MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT: '''
+class B extends A {
+^^^^^^^^^^^^^^^^^'''}),
+
+ const Test('''
+class I {}
+class A { A(b); }
+class B extends A implements I {
+ a() {}
+
+ lot() {}
+
+ of() {}
+
+ var members;
+}
+main() => new B();''',
+ const {
+ MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT: '''
+class B extends A implements I {
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^'''}),
+
+ const Test('''
+class M<T> {}
+class A { A(b); }
+class B extends A with M<int> {
+ a() {}
+
+ lot() {}
+
+ of() {}
+
+ var members;
+}
+main() => new B();''',
+ const {
+ MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT: '''
+class B extends A with M<int> {
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^'''}),
+
+ const Test('''
+class A { A(b); }
+class B
+ extends A {
+ a() {}
+
+ lot() {}
+
+ of() {}
+
+ var members;
+}
+main() => new B();''',
+ const {
+ MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT: '''
+class B
+ extends A {
+'''}),
+
+ const Test('''
+void foo(int a) {
+ // a
+ // non-empty
+ // body
+}
+main() => foo('');''',
+ const {
+ MessageKind.THIS_IS_THE_METHOD: '''
+void foo(int a) {
+^^^^^^^^^^^^^^^'''}),
+
+ const Test('''
+void foo(int a,
+ int b) {
+ // a
+ // non-empty
+ // body
+}
+main() => foo('', 0);''',
+ const {
+ MessageKind.THIS_IS_THE_METHOD: '''
+void foo(int a,
+ int b) {
+'''}),
+
+ const Test('''
+class A {
+ int foo() {
+ // a
+ // non-empty
+ // body
+ }
+}
+class B extends A {
+ int get foo {
+ // a
+ // non-empty
+ // body
+ return 0;
+ }
+}
+main() => new B();''',
+ const {
+ MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER: '''
+ int get foo {
+ ^^^^^^^^^^^''',
+ MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT: '''
+ int foo() {
+ ^^^^^^^^^'''}),
+];
+
+class Test {
+ final String code;
+ final Map<MessageKind, String> kindToSpan;
+
+ const Test(this.code, this.kindToSpan);
+}
+
+const String MARKER = '---marker---';
+
+main() {
+ asyncTest(() async {
+ var cachedCompiler;
+ for (Test test in TESTS) {
+ DiagnosticCollector collector = new DiagnosticCollector();
+ CompilationResult result = await runCompiler(
+ memorySourceFiles: {'main.dart': test.code},
+ options: [Flags.analyzeOnly],
+ diagnosticHandler: collector,
+ cachedCompiler: cachedCompiler);
+ cachedCompiler = result.compiler;
+ MemorySourceFileProvider provider = cachedCompiler.provider;
+ Map<MessageKind, String> kindToSpan =
+ new Map<MessageKind, String>.from(test.kindToSpan);
+ for (CollectedMessage message in collector.messages) {
+ String expectedSpanText = kindToSpan[message.messageKind];
+ if (expectedSpanText != null) {
+ SourceFile sourceFile = provider.getSourceFile(message.uri);
+ String locationMessage =
+ sourceFile.getLocationMessage(MARKER, message.begin, message.end);
+ // Remove `filename:line:column:` and message.
+ String strippedLocationMessage = locationMessage.substring(
+ locationMessage.indexOf(MARKER) + MARKER.length + 1);
+ Expect.equals(expectedSpanText, strippedLocationMessage,
+ "Unexpected span for ${message.messageKind} in\n${test.code}"
+ "\nExpected:${expectedSpanText.codeUnits}"
+ "\nActual :${strippedLocationMessage.codeUnits}");
+ kindToSpan.remove(message.messageKind);
+ }
+ }
+ kindToSpan.forEach((MessageKind kind, _) {
+ Expect.fail("Missing message kin $kind in\n${test.code}");
+ });
+ }
+ });
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/type_variable_bound_test.dart b/tests/compiler/dart2js/type_variable_bound_test.dart
index d8a6903..544d664 100644
--- a/tests/compiler/dart2js/type_variable_bound_test.dart
+++ b/tests/compiler/dart2js/type_variable_bound_test.dart
@@ -17,141 +17,136 @@
});
}
-test(String source, {var errors, var warnings}) {
+Future test(String source, {var errors, var warnings}) async{
if (errors == null) errors = [];
if (errors is! List) errors = [errors];
if (warnings == null) warnings = [];
if (warnings is! List) warnings = [warnings];
- asyncTest(() => compile(source).then((compiler) {
- DiagnosticCollector collector = compiler.diagnosticCollector;
- Expect.equals(!errors.isEmpty, compiler.compilationFailed);
- Expect.equals(errors.length, collector.errors.length,
- 'unexpected error count: ${collector.errors.length} '
- 'expected ${errors.length}');
- Expect.equals(warnings.length, collector.warnings.length,
- 'unexpected warning count: ${collector.warnings.length} '
- 'expected ${warnings.length}');
+ var compiler = await compile(source);
+ DiagnosticCollector collector = compiler.diagnosticCollector;
+ Expect.equals(!errors.isEmpty, compiler.compilationFailed);
+ Expect.equals(errors.length, collector.errors.length,
+ 'unexpected error count: ${collector.errors.length} '
+ 'expected ${errors.length}');
+ Expect.equals(warnings.length, collector.warnings.length,
+ 'unexpected warning count: ${collector.warnings.length} '
+ 'expected ${warnings.length}');
- for (int i = 0 ; i < errors.length ; i++) {
- Expect.equals(errors[i], collector.errors.elementAt(i).message.kind);
- }
- for (int i = 0 ; i < warnings.length ; i++) {
- Expect.equals(warnings[i], collector.warnings.elementAt(i).message.kind);
- }
- }));
+ for (int i = 0 ; i < errors.length ; i++) {
+ Expect.equals(errors[i], collector.errors.elementAt(i).message.kind);
+ }
+ for (int i = 0 ; i < warnings.length ; i++) {
+ Expect.equals(warnings[i], collector.warnings.elementAt(i).message.kind);
+ }
}
-test1() {
- asyncTest(() => compile(r"""
+Future test1() async {
+ var compiler = await compile(r"""
class A<T extends T> {}
void main() {
new A();
}
-""").then((compiler) {
- DiagnosticCollector collector = compiler.diagnosticCollector;
- Expect.isFalse(compiler.compilationFailed);
- Expect.isTrue(collector.errors.isEmpty,
- 'unexpected errors: ${collector.errors}');
- Expect.equals(1, collector.warnings.length,
- 'expected exactly one warning, but got ${collector.warnings}');
+""");
+ DiagnosticCollector collector = compiler.diagnosticCollector;
+ Expect.isFalse(compiler.compilationFailed);
+ Expect.isTrue(collector.errors.isEmpty,
+ 'unexpected errors: ${collector.errors}');
+ Expect.equals(1, collector.warnings.length,
+ 'expected exactly one warning, but got ${collector.warnings}');
- print(collector.warnings.elementAt(0));
- Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
- collector.warnings.elementAt(0).message.kind);
- Expect.equals("T",
- collector.warnings.elementAt(0).message.arguments['typeVariableName']);
- }));
+ print(collector.warnings.elementAt(0));
+ Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+ collector.warnings.elementAt(0).message.kind);
+ Expect.equals("T",
+ collector.warnings.elementAt(0).message.arguments['typeVariableName']);
}
-test2() {
- asyncTest(() => compile(r"""
+Future test2() async {
+ var compiler = await compile(r"""
class B<T extends S, S extends T> {}
void main() {
new B();
}
-""").then((compiler) {
- DiagnosticCollector collector = compiler.diagnosticCollector;
- Expect.isFalse(compiler.compilationFailed);
- print(collector.errors);
- Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
- Expect.equals(2, collector.warnings.length,
- 'expected exactly two errors, but got ${collector.warnings}');
+""");
+ DiagnosticCollector collector = compiler.diagnosticCollector;
+ Expect.isFalse(compiler.compilationFailed);
+ print(collector.errors);
+ Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
+ Expect.equals(2, collector.warnings.length,
+ 'expected exactly two errors, but got ${collector.warnings}');
- Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
- collector.warnings.elementAt(0).message.kind);
- Expect.equals("T",
- collector.warnings.elementAt(0).message.arguments['typeVariableName']);
+ Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+ collector.warnings.elementAt(0).message.kind);
+ Expect.equals("T",
+ collector.warnings.elementAt(0).message.arguments['typeVariableName']);
- Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
- collector.warnings.elementAt(1).message.kind);
- Expect.equals("S",
- collector.warnings.elementAt(1).message.arguments['typeVariableName']);
- }));
+ Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+ collector.warnings.elementAt(1).message.kind);
+ Expect.equals("S",
+ collector.warnings.elementAt(1).message.arguments['typeVariableName']);
}
-test3() {
- asyncTest(() => compile(r"""
+Future test3() async {
+ var compiler = await compile(r"""
class C<T extends S, S extends U, U extends T> {}
void main() {
new C();
}
-""").then((compiler) {
- DiagnosticCollector collector = compiler.diagnosticCollector;
- Expect.isFalse(compiler.compilationFailed);
- print(collector.errors);
- Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
- Expect.equals(3, collector.warnings.length,
- 'expected exactly one error, but got ${collector.warnings}');
+""");
+ DiagnosticCollector collector = compiler.diagnosticCollector;
+ Expect.isFalse(compiler.compilationFailed);
+ print(collector.errors);
+ Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
+ Expect.equals(3, collector.warnings.length,
+ 'expected exactly one error, but got ${collector.warnings}');
- Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
- collector.warnings.elementAt(0).message.kind);
- Expect.equals("T",
- collector.warnings.elementAt(0).message.arguments['typeVariableName']);
+ Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+ collector.warnings.elementAt(0).message.kind);
+ Expect.equals("T",
+ collector.warnings.elementAt(0).message.arguments['typeVariableName']);
- Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
- collector.warnings.elementAt(1).message.kind);
- Expect.equals("S",
- collector.warnings.elementAt(1).message.arguments['typeVariableName']);
+ Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+ collector.warnings.elementAt(1).message.kind);
+ Expect.equals("S",
+ collector.warnings.elementAt(1).message.arguments['typeVariableName']);
- Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
- collector.warnings.elementAt(2).message.kind);
- Expect.equals("U",
- collector.warnings.elementAt(2).message.arguments['typeVariableName']);
- }));
+ Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+ collector.warnings.elementAt(2).message.kind);
+ Expect.equals("U",
+ collector.warnings.elementAt(2).message.arguments['typeVariableName']);
}
-test4() {
- asyncTest(() => compile(r"""
+Future test4() async {
+ var compiler = await compile(r"""
class D<T extends S, S extends U, U extends S> {}
void main() {
new D();
}
-""").then((compiler) {
- DiagnosticCollector collector = compiler.diagnosticCollector;
- Expect.isFalse(compiler.compilationFailed);
- print(collector.errors);
- Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
- Expect.equals(2, collector.warnings.length,
- 'expected exactly one error, but got ${collector.warnings}');
+""");
+ DiagnosticCollector collector = compiler.diagnosticCollector;
+ Expect.isFalse(compiler.compilationFailed);
+ print(collector.errors);
+ Expect.isTrue(collector.errors.isEmpty, 'unexpected errors');
+ Expect.equals(2, collector.warnings.length,
+ 'expected exactly one error, but got ${collector.warnings}');
- Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
- collector.warnings.elementAt(0).message.kind);
- Expect.equals("S",
- collector.warnings.elementAt(0).message.arguments['typeVariableName']);
+ Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+ collector.warnings.elementAt(0).message.kind);
+ Expect.equals("S",
+ collector.warnings.elementAt(0).message.arguments['typeVariableName']);
- Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
- collector.warnings.elementAt(1).message.kind);
- Expect.equals("U",
- collector.warnings.elementAt(1).message.arguments['typeVariableName']);
- }));
+ Expect.equals(MessageKind.CYCLIC_TYPE_VARIABLE,
+ collector.warnings.elementAt(1).message.kind);
+ Expect.equals("U",
+ collector.warnings.elementAt(1).message.arguments['typeVariableName']);
}
-test5() {
- test(r"""
+Future test5() {
+ return test(r"""
class A<T extends num> {}
void main() {
@@ -164,8 +159,8 @@
""");
}
-test6() {
- test(r"""
+Future test6() {
+ return test(r"""
class A<T extends num> {}
void main() {
@@ -174,8 +169,8 @@
""", warnings: MessageKind.INVALID_TYPE_VARIABLE_BOUND);
}
-test7() {
- test(r"""
+Future test7() {
+ return test(r"""
class A<T extends num> {}
class B<T> extends A<T> {} // Warning produced here.
@@ -186,8 +181,8 @@
""", warnings: MessageKind.INVALID_TYPE_VARIABLE_BOUND);
}
-test8() {
- test(r"""
+Future test8() {
+ return test(r"""
class B<T extends B<T>> {}
class C<T extends B<T>> extends B<T> {}
class D<T extends C<T>> extends C<T> {}
@@ -213,8 +208,8 @@
""");
}
-test9() {
- test(r"""
+Future test9() {
+ return test(r"""
class B<T extends B<T>> {}
class C<T extends B<T>> extends B<T> {}
class D<T extends C<T>> extends C<T> {}
@@ -229,8 +224,8 @@
MessageKind.INVALID_TYPE_VARIABLE_BOUND]);
}
-test10() {
- test(r"""
+Future test10() {
+ return test(r"""
class A {
const A();
}
@@ -246,8 +241,8 @@
// TODO(het): The error is reported twice because both the Dart and JS constant
// compilers are run on the const constructor, investigate why.
-test11() {
- test(r"""
+Future test11() {
+ return test(r"""
class A {
const A();
}
@@ -265,15 +260,17 @@
}
main() {
- test1();
- test2();
- test3();
- test4();
- test5();
- test6();
- test7();
- test8();
- test9();
- test10();
- test11();
+ asyncTest(() async {
+ await test1();
+ await test2();
+ await test3();
+ await test4();
+ await test5();
+ await test6();
+ await test7();
+ await test8();
+ await test9();
+ await test10();
+ await test11();
+ });
}
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index dfe56d3..3a172de 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -21,6 +21,7 @@
compute_this_script_test: Skip # Issue 17458
[ $compiler == dart2js && $cps_ir ]
+foreign_test: RuntimeError # Expect.equals(expected: <1234567891011>, actual: <1234567891011>) fails.
native_exception_test: RuntimeError # Issue 24421
optimization_hints_test: RuntimeError # Please triage this failure.
subclassing_constructor_2_test: RuntimeError # Please triage this failure.
diff --git a/tests/html/html.status b/tests/html/html.status
index 8a8dae6..eaf77bd 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -18,6 +18,11 @@
native_gc_test: Skip # Dartium JSInterop failure
transferables_test: RuntimeError # Dartium JSInterop failure
+blob_constructor_test: RuntimeError # Dartium 45 roll. Issue 25754
+crypto_test/functional: RuntimeError # Dartium 45 roll. Issue 25754
+svgelement_test/constructors: RuntimeError # Dartium 45 roll. Issue 25754
+url_test: RuntimeError # Dartium 45 roll. Issue 25754
+
[ $compiler == none && ($runtime == drt || $runtime == dartium ) ]
worker_api_test: Fail # Issue 10223
resource_http_test: Fail # Issue 24203
@@ -29,6 +34,7 @@
[ $compiler == dart2js ]
input_element_test/attributes: Fail # Issue 21555
wrapping_collections_test: SkipByDesign # Testing an issue that is only relevant to Dartium
+js_typed_interop_default_arg_test/default_value: MissingCompileTimeError # Issue #25759
[ $compiler == dart2js && $checked ]
js_function_getter_trust_types_test: Skip # --trust-type-annotations incompatible with --checked
@@ -121,6 +127,9 @@
[$runtime == drt || $runtime == dartium || $runtime == chrome || $runtime == chromeOnAndroid || $runtime == ContentShellOnAndroid ]
webgl_1_test: Pass, Fail # Issue 8219
+element_animate_test/omit_timing: RuntimeError # Dartium 45 roll. Issue 25786
+element_animate_test/simple_timing: RuntimeError # Dartium 45 roll. Issue 25786
+element_animate_test/timing_dict: RuntimeError # Dartium 45 roll. Issue 25786
[ $compiler == none && ($runtime == drt || $runtime == dartium) && $system == windows ]
websql_test: Skip # Issue 4941: stderr contains a backtrace.
@@ -380,19 +389,20 @@
[ $compiler == dart2js && $csp && ($runtime == drt || $runtime == safari || $runtime == ff || $runtime == chrome || $runtime == chromeOnAndroid) ]
# Note: these tests are all injecting scripts by design. This is not allowed under CSP.
-event_customevent_test: Fail # Test cannot run under CSP restrictions.
-js_interop_1_test: Skip # Test cannot run under CSP restrictions (times out).
-js_test: Skip # Test cannot run under CSP restrictions (times out).
-js_array_test: Skip # Test cannot run under CSP restrictions.
-js_typed_interop_test: Skip # Test cannot run under CSP restrictions.
-js_function_getter_test: Skip # Test cannot run under CSP restrictions.
-js_function_getter_trust_types_test: Skip # Test cannot run under CSP restrictions.
-js_dart_to_string_test: Skip # Test cannot run under CSP restrictions.
-mirrors_js_typed_interop_test: Skip # Test cannot run under CSP restrictions.
-postmessage_structured_test: Skip # Test cannot run under CSP restrictions (times out).
+event_customevent_test: SkipByDesign
+js_interop_1_test: SkipByDesign
+js_test: SkipByDesign
+js_array_test: SkipByDesign
+js_typed_interop_test: SkipByDesign
+js_typed_interop_default_arg_test: SkipByDesign
+js_function_getter_test: SkipByDesign
+js_function_getter_trust_types_test: SkipByDesign
+js_dart_to_string_test: SkipByDesign
+mirrors_js_typed_interop_test: SkipByDesign
+postmessage_structured_test: SkipByDesign
-[ $compiler == dart2js && $runtime == chrome]
-svgelement_test/supported_altGlyph: RuntimeError # Issue 23144
+[ $compiler == dart2js && ($runtime == chrome || $runtime == drt) ]
+svgelement_test/supported_altGlyph: RuntimeError # Issue 25787
[ ($runtime == dartium) && ($system == macos || $system == windows || $system == linux)]
# Desktop operating systems do not support touch events on chrome 34 dartium.
@@ -420,9 +430,7 @@
typing_test: StaticWarning
webgl_1_test: StaticWarning
window_nosuchmethod_test: StaticWarning
-
-[ $compiler == dart2js && $cps_ir ]
-resource_http_test: Crash # (await for(var b in r.openRead()){bytes.addAll(b);}): await for
+js_typed_interop_default_arg_test/default_value: MissingCompileTimeError # Issue #25759
[ $compiler == dart2js && $cps_ir && $browser ]
# Custom element support:
@@ -436,20 +444,9 @@
custom_elements_test/innerHtml: RuntimeError # Need custom element support #25484
custom_elements_test/register: RuntimeError # Need custom element support #25484
-# New js-interop support via package:js is only implemented in SSA:
-js_array_test: RuntimeError # Need package:js support #24978
-js_dart_to_string_test: RuntimeError # Need package:js support #24978
-js_function_getter_test/call: RuntimeError # Need package:js support #24978
-js_function_getter_test: RuntimeError # Need package:js support #24978
-js_function_getter_trust_types_test: RuntimeError # Need package:js support #24978
-js_typed_interop_anonymous2_exp_test: RuntimeError # Need package:js support #24978
-js_typed_interop_anonymous2_test: RuntimeError # Need package:js support #24978
-js_typed_interop_anonymous_exp_test: RuntimeError # Need package:js support #24978
-js_typed_interop_anonymous_test: RuntimeError # Need package:js support #24978
-js_typed_interop_side_cast_exp_test: RuntimeError # Need package:js support #24978
-js_typed_interop_side_cast_test: RuntimeError # Need package:js support #24978
-js_typed_interop_test: RuntimeError # Need package:js support #24978
-mirrors_js_typed_interop_test: RuntimeError # Need package:js support #24978
+js_typed_interop_side_cast_exp_test: RuntimeError # Corner case in package:js that we might want to remove (See comment in #24978).
+js_typed_interop_test/static_method_tearoff_1: RuntimeError # Tree-shaking a used tear-off (#24978, #25720).
+js_typed_interop_default_arg_test/explicit_argument: RuntimeError # Tree-shaking a used tear-off (#24978, #25720).
# These are raw dart:js tests that fail due to bugs in the CPS IR:
js_test/Dart_functions: RuntimeError # Tree-shaking an escaping closure #25720
diff --git a/tests/html/js_typed_interop_default_arg_test.dart b/tests/html/js_typed_interop_default_arg_test.dart
new file mode 100644
index 0000000..69a0756
--- /dev/null
+++ b/tests/html/js_typed_interop_default_arg_test.dart
@@ -0,0 +1,58 @@
+// 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.
+
+@JS()
+library js_typed_interop_test;
+
+import 'dart:html';
+
+import 'package:expect/expect.dart' show NoInline;
+import 'package:js/js.dart';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+_injectJs() {
+ document.body.append(new ScriptElement()
+ ..type = 'text/javascript'
+ ..innerHtml = r"""
+ var Foo = {
+ get42: function(b) { return arguments.length >= 1 ? b : 42; },
+ get43: function(b) { return arguments.length >= 1 ? b : 43; }
+ };
+""");
+}
+
+@JS()
+class Foo {
+ // Note: it's invalid to provide a default value.
+ external static num get42([num b
+ = 3 /// default_value: compile-time error
+ ]);
+ external static num get43([num b]);
+}
+
+main() {
+ _injectJs();
+ useHtmlConfiguration();
+
+ test('call directly from dart', () {
+ expect(Foo.get42(2), 2);
+ expect(Foo.get42(), 42);
+ });
+
+ test('call tearoff from dart with arg', () {
+ var f = Foo.get42;
+ expect(f(2), 2); /// explicit_argument: ok
+ });
+
+ test('call tearoff from dart with default', () {
+ var f = Foo.get42;
+ // Note: today both SSA and CPS remove the extra argument on static calls,
+ // but they fail to do so on tearoffs.
+ expect(f(), 3); /// default_value: continued
+
+ f = Foo.get43;
+ expect(f(), 43);
+ });
+}
diff --git a/tests/html/js_typed_interop_test.dart b/tests/html/js_typed_interop_test.dart
index 14d931f..431d533 100644
--- a/tests/html/js_typed_interop_test.dart
+++ b/tests/html/js_typed_interop_test.dart
@@ -124,6 +124,7 @@
external callClosureWithArg1(Function closure, arg1);
external callClosureWithArg2(Function closure, arg1, arg2);
external Bar getBar();
+
external static num multiplyDefault2(num a, [num b]);
}
@@ -277,14 +278,26 @@
});
});
- group('static method', () {
- test('call from dart', () {
+ group('static_method_call', () {
+ test('call directly from dart', () {
expect(Foo.multiplyDefault2(6, 7), equals(42));
expect(Foo.multiplyDefault2(6), equals(12));
+ });
+ });
+
+ // Note: these extra groups are added to be able to mark each test
+ // individually in status files. This should be split as separate test files.
+ group('static_method_tearoff_1', () {
+ test('call tearoff from dart', () {
MultiplyWithDefault tearOffMethod = Foo.multiplyDefault2;
expect(tearOffMethod(6, 6), equals(36));
+ });
+ });
+
+ group('static_method_tearoff_2', () {
+ test('call tearoff from dart', () {
+ MultiplyWithDefault tearOffMethod = Foo.multiplyDefault2;
expect(tearOffMethod(6), equals(12));
- Function untypedTearOff = Foo.multiplyDefault2;
});
});
diff --git a/tests/isolate/timer_isolate_test.dart b/tests/isolate/timer_isolate_test.dart
index 7513dad..cb8fcbb 100644
--- a/tests/isolate/timer_isolate_test.dart
+++ b/tests/isolate/timer_isolate_test.dart
@@ -23,18 +23,16 @@
main() {
test("timer in isolate", () {
- int startTime;
- int endTime;
-
+ Stopwatch stopwatch = new Stopwatch();
ReceivePort port = new ReceivePort();
port.first.then(expectAsync((msg) {
expect("timer_fired", msg);
- int endTime = (new DateTime.now()).millisecondsSinceEpoch;
- expect(endTime - startTime + safetyMargin, greaterThanOrEqualTo(TIMEOUT.inMilliseconds));
+ expect(stopwatch.elapsedMilliseconds + safetyMargin,
+ greaterThanOrEqualTo(TIMEOUT.inMilliseconds));
}));
- startTime = (new DateTime.now()).millisecondsSinceEpoch;
+ stopwatch.start();
var remote = Isolate.spawn(createTimer, port.sendPort);
});
}
diff --git a/tests/language/async_star_no_cancel2_test.dart b/tests/language/async_star_no_cancel2_test.dart
new file mode 100644
index 0000000..fcc82ac
--- /dev/null
+++ b/tests/language/async_star_no_cancel2_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+var events = [];
+
+var timer;
+ticker(period) async* {
+ var sc;
+ sc = new StreamController(onListen: () {
+ events.add("listen");
+ timer = new Timer.periodic(period, (_) {
+ sc.add(null);
+ });
+ }, onCancel: () {
+ events.add("cancel");
+ timer.cancel();
+ });
+
+ try {
+ var counter = 0;
+ await for (var tick in sc.stream) {
+ counter++;
+ }
+ } finally {
+ events.add("finally");
+ }
+}
+
+void main() {
+ asyncStart();
+ events.add("main");
+ final subscription =
+ ticker(const Duration(milliseconds: 20)).listen((val) { });
+
+ bool cancelFinished = false;
+ new Timer(const Duration(milliseconds: 100), () async {
+ // Despite the cancel call below, the stream doesn't stop.
+ // The async* function is not blocked at any await (since the inner timer
+ // continuously ticks), but since there/ is no yield-point in the function
+ // it won't cancel.
+ new Timer(const Duration(milliseconds: 30), () {
+ Expect.isFalse(cancelFinished);
+ Expect.listEquals(["main", "listen", "invoke cancel"], events);
+ timer.cancel();
+ asyncEnd();
+ });
+
+ events.add("invoke cancel");
+ await subscription.cancel();
+ // This line should never be reached, since the cancel-future doesn't
+ // complete.
+ cancelFinished = true;
+ });
+}
diff --git a/tests/language/async_star_no_cancel_test.dart b/tests/language/async_star_no_cancel_test.dart
new file mode 100644
index 0000000..82cbe22
--- /dev/null
+++ b/tests/language/async_star_no_cancel_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+var events = [];
+
+ticker() async* {
+ var sc;
+ var sentTickCount = 0;
+ sc = new StreamController(onListen: () {
+ events.add("listen");
+ }, onCancel: () {
+ events.add("cancel");
+ });
+
+ try {
+ var counter = 0;
+ await for (var tick in sc.stream) {
+ counter++;
+ }
+ } finally {
+ events.add("finally");
+ }
+}
+
+void main() {
+ asyncStart();
+ events.add("main");
+ final subscription = ticker().listen((val) { });
+
+ bool cancelFinished = false;
+ // Cancel the subscription.
+ // The async* function is blocked on an `await` (the inner stream) and won't
+ // be able to complete.
+ Timer.run(() {
+ events.add("invoke cancel");
+ subscription.cancel().then((_) => cancelFinished = true);
+ });
+
+ new Timer(const Duration(milliseconds: 100), () {
+ Expect.isFalse(cancelFinished);
+ Expect.listEquals(["main", "listen", "invoke cancel"], events);
+ asyncEnd();
+ });
+}
diff --git a/tests/language/for_in3_test.dart b/tests/language/for_in3_test.dart
new file mode 100644
index 0000000..75ee485
--- /dev/null
+++ b/tests/language/for_in3_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Dart test for testing that strings aren't iterable.
+
+main() {
+ Expect.throws(() {
+ var chars = [];
+ for (var c in "foo") chars.add(c);
+ }, (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 5ba9267..2d38d62 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -55,8 +55,6 @@
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
-issue_25671a_test/01: Skip # RuntimeError (Issue 25671, Issue 25737)
-issue_25671b_test/01: Skip # RuntimeError (Issue 25671, Issue 25737)
[ ($compiler == none || $compiler == precompiler) && $checked ]
type_variable_bounds4_test/01: Fail # Issue 14006
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 03ae9f9..060a61d 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -34,8 +34,6 @@
library_env_test/has_no_io_support: RuntimeError, OK
library_env_test/has_no_mirror_support: RuntimeError, OK
-accessor_conflict_export2_test: Crash # Issue 25626
-accessor_conflict_export_test: Crash # Issue 25626
accessor_conflict_import2_test: RuntimeError # Issue 25626
accessor_conflict_import_prefixed2_test: RuntimeError # Issue 25626
accessor_conflict_import_prefixed_test: RuntimeError # Issue 25626
@@ -44,6 +42,8 @@
[ $compiler == dart2js && $runtime == jsshell ]
await_for_test: Skip # Jsshell does not provide periodic timers, Issue 7728
async_star_test: RuntimeError # Jsshell does not provide non-zero timers, Issue 7728
+async_star_no_cancel_test: RuntimeError # Need triage
+async_star_no_cancel2_test: RuntimeError # Need triage
[ $compiler == dart2js && $browser ]
config_import_test: Fail # Test flag is not passed to the compiler.
@@ -238,6 +238,8 @@
regress_22443_test: Pass,RuntimeError # Issue 17458
[ $compiler == dart2js && $cps_ir == false ]
+accessor_conflict_export2_test: Crash # Issue 25626
+accessor_conflict_export_test: Crash # Issue 25626
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
@@ -249,37 +251,33 @@
issue23244_test: RuntimeError # 23244
[ $compiler == dart2js && $cps_ir ]
+accessor_conflict_export_test: CompileTimeError # Issue 25747
+accessor_conflict_export2_test: CompileTimeError # Issue 25747
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
async_await_syntax_test/a09a: Crash # (a09a()async*{yield 0;}): cannot handle sync*/async* functions
async_await_syntax_test/a10a: Crash # (a10a()async*{yield* [] ;}): cannot handle sync*/async* functions
async_await_syntax_test/a11d: Crash # (get async async*{}): cannot handle sync*/async* functions
async_await_syntax_test/b03a: Crash # (b03a()async*{}): cannot handle sync*/async* functions
-async_await_syntax_test/b06a: Crash # (await for(var o in st){}): await for
async_await_syntax_test/b09a: Crash # (b09a()async*{yield 0;}): cannot handle sync*/async* functions
async_await_syntax_test/b10a: Crash # (b10a()async*{yield* [] ;}): cannot handle sync*/async* functions
async_await_syntax_test/b11d: Crash # (get async async*{}): cannot handle sync*/async* functions
async_await_syntax_test/c03a: Crash # (c03a()async*{}): cannot handle sync*/async* functions
-async_await_syntax_test/c06a: Crash # (await for(var o in st){}): await for
async_await_syntax_test/c09a: Crash # (c09a()async*{yield 0;}): cannot handle sync*/async* functions
async_await_syntax_test/c10a: Crash # (c10a()async*{yield* [] ;}): cannot handle sync*/async* functions
async_await_syntax_test/d03a: Crash # (()async*{}): cannot handle sync*/async* functions
-async_await_syntax_test/d06a: Crash # (await for(var o in st){}): await for
async_await_syntax_test/d09a: Crash # (()async*{yield 0;}): cannot handle sync*/async* functions
async_await_syntax_test/d10a: Crash # (()async*{yield* [] ;}): cannot handle sync*/async* functions
-async_await_test/02: Crash # bailout: (await for
-async_await_test/03: Crash # bailout: (await for
-async_await_test/none: Crash # bailout: (await for
async_or_generator_return_type_stacktrace_test/02: Crash # (void badReturnTypeAsyncStar()async*{}): cannot handle sync*/async* functions
async_return_types_test/nestedFuture: Crash # cannot handle sync*/async* functions
async_return_types_test/none: Crash # cannot handle sync*/async* functions
async_return_types_test/tooManyTypeParameters: Crash # cannot handle sync*/async* functions
async_return_types_test/wrongReturnType: Crash # cannot handle sync*/async* functions
async_return_types_test/wrongTypeParameter: Crash # cannot handle sync*/async* functions
-async_star_await_pauses_test: Crash # (await for(var i in ... await for
async_star_cancel_and_throw_in_finally_test: Crash # (foo()async*{try {in... cannot handle sync*/async* functions
async_star_cancel_while_paused_test: Crash # (f()async*{list.add(... cannot handle sync*/async* functions
+async_star_no_cancel_test: Crash # (foo()async*{try {in... cannot handle sync*/async* functions
+async_star_no_cancel2_test: Crash # (foo()async*{try {in... cannot handle sync*/async* functions
async_star_regression_2238_test: Crash # (f()async*{label1:label2:yield 0;}): cannot handle sync*/async* functions
async_star_regression_23116_test: Crash # (Stream<int> foo(Com... cannot handle sync*/async* functions
async_star_regression_fisk_test: Crash # (fisk()async*{res.ad... cannot handle sync*/async* functions
@@ -290,11 +288,7 @@
asyncstar_throw_in_catch_test: Crash # (foo4(Tracer tracer)... cannot handle sync*/async* functions
asyncstar_yield_test: Crash # (Stream<int> foo4()a... cannot handle sync*/async* functions
asyncstar_yieldstar_test: Crash # (foo2(Stream subStream)async*{yield* subStream;}): cannot handle sync*/async* functions
-await_for_cancel_test: Crash # (await for(var x in controller.stream){for(int j=0;j<10;j++ ){if(j==5)continue outer;}}): await for
-await_for_test: Crash # (await for(var x in infiniteStream()){i++ ;if(i>10)break;t4.record(x);}): await for
-await_for_use_local_test: Crash # (await for(var v in s){accum+= v;}): await for
call_closurization_test: RuntimeError # Bad type inference for ".call" tear-off.
-deferred_super_dependency_test/01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
field3a_negative_test: Fail # Bogus result from type inference in case of invalid program.
gc_test: Crash # Internal Error: Pending statics (see above).
if_null_assignment_static_test/29: Crash # Pending statics: JSArray
@@ -303,10 +297,10 @@
if_null_assignment_static_test/33: Crash # Pending statics: JSArray
if_null_assignment_static_test/35: Crash # Pending statics: JSArray
invocation_mirror_test: Crash # (super[37]=42): visitUnresolvedSuperIndexSet
-regress_23500_test/01: Crash # (await for(var c in new Stream.fromIterable([] )){}): await for
-savannah_test: RuntimeError # Success depends on the variable hints.
+many_calls_test: Crash # Internal Error: Pending statics (see above).
+mixin_bound_test: RuntimeError # TypeError: Cannot read property 'toString$0' of undefined
super_call4_test: RuntimeError # Please triage this failure.
-super_getter_setter_test: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
+super_getter_setter_test: RuntimeError # Expect.equals(expected: <42>, actual: <null>) fails.
super_operator_index5_test: Crash # (super[0]=42): visitUnresolvedSuperIndexSet
super_operator_index7_test: Crash # (super[0]=42): visitUnresolvedSuperIndexSet
super_operator_index8_test: Crash # (super[f()]=g()): visitUnresolvedSuperIndexSet
diff --git a/tests/language/regress_25550_test.dart b/tests/language/regress_25550_test.dart
new file mode 100644
index 0000000..4a8a7c5
--- /dev/null
+++ b/tests/language/regress_25550_test.dart
@@ -0,0 +1,17 @@
+// 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.
+
+typedef int Adder(int a, int b);
+
+class Mock {
+ noSuchMethod(i) => null;
+}
+
+class MockAdder extends Mock {
+ int call(int a, int b);
+}
+
+main() {
+ Adder adder = new MockAdder();
+}
diff --git a/tests/lib/async/stream_view_test.dart b/tests/lib/async/stream_view_test.dart
new file mode 100644
index 0000000..5b8308a
--- /dev/null
+++ b/tests/lib/async/stream_view_test.dart
@@ -0,0 +1,37 @@
+// 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.
+
+// Tests the StreamView class.
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "package:async_helper/async_helper.dart";
+
+main() {
+ asyncStart();
+ runTest().whenComplete(asyncEnd);
+}
+
+Future runTest() async {
+ unreachable([a,b]) { throw "UNREACHABLE"; }
+ int tick = 0;
+ ticker() { tick++; }
+
+ asyncStart();
+
+ // Is const constructor.
+ Stream<int> s = const StreamView<int>(const Stream<int>.empty());
+
+ Expect.isFalse(s is Stream<String>); // Respects type parameter.
+ StreamSubscription<int> sub =
+ s.listen(unreachable, onError: unreachable, onDone: ticker);
+ Expect.isFalse(sub is StreamSubscription<String>); // Type parameter in sub.
+
+ Stream iterableStream = new Stream.fromIterable([1, 2, 3]);
+ Expect.listEquals([1, 2, 3], await iterableStream.toList());
+
+ asyncEnd();
+}
+
+Future flushMicrotasks() => new Future.delayed(Duration.ZERO);
diff --git a/tests/lib/async/timer_repeat_test.dart b/tests/lib/async/timer_repeat_test.dart
index e963c5a..1ed5139 100644
--- a/tests/lib/async/timer_repeat_test.dart
+++ b/tests/lib/async/timer_repeat_test.dart
@@ -11,16 +11,24 @@
const int ITERATIONS = 5;
Timer timer;
-int startTime;
+Stopwatch stopwatch = new Stopwatch();
int iteration;
+// Some browsers (Firefox and IE so far) can trigger too early. Add a safety
+// margin. We use identical(1, 1.0) as an easy way to know if the test is
+// compiled by dart2js.
+int get safetyMargin => identical(1, 1.0) ? 100 : 0;
+
void timeoutHandler(Timer timer) {
- int endTime = (new DateTime.now()).millisecondsSinceEpoch;
iteration++;
- if (iteration < ITERATIONS) {
- startTime = (new DateTime.now()).millisecondsSinceEpoch;
- } else {
- expect(iteration, ITERATIONS);
+ expect(iteration, lessThanOrEqualTo(ITERATIONS));
+ if (iteration == ITERATIONS) {
+ // When we are done with all of the iterations, we expect a
+ // certain amount of time to have passed. Checking the time on
+ // each iteration doesn't work because the timeoutHandler runs
+ // concurrently with the periodic timer.
+ expect(stopwatch.elapsedMilliseconds + safetyMargin,
+ greaterThanOrEqualTo(ITERATIONS * TIMEOUT.inMilliseconds));
timer.cancel();
}
}
@@ -28,7 +36,7 @@
main() {
test("timer_repeat", () {
iteration = 0;
- startTime = new DateTime.now().millisecondsSinceEpoch;
+ stopwatch.start();
timer = new Timer.periodic(TIMEOUT,
expectAsync(timeoutHandler, count: ITERATIONS));
});
diff --git a/tests/lib/async/timer_test.dart b/tests/lib/async/timer_test.dart
index fc7ee87..d08754b 100644
--- a/tests/lib/async/timer_test.dart
+++ b/tests/lib/async/timer_test.dart
@@ -11,7 +11,7 @@
const int DECREASE = 200;
const int ITERATIONS = 5;
-int startTime;
+Stopwatch stopwatch = new Stopwatch();
int timeout;
int iteration;
@@ -21,13 +21,13 @@
int get safetyMargin => identical(1, 1.0) ? 100 : 0;
void timeoutHandler() {
- int endTime = (new DateTime.now()).millisecondsSinceEpoch;
- expect(endTime - startTime + safetyMargin, greaterThanOrEqualTo(timeout));
+ expect(stopwatch.elapsedMilliseconds + safetyMargin,
+ greaterThanOrEqualTo(timeout));
if (iteration < ITERATIONS) {
iteration++;
timeout = timeout - DECREASE;
Duration duration = new Duration(milliseconds: timeout);
- startTime = (new DateTime.now()).millisecondsSinceEpoch;
+ stopwatch.reset();
new Timer(duration, expectAsync(timeoutHandler));
}
}
@@ -37,7 +37,7 @@
iteration = 0;
timeout = STARTTIMEOUT;
Duration duration = new Duration(milliseconds: timeout);
- startTime = (new DateTime.now()).millisecondsSinceEpoch;
+ stopwatch.start();
new Timer(duration, expectAsync(timeoutHandler));
});
}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 317880e..3bd73ed 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -188,6 +188,12 @@
[ ($runtime == vm || $runtime == dart_precompiled) ]
js/*: Skip
+# 'js' tests import the dart:js library, so they only make sense in
+# a browser environment.
+[ $runtime == dart_product ]
+js/*: SkipByDesign
+mirrors/*: SkipByDesign
+
[ $compiler == dart2js && $minified ]
mirrors/mirrors_used_get_name_test: RuntimeError
mirrors/mirrors_used_get_name2_test: RuntimeError
diff --git a/tests/standalone/assert_assignable_canon_test.dart b/tests/standalone/assert_assignable_canon_test.dart
new file mode 100644
index 0000000..7c34328
--- /dev/null
+++ b/tests/standalone/assert_assignable_canon_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=--enable-inlining-annotations --optimization-counter-threshold=10 --no-background-compilation
+
+const AlwaysInline = "AlwaysInline";
+const NeverInline = "NeverInline";
+
+abstract class A<T extends A<T>> {
+ @AlwaysInline
+ f(x) => new R<T>(x);
+}
+
+class B extends A<B> {}
+
+class R<T> {
+ @AlwaysInline
+ R(T field);
+}
+
+class C extends B {}
+
+class D extends C {}
+
+// f will be inlined and T=B will be forwarded to AssertAssignable in the
+// R. However B will be wrapped in the TypeRef which breaks runtime TypeCheck
+// function (Instance::IsInstanceOf does not work for TypeRefs).
+@NeverInline
+f(o) => new B().f(o);
+
+main() {
+ final o = new D();
+ for (var i = 0; i < 10; i++) {
+ f(o);
+ }
+}
diff --git a/tests/standalone/fields_may_be_reset_test.dart b/tests/standalone/fields_may_be_reset_test.dart
new file mode 100644
index 0000000..3ab6fc6
--- /dev/null
+++ b/tests/standalone/fields_may_be_reset_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--fields_may_be_reset
+
+main() {
+ print("Okay");
+}
diff --git a/tests/standalone/full_coverage_test.dart b/tests/standalone/full_coverage_test.dart
index 98495b1..e719d42 100644
--- a/tests/standalone/full_coverage_test.dart
+++ b/tests/standalone/full_coverage_test.dart
@@ -17,6 +17,9 @@
Platform.script.resolve('../../tools/full-coverage.dart').toFilePath();
final String packageRoot = Platform.packageRoot;
final List dartBaseArgs = ['--package-root=${packageRoot}', '--checked',];
+final Stopwatch sw = new Stopwatch();
+
+int elapsed() => sw.elapsedMilliseconds;
// With line numbers starting at 0, the list of hits can be understood as
// follows:
@@ -88,13 +91,14 @@
generateCoverage(String workingDirectory) {
for (var coverageProg in coverageTests) {
+ print('[+${elapsed()}ms] Generating data for ${coverageProg["name"]}');
var progPath = path.join(workingDirectory, coverageProg['name']);
var script = path.join(progPath, "${coverageProg['name']}.dart");
var dartArgs = new List.from(dartBaseArgs)
..addAll(['--coverage-dir=${progPath}', '${script}']);
var result = Process.runSync(Platform.executable, dartArgs);
if (result.exitCode != 0) {
- print("Coverage generator returned exitCode: ${result.exitCode}.");
+ print("[+${elapsed()}ms] Got exitCode: ${result.exitCode}.");
print("stderr:\n${result.stderr}\n");
expect(result.exitCode, 0);
}
@@ -212,6 +216,7 @@
main() {
String testingDirectory;
+ sw.start();
setUp(() {
testingDirectory = prepareEnv();
@@ -220,20 +225,23 @@
tearDown(() => destroyEnv(testingDirectory));
test('CoverageTests', () {
- print('Generating coverage data...');
+ print('[+${elapsed()}ms] Generating coverage data...');
generateCoverage(testingDirectory);
- print('Done Generating coverage data.');
+ print('[+${elapsed()}ms] Done Generating coverage data.');
- print('Running tests...');
+ print('[+${elapsed()}ms] Running tests...');
coverageTests.forEach((cTest) {
String programDir = path.join(testingDirectory, cTest['name']);
String programPath = path.join(programDir, "${cTest['name']}.dart");
+ print('[+${elapsed()}ms] Testing lcov for ${cTest["name"]}');
testCoverage(programDir, programPath,
new LcovDescriptor(programPath),
new List.from(cTest['expectedHits']));
+ print('[+${elapsed()}ms] Testing pretty print for ${cTest["name"]}');
testCoverage(programDir, programPath,
new PrettyPrintDescriptor(programPath),
new List.from(cTest['expectedHits']));
});
+ print('[+${elapsed()}ms] Done.');
});
}
diff --git a/tests/standalone/io/certificates/client1.p12 b/tests/standalone/io/certificates/client1.p12
new file mode 100644
index 0000000..0b51218
--- /dev/null
+++ b/tests/standalone/io/certificates/client1.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client1_key.p12 b/tests/standalone/io/certificates/client1_key.p12
new file mode 100644
index 0000000..a65c398
--- /dev/null
+++ b/tests/standalone/io/certificates/client1_key.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client1_key_malformed.pem b/tests/standalone/io/certificates/client1_key_malformed.pem
new file mode 100644
index 0000000..33a79bf
--- /dev/null
+++ b/tests/standalone/io/certificates/client1_key_malformed.pem
@@ -0,0 +1,18 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE4jAcBgoqhkiG9w0BDAEBMA4ECF4ZB27y60SWAgIIAASCBMCEL3ZCzfC0q+m+
+B8gM9jQe1JFRD5reAuwK6+3speBS4KE+wjbcyQq09/5UoQu3Dci1WG1nKLB1u0Bk
+w9NuRahWCpvVLzz/GQ6Psesixq3V69zD3N6iMl/XQKymQBwGK51xIkeJO+6Skh2d
++qoyBHINTlKY9+548Zgqu+Z3mI3pGmdhd7hCiamiffDwCLEqRxbXdZdLpC9GpAP5
+HOqXHzN2aZbAGHb1GkHVxskSNzAwlEEZhh4Ibe6o7U65hoL9borewT+gj6sQohI5
+/LHL0P2bVvtRZiwBVPUX8HZWuVYIFb6GEGTTqOofNhNHvHaKUlD8Uxi5/h/Xi8fq
+xpdkjIn7VXj9e+I3TkfiphDtk0+Q+f+UkuPyuzU1PafinPfRK1J6gk+ZqAQHW/sp
+g6GVr2r4PkOrBPsA6jmCnQhs2C4MlZyR2p65qjVutdkKU5NgftW+giK9shgglcza
+38RF8i01THOnD3j+2teM/t/Ziqb2PGWv/bmvhcYqt1aG186Pe3bBCxhh/L7bqNKD
+q7sxDmaDE2pTkfyvh07udarmBQc5gvfXYqwghbqP/n7wizqjeEJgAwwHyi8LLsFV
+XreBQ/8Z2gQwXurrh5WD+7KSgvgopW/oVC8a3++8Hmf5Nkj27lACzoDWTG2/Swah
+O1MmdtPyy/KCbf5ujt2BlXM9D206Rsr6hoO9UZ1s1ohRdJReVGc4NZ4XrVWc4TKT
+gUAFTaHIKgFe/DgLaQn8L8Pqb8B/JfoSgQ74r69S434Kc+EDKui8wnkgso5bqrr1
+M07H9Xo+OtG1D6rma2EUlpoU06CAIcyqNx5fHJ3xfk9GHScQi4U6vEDCAQTNTS65
+I5AOHthZ2kZzfXvP6TF39S5D37NrV7/WJu7ZFaJx3bUGwnS2HYTwjFPABHpVLMwJ
+nBylVJs+h7bCZdBNCWgTytcn1mYMCvXVmrW8VTwBRjUQsy4rgE2wjpZuIM9rx+gZ
+HtNvy5t2RlOSqVKapyvV0ll7qbT1lwGIePxjttiWmNbgbwRBQzjv6FZ1Yo331Fl4
diff --git a/tests/standalone/io/certificates/client_authority.p12 b/tests/standalone/io/certificates/client_authority.p12
new file mode 100644
index 0000000..a873b2a
--- /dev/null
+++ b/tests/standalone/io/certificates/client_authority.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client_authority_malformed.pem b/tests/standalone/io/certificates/client_authority_malformed.pem
new file mode 100644
index 0000000..d206dce3
--- /dev/null
+++ b/tests/standalone/io/certificates/client_authority_malformed.pem
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
+bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAaMRgw
+FgYDVQQDEw9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCi6wJAs6nppNmTZ3e/wE9l0pAmkMtDONwB9o115XXTG3rmSKfZOxa8
+TFjSn818Pr1OYb9fPdI1Y6x4WY9PELUtQyEBlNcKjwg96vhrP4p2DhqbWsI5nASH
+DSjJsM75bQ7D7qHYzriuAl0Fk1C4LcodRj+5wmErMtvGJG0x06qFbxCCMAJ2kC+h
+SneTN955/YHSXADgxjFlt3s1T0QPnqrr+G7Ro6PrVKLPBulglq7wAeTwrGkPRUt0
+3lDGOSi6i97NbpiXwrGp5XiLUtVCiID6Ro0xKWH4sjJ4JnVjIUG8CQWERc6sFDJM
diff --git a/tests/standalone/io/certificates/server_chain.p12 b/tests/standalone/io/certificates/server_chain.p12
new file mode 100644
index 0000000..c9416eb
--- /dev/null
+++ b/tests/standalone/io/certificates/server_chain.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/server_chain_malformed1.pem b/tests/standalone/io/certificates/server_chain_malformed1.pem
new file mode 100644
index 0000000..cbbeb55
--- /dev/null
+++ b/tests/standalone/io/certificates/server_chain_malformed1.pem
@@ -0,0 +1,7 @@
+-----BEGIN CERTIFICATE-----
+MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
+WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
+/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
+KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
diff --git a/tests/standalone/io/certificates/server_chain_malformed2.pem b/tests/standalone/io/certificates/server_chain_malformed2.pem
new file mode 100644
index 0000000..2c99e78
--- /dev/null
+++ b/tests/standalone/io/certificates/server_chain_malformed2.pem
@@ -0,0 +1,42 @@
+-----BEGIN CERTIFICATE-----
+MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
+WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
+/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
+KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
+oJsfgxy9SUM8Bsc9WMYKMUdqLO1QKs1A5YwqZuO7Mwj+4LY2QDixC7Ua7V9YAPo2
+1SBeLvMCHbYxSPCuxcZ/kDkgax/DF9u7aZnGhMImkwBka0OQFvpfjKtTIuoobTpe
+PAG7MQYXk4RjnjdyEX/9XAQzvNo1CDObAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
+bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
+ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSvhJo6taTggJQBukEvMo/PDk8tKTAf
+BgNVHSMEGDAWgBS98L4T5RaIToE3DkBRsoeWPil0eDAOBgNVHQ8BAf8EBAMCA6gw
+EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAHLOt0mL2S4A
+B7vN7KsfQeGlVgZUVlEjem6kqBh4fIzl4CsQuOO8oJ0FlO1z5JAIo98hZinymJx1
+phBVpyGIKakT/etMH0op5evLe9dD36VA3IM/FEv5ibk35iGnPokiJXIAcdHd1zam
+YaTHRAnZET5S03+7BgRTKoRuszhbvuFz/vKXaIAnVNOF4Gf2NUJ/Ax7ssJtRkN+5
+UVxe8TZVxzgiRv1uF6NTr+J8PDepkHCbJ6zEQNudcFKAuC56DN1vUe06gRDrNbVq
+2JHEh4pRfMpdsPCrS5YHBjVq/XHtFHgwDR6g0WTwSUJvDeM4OPQY5f61FB0JbFza
+PkLkXmoIod8=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNVoXDTI1MTAyNDEwMjYzNVowIDEeMBwG
+A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA6GndRFiXk+2q+Ig7ZOWKKGta+is8137qyXz+eVFs5sA0ajMN
+ZBAMWS0TIXw/Yks+y6fEcV/tfv91k1eUN4YXPcoxTdDF97d2hO9wxumeYOMnQeDy
+VZVDKQBZ+jFMeI+VkNpMEdmsLErpZDGob/1dC8tLEuR6RuRR8X6IDGMPOCMw1jLK
+V1bQjPtzqKadTscfjLuKxuLgspJdTrzsu6hdcl1mm8K6CjTY2HNXWxs1yYmwfuQ2
+Z4/8sOMNqFqLjN+ChD7pksTMq7IosqGiJzi2bpd5f44ek/k822Y0ATncJHk4h1Z+
+kZBnW6kgcLna1gDri9heRwSZ+M8T8nlHgIMZIQIDAQABo3sweTASBgNVHRMBAf8E
+CDAGAQH/AgEAMB0GA1UdDgQWBBS98L4T5RaIToE3DkBRsoeWPil0eDAfBgNVHSME
+GDAWgBRxD5DQHTmtpDFKDOiMf5FAi6vfbzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAD+4KpUeV5mUPw5IG/7w
+eOXnUpeS96XFGuS1JuFo/TbgntPWSPyo+rD4GrPIkUXyoHaMCDd2UBEjyGbBIKlB
+NZA3RJOAEp7DTkLNK4RFn/OEcLwG0J5brL7kaLRO4vwvItVIdZ2XIqzypRQTc0MG
+MmF08zycnSlaN01ryM67AsMhwdHqVa+uXQPo8R8sdFGnZ33yywTYD73FeImXilQ2
+rDnFUVqmrW1fjl0Fi4rV5XI0EQiPrzKvRtmF8ZqjGATPOsRd64cwQX6V+P5hNeIR
+9pba6td7AbNGausHfacRYMyoGJWWWkFPd+7jWOCPqW7Fk1tmBgdB8GzXa3inWIRM
+RUE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/server_key.p12 b/tests/standalone/io/certificates/server_key.p12
new file mode 100644
index 0000000..8b59c9b
--- /dev/null
+++ b/tests/standalone/io/certificates/server_key.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/trusted_certs.p12 b/tests/standalone/io/certificates/trusted_certs.p12
new file mode 100644
index 0000000..71ffe1b
--- /dev/null
+++ b/tests/standalone/io/certificates/trusted_certs.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/trusted_certs_malformed.pem b/tests/standalone/io/certificates/trusted_certs_malformed.pem
new file mode 100644
index 0000000..ea26cc7
--- /dev/null
+++ b/tests/standalone/io/certificates/trusted_certs_malformed.pem
@@ -0,0 +1,8 @@
+-----BEGIN CERTIFICATE-----
+MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
+YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
+A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMl+dcraUM/E7E6zl7+7hK9oUJYXJLnfiMtP/TRFVbH4+2aEN8vXzPbzKdR3
+FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
+ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
+wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
diff --git a/tests/standalone/io/secure_server_client_certificate_test.dart b/tests/standalone/io/secure_server_client_certificate_test.dart
index 0ba4103..97bbc4f 100644
--- a/tests/standalone/io/secure_server_client_certificate_test.dart
+++ b/tests/standalone/io/secure_server_client_certificate_test.dart
@@ -12,26 +12,32 @@
String localFile(path) => Platform.script.resolve(path).toFilePath();
-SecurityContext serverContext = new SecurityContext()
- ..useCertificateChainSync(localFile('certificates/server_chain.pem'))
- ..usePrivateKeySync(localFile('certificates/server_key.pem'),
+SecurityContext serverContext(String certType) => new SecurityContext()
+ ..useCertificateChainSync(localFile('certificates/server_chain.$certType'))
+ ..usePrivateKeySync(localFile('certificates/server_key.$certType'),
password: 'dartdart')
- ..setTrustedCertificatesSync(localFile('certificates/client_authority.pem'))
- ..setClientAuthoritiesSync(localFile('certificates/client_authority.pem'));
+ ..setTrustedCertificatesSync(localFile(
+ 'certificates/client_authority.$certType'))
+ ..setClientAuthoritiesSync(localFile(
+ 'certificates/client_authority.$certType'));
-SecurityContext clientCertContext = new SecurityContext()
- ..setTrustedCertificatesSync(localFile('certificates/trusted_certs.pem'))
- ..useCertificateChainSync(localFile('certificates/client1.pem'))
- ..usePrivateKeySync(localFile('certificates/client1_key.pem'),
+SecurityContext clientCertContext(String certType) => new SecurityContext()
+ ..setTrustedCertificatesSync(localFile(
+ 'certificates/trusted_certs.$certType'))
+ ..useCertificateChainSync(localFile('certificates/client1.$certType'))
+ ..usePrivateKeySync(localFile('certificates/client1_key.$certType'),
password: 'dartdart');
-SecurityContext clientNoCertContext = new SecurityContext()
- ..setTrustedCertificatesSync(localFile('certificates/trusted_certs.pem'));
+SecurityContext clientNoCertContext(String certType) => new SecurityContext()
+ ..setTrustedCertificatesSync(localFile(
+ 'certificates/trusted_certs.$certType'));
-Future testClientCertificate({bool required, bool sendCert}) async {
- var server = await SecureServerSocket.bind(HOST, 0, serverContext,
+Future testClientCertificate(
+ {bool required, bool sendCert, String certType}) async {
+ var server = await SecureServerSocket.bind(HOST, 0, serverContext(certType),
requestClientCertificate: true, requireClientCertificate: required);
- var clientContext = sendCert ? clientCertContext : clientNoCertContext;
+ var clientContext =
+ sendCert ? clientCertContext(certType) : clientNoCertContext(certType);
var clientEndFuture =
SecureSocket.connect(HOST, server.port, context: clientContext);
if (required && !sendCert) {
@@ -68,9 +74,16 @@
main() async {
asyncStart();
HOST = (await InternetAddress.lookup("localhost")).first;
- await testClientCertificate(required: false, sendCert: true);
- await testClientCertificate(required: true, sendCert: true);
- await testClientCertificate(required: false, sendCert: false);
- await testClientCertificate(required: true, sendCert: false);
+ await testClientCertificate(required: false, sendCert: true, certType: 'pem');
+ await testClientCertificate(required: true, sendCert: true, certType: 'pem');
+ await testClientCertificate(
+ required: false, sendCert: false, certType: 'pem');
+ await testClientCertificate(required: true, sendCert: false, certType: 'pem');
+
+ await testClientCertificate(required: false, sendCert: true, certType: 'p12');
+ await testClientCertificate(required: true, sendCert: true, certType: 'p12');
+ await testClientCertificate(
+ required: false, sendCert: false, certType: 'p12');
+ await testClientCertificate(required: true, sendCert: false, certType: 'p12');
asyncEnd();
}
diff --git a/tests/standalone/io/secure_socket_test.dart b/tests/standalone/io/secure_socket_test.dart
index 443e90b..dbd7271 100644
--- a/tests/standalone/io/secure_socket_test.dart
+++ b/tests/standalone/io/secure_socket_test.dart
@@ -7,6 +7,7 @@
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write
+import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
import "package:path/path.dart";
import "dart:async";
@@ -14,19 +15,20 @@
String localFile(path) => Platform.script.resolve(path).toFilePath();
-SecurityContext serverContext = new SecurityContext()
- ..useCertificateChainSync(localFile('certificates/server_chain.pem'))
- ..usePrivateKeySync(localFile('certificates/server_key.pem'),
+SecurityContext serverContext(String certType) => new SecurityContext()
+ ..useCertificateChainSync(localFile('certificates/server_chain.$certType'))
+ ..usePrivateKeySync(localFile('certificates/server_key.$certType'),
password: 'dartdart');
-SecurityContext clientContext = new SecurityContext()
- ..setTrustedCertificatesSync(localFile('certificates/trusted_certs.pem'));
+SecurityContext clientContext(String certType) => new SecurityContext()
+ ..setTrustedCertificatesSync(localFile(
+ 'certificates/trusted_certs.$certType'));
-Future<HttpServer> startServer() {
+Future<HttpServer> startServer(String certType) {
return HttpServer.bindSecure(
"localhost",
0,
- serverContext,
+ serverContext(certType),
backlog: 5).then((server) {
server.listen((HttpRequest request) {
request.listen(
@@ -43,10 +45,11 @@
});
}
-void main() {
+Future test(String certType) {
List<int> body = <int>[];
- startServer().then((server) {
- SecureSocket.connect("localhost", server.port, context: clientContext)
+ startServer(certType).then((server) {
+ SecureSocket.connect(
+ "localhost", server.port, context: clientContext(certType))
.then((socket) {
socket.write("GET / HTTP/1.0\r\nHost: localhost\r\n\r\n");
socket.close();
@@ -68,3 +71,10 @@
});
});
}
+
+main() async {
+ asyncStart();
+ await test('pem');
+ await test('p12');
+ asyncEnd();
+}
diff --git a/tests/standalone/io/security_context_argument_test.dart b/tests/standalone/io/security_context_argument_test.dart
index 60577b2..91de8dc 100644
--- a/tests/standalone/io/security_context_argument_test.dart
+++ b/tests/standalone/io/security_context_argument_test.dart
@@ -34,6 +34,32 @@
Expect.throws(() => c.usePrivateKeySync(
localFile('certificates/server_key.pem'), password: 3),
argumentOrTypeError);
+
+ // Empty data.
+ Expect.throws(() => c.usePrivateKeyBytes([], password: 'dartdart'),
+ tlsException);
+ Expect.throws(() => c.setTrustedCertificatesBytes([]), tlsException);
+ Expect.throws(() => c.useCertificateChainBytes([]), tlsException);
+ Expect.throws(() => c.setClientAuthoritiesBytes([]), argumentError);
+
+ // Malformed PEM certs.
+ Expect.throws(() => c.usePrivateKeySync(
+ localFile('certificates/client1_key_malformed.pem'),
+ password: "dartdart"),
+ tlsException);
+ Expect.throws(() => c.setTrustedCertificatesSync(
+ localFile('certificates/trusted_certs_malformed.pem')),
+ tlsException);
+ Expect.throws(() => c.useCertificateChainSync(
+ localFile('certificates/server_chain_malformed1.pem')),
+ tlsException);
+ Expect.throws(() => c.useCertificateChainSync(
+ localFile('certificates/server_chain_malformed2.pem')),
+ tlsException);
+ Expect.throws(() => c.setClientAuthoritiesSync(
+ localFile('certificates/client_authority_malformed.pem')),
+ argumentError);
+
c.usePrivateKeySync(
localFile('certificates/server_key.pem'), password: "dartdart");
}
diff --git a/tests/standalone/io/sleep_test.dart b/tests/standalone/io/sleep_test.dart
index 795de81..91c6625 100644
--- a/tests/standalone/io/sleep_test.dart
+++ b/tests/standalone/io/sleep_test.dart
@@ -2,15 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import "package:expect/expect.dart";
import "dart:io";
+import "package:unittest/unittest.dart";
test(int milliseconds) {
var watch = new Stopwatch();
watch.start();
sleep(new Duration(milliseconds: milliseconds));
watch.stop();
- Expect.isTrue(watch.elapsedMilliseconds + 1 >= milliseconds);
+ expect(watch.elapsedMilliseconds, greaterThanOrEqualTo(milliseconds));
}
main() {
@@ -18,6 +18,12 @@
test(1);
test(10);
test(100);
- Expect.throws(() => sleep(new Duration(milliseconds: -1)),
- (e) => e is ArgumentError);
+ bool sawError = false;
+ try {
+ sleep(new Duration(milliseconds: -1));
+ expect(false, isTrue); // should not reach here.
+ } on ArgumentError catch(e) {
+ sawError = true;
+ }
+ expect(sawError, isTrue);
}
diff --git a/tests/standalone/javascript_compatibility_errors_test.dart b/tests/standalone/javascript_compatibility_errors_test.dart
deleted file mode 100644
index 6404a2e..0000000
--- a/tests/standalone/javascript_compatibility_errors_test.dart
+++ /dev/null
@@ -1,183 +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.
-
-// VMOptions=--warn_on_javascript_compatibility --warning_as_error --optimization_counter_threshold=5
-
-import "package:expect/expect.dart";
-
-f(x, y) {
- // Unoptimized and optimized code.
- 1 is double; /// 00: ok
- if (1 is double) { x++; } /// 01: ok
- try { 1 as double; } on CastError catch (e) { } /// 02: ok
- try { var y = 1 as double; } on CastError catch (e) { } /// 03: ok
- 1.0 is int; /// 04: ok
- if (1.0 is int) { x++; } /// 05: ok
- try { 1.0 as int; } on CastError catch (e) { } /// 06: ok
- try { var z = 1.0 as int; } on CastError catch (e) { } /// 07: ok
-
- x is double; /// 10: ok
- if (x is double) { } /// 11: ok
- try { x as double; } on CastError catch (e) { } /// 12: ok
- try { var z = x as double; } on CastError catch (e) { } /// 13: ok
- y is int; /// 14: ok
- if (y is int) { } /// 15: ok
- try { y as int; } on CastError catch (e) { } /// 16: ok
- try { var z = y as int; } on CastError catch (e) { } /// 17: ok
-
- // It is a compile-time error if evaluation of a constant object results in
- // an uncaught exception being thrown, a JavascriptCompatibilityError here.
- "${1.0}"; /// 20: compile-time error
- var z = "${1.0}"; /// 21: compile-time error
-
- (1.0).toString(); /// 22: ok
- var z = (1.0).toString(); /// 23: ok
- "$y"; /// 24: ok
- var z = "$y"; /// 25: ok
- y.toString(); /// 26: ok
- var z = y.toString(); /// 27: ok
-
- var a = "yz";
- var b = "xyz";
- b = b.substring(1);
- if (identical(a, b)) { } /// 28: ok
-
- if (identical(x, y)) { } /// 29: ok
- if (identical(y, x)) { } /// 30: ok
-
- if (x > 10) {
- // Optimized code.
- x is double; /// 40: ok
- if (x is double) { } /// 41: ok
- try { x as double; } on CastError catch (e) { } /// 42: ok
- try { var z = x as double; } on CastError catch (e) { } /// 43: ok
- y is int; /// 44: ok
- if (y is int) { } /// 45: ok
- try { y as int; } on CastError catch (e) { } /// 46: ok
- try { var z = y as int; } on CastError catch (e) { } /// 47: ok
-
- "${1.0}"; /// 50: compile-time error
- var z = "${1.0}"; /// 51: compile-time error
-
- (1.0).toString(); /// 52: ok
- var z = (1.0).toString(); /// 53: ok
- "$y"; /// 54: ok
- var z = "$y"; /// 55: ok
- y.toString(); /// 56: ok
- var z = y.toString(); /// 57: ok
-
- var a = "yz";
- var b = "xyz";
- b = b.substring(1);
- if (identical(a, b)) { } /// 58: ok
-
- if (identical(x, y)) { } /// 59: ok
- if (identical(y, x)) { } /// 60: ok
- }
-}
-
-k(x, y) {
- // Unoptimized and optimized code.
- 1.5 is double;
- if (1.5 is double) { x++; }
- try { 1.5 as double; } on CastError catch (e) { }
- try { var y = 1.5 as double; } on CastError catch (e) { }
- 1.5 is int;
- if (1.5 is int) { x++; }
- try { 1.5 as int; } on CastError catch (e) { }
- try { var z = 1.5 as int; } on CastError catch (e) { }
-
- 1.5 is double;
- if (1.5 is double) { x++; }
- try { 1.5 as double; } on CastError catch (e) { }
- try { var y = 1.5 as double; } on CastError catch (e) { }
- 1.5 is int;
- if (1.5 is int) { x++; }
- try { 1.5 as int; } on CastError catch (e) { }
- try { var z = 1.5 as int; } on CastError catch (e) { }
-
- x is double;
- if (x is double) { }
- try { x as double; } on CastError catch (e) { }
- try { var z = x as double; } on CastError catch (e) { }
- y is int;
- if (y is int) { }
- try { y as int; } on CastError catch (e) { }
- try { var z = y as int; } on CastError catch (e) { }
-
- "${1.5}";
- var z = "${1.5}";
- (1.5).toString();
- z = (1.5).toString();
- "$y";
- z = "$y";
- y.toString();
- z = y.toString();
-
- var a = "xyz";
- var b = "xyz";
- b = b.substring(1);
- if (identical(a, b)) { }
-
- if (identical(x, y)) { }
- if (identical(y, x)) { }
-
- if (x > 10) {
- // Optimized code.
- x is double;
- if (x is double) { }
- try { x as double; } on CastError catch (e) { }
- try { var z = x as double; } on CastError catch (e) { }
- y is int;
- if (y is int) { }
- try { y as int; } on CastError catch (e) { }
- try { var z = y as int; } on CastError catch (e) { }
-
- "${1.5}";
- var z = "${1.5}";
- (1.5).toString();
- z = (1.5).toString();
- "$y";
- z = "$y";
- y.toString();
- z = y.toString();
-
- var a = "xyz";
- var b = "xyz";
- b = b.substring(1);
- if (identical(a, b)) { }
-
- if (identical(x, y)) { }
- if (identical(y, x)) { }
- }
-}
-
-g(x, y) => f(x, y); // Test inlining calls.
-h(x, y) => g(x, y);
-
-// We don't test for _JavascriptCompatibilityError since it's not visible.
-// It should not be visible since it doesn't exist on dart2js.
-bool isJavascriptCompatibilityError(e) =>
- e is Error && "$e".contains("Javascript Compatibility Error");
-
-main() {
- // The warning (or error in case of --warning_as_error) is issued at
- // most once per location.
- var numWarnings = 0;
- for (var i = 0; i < 20; i++) {
- try {
- h(i, i * 1.0);
- } catch(e) {
- Expect.isTrue(isJavascriptCompatibilityError(e));
- numWarnings++;
- }
- }
- Expect.equals(1, numWarnings);
- // No warnings (errors) should be issued after this point.
- for (var i = 0; i < 20; i++) {
- k(i * 1.0, i);
- k(i * 1.0, i + 0.5);
- }
-}
-
diff --git a/tests/standalone/javascript_compatibility_warnings_test.dart b/tests/standalone/javascript_compatibility_warnings_test.dart
deleted file mode 100644
index bb744b1..0000000
--- a/tests/standalone/javascript_compatibility_warnings_test.dart
+++ /dev/null
@@ -1,84 +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.
-
-// VMOptions=--warn_on_javascript_compatibility --no_warning_as_error --optimization_counter_threshold=5
-
-import "package:expect/expect.dart";
-
-f(x, y) {
- // Unoptimized and optimized code.
- 1 is double; /// 00: ok
- if (1 is double) { x++; } /// 01: ok
- try { 1 as double; } on CastError catch (e) { } /// 02: ok
- try { var y = 1 as double; } on CastError catch (e) { } /// 03: ok
- 1.0 is int; /// 04: ok
- if (1.0 is int) { x++; } /// 05: ok
- try { 1.0 as int; } on CastError catch (e) { } /// 06: ok
- try { var z = 1.0 as int; } on CastError catch (e) { } /// 07: ok
-
- x is double; /// 10: ok
- if (x is double) { } /// 11: ok
- try { x as double; } on CastError catch (e) { } /// 12: ok
- try { var z = x as double; } on CastError catch (e) { } /// 13: ok
- y is int; /// 14: ok
- if (y is int) { } /// 15: ok
- try { y as int; } on CastError catch (e) { } /// 16: ok
- try { var z = y as int; } on CastError catch (e) { } /// 17: ok
-
- "${1.0}"; /// 20: ok
- var z = "${1.0}"; /// 21: ok
- (1.0).toString(); /// 22: ok
- var z = (1.0).toString(); /// 23: ok
- "$y"; /// 24: ok
- var z = "$y"; /// 25: ok
- y.toString(); /// 26: ok
- var z = y.toString(); /// 27: ok
-
- var a = "yz";
- var b = "xyz";
- b = b.substring(1);
- if (identical(a, b)) { } /// 28: ok
-
- if (identical(x, y)) { } /// 29: ok
- if (identical(y, x)) { } /// 30: ok
-
- if (x > 10) {
- // Optimized code.
- x is double; /// 40: ok
- if (x is double) { } /// 41: ok
- try { x as double; } on CastError catch (e) { } /// 42: ok
- try { var z = x as double; } on CastError catch (e) { } /// 43: ok
- y is int; /// 44: ok
- if (y is int) { } /// 45: ok
- try { y as int; } on CastError catch (e) { } /// 46: ok
- try { var z = y as int; } on CastError catch (e) { } /// 47: ok
-
- "${1.0}"; /// 50: ok
- var z = "${1.0}"; /// 51: ok
- (1.0).toString(); /// 52: ok
- var z = (1.0).toString(); /// 53: ok
- "$y"; /// 54: ok
- var z = "$y"; /// 55: ok
- y.toString(); /// 56: ok
- var z = y.toString(); /// 57: ok
-
- var a = "yz";
- var b = "xyz";
- b = b.substring(1);
- if (identical(a, b)) { } /// 58: ok
-
- if (identical(x, y)) { } /// 59: ok
- if (identical(y, x)) { } /// 60: ok
- }
-}
-
-g(x, y) => f(x, y); // Test inlining calls.
-h(x, y) => g(x, y);
-
-main() {
- for (var i = 0; i < 20; i++) {
- h(i, i* 1.0);
- }
-}
-
diff --git a/tests/standalone/javascript_int_overflow_literal_test.dart b/tests/standalone/javascript_int_overflow_literal_test.dart
deleted file mode 100644
index d54df3a..0000000
--- a/tests/standalone/javascript_int_overflow_literal_test.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.
-
-// VMOptions=--throw_on_javascript_int_overflow --print_stacktrace_at_throw
-
-
-import "package:expect/expect.dart";
-
-int literals() {
- var okay_literal = 0x20000000000000;
- var too_big_literal = 0x20000000000001; /// 01: compile-time error
- return okay_literal;
-}
-
-main() {
- Expect.equals(0x20000000000000, literals());
-}
diff --git a/tests/standalone/javascript_int_overflow_test.dart b/tests/standalone/javascript_int_overflow_test.dart
deleted file mode 100644
index 2661cd2..0000000
--- a/tests/standalone/javascript_int_overflow_test.dart
+++ /dev/null
@@ -1,151 +0,0 @@
-// 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.
-
-// VMOptions=--throw_on_javascript_int_overflow --print_stacktrace_at_throw --optimization_counter_threshold=10 --no-use-osr
-
-
-import "package:expect/expect.dart";
-import 'dart:typed_data';
-
-
-double dti_arg;
-int double_to_int() {
- return dti_arg.toInt();
-}
-
-
-int ia_arg1;
-int ia_arg2;
-int integer_add() {
- return ia_arg1 + ia_arg2;
-}
-
-
-int is_arg;
-int integer_shift() {
- return is_arg << 1;
-}
-
-
-int max_add_throws() {
- return 0x20000000000000 + 1;
-}
-
-
-int min_sub_throws() {
- return -0x20000000000000 - 1;
-}
-
-
-int n_arg;
-int negate() {
- return -n_arg;
-}
-
-
-int max_literal() {
- return 0x20000000000000;
-}
-
-
-int min_literal() {
- var min_literal = -0x20000000000000;
- return min_literal;
-}
-
-
-int doNotThrow1(a, b) {
- return (a << b) & 0xFFFFFFFF;
-}
-
-int doNotThrow2(a, b) {
- return (a << b) & 0xFFFFFFFF;
-}
-
-
-int doNotThrow3(a, b) {
- return (a << b) & 0x7FFFFFFF;
-}
-
-
-int doNotThrow4(a, b) {
- return (a << b) & 0x7FFFFFFF;
-}
-
-
-// We don't test for the _JavascriptIntegerOverflowError since it's not visible.
-// It should not be visible since it doesn't exist on dart2js.
-bool isJavascriptIntError(e) =>
- e is Error && "$e".startsWith("Javascript Integer Overflow:");
-
-main() {
- Expect.equals(0x20000000000000, max_literal());
- Expect.equals(-0x20000000000000, min_literal());
-
- // Run the tests once before optimizations.
- dti_arg = 1.9e17;
- Expect.throws(double_to_int, isJavascriptIntError);
-
- ia_arg1 = (1 << 53);
- ia_arg2 = (1 << 53);
- Expect.throws(integer_add, isJavascriptIntError);
-
- n_arg = -0x20000000000000;
- Expect.equals(0x20000000000000, negate());
-
- is_arg = (1 << 53);
- Expect.throws(integer_shift, isJavascriptIntError);
-
- Expect.throws(max_add_throws, isJavascriptIntError);
- Expect.throws(min_sub_throws, isJavascriptIntError);
-
- for (int i = 0; i < 20; i++) {
- dti_arg = i.toDouble();
- // Expect.throws calls through the closure, so we have to here, too.
- var f = double_to_int;
- Expect.equals(i, f());
-
- ia_arg1 = i;
- ia_arg2 = i;
- f = integer_add;
- Expect.equals(i + i, f());
-
- n_arg = i;
- f = negate;
- Expect.equals(-i, f());
-
- is_arg = i;
- f = integer_shift;
- Expect.equals(i << 1, f());
- }
-
- // The optimized functions should now deoptimize and throw the error.
- dti_arg = 1.9e17;
- Expect.throws(double_to_int, isJavascriptIntError);
-
- ia_arg1 = (1 << 53);
- ia_arg2 = (1 << 53);
- Expect.throws(integer_add, isJavascriptIntError);
-
- n_arg = -0x20000000000000;
- Expect.equals(0x20000000000000, negate());
-
- is_arg = (1 << 53);
- Expect.throws(integer_shift, isJavascriptIntError);
-
- Expect.throws(max_add_throws, isJavascriptIntError);
- Expect.throws(min_sub_throws, isJavascriptIntError);
-
- for (int i = 0; i < 20; i++) {
- Expect.equals(0xAFAFA000, doNotThrow1(0xFAFAFA, 12));
- Expect.equals(0x2FAFA000, doNotThrow3(0xFAFAFA, 12));
- Expect.equals(0xABABA000, doNotThrow2(0xFAFAFAABABA, 12));
- Expect.equals(0x2BABA000, doNotThrow4(0xFAFAFAABABA, 12));
- }
- for (int i = 0; i < 20; i++) {
- Expect.equals(0xABABA000, doNotThrow1(0xFAFAFAABABA, 12));
- Expect.equals(0x2BABA000, doNotThrow3(0xFAFAFAABABA, 12));
- }
-
-}
diff --git a/tests/standalone/link_natives_lazily_test.dart b/tests/standalone/link_natives_lazily_test.dart
new file mode 100644
index 0000000..35a53a1
--- /dev/null
+++ b/tests/standalone/link_natives_lazily_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--link_natives_lazily
+
+main() {
+ print("Okay");
+}
diff --git a/tests/standalone/no_allow_absolute_addresses_test.dart b/tests/standalone/no_allow_absolute_addresses_test.dart
new file mode 100644
index 0000000..e013c5e
--- /dev/null
+++ b/tests/standalone/no_allow_absolute_addresses_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--no_allow_absolute_addresses
+
+main() {
+ print("Okay");
+}
diff --git a/tests/standalone/no_lazy_dispatchers_test.dart b/tests/standalone/no_lazy_dispatchers_test.dart
index 999505f..f45ba1c 100644
--- a/tests/standalone/no_lazy_dispatchers_test.dart
+++ b/tests/standalone/no_lazy_dispatchers_test.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// VMOptions=--no-lazy-dispatchers
+// VMOptions=--no_lazy_dispatchers
main() {
print("Okay");
diff --git a/tests/standalone/precompilation_dart2js_test.dart b/tests/standalone/precompilation_dart2js_test.dart
index d7a8b71..0deafcb 100644
--- a/tests/standalone/precompilation_dart2js_test.dart
+++ b/tests/standalone/precompilation_dart2js_test.dart
@@ -77,7 +77,7 @@
result = Process.runSync(
cc,
- [shared, cc_flags, "-o", libname, "precompiled.S"],
+ [shared, cc_flags, "-nostartfiles", "-o", libname, "precompiled.S"],
workingDirectory: tmp.path);
if (result.exitCode != 0) {
print(result.stdout);
diff --git a/tests/standalone/precompilation_test.dart b/tests/standalone/precompilation_test.dart
index e58c5fe..e65bf17 100644
--- a/tests/standalone/precompilation_test.dart
+++ b/tests/standalone/precompilation_test.dart
@@ -74,7 +74,7 @@
result = Process.runSync(
cc,
- [shared, cc_flags, "-o", libname, "precompiled.S"],
+ [shared, cc_flags, "-nostartfiles", "-o", libname, "precompiled.S"],
workingDirectory: tmp.path);
if (result.exitCode != 0) {
print(result.stdout);
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 438e394..43cd0bc 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -18,8 +18,6 @@
issue14236_test: Pass # Do not remove this line. It serves as a marker for Issue 14516 comment #4.
-javascript_compatibility_errors_test/none: Fail, OK # Not possible to exclude or annotate with '/// none:'
-
[ ($runtime != vm && $runtime != dart_precompiled) && ($runtime != drt || $compiler != none)) ]
no_assert_test: Fail, OK # This is testing a vm flag.
@@ -27,9 +25,6 @@
package/package_isolate_test: Fail # Issue 12474
io/observatory_test: Fail
package/scenarios/invalid/same_package_twice_test: Pass # Issue 24119
-javascript_int_overflow_test: Skip # Fails if the bot's uptime becomes too high.
-javascript_int_overflow_literal_test: Skip # Fails if the bot's uptime becomes too high.
-
[ ($runtime == vm || $runtime == dart_precompiled) && $checked ]
# These tests have type errors on purpose.
@@ -68,8 +63,6 @@
http_launch_test: Skip
vmservice/*: SkipByDesign # Do not run standalone vm service tests in browser.
issue14236_test: Skip # Issue 14236 Script snapshots do not work in the browser.
-javascript_compatibility_errors_test: Skip
-javascript_compatibility_warnings_test: Skip
oom_error_stacktrace_test: Skip
out_of_memory_test: Skip
verbose_gc_to_bmu_test: Skip
@@ -78,7 +71,6 @@
noopt_test: Skip # Standalone only test.
[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
-javascript_int_overflow_literal_test/01: Fail, OK
issue14236_test: Skip # Analyzer can't handle Script snapshots.
# test issue https://code.google.com/p/dart/issues/detail?id=11518
@@ -109,13 +101,9 @@
pow_test: Skip # Precision > 53 bits.
double_smi_comparison_test: Skip # Precision > 53 bits.
http_launch_test: Skip
-javascript_int_overflow_test: Skip
-javascript_int_overflow_literal_test: Skip
oom_error_stacktrace_test: RuntimeError, OK # (OOM on JS may produce a stacktrace).
vmservice/*: Skip # Do not run standalone vm service tests with dart2js.
issue14236_test: Skip # dart2js does not deal with Script snapshots.
-javascript_compatibility_errors_test: Skip
-javascript_compatibility_warnings_test: Skip
unboxed_int_converter_test: Skip
pair_location_remapping_test: Skip
precompilation_test: Skip # Standalone only test.
@@ -156,9 +144,6 @@
out_of_memory_test: Skip # passes on Mac, crashes on Linux
oom_error_stacktrace_test: Skip # Fails on Linux
-[ $arch == simmips || $arch == mips ]
-javascript_int_overflow_test: Skip # --throw_on_javascript_int_overflow not supported on MIPS.
-
[ $arch == mips ]
io/signals_test: Fail # Issue 17440
io/file_stat_test: Fail # Issue 17440
@@ -176,10 +161,6 @@
[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) && $unchecked ]
assert_test: Fail # Issue 14651.
-[ ($compiler == none || $compiler == precompiler) && ($runtime == dartium || $runtime == ContentShellOnAndroid) ]
-javascript_int_overflow_literal_test/01: Fail # Issue 14651.
-javascript_int_overflow_test: Fail # Issue 14651.
-
[ $compiler == none && $runtime == drt ]
map_literal_oom_test: RuntimeError # Issue 24571
@@ -197,8 +178,6 @@
package/scenarios/packages_file_in_parent/sub/packages_file_in_parent_test: StaticWarning
typed_data_test: StaticWarning
typed_data_view_test: StaticWarning
-javascript_compatibility_errors_test: Skip
-javascript_compatibility_warnings_test: Skip
[ $compiler == dart2analyzer ]
package/package1_test: CompileTimeError
@@ -217,6 +196,7 @@
verbose_gc_to_bmu_test: Skip
io/platform_resolved_executable_test/06: RuntimeError # Issue 23641
io/process_sync_test: Pass, Timeout # Issue 24596
+io/sleep_test: Pass, Fail # Issue 25757
[ $arch != ia32 && $arch != x64 && $arch != simarm && $arch != simarmv5te && $mode == debug ]
verified_mem_test: Skip # Not yet implemented.
@@ -233,9 +213,12 @@
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.
+[ $arch == ia32 ]
+no_allow_absolute_addresses_test: SkipByDesign # Not supported.
+link_natives_lazily_test: SkipByDesign # Not supported.
+
[ ($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
assert_test: RuntimeError # Expects line and column numbers
precompilation_test: Skip # Platform.executable
diff --git a/tools/VERSION b/tools/VERSION
index 4d09691..fde1253 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 1
MINOR 15
PATCH 0
-PRERELEASE 2
+PRERELEASE 3
PRERELEASE_PATCH 0
diff --git a/tools/bots/cross-vm.py b/tools/bots/cross-vm.py
index 9fd751f..9865547 100644
--- a/tools/bots/cross-vm.py
+++ b/tools/bots/cross-vm.py
@@ -47,7 +47,7 @@
with bot.BuildStep('Create build tarball'):
run(['tar', '-cjf', tarball, '--exclude=**/obj',
'--exclude=**/obj.host', '--exclude=**/obj.target',
- '--exclude=**/*analyzer*', 'out/', 'tools/testing/bin/'])
+ '--exclude=**/*analyzer*', 'out/'])
with bot.BuildStep('Upload build tarball'):
uri = "%s/%s" % (GCS_BUCKET, tarball)
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index c84f40d..1e4fc74 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -143,7 +143,7 @@
for library in ['analyzer', 'analysis_server']:
copytree(join(home, 'pkg', library), join(lib_dir, library),
ignore=ignore_patterns('*.svn', 'doc', '*.py', '*.gypi', '*.sh',
- '.gitignore'))
+ '.gitignore', 'packages'))
def CopyDartdocResources(home, sdk_root):
RESOURCE_DIR = join(sdk_root, 'bin', 'snapshots', 'resources')
diff --git a/tools/create_tarball.py b/tools/create_tarball.py
index 462bd9d..887bc86 100755
--- a/tools/create_tarball.py
+++ b/tools/create_tarball.py
@@ -40,8 +40,7 @@
versiondir = ''
# Ignore Git/SVN files, checked-in binaries, backup files, etc..
-ignoredPaths = ['tools/testing/bin',
- 'tools/sdks',
+ignoredPaths = ['tools/sdks',
'third_party/7zip', 'third_party/android_tools',
'third_party/clang', 'third_party/d8',
'third_party/firefox_jsshell']
diff --git a/tools/dartium/archive.py b/tools/dartium/archive.py
index 5f8bae8..973731d 100755
--- a/tools/dartium/archive.py
+++ b/tools/dartium/archive.py
@@ -21,7 +21,7 @@
CONTENTSHELL_FILES = ['content_shell', 'content_shell.pak', 'fonts.conf',
'libffmpegsumo.so', 'libosmesa.so', 'lib',
'icudtl.dat', 'AHEM____.TTF', 'GardinerModBug.ttf',
- 'GardinerModCat.ttf']
+ 'GardinerModCat.ttf', 'natives_blob.bin']
CHROMEDRIVER_FILES = ['chromedriver']
elif HOST_OS == 'win':
# TODO: provide proper list.
diff --git a/tools/dartium/test.py b/tools/dartium/test.py
index d879d6e..0f16b41 100755
--- a/tools/dartium/test.py
+++ b/tools/dartium/test.py
@@ -183,8 +183,7 @@
'arch': options.arch,
}
- test_script = os.path.join(srcpath, 'webkit', 'tools', 'layout_tests',
- 'run_webkit_tests.py')
+ test_script = os.path.join(srcpath, 'third_party', 'WebKit', 'Tools', 'Scripts', 'run-webkit-tests')
errors = False
for component in components:
diff --git a/tools/dartium/update_deps.py b/tools/dartium/update_deps.py
index 6e27437..3370a24 100755
--- a/tools/dartium/update_deps.py
+++ b/tools/dartium/update_deps.py
@@ -41,8 +41,9 @@
########################################################################
BRANCH_CURRENT="dart/dartium"
-BRANCH_NEXT="dart/dartium"
-BRANCH_MULTIVM="dart/multivm"
+BRANCH_NEXT="dart/2454_1"
+
+# (repo_name, deps_dir, repo_branch, prefix, repos, branch)
TARGETS = {
'dartium': (
@@ -56,9 +57,9 @@
),
'integration': (
# TODO(jacobr): what is the git repo for integration if any?
- 'https://dart.googlecode.com/svn/branches/dartium_integration/deps/dartium.deps',
+ 'git@github.com:dart-lang/sdk.git',
'tools/deps/dartium.deps',
- 'origin/master',
+ 'origin/integration',
'dartium',
# TODO(vsm): Reenable 'chromium'
['webkit'],
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index accf568..43447ed 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -8,13 +8,9 @@
# Now we need to override some settings and add some new ones.
vars.update({
- "chromium_url": "http://src.chromium.org/svn",
- "dartium_base": "http://src.chromium.org",
- "dartium_chromium_branch": "master",
- "dartium_chromium_commit": "62a7524d4f71c9e0858d24b0aa1bbff3a2d09bff",
- "chromium_base_revision": "297060",
- "dartium_webkit_branch": "/blink/branches/dart/dartium",
- "dartium_webkit_revision": "202760",
+ "dartium_chromium_commit": "8df9de5a8f073d9c0feadf8d652408807e4a254e",
+ "dartium_webkit_commit": "1d73225937ba77bba2d4279fe7b23bfb542d35d9",
+ "chromium_base_revision": "338390",
# We use mirrors of all github repos to guarantee reproducibility and
# consistency between what users see and what the bots see.
@@ -69,39 +65,19 @@
"yaml_rev": "@563a5ffd4a800a2897b8f4dd6b19f2a370df2f2b",
"zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
"web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
- "WebCore_rev": "@4f90b41b0165f23f412cecdba07b7d81d3fbb5b5",
+ "WebCore_rev": "@5ecb723fd9ffcc0d108f5e0e24d12b8b3df7b200",
"co19_rev": "@3ed795ea02e022ef19c77cf1b6095b7c8f5584d0",
})
-def massage_deps(deps):
- for key, value in deps.items():
- if value is None: continue
-
- if value.startswith('/trunk'):
- deps[key] = Var("chromium_url") + value
- continue
-
- if value.startswith(Var("webkit_trunk")):
- path, revision = value.split('@') # and svn revision.
- path = path[len(Var("webkit_trunk")):] # Strip WebKit repo.
- value = (Var("dartium_base") + Var("dartium_webkit_branch") + path +
- '@' + Var("dartium_webkit_revision"))
- deps[key] = value
- continue
-
-massage_deps(deps)
-for os_deps in deps_os.values():
- massage_deps(os_deps)
-
deps.update({
"src":
Var("chromium_git") + "/dart/dartium/src.git" + "@" +
Var("dartium_chromium_commit"),
"src/third_party/WebKit":
- Var("dartium_base") + Var("dartium_webkit_branch") + "@" +
- Var("dartium_webkit_revision"),
+ Var("chromium_git") + "/dart/dartium/blink.git" + "@" +
+ Var("dartium_webkit_commit"),
"src/dart/third_party/pkg/args":
(Var("github_mirror") % "args") + Var("args_tag"),
@@ -232,20 +208,6 @@
Var('webkit_revision') + "\\n')" ],
})
hooks.append({
- "name": "checked_in_dart_binaries",
- "pattern": ".",
- "action": [
- "download_from_google_storage",
- "--no_auth",
- "--no_resume",
- "--bucket",
- "dart-dependencies",
- "--recursive",
- "--directory",
- "src/dart/tools/testing/bin",
- ],
-})
-hooks.append({
"name": "checked_in_dart_sdks",
"pattern": ".",
"action": [
diff --git a/tools/deps/dartium.deps/DEPS.chromium b/tools/deps/dartium.deps/DEPS.chromium
index c4117a5..4abb484 100644
--- a/tools/deps/dartium.deps/DEPS.chromium
+++ b/tools/deps/dartium.deps/DEPS.chromium
@@ -1,81 +1,76 @@
-# This file is automatically processed to create .DEPS.git which is the file
-# that gclient uses under git.
+# This file is used to manage the dependencies of the Chromium src repo. It is
+# used by gclient to determine what version of each dependency to check out, and
+# where.
#
-# See http://code.google.com/p/chromium/wiki/UsingGit
-#
-# To test manually, run:
-# python tools/deps2git/deps2git.py -o .DEPS.git -w <gclientdir>
-# where <gcliendir> is the absolute path to the directory containing the
-# .gclient file (the parent of 'src').
-#
-# Then commit .DEPS.git locally (gclient doesn't like dirty trees) and run
-# gclient sync
-# Verify the thing happened you wanted. Then revert your .DEPS.git change
-# DO NOT CHECK IN CHANGES TO .DEPS.git upstream. It will be automatically
-# updated by a bot when you modify this one.
+# For more information, please refer to the official documentation:
+# https://sites.google.com/a/chromium.org/dev/developers/how-tos/get-the-code
#
# When adding a new dependency, please update the top-level .gitignore file
# to list the dependency's destination directory.
+#
+# -----------------------------------------------------------------------------
+# Rolling deps
+# -----------------------------------------------------------------------------
+# All repositories in this file are git-based, using Chromium git mirrors where
+# necessary (e.g., a git mirror is used when the source project is SVN-based).
+# To update the revision that Chromium pulls for a given dependency:
+#
+# # Create and switch to a new branch
+# git new-branch depsroll
+# # Run roll-dep (provided by depot_tools) giving the dep's path and the
+# # desired SVN revision number (e.g., third_party/foo/bar and a revision such
+# # number from Subversion)
+# roll-dep third_party/foo/bar REVISION_NUMBER
+# # You should now have a modified DEPS file; commit and upload as normal
+# git commit -a
+# git cl upload
+
vars = {
# 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',
- 'sourceforge_url': 'http://svn.code.sf.net/p/%(repo)s/code',
- 'llvm_url': 'http://src.chromium.org/llvm-project',
- 'llvm_git': 'https://llvm.googlesource.com',
- 'libcxx_revision': '48198f9110397fff47fe7c37cbfa296be7d44d3d',
- 'libcxxabi_revision': '4ad1009ab3a59fa7a6896d74d5e4de5885697f95',
- 'webkit_trunk': 'http://src.chromium.org/blink/trunk',
- 'webkit_revision': '889f35a63b23d86c0f318af9a65a875117811cfd', # from svn revision 182778
+ 'webkit_revision': 'abaaf1d0b6b6483140b5dca34e80fc259833ddf7', # from svn revision 198714
'chromium_git': 'https://chromium.googlesource.com',
- 'chromiumos_git': 'https://chromium.googlesource.com/chromiumos',
- 'pdfium_git': 'https://pdfium.googlesource.com',
- 'skia_git': 'https://skia.googlesource.com',
- 'boringssl_git': 'https://boringssl.googlesource.com',
- 'libvpx_revision': 'efe9712d52c2d216fb3d1ceb508b8148847a7e4b',
+ 'libvpx_revision': '96484d320036bbc1e30f1dea232799a3e0517b1d',
'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac',
- 'skia_revision': 'b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49a',
+ 'skia_revision': 'ea561bf055bb803f4c10ca323ea60a9d94da7956',
# Three lines of non-changing comments so that
- # the commit queue can handle CLs rolling Skia
- # and V8 without interference from each other.
- 'v8_branch': 'trunk',
- 'v8_revision': '5830436a84f7792f61451af9bccd991d923fe81c', # from svn revision 24223
- # Three lines of non-changing comments so that
- # the commit queue can handle CLs rolling WebRTC
- # and V8 without interference from each other.
+ # the commit queue can handle CLs rolling V8
+ # and whatever else without interference from each other.
+ 'v8_revision': '7f211533faba9dd85708b1394186c7fe99b88392',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling swarming_client
# and whatever else without interference from each other.
- 'swarming_revision': '79940aeeec0ace78ade0fec27515850268761af5',
+ 'swarming_revision': 'b39a448d8522392389b28f6997126a6ab04bfe87',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling ANGLE
# and whatever else without interference from each other.
- "angle_revision": "df647a2a354d5dc9affdd6a982fccb6b95d361b0",
+ 'angle_revision': '44897140a2ae07dc5ba88190100179baa6fe7914',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling build tools
# and whatever else without interference from each other.
- 'buildtools_revision': '56bc51aff4175d3fa27dcd0faa2c345ab046c8a5',
+ 'buildtools_revision': 'ecc8e253abac3b6186a97573871a084f4c0ca3ae',
# Three lines of non-changing comments so that
- # the commit queue can handle CLs rolling PDFIum
+ # the commit queue can handle CLs rolling PDFium
# and whatever else without interference from each other.
- 'pdfium_revision': '7a649fe262d77f93ad3213f53e973a7665d95a23',
+ 'pdfium_revision': 'cc2323f0d0d626edac4a426097eb38b53ba54848',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling openmax_dl
# and whatever else without interference from each other.
- 'openmax_dl_revision': '79e64bc9243e5ff11822434cf39b9fabefff3bfb',
+ 'openmax_dl_revision': '22bb1085a6a0f6f3589a8c3d60ed0a9b82248275',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling BoringSSL
# and whatever else without interference from each other.
- 'boringssl_revision': '01fe820ab957514f6b83e511492de1b3c03649d5',
+ 'boringssl_revision': 'de24aadc5bc01130b6a9d25582203bb5308fabe1',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling nss
# and whatever else without interference from each other.
- 'nss_revision': '87b96db4268293187d7cf741907a6d5d1d8080e0',
+ 'nss_revision': 'aab0d08a298b29407397fbb1c4219f99e99431ed', # from svn revision 295435
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling google-toolbox-for-mac
# and whatever else without interference from each other.
- 'google_toolbox_for_mac_revision': 'a09526298f9dd1ec49d3b3ac5608d2a257b94cef',
+ 'google_toolbox_for_mac_revision': 'ce47a231ea0b238fbe95538e86cc61d74c234be6', # from svn revision 705
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling lighttpd
# and whatever else without interference from each other.
@@ -83,11 +78,11 @@
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling lss
# and whatever else without interference from each other.
- 'lss_revision': '952107fa7cea0daaabead28c0e92d579bee517eb',
+ 'lss_revision': '6f97298fe3794e92c8c896a6bc06e0b36e4c3de3',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling NaCl
# and whatever else without interference from each other.
- 'nacl_revision': 'c65c1ed84d500015273d5e72c6ddcebc2a23f9b8', # from svn revision r13797
+ 'nacl_revision': 'b3d4cc125348924f727d3b87cee3674a839b54a0',
}
# Only these hosts are allowed for dependencies in this DEPS file.
@@ -96,11 +91,12 @@
'chromium.googlesource.com',
'boringssl.googlesource.com',
'pdfium.googlesource.com',
+ 'android.googlesource.com',
]
deps = {
'src/breakpad/src':
- Var('chromium_git') + '/external/google-breakpad/src.git' + '@' + '35189355da4b65ed5e7692f790c240a9ab347731', # from svn revision 1387
+ Var('chromium_git') + '/external/google-breakpad/src.git' + '@' + '242fb9a38db6ba534b1f7daa341dd4d79171658b', # from svn revision 1471
'src/buildtools':
Var('chromium_git') + '/chromium/buildtools.git' + '@' + Var('buildtools_revision'),
@@ -109,10 +105,10 @@
Var('chromium_git') + '/external/open-vcdiff.git' + '@' + '438f2a5be6d809bc21611a94cd37bfc8c28ceb33', # from svn revision 41
'src/testing/gtest':
- Var('chromium_git') + '/external/googletest.git' + '@' + '4650552ff637bb44ecf7784060091cbed3252211', # from svn revision 692
+ Var('chromium_git') + '/external/googletest.git' + '@' + '23574bf2333f834ff665f894c97bef8a5b33a0a9', # from svn revision 711
'src/testing/gmock':
- Var('chromium_git') + '/external/googlemock.git' + '@' + '896ba0e03f520fb9b6ed582bde2bd00847e3c3f2', # from svn revision 485
+ Var('chromium_git') + '/external/googlemock.git' + '@' + '29763965ab52f24565299976b936d1265cb6a271', # from svn revision 501
'src/third_party/angle':
Var('chromium_git') + '/angle/angle.git' + '@' + Var('angle_revision'),
@@ -120,47 +116,38 @@
'src/third_party/colorama/src':
Var('chromium_git') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8',
+ 'src/third_party/crashpad/crashpad':
+ Var('chromium_git') + '/crashpad/crashpad.git' + '@' + '797adb320680a4a8ad39428075cca287e04b111f',
+
'src/third_party/trace-viewer':
- Var('chromium_git') + '/external/trace-viewer.git' + '@' + '76a4496033c164d8be9ee8c57f702b0859cb1911',
+ Var('chromium_git') + '/external/trace-viewer.git' + '@' + '4f30209abd53c699c937519f39ce41888f93507b',
'src/third_party/WebKit':
Var('chromium_git') + '/chromium/blink.git' + '@' + Var('webkit_revision'),
'src/third_party/icu':
- Var('chromium_git') + '/chromium/deps/icu52.git' + '@' + 'd2abf6c1e1f986f4a8db0341b8a8c55c55ec1174', # from svn revision 292003
+ Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'c81a1a3989c3b66fa323e9a6ee7418d7c08297af',
'src/third_party/libexif/sources':
Var('chromium_git') + '/chromium/deps/libexif/sources.git' + '@' + 'ed98343daabd7b4497f97fda972e132e6877c48a',
- 'src/third_party/hunspell':
- Var('chromium_git') + '/chromium/deps/hunspell.git' + '@' + 'c956c0e97af00ef789afb2f64d02c9a5a50e6eb1',
-
'src/third_party/hunspell_dictionaries':
- Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '4560bdd463a3500e2334e85c8a0e9e5d5d6774e7',
+ Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'c106afdcec5d3de2622e19f1b3294c47bbd8bd72',
'src/third_party/safe_browsing/testing':
Var('chromium_git') + '/external/google-safe-browsing/testing.git' + '@' + '9d7e8064f3ca2e45891470c9b5b1dce54af6a9d6',
- 'src/third_party/cacheinvalidation/src':
- Var('chromium_git') + '/external/google-cache-invalidation-api/src.git' + '@' + 'c91bd9d9fed06bf440be64f87b94a2effdb32bc4', # from svn revision 341
-
'src/third_party/leveldatabase/src':
- Var('chromium_git') + '/external/leveldb.git' + '@' + '3f77584eb3f9754bbb7079070873ece3f30a1e6b',
-
- 'src/third_party/libc++/trunk':
- Var('chromium_git') + '/chromium/llvm-project/libcxx.git' + '@' + Var('libcxx_revision'),
-
- 'src/third_party/libc++abi/trunk':
- Var('chromium_git') + '/chromium/llvm-project/libcxxabi.git' + '@' + Var('libcxxabi_revision'),
+ Var('chromium_git') + '/external/leveldb.git' + '@' + '40c17c0b84ac0b791fb434096fd5c05f3819ad55',
'src/third_party/snappy/src':
Var('chromium_git') + '/external/snappy.git' + '@' + '762bb32f0c9d2f31ba4958c7c0933d22e80c20bf',
'src/tools/grit':
- Var('chromium_git') + '/external/grit-i18n.git' + '@' + '740badd5e3e44434a9a47b5d16749daac1e8ea80', # from svn revision 176
+ Var('chromium_git') + '/external/grit-i18n.git' + '@' + '1dac9ae64b0224beb1547810933a6f9998d0d55e', # from svn revision 191
'src/tools/gyp':
- Var('chromium_git') + '/external/gyp.git' + '@' + '46282cedf40ff7fe803be4af357b9d59050f02e4', # from svn revision 1977
+ Var('chromium_git') + '/external/gyp.git' + '@' + '5122240c5e5c4d8da12c543d82b03d6089eb77c5',
'src/tools/swarming_client':
Var('chromium_git') + '/external/swarming.client.git' + '@' + Var('swarming_revision'),
@@ -171,21 +158,12 @@
'src/native_client':
Var('chromium_git') + '/native_client/src/native_client.git' + '@' + Var('nacl_revision'),
- 'src/chrome/test/data/extensions/api_test/permissions/nacl_enabled/bin':
- Var('chromium_git') + '/native_client/src/native_client/tests/prebuilt.git' + '@' + '3e17365176c94624f46cace174f61834b7f3c35d',
-
'src/third_party/sfntly/cpp/src':
Var('chromium_git') + '/external/sfntly/cpp/src.git' + '@' + Var('sfntly_revision'),
'src/third_party/skia':
Var('chromium_git') + '/skia.git' + '@' + Var('skia_revision'),
- 'src/third_party/ots':
- Var('chromium_git') + '/external/ots.git' + '@' + '98897009f3ea8a5fa3e20a4a74977da7aaa8e61a',
-
- 'src/third_party/brotli/src':
- Var('chromium_git') + '/external/font-compression-reference.git' + '@' + '6cef49677dc4c650ef6e3f56041e0a41803afa8c',
-
'src/tools/page_cycler/acid3':
Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + '6be0a66a1ebd7ebc5abc1b2f405a945f6d871521',
@@ -199,10 +177,7 @@
Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0',
'src/third_party/webgl/src':
- Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'b1a7210dc4034793e34a2149cb571e85700a85f2',
-
- 'src/third_party/swig/Lib':
- Var('chromium_git') + '/chromium/deps/swig/Lib.git' + '@' + 'f2a695d52e61e6a8d967731434f165ed400f0d69',
+ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '8986f8bfa84547b1a30a9256ebdd665024d68d71',
'src/third_party/webdriver/pylib':
Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
@@ -211,28 +186,25 @@
Var('chromium_git') + '/chromium/deps/libvpx.git' + '@' + Var('libvpx_revision'),
'src/third_party/ffmpeg':
- Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '438ff61fe51641665f0ec3bc55e7b416d0aa251a',
+ Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'f76066ad9f4aea07a53890b54d24cc22830b9efd',
'src/third_party/libjingle/source/talk':
- Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '40539b82d5a2c9bcf23d078e997ce0368160f5a3',
+ Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + 'f7c923ddc729dc7f002b0e194ab72b661f932c00', # commit position 9564
'src/third_party/usrsctp/usrsctplib':
- Var('chromium_git') + '/external/usrsctplib.git' + '@' + '8975bd5397c2ec97f50e0b87b544054e0536bfe1',
+ Var('chromium_git') + '/external/usrsctplib.git' + '@' + '36444a999739e9e408f8f587cb4c3ffeef2e50ac', # from svn revision 9215
'src/third_party/libsrtp':
- Var('chromium_git') + '/chromium/deps/libsrtp.git' + '@' + '98284c8600c73812ff4716a6ea157d1e11d417dc',
-
- 'src/third_party/speex':
- Var('chromium_git') + '/chromium/deps/speex.git' + '@' + '5260621c36c227209c7ba64ea71ca3418cf9e2b4',
+ Var('chromium_git') + '/chromium/deps/libsrtp.git' + '@' + '9c53f858cddd4d890e405e91ff3af0b48dfd90e6', # from svn revision 295151
'src/third_party/yasm/source/patched-yasm':
- Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + 'c960eb11ccda80b10ed50be39df4f0663b371d1d',
+ Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + '4671120cd8558ce62ee8672ebf3eb6f5216f909b',
'src/third_party/libjpeg_turbo':
- Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '034e9a9747e0983bc19808ea70e469bc8342081f',
+ Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + 'f4631b6ee8b1dbb05e51ae335a7886f9ac598ab6',
'src/third_party/flac':
- Var('chromium_git') + '/chromium/deps/flac.git' + '@' + '0635a091379d9677f1ddde5f2eec85d0f096f219',
+ Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'c291ce676d2c855f7b2739f00f5c7f7e813813dc',
'src/third_party/pyftpdlib/src':
Var('chromium_git') + '/external/pyftpdlib.git' + '@' + '2be6d65e31c7ee6320d059f581f05ae8d89d7e45',
@@ -241,38 +213,36 @@
Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
'src/third_party/webrtc':
- Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '53545bbfc47f2cddb7038395369a0dcd457c8b34',
+ Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '847b12a225694e10425c8a9b31e0eec028baf841', # commit position 9565
'src/third_party/openmax_dl':
Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
- 'src/third_party/jsoncpp/source/include':
- Var('chromium_git') + '/external/jsoncpp/jsoncpp/include.git' + '@' + 'b0dd48e02b6e6248328db78a65b5c601f150c349',
-
- 'src/third_party/jsoncpp/source/src/lib_json':
- Var('chromium_git') + '/external/jsoncpp/jsoncpp/src/lib_json.git' + '@' + 'a8caa51ba2f80971a45880425bf2ae864a786784',
+ 'src/third_party/jsoncpp/source':
+ Var('chromium_git') + '/external/github.com/open-source-parsers/jsoncpp.git' + '@' + 'f572e8e42e22cfcf5ab0aea26574f408943edfa4', # from svn 248
'src/third_party/libyuv':
- Var('chromium_git') + '/external/libyuv.git' + '@' + '455c66b4375d72984b79249616d0a708ad568894',
+ Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '0e83b64e8879e9469919dc96b5d970c7c5bd05af', # from version 1444
'src/third_party/smhasher/src':
Var('chromium_git') + '/external/smhasher.git' + '@' + 'e87738e57558e0ec472b2fc3a643b838e5b6e88f',
'src/third_party/libaddressinput/src':
- Var('chromium_git') + '/external/libaddressinput.git' + '@' + '945d96387a716d0d82b195fa69a5e9a701249517', # from svn revision 334
+ Var('chromium_git') + '/external/libaddressinput.git' + '@' + '5eeeb797e79fa01503fcdcbebdc50036fac023ef',
+ # These are all at libphonenumber r728.
'src/third_party/libphonenumber/src/phonenumbers':
- Var('chromium_git') + '/external/libphonenumber/cpp/src/phonenumbers.git' + '@' + '8d8b5b3b2035197795d27573d4cf566b5d9ad689',
+ Var('chromium_git') + '/external/libphonenumber/cpp/src/phonenumbers.git' + '@' + '0d6e3e50e17c94262ad1ca3b7d52b11223084bca',
'src/third_party/libphonenumber/src/test':
- Var('chromium_git') + '/external/libphonenumber/cpp/test.git' + '@' + '883b7b86541d64b2691f7c0e65facb0b08db73e8',
+ Var('chromium_git') + '/external/libphonenumber/cpp/test.git' + '@' + 'f351a7e007f9c9995494499120bbc361ca808a16',
'src/third_party/libphonenumber/src/resources':
- Var('chromium_git') + '/external/libphonenumber/resources.git' + '@' + 'de095548d2ae828a414e01f3951bfefba902b4e4',
+ Var('chromium_git') + '/external/libphonenumber/resources.git' + '@' + 'b6dfdc7952571ff7ee72643cd88c988cbe966396',
'src/tools/deps2git':
Var('chromium_git') + '/chromium/tools/deps2git.git' + '@' + 'f04828eb0b5acd3e7ad983c024870f17f17b06d9',
'src/third_party/webpagereplay':
- Var('chromium_git') + '/external/web-page-replay.git' + '@' + '2f7b704b8b567983c040f555d3e46f9766db8e87',
+ Var('chromium_git') + '/external/github.com/chromium/web-page-replay.git' + '@' + '5da5975950daa7b30a6938da73fd0b3200901b0c',
'src/third_party/pywebsocket/src':
Var('chromium_git') + '/external/pywebsocket/src.git' + '@' + 'cb349e87ddb30ff8d1fa1a89be39cec901f4a29c',
@@ -281,25 +251,25 @@
Var('chromium_git') + '/chromium/deps/opus.git' + '@' + 'cae696156f1e60006e39821e79a1811ae1933c69',
'src/media/cdm/ppapi/api':
- Var('chromium_git') + '/chromium/cdm.git' + '@' + '41c8183a3966a17b440dbe606cb2840e1b7ce884',
+ Var('chromium_git') + '/chromium/cdm.git' + '@' + '7377023e384f296cbb27644eb2c485275f1f92e8', # from svn revision 294518
'src/third_party/mesa/src':
- Var('chromium_git') + '/chromium/deps/mesa.git' + '@' + '457812d99a213dedf1c4cd38018ff48118d0c44f',
+ Var('chromium_git') + '/chromium/deps/mesa.git' + '@' + '071d25db04c23821a12a8b260ab9d96a097402f0',
'src/third_party/cld_2/src':
- Var('chromium_git') + '/external/cld2.git' + '@' + 'bb5c092e8c02dcc2319c5056aff2182199d51c2f',
-
- 'src/chrome/browser/resources/pdf/html_office':
- Var('chromium_git') + '/chromium/html-office-public.git' + '@' + 'eeff97614f65e0578529490d44d412032c3d7359',
-
- 'src/third_party/libwebm/source':
- Var('chromium_git') + '/webm/libwebm.git' + '@' + '0d4cb404ea4195e5e21d04db2c955615535ce62e',
+ Var('chromium_git') + '/external/cld2.git' + '@' + '14d9ef8d4766326f8aa7de54402d1b9c782d4481', # from svn revision 193
'src/third_party/pdfium':
'https://pdfium.googlesource.com/pdfium.git' + '@' + Var('pdfium_revision'),
'src/third_party/boringssl/src':
'https://boringssl.googlesource.com/boringssl.git' + '@' + Var('boringssl_revision'),
+
+ 'src/third_party/py_trace_event/src':
+ Var('chromium_git') + '/external/py_trace_event.git' + '@' + 'dd463ea9e2c430de2b9e53dea57a77b4c3ac9b30',
+
+ 'src/third_party/dom_distiller_js/dist':
+ Var('chromium_git') + '/external/github.com/chromium/dom-distiller-dist.git' + '@' + '81e5b59da2a7a0a518b90b5ded58670322c98128',
}
@@ -334,9 +304,6 @@
'src/third_party/nss':
Var('chromium_git') + '/chromium/deps/nss.git' + '@' + Var('nss_revision'),
- 'src/third_party/swig/win':
- Var('chromium_git') + '/chromium/deps/swig/win.git' + '@' + '986f013ba518541adf5c839811efb35630a31031',
-
# GNU binutils assembler for x86-32.
'src/third_party/gnu_binutils':
Var('chromium_git') + '/native_client/deps/third_party/gnu_binutils.git' + '@' + 'f4003433b61b25666565690caf3d7a7a1a4ec436',
@@ -351,8 +318,15 @@
# Binaries for nacl sdk.
'src/third_party/nacl_sdk_binaries':
Var('chromium_git') + '/chromium/deps/nacl_sdk_binaries.git' + '@' + '759dfca03bdc774da7ecbf974f6e2b84f43699a5',
+
+ # ANGLE uses dEQP for GPU testing
+ 'src/third_party/deqp/src':
+ 'https://android.googlesource.com/platform/external/deqp@194294e69d44eac48bc1fb063bd607189650aa5e',
},
'ios': {
+ 'src/ios/third_party/gcdwebserver/src':
+ Var('chromium_git') + '/external/github.com/swisspol/GCDWebServer.git' + '@' + '3d5fd0b8281a7224c057deb2d17709b5bea64836',
+
'src/third_party/google_toolbox_for_mac/src':
Var('chromium_git') + '/external/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'),
@@ -360,45 +334,16 @@
Var('chromium_git') + '/chromium/deps/nss.git' + '@' + Var('nss_revision'),
# class-dump utility to generate header files for undocumented SDKs
- 'src/testing/iossim/third_party/class-dump':
- Var('chromium_git') + '/chromium/deps/class-dump.git' + '@' + '89bd40883c767584240b4dade8b74e6f57b9bdab',
+ 'src/third_party/class-dump/src':
+ Var('chromium_git') + '/external/github.com/nygard/class-dump.git' + '@' + '93e7c6a5419380d89656dcc511dc60d475199b67',
# Code that's not needed due to not building everything
- 'src/build/util/support': None,
- 'src/chrome/test/data/extensions/api_test/permissions/nacl_enabled/bin': None,
'src/chrome/test/data/perf/canvas_bench': None,
'src/chrome/test/data/perf/frame_rate/content': None,
- 'src/media/cdm/ppapi/api': None,
'src/native_client': None,
- 'src/third_party/bidichecker': None,
- 'src/third_party/brotli/src': None,
- 'src/third_party/cld_2/src': None,
'src/third_party/ffmpeg': None,
'src/third_party/hunspell_dictionaries': None,
- 'src/third_party/hunspell': None,
- 'src/third_party/libc++/trunk': None,
- 'src/third_party/libc++abi/trunk': None,
- 'src/third_party/libexif/sources': None,
- 'src/third_party/libjpeg_turbo': None,
- 'src/third_party/libsrtp': None,
- 'src/third_party/opus/src': None,
- 'src/third_party/openmax_dl': None,
- 'src/third_party/ots': None,
- 'src/third_party/pymox/src': None,
- 'src/third_party/safe_browsing/testing': None,
- 'src/third_party/scons-2.0.1': None,
- 'src/third_party/sfntly/cpp/src': None,
- 'src/third_party/speex': None,
- 'src/third_party/swig/Lib': None,
- 'src/third_party/usrsctp/usrsctplib': None,
- 'src/third_party/v8-i18n': None,
- 'src/third_party/webdriver/pylib': None,
'src/third_party/webgl': None,
- 'src/third_party/webpagereplay': None,
- 'src/third_party/WebKit/LayoutTests/w3c/web-platform-tests': None,
- 'src/third_party/WebKit/LayoutTests/w3c/csswg-test': None,
- 'src/third_party/yasm/source/patched-yasm': None,
- 'src/tools/page_cycler/acid3': None,
},
'mac': {
'src/chrome/tools/test/reference_build/chrome_mac':
@@ -414,9 +359,6 @@
'src/third_party/lighttpd':
Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'),
- 'src/third_party/swig/mac':
- Var('chromium_git') + '/chromium/deps/swig/mac.git' + '@' + '1b182eef16df2b506f1d710b34df65d55c1ac44e',
-
# NSS, for SSLClientSocketNSS.
'src/third_party/nss':
Var('chromium_git') + '/chromium/deps/nss.git' + '@' + Var('nss_revision'),
@@ -432,58 +374,59 @@
'src/third_party/xdg-utils':
Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
- 'src/third_party/swig/linux':
- Var('chromium_git') + '/chromium/deps/swig/linux.git' + '@' + '866b8e0e0e0cfe99ebe608260030916ca0c3f92d',
-
'src/third_party/lss':
Var('chromium_git') + '/external/linux-syscall-support/lss.git' + '@' + Var('lss_revision'),
# For Linux and Chromium OS.
'src/third_party/cros_system_api':
- Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + 'f0fc55329fa536195861778a2ddc6115b4a977bc',
+ Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '513f58ccbcecfd4a3d21545f67136090838eaf52',
# Note that this is different from Android's freetype repo.
'src/third_party/freetype2/src':
- Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + 'd699c2994ecc178c4ed05ac2086061b2034c2178',
+ Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + '1dd5f5f4a909866f15c92a45c9702bce290a0151',
# Build tools for Chrome OS.
'src/third_party/chromite':
- Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8e92d5c24da7967e27ab2498abc2d2f7ac6ec65a',
+ Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e19f83ba227bf1ec0077f5d3a816a415f1dd88d0',
# Dependency of chromite.git.
'src/third_party/pyelftools':
Var('chromium_git') + '/chromiumos/third_party/pyelftools.git' + '@' + 'bdc1d380acd88d4bfaf47265008091483b0d614e',
- 'src/third_party/undoview':
- Var('chromium_git') + '/chromium/deps/undoview.git' + '@' + '3ba503e248f3cdbd81b78325a24ece0984637559',
-
'src/third_party/liblouis/src':
Var('chromium_git') + '/external/liblouis-github.git' + '@' + '5f9c03f2a3478561deb6ae4798175094be8a26c2',
# Used for embedded builds. CrOS & Linux use the system version.
'src/third_party/fontconfig/src':
Var('chromium_git') + '/external/fontconfig.git' + '@' + 'f16c3118e25546c1b749f9823c51827a60aeb5c1',
+
+ 'src/third_party/stp/src':
+ Var('chromium_git') + '/external/github.com/stp/stp.git' + '@' + 'fc94a599207752ab4d64048204f0c88494811b62',
},
'android': {
'src/third_party/android_protobuf/src':
- Var('chromium_git') + '/external/android_protobuf.git' + '@' + '94f522f907e3f34f70d9e7816b947e62fddbb267',
-
- # Whenever you roll this please also change frameworks/webview in
- # src/android_webview/buildbot/aosp_manifest.xml to point to the same revision.
- 'src/third_party/android_webview_glue/src':
- Var('chromium_git') + '/external/android_webview_glue.git' + '@' + 'a1b0248c80f239e2f6476b9f395b27d0ba1eb3cd',
+ Var('chromium_git') + '/external/android_protobuf.git' + '@' + '999188d0dc72e97f7fe08bb756958a2cf090f4e7',
'src/third_party/android_tools':
- Var('chromium_git') + '/android_tools.git' + '@' + 'd2b86205ff973a3844020feacb35ca6b1d82efbe',
+ Var('chromium_git') + '/android_tools.git' + '@' + '21f4bcbd6cd927e4b4227cfde7d5f13486be1236',
'src/third_party/apache-mime4j':
Var('chromium_git') + '/chromium/deps/apache-mime4j.git' + '@' + '28cb1108bff4b6cf0a2e86ff58b3d025934ebe3a',
+ 'src/third_party/appurify-python/src':
+ Var('chromium_git') + '/external/github.com/appurify/appurify-python.git' + '@' + 'ee7abd5c5ae3106f72b2a0b9d2cb55094688e867',
+
+ 'src/third_party/cardboard-java/src':
+ Var('chromium_git') + '/external/github.com/googlesamples/cardboard-java.git' + '@' + '08ad25a04f2801bd822c3f2cd28301b68d74aef6',
+
+ 'src/third_party/errorprone/lib':
+ Var('chromium_git') + '/chromium/third_party/errorprone.git' + '@' + '6c66e56c0f9d750aef83190466df834f9d6af8ab',
+
'src/third_party/findbugs':
Var('chromium_git') + '/chromium/deps/findbugs.git' + '@' + '7f69fa78a6db6dc31866d09572a0e356e921bf12',
- 'src/third_party/freetype':
- Var('chromium_git') + '/chromium/src/third_party/freetype.git' + '@' + 'a2b9955b49034a51dfbc8bf9f4e9d312149cecac',
+ 'src/third_party/freetype-android/src':
+ Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + 'e186230678ee8e4ea4ac4797ece8125761e3225a',
'src/third_party/elfutils/src':
Var('chromium_git') + '/external/elfutils.git' + '@' + '249673729a7e5dbd5de4f3760bdcaa3d23d154d7',
@@ -501,19 +444,32 @@
Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919',
'src/third_party/junit/src':
- Var('chromium_git') + '/external/junit.git' + '@' + 'c62e2df8dbecccb1b434d4ba8843b59e90b03266',
+ Var('chromium_git') + '/external/junit.git' + '@' + '45a44647e7306262162e1346b750c3209019f2e1',
+
+ 'src/third_party/mockito/src':
+ Var('chromium_git') + '/external/mockito/mockito.git' + '@' + 'ed99a52e94a84bd7c467f2443b475a22fcc6ba8e',
+
+ 'src/third_party/robolectric/lib':
+ Var('chromium_git') + '/chromium/third_party/robolectric.git' + '@' + '6b63c99a8b6967acdb42cbed0adb067c80efc810',
+
+ 'src/third_party/ub-uiautomator/lib':
+ Var('chromium_git') + '/chromium/third_party/ub-uiautomator.git' + '@' + 'e6f02481bada8bdbdfdd7987dd6e648c44a3adcb',
'src/third_party/lss':
Var('chromium_git') + '/external/linux-syscall-support/lss.git' + '@' + Var('lss_revision'),
- 'src/third_party/eyesfree/src/android/java/src/com/googlecode/eyesfree/braille':
- Var('chromium_git') + '/external/eyes-free/braille/client/src/com/googlecode/eyesfree/braille.git' + '@' + '77bf6edb0138e3a38a2772248696f130dab45e34',
+ 'src/third_party/requests/src':
+ Var('chromium_git') + '/external/github.com/kennethreitz/requests.git' + '@' + 'f172b30356d821d180fa4ecfa3e71c7274a32de4',
+
+ 'src/third_party/custom_tabs_client/src':
+ Var('chromium_git') + '/external/github.com/GoogleChrome/custom-tabs-client.git' + '@' + 'ef3ea193af9f4e45dd5094e8b6a952fb213bf11e',
},
}
include_rules = [
# Everybody can use some things.
+ # NOTE: THIS HAS TO STAY IN SYNC WITH third_party/DEPS which disallows these.
'+base',
'+build',
'+ipc',
@@ -531,14 +487,11 @@
# checkdeps.py shouldn't check include paths for files in these dirs:
skip_child_includes = [
'breakpad',
- 'delegate_execute',
- 'metro_driver',
'native_client_sdk',
- 'o3d',
+ 'out',
'sdch',
'skia',
'testing',
- 'third_party',
'v8',
'win8',
]
@@ -563,42 +516,31 @@
'name': 'nacltools',
'pattern': '.',
'action': [
- 'python', 'src/build/download_nacl_toolchains.py',
- '--exclude', 'arm_trusted',
+ 'python',
+ 'src/build/download_nacl_toolchains.py',
+ '--mode', 'nacl_core_sdk',
+ 'sync', '--extract',
],
},
{
- # Downloads an ARM sysroot image to src/arm-sysroot. This image updates
- # at about the same rate that the chrome build deps change.
- # This script is a no-op except for linux users who have
- # target_arch=arm in their GYP_DEFINES.
- 'name': 'sysroot',
+ # This downloads SDK extras and puts them in the
+ # third_party/android_tools/sdk/extras directory on the bots. Developers
+ # need to manually install these packages and accept the ToS.
+ 'name': 'sdkextras',
'pattern': '.',
- 'action': ['python', 'src/build/linux/install-arm-sysroot.py',
- '--linux-only'],
+ # When adding a new sdk extras package to download, add the package
+ # directory and zip file to .gitignore in third_party/android_tools.
+ 'action': ['python', 'src/build/download_sdk_extras.py'],
},
{
- # Downloads the Debian Wheezy sysroot to chrome/installer/linux if needed.
+ # Downloads the current stable linux sysroot to build/linux/ if needed.
# This sysroot updates at about the same rate that the chrome build deps
# change. This script is a no-op except for linux users who are doing
- # official chrome builds.
+ # official chrome builds or cross compiling.
'name': 'sysroot',
'pattern': '.',
- 'action': [
- 'python',
- 'src/chrome/installer/linux/sysroot_scripts/install-debian.wheezy.sysroot.py',
- '--linux-only',
- '--arch=amd64'],
- },
- {
- # Same as above, but for 32-bit Linux.
- 'name': 'sysroot',
- 'pattern': '.',
- 'action': [
- 'python',
- 'src/chrome/installer/linux/sysroot_scripts/install-debian.wheezy.sysroot.py',
- '--linux-only',
- '--arch=i386'],
+ 'action': ['python', 'src/build/linux/sysroot_scripts/install-sysroot.py',
+ '--running-as-hook'],
},
{
# Update the Windows toolchain if necessary.
@@ -606,6 +548,17 @@
'pattern': '.',
'action': ['python', 'src/build/vs_toolchain.py', 'update'],
},
+ # Pull binutils for linux, enabled debug fission for faster linking /
+ # debugging when used with clang on Ubuntu Precise.
+ # https://code.google.com/p/chromium/issues/detail?id=352046
+ {
+ 'name': 'binutils',
+ 'pattern': 'src/third_party/binutils',
+ 'action': [
+ 'python',
+ 'src/third_party/binutils/download.py',
+ ],
+ },
{
# Pull clang if needed or requested via GYP_DEFINES.
# Note: On Win, this should run after win_toolchain, as it may use it.
@@ -614,16 +567,14 @@
'action': ['python', 'src/tools/clang/scripts/update.py', '--if-needed'],
},
{
- # Update LASTCHANGE. This is also run by export_tarball.py in
- # src/tools/export_tarball - please keep them in sync.
+ # Update LASTCHANGE.
'name': 'lastchange',
'pattern': '.',
'action': ['python', 'src/build/util/lastchange.py',
'-o', 'src/build/util/LASTCHANGE'],
},
{
- # Update LASTCHANGE.blink. This is also run by export_tarball.py in
- # src/tools/export_tarball - please keep them in sync.
+ # Update LASTCHANGE.blink.
'name': 'lastchange',
'pattern': '.',
'action': ['python', 'src/build/util/lastchange.py',
@@ -654,17 +605,6 @@
],
},
{
- 'name': 'gn_linux32',
- 'pattern': '.',
- 'action': [ 'download_from_google_storage',
- '--no_resume',
- '--platform=linux*',
- '--no_auth',
- '--bucket', 'chromium-gn',
- '-s', 'src/buildtools/linux32/gn.sha1',
- ],
- },
- {
'name': 'gn_linux64',
'pattern': '.',
'action': [ 'download_from_google_storage',
@@ -709,15 +649,38 @@
'-s', 'src/buildtools/linux64/clang-format.sha1',
],
},
- # Pull binutils for linux, enabled debug fission for faster linking /
- # debugging when used with clang on Ubuntu Precise.
- # https://code.google.com/p/chromium/issues/detail?id=352046
+ # Pull luci-go binaries (isolate, swarming) using checked-in hashes.
{
- 'name': 'binutils',
- 'pattern': 'src/third_party/binutils',
- 'action': [
- 'python',
- 'src/third_party/binutils/download.py',
+ 'name': 'luci-go_win',
+ 'pattern': '.',
+ 'action': [ 'download_from_google_storage',
+ '--no_resume',
+ '--platform=win32',
+ '--no_auth',
+ '--bucket', 'chromium-luci',
+ '-d', 'src/tools/luci-go/win64',
+ ],
+ },
+ {
+ 'name': 'luci-go_mac',
+ 'pattern': '.',
+ 'action': [ 'download_from_google_storage',
+ '--no_resume',
+ '--platform=darwin',
+ '--no_auth',
+ '--bucket', 'chromium-luci',
+ '-d', 'src/tools/luci-go/mac64',
+ ],
+ },
+ {
+ 'name': 'luci-go_linux',
+ 'pattern': '.',
+ 'action': [ 'download_from_google_storage',
+ '--no_resume',
+ '--platform=linux*',
+ '--no_auth',
+ '--bucket', 'chromium-luci',
+ '-d', 'src/tools/luci-go/linux64',
],
},
# Pull eu-strip binaries using checked-in hashes.
@@ -750,7 +713,19 @@
'action': ['python',
'src/build/get_syzygy_binaries.py',
'--output-dir=src/third_party/syzygy/binaries',
- '--revision=363bc02a09c380b6f5f397606cc0744d85d54a51',
+ '--revision=e50a9822fc8aeb5e7902da5e2940ea135d732e57',
+ '--overwrite',
+ ],
+ },
+ {
+ 'name': 'kasko',
+ 'pattern': '.',
+ 'action': ['python',
+ 'src/build/get_syzygy_binaries.py',
+ '--output-dir=src/third_party/kasko',
+ '--revision=283aeaceeb22e2ba40a1753e3cb32454b59cc017',
+ '--resource=kasko.zip',
+ '--resource=kasko_symbols.zip',
'--overwrite',
],
},
@@ -768,6 +743,40 @@
'src/third_party/apache-win32',
],
},
+ # Pull the mojo_shell binary, used for mojo development
+ {
+ 'name': 'download_mojo_shell',
+ 'pattern': '',
+ 'action': [ 'python',
+ 'src/third_party/mojo/src/mojo/public/tools/download_shell_binary.py',
+ '--tools-directory=../../../../../../tools',
+ ],
+ },
+ {
+ # Pull sanitizer-instrumented third-party libraries if requested via
+ # GYP_DEFINES.
+ 'name': 'instrumented_libraries',
+ 'pattern': '\\.sha1',
+ 'action': ['python', 'src/third_party/instrumented_libraries/scripts/download_binaries.py'],
+ },
+ {
+ # Ensure that while generating dependencies lists in .gyp files we don't
+ # accidentally reference any .pyc files whose corresponding .py files have
+ # already been deleted.
+ # We should actually try to avoid generating .pyc files, crbug.com/500078.
+ 'name': 'remove_stale_pyc_files',
+ 'pattern': '.',
+ 'action': [
+ 'python',
+ 'src/tools/remove_stale_pyc_files.py',
+ 'src/android_webview/tools',
+ 'src/gpu/gles2_conform_support',
+ 'src/ppapi',
+ 'src/printing',
+ 'src/third_party/closure_compiler/build',
+ 'src/tools',
+ ],
+ },
{
# A change to a .gyp, .gypi, or to GYP itself should run the generator.
'name': 'gyp',
@@ -786,15 +795,4 @@
'--running-as-hook',
],
},
- {
- # Ensure that we don't accidentally reference any .pyc files whose
- # corresponding .py files have already been deleted.
- 'name': 'remove_stale_pyc_files',
- 'pattern': 'src/tools/.*\\.py',
- 'action': [
- 'python',
- 'src/tools/remove_stale_pyc_files.py',
- 'src/tools',
- ],
- },
]
diff --git a/tools/dom/dom.py b/tools/dom/dom.py
index c69d065..1316ab1 100755
--- a/tools/dom/dom.py
+++ b/tools/dom/dom.py
@@ -148,7 +148,7 @@
print('Browse tests at '
'\033[94mhttp://localhost:%d/root_build/generated_tests/\033[0m' % port)
return call([
- utils.DartBinary(),
+ utils.CheckedInSdkExecutable(),
os.path.join('tools', 'testing', 'dart', 'http_server.dart'),
'--port=%d' % port,
'--crossOriginPort=%d' % (port + 1),
diff --git a/tools/dom/new_scripts/dart_utilities.py b/tools/dom/new_scripts/dart_utilities.py
index f67437b..3972783 100644
--- a/tools/dom/new_scripts/dart_utilities.py
+++ b/tools/dom/new_scripts/dart_utilities.py
@@ -156,7 +156,6 @@
DartUtilities.has_extended_attribute = v8_utilities.has_extended_attribute
DartUtilities.has_extended_attribute_value = v8_utilities.has_extended_attribute_value
DartUtilities.measure_as = _measure_as
-DartUtilities.per_context_enabled_function_name = v8_utilities.per_context_enabled_function_name
DartUtilities.runtime_enabled_function_name = v8_utilities.runtime_enabled_function_name
DartUtilities.scoped_name = _scoped_name
DartUtilities.strip_suffix = v8_utilities.strip_suffix
diff --git a/tools/dom/new_scripts/dependency.py b/tools/dom/new_scripts/dependency.py
new file mode 100644
index 0000000..060277e
--- /dev/null
+++ b/tools/dom/new_scripts/dependency.py
@@ -0,0 +1,9 @@
+builder = None
+
+def set_builder(created_builder):
+ global builder;
+ builder = created_builder
+
+def get_interfaces_info():
+ global builder;
+ return builder._info_collector.interfaces_info
diff --git a/tools/dom/scripts/dartdomgenerator.py b/tools/dom/scripts/dartdomgenerator.py
index 5a35903..4b07d77 100755
--- a/tools/dom/scripts/dartdomgenerator.py
+++ b/tools/dom/scripts/dartdomgenerator.py
@@ -45,6 +45,7 @@
import time
from dartmetadata import DartMetadata
from generator import TypeRegistry
+from generate_blink_file import Generate_Blink
from htmleventgenerator import HtmlEventGenerator
from htmlrenamer import HtmlRenamer
from systemhtml import DartLibraryEmitter, Dart2JSBackend,\
@@ -78,8 +79,9 @@
common_database.Load()
return common_database
-def GenerateFromDatabase(common_database, dart2js_output_dir,
- dartium_output_dir, update_dom_metadata=False,
+def GenerateFromDatabase(common_database,
+ dart2js_output_dir, dartium_output_dir, blink_output_dir,
+ update_dom_metadata=False,
logging_level=logging.WARNING, dart_js_interop=False):
print '\n ----- Accessing DOM using %s -----\n' % ('dart:js' if dart_js_interop else 'C++')
@@ -194,6 +196,14 @@
webkit_database, dartium_output_dir, type_registry, renamer)
emitters.Flush()
+ if blink_output_dir:
+ print '\nGenerating _blink:\n'
+ start_time = time.time()
+
+ Generate_Blink(blink_output_dir, webkit_database, type_registry)
+
+ print 'Generated _blink in %s seconds' % round(time.time() - start_time, 2)
+
if update_dom_metadata:
metadata.Flush()
@@ -222,8 +232,8 @@
help='Use fremontcut in parallel mode.')
parser.add_option('--systems', dest='systems',
action='store', type='string',
- default='htmldart2js,htmldartium',
- help='Systems to generate (htmldart2js, htmldartium)')
+ default='htmldart2js,htmldartium,_blink',
+ help='Systems to generate (htmldart2js, htmldartium, _blink)')
parser.add_option('--output-dir', dest='output_dir',
action='store', type='string',
default=None,
@@ -267,6 +277,9 @@
dartium_output_dir = None
if 'htmldartium' in systems:
dartium_output_dir = os.path.join(output_dir, 'dartium')
+ blink_output_dir = None
+ if '_blink' in systems:
+ blink_output_dir = os.path.join(output_dir, 'dartium')
logging_level = options.logging_level \
if options.logging == logging.NOTSET else options.logging
@@ -278,8 +291,13 @@
# Parse the IDL and create the database.
database = fremontcutbuilder.main(options.parallel, logging_level=logging_level, examine_idls=options.examine_idls)
- GenerateFromDatabase(database, dart2js_output_dir, dartium_output_dir,
- options.update_dom_metadata, logging_level, options.dart_js_interop)
+ GenerateFromDatabase(database,
+ dart2js_output_dir,
+ dartium_output_dir,
+ blink_output_dir,
+ options.update_dom_metadata,
+ logging_level,
+ options.dart_js_interop)
file_generation_start_time = time.time()
@@ -300,6 +318,14 @@
os.path.join(dartium_output_dir, '%s_dartium.dart' % library_name),
os.path.join('..', '..', '..', 'sdk', 'lib', library_name, 'dartium'))
+ if '_blink' in systems:
+ _logger.info('Generating dartium _blink file.')
+ file_generation_start_time = time.time()
+
+ GenerateSingleFile(
+ os.path.join(dartium_output_dir, '%s_dartium.dart' % '_blink'),
+ os.path.join('..', '..', '..', 'sdk', 'lib', '_blink', 'dartium'))
+
print '\nGenerating single file %s seconds' % round(time.time() - file_generation_start_time, 2)
end_time = time.time()
diff --git a/tools/dom/scripts/dartgenerator.py b/tools/dom/scripts/dartgenerator.py
index 1b8db33..55a3499 100755
--- a/tools/dom/scripts/dartgenerator.py
+++ b/tools/dom/scripts/dartgenerator.py
@@ -38,6 +38,10 @@
if IsRegisteredType(type_name):
return True
+ # References a typedef - normally a union type.
+ if database.HasTypeDef(type_name):
+ return True
+
if type_name.endswith('?'):
return self._IsCompoundType(database, type_name[:-len('?')])
diff --git a/tools/dom/scripts/database.py b/tools/dom/scripts/database.py
index fc8b659..19ca222 100755
--- a/tools/dom/scripts/database.py
+++ b/tools/dom/scripts/database.py
@@ -44,6 +44,8 @@
self._interfaces_to_delete = []
self._enums = {}
self._all_dictionaries = {}
+ # TODO(terry): Hack to remember all typedef unions.
+ self._all_type_defs = {}
def Clone(self):
new_database = Database(self._root_dir)
@@ -52,6 +54,7 @@
self._interfaces_to_delete)
new_database._enums = copy.deepcopy(self._enums)
new_database._all_dictionaries = copy.deepcopy(self._all_dictionaries)
+ new_database._all_type_defs = copy.deepcopy(self._all_type_defs)
return new_database
@@ -282,6 +285,29 @@
res.append(dictionary)
return res
+ def HasTypeDef(self, type_def_name):
+ """Returns True if the typedef is in memory"""
+ return type_def_name in self._all_type_defs
+
+ def GetTypeDef(self, type_def_name):
+ """Returns an IDLTypeDef corresponding to the type_def_name
+ from memory.
+
+ Args:
+ type_def_name -- the name of the typedef.
+ """
+ if type_def_name not in self._all_type_defs:
+ raise RuntimeError('Typedef %s is not loaded' % type_def_name)
+ return self._all_type_defs[type_def_name]
+
+ def AddTypeDef(self, type_def):
+ """Add only a typedef that a unions they map to any (no type)."""
+ type_def_name = type_def.id
+ if type_def_name in self._all_type_defs:
+ raise RuntimeError('Typedef %s already exists' % type_def_name)
+ self._all_type_defs[type_def_name] = type_def
+ print ' Added typedef %s' % type_def_name
+
def TransitiveSecondaryParents(self, interface, propagate_event_target):
"""Returns a list of all non-primary parents.
diff --git a/tools/dom/scripts/databasebuilder.py b/tools/dom/scripts/databasebuilder.py
index f61b81b..ceb6eb1 100755
--- a/tools/dom/scripts/databasebuilder.py
+++ b/tools/dom/scripts/databasebuilder.py
@@ -20,9 +20,7 @@
import compiler
import compute_interfaces_info_individual
-from compute_interfaces_info_individual import compute_info_individual, info_individual
-import compute_interfaces_info_overall
-from compute_interfaces_info_overall import compute_interfaces_info_overall, interfaces_info
+from compute_interfaces_info_individual import InterfaceInfoCollector
import idl_definitions
from idlnode import *
@@ -132,7 +130,7 @@
# Create compiler.
self.idl_compiler = compiler.IdlCompilerDart(self.output_directory,
attrib_file,
- interfaces_info=interfaces_info,
+ interfaces_info=provider._info_collector.interfaces_info,
only_if_changed=True)
def format_exception(self, e):
@@ -168,13 +166,15 @@
def __init__(self, database):
"""DatabaseBuilder is used for importing and merging interfaces into
the Database"""
+ self._info_collector = InterfaceInfoCollector()
+
self._database = database
self._imported_interfaces = []
self._impl_stmts = []
self.conditionals_met = set()
# Spin up the new IDL parser.
- self.build = Build(None)
+ self.build = Build(self)
# Global typedef to mapping.
self.global_type_defs = monitored.Dict('databasebuilder.global_type_defs', {
@@ -186,13 +186,21 @@
# a type name.
def _resolve_type_defs(self, idl_file):
for type_node in idl_file.all(IDLType):
+ resolved = False
type_name = type_node.id
for typedef in self.global_type_defs:
seq_name_typedef = 'sequence<%s>' % typedef
if type_name == typedef:
type_node.id = self.global_type_defs[typedef]
+ resolved = True
elif type_name == seq_name_typedef:
type_node.id = 'sequence<%s>' % self.global_type_defs[typedef]
+ resolved = True
+ if not(resolved):
+ for typedef in idl_file.typeDefs:
+ if type_name == typedef.id:
+ type_node.id = typedef.type.id
+ resolved = True
def _strip_ext_attributes(self, idl_file):
"""Strips unuseful extended attributes."""
@@ -559,11 +567,11 @@
if not(is_dart_idl):
start_time = time.time()
- # 2-stage computation: individual, then overall
+ # Compute information for individual files
+ # Information is stored in global variables interfaces_info and
+ # partial_interface_files.
for file_path in file_paths:
- compute_info_individual(file_path)
- info_individuals = [info_individual()]
- compute_interfaces_info_overall(info_individuals)
+ self._info_collector.collect_info(file_path)
end_time = time.time()
print 'Compute dependencies %s seconds' % round((end_time - start_time), 2)
@@ -572,7 +580,7 @@
# file is special in that more than one interface can exist in this file.
implement_pairs = self._compute_dart_idl_implements(file_paths[0])
- interfaces_info['__dart_idl___'] = {
+ self._info_collector.interfaces_info['__dart_idl___'] = {
'implement_pairs': implement_pairs,
}
@@ -645,6 +653,10 @@
for dictionary in idl_file.dictionaries:
self._database.AddDictionary(dictionary)
+ # TODO(terry): Hack to remember all typedef unions they're mapped to any
+ # - no type.
+ for typedef in idl_file.typeDefs:
+ self._database.AddTypeDef(typedef)
def _is_node_enabled(self, node, idl_defines):
if not 'Conditional' in node.ext_attrs:
diff --git a/tools/dom/scripts/fremontcutbuilder.py b/tools/dom/scripts/fremontcutbuilder.py
index ed11625..d368470 100755
--- a/tools/dom/scripts/fremontcutbuilder.py
+++ b/tools/dom/scripts/fremontcutbuilder.py
@@ -10,6 +10,7 @@
import sys
import time
import utilities
+import dependency
_logger = logging.getLogger('fremontcutbuilder')
@@ -50,6 +51,7 @@
db.Delete()
builder = databasebuilder.DatabaseBuilder(db)
+ dependency.set_builder(builder)
# TODO(vsm): Move this to a README.
# This is the Dart SVN revision.
diff --git a/tools/dom/scripts/generate_blink_file.py b/tools/dom/scripts/generate_blink_file.py
new file mode 100644
index 0000000..d5ea86f
--- /dev/null
+++ b/tools/dom/scripts/generate_blink_file.py
@@ -0,0 +1,275 @@
+#!/usr/bin/python
+#
+# 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.
+
+"""Generates sdk/lib/_blink/dartium/_blink_dartium.dart file."""
+
+import os
+
+from generator import AnalyzeOperation, AnalyzeConstructor
+
+HEADER = """/* 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.
+ *
+ * DO NOT EDIT
+ * Auto-generated _blink library.
+ */
+library dart.dom._blink;
+
+import 'dart:js' as js;
+import 'dart:html' show DomException;
+// This is a place to put custom renames if we need them.
+final resolverMap = {
+};
+
+dynamic resolver(String s) {
+"""
+
+END_RESOLVER = """
+ // Failed to find it, check for custom renames
+ dynamic obj = resolverMap[s];
+ if (obj != null) return obj;
+ throw("No such interface exposed in blink: ${s}");
+}
+
+"""
+
+BLINK_UTILS = """
+// _Utils native entry points
+class Blink_Utils {
+ static window() native "Utils_window";
+
+ static forwardingPrint(message) native "Utils_forwardingPrint";
+
+ static spawnDomUri(uri) native "Utils_spawnDomUri";
+
+ static void spawnDomHelper(Function f, int replyTo) native "Utils_spawnDomHelper";
+
+ static register(document, tag, customType, extendsTagName) native "Utils_register";
+
+ static createElement(document, tagName) native "Utils_createElement";
+
+ static constructElement(element_type, jsObject) native "Utils_constructor_create";
+
+ static initializeCustomElement(element) native "Utils_initializeCustomElement";
+
+ static changeElementWrapper(element, type) native "Utils_changeElementWrapper";
+}
+
+class Blink_DOMWindowCrossFrame {
+ // FIXME: Return to using explicit cross frame entry points after roll to M35
+ static get_history(_DOMWindowCrossFrame) native "Window_history_cross_frame_Getter";
+
+ static get_location(_DOMWindowCrossFrame) native "Window_location_cross_frame_Getter";
+
+ static get_closed(_DOMWindowCrossFrame) native "Window_closed_Getter";
+
+ static get_opener(_DOMWindowCrossFrame) native "Window_opener_Getter";
+
+ static get_parent(_DOMWindowCrossFrame) native "Window_parent_Getter";
+
+ static get_top(_DOMWindowCrossFrame) native "Window_top_Getter";
+
+ static close(_DOMWindowCrossFrame) native "Window_close_Callback";
+
+ static postMessage(_DOMWindowCrossFrame, message, targetOrigin, [messagePorts]) native "Window_postMessage_Callback";
+}
+
+class Blink_HistoryCrossFrame {
+ // _HistoryCrossFrame native entry points
+ static back(_HistoryCrossFrame) native "History_back_Callback";
+
+ static forward(_HistoryCrossFrame) native "History_forward_Callback";
+
+ static go(_HistoryCrossFrame, distance) native "History_go_Callback";
+}
+
+class Blink_LocationCrossFrame {
+ // _LocationCrossFrame native entry points
+ static set_href(_LocationCrossFrame, h) native "Location_href_Setter";
+}
+
+class Blink_DOMStringMap {
+ // _DOMStringMap native entry points
+ static containsKey(_DOMStringMap, key) native "DOMStringMap_containsKey_Callback";
+
+ static item(_DOMStringMap, key) native "DOMStringMap_item_Callback";
+
+ static setItem(_DOMStringMap, key, value) native "DOMStringMap_setItem_Callback";
+
+ static remove(_DOMStringMap, key) native "DOMStringMap_remove_Callback";
+
+ static get_keys(_DOMStringMap) native "DOMStringMap_getKeys_Callback";
+}
+
+// Calls through JsNative but returns DomException instead of error strings.
+class Blink_JsNative_DomException {
+ static getProperty(js.JsObject o, name) {
+ try {
+ return js.JsNative.getProperty(o, name);
+ } catch (e) {
+ // Re-throw any errors (returned as a string) as a DomException.
+ throw new DomException.jsInterop(e);
+ }
+ }
+
+ static callMethod(js.JsObject o, String method, List args) {
+ try {
+ return js.JsNative.callMethod(o, method, args);
+ } catch (e) {
+ // Re-throw any errors (returned as a string) as a DomException.
+ throw new DomException.jsInterop(e);
+ }
+ }
+}"""
+
+CLASS_DEFINITION = """class Blink%s {
+ static final instance = new Blink%s();
+
+"""
+
+CLASS_DEFINITION_EXTENDS = """class Blink%s extends Blink%s {
+ static final instance = new Blink%s();
+
+"""
+
+#(interface_name)
+CONSTRUCTOR_0 = ' constructorCallback_0_() => new js.JsObject(Blink_JsNative_DomException.getProperty(js.context, "%s"), []);\n\n'
+
+#(argument_count, arguments, interface_name, arguments)
+CONSTRUCTOR_ARGS = ' constructorCallback_%s_(%s) => new js.JsObject(Blink_JsNative_DomException.getProperty(js.context, "%s"), [%s]);\n\n'
+
+#(attribute_name, attribute_name)
+ATTRIBUTE_GETTER = ' %s_Getter_(mthis) => Blink_JsNative_DomException.getProperty(mthis, "%s");\n\n'
+ATTRIBUTE_SETTER = ' %s_Setter_(mthis, __arg_0) => mthis["%s"] = __arg_0;\n\n'
+
+#(operation_name, operationName)
+OPERATION_0 = ' %s_Callback_0_(mthis) => Blink_JsNative_DomException.callMethod(mthis, "%s", []);\n\n'
+
+#(operation_name, argument_count, arguments, operation_name, arguments)
+ARGUMENT_NUM = "__arg_%s"
+OPERATION_ARGS = ' %s_Callback_%s_(mthis, %s) => Blink_JsNative_DomException.callMethod(mthis, "%s", [%s]);\n\n'
+
+CLASS_DEFINITION_END = """}
+
+"""
+
+def ConstantOutputOrder(a, b):
+ """Canonical output ordering for constants."""
+ return cmp(a.id, b.id)
+
+def generate_parameter_entries(param_infos):
+ optional_default_args = 0;
+ for argument in param_infos:
+ if argument.is_optional:
+ optional_default_args += 1
+
+ arg_count = len(param_infos)
+ min_arg_count = arg_count - optional_default_args
+ lb = min_arg_count - 2 if min_arg_count > 2 else 0
+ return (lb, arg_count + 1)
+
+def Generate_Blink(output_dir, database, type_registry):
+ blink_filename = os.path.join(output_dir, '_blink_dartium.dart')
+ blink_file = open(blink_filename, 'w')
+
+ blink_file.write(HEADER);
+
+ interfaces = database.GetInterfaces()
+ for interface in interfaces:
+ name = interface.id
+ resolver_entry = ' if (s == "%s") return Blink%s.instance;\n' % (name, name)
+ blink_file.write(resolver_entry)
+
+ blink_file.write(END_RESOLVER);
+
+ for interface in interfaces:
+ name = interface.id
+
+ if interface.parents and len(interface.parents) > 0 and interface.parents[0].id:
+ extends = interface.parents[0].id
+ class_def = CLASS_DEFINITION_EXTENDS % (name, extends, name)
+ else:
+ class_def = CLASS_DEFINITION % (name, name)
+ blink_file.write(class_def);
+
+ analyzed_constructors = AnalyzeConstructor(interface)
+ if analyzed_constructors:
+ _Emit_Blink_Constructors(blink_file, analyzed_constructors)
+ elif 'Constructor' in interface.ext_attrs:
+ # Zero parameter constructor.
+ blink_file.write(CONSTRUCTOR_0 % name)
+
+ _Process_Attributes(blink_file, interface.attributes)
+ _Process_Operations(blink_file, interface, interface.operations)
+
+ secondary_parents = database.TransitiveSecondaryParents(interface, False)
+ for secondary in secondary_parents:
+ _Process_Attributes(blink_file, secondary.attributes)
+ _Process_Operations(blink_file, secondary, secondary.operations)
+
+ blink_file.write(CLASS_DEFINITION_END);
+
+ blink_file.write(BLINK_UTILS)
+
+ blink_file.close()
+
+def _Emit_Blink_Constructors(blink_file, analyzed_constructors):
+ (arg_min_count, arg_max_count) = generate_parameter_entries(analyzed_constructors.param_infos)
+ name = analyzed_constructors.js_name
+ if not(name):
+ name = analyzed_constructors.type_name
+
+ for callback_index in range(arg_min_count, arg_max_count):
+ if callback_index == 0:
+ blink_file.write(CONSTRUCTOR_0 % (name))
+ else:
+ arguments = []
+ for i in range(0, callback_index):
+ arguments.append(ARGUMENT_NUM % i)
+ argument_list = ', '.join(arguments)
+ blink_file.write(CONSTRUCTOR_ARGS % (callback_index, argument_list, name, argument_list))
+
+def _Process_Attributes(blink_file, attributes):
+ # Emit an interface's attributes and operations.
+ for attribute in sorted(attributes, ConstantOutputOrder):
+ name = attribute.id
+ if attribute.is_read_only:
+ blink_file.write(ATTRIBUTE_GETTER % (name, name))
+ else:
+ blink_file.write(ATTRIBUTE_GETTER % (name, name))
+ blink_file.write(ATTRIBUTE_SETTER % (name, name))
+
+def _Process_Operations(blink_file, interface, operations):
+ analyzeOperations = []
+
+ for operation in sorted(operations, ConstantOutputOrder):
+ if len(analyzeOperations) == 0:
+ analyzeOperations.append(operation)
+ else:
+ if analyzeOperations[0].id == operation.id:
+ # Handle overloads
+ analyzeOperations.append(operation)
+ else:
+ _Emit_Blink_Operation(blink_file, interface, analyzeOperations)
+ analyzeOperations = [operation]
+ if len(analyzeOperations) > 0:
+ _Emit_Blink_Operation(blink_file, interface, analyzeOperations)
+
+def _Emit_Blink_Operation(blink_file, interface, analyzeOperations):
+ analyzed = AnalyzeOperation(interface, analyzeOperations)
+ (arg_min_count, arg_max_count) = generate_parameter_entries(analyzed.param_infos)
+ name = analyzed.js_name
+
+ for callback_index in range(arg_min_count, arg_max_count):
+ if callback_index == 0:
+ blink_file.write(OPERATION_0 % (name, name))
+ else:
+ arguments = []
+ for i in range(0, callback_index):
+ arguments.append(ARGUMENT_NUM % i)
+ argument_list = ', '.join(arguments)
+ blink_file.write(OPERATION_ARGS % (name, callback_index, argument_list, name, argument_list))
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index 6d235b81..bb26d6f 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -457,7 +457,14 @@
parameter declaration.
"""
def FormatParam(param):
- dart_type = rename_type(param.type_id) if param.type_id else 'dynamic'
+ # Is the type a typedef if so it's a union so it's dynamic.
+ # TODO(terry): This may have to change for dart2js for code shaking the
+ # return types (unions) needs to be emitted with @create
+ # annotations and/or with JS('type1|type2',...)
+ if hasattr(rename_type, 'im_self') and rename_type.im_self._database.HasTypeDef(param.type_id):
+ dart_type = 'dynamic'
+ else:
+ dart_type = rename_type(param.type_id) if param.type_id else 'dynamic'
return (TypeOrNothing(dart_type, param.type_id), param.name)
required = []
optional = []
@@ -1367,6 +1374,9 @@
def HasInterface(self, type_name):
return self._database.HasInterface(type_name)
+ def HasTypeDef(self, type_def_name):
+ return self._database.HasTypeDef(type_def_name)
+
def TypeInfo(self, type_name):
if not type_name in self._cache:
self._cache[type_name] = self._TypeInfo(type_name)
@@ -1379,7 +1389,11 @@
match = re.match(r'(?:sequence<([\w ]+)>|(\w+)\[\])$', type_name)
if match:
type_data = TypeData('Sequence')
- item_info = self.TypeInfo(match.group(1) or match.group(2))
+ if self.HasTypeDef(match.group(1) or match.group(2)):
+ # It's a typedef (union)
+ item_info = self.TypeInfo('any')
+ else:
+ item_info = self.TypeInfo(match.group(1) or match.group(2))
# TODO(vsm): Generalize this code.
if 'SourceInfo' in type_name:
type_data.native_type = 'const Vector<RefPtr<SourceInfo> >& '
@@ -1393,8 +1407,23 @@
if self._database.HasInterface(type_name):
interface = self._database.GetInterface(type_name)
- else:
+ elif self._database.HasDictionary(type_name):
interface = self._database.GetDictionary(type_name)
+ elif type_name.startswith('sequence<('):
+ if type_name.find(' or ') != -1:
+ # Union type of sequence is an any type (no type).
+ type_data = TypeData('Sequence')
+ item_info = self.TypeInfo('any')
+ return SequenceIDLTypeInfo(type_name, type_data, item_info)
+ elif type_name.startswith('sequence<sequence<'):
+ # TODO(terry): Cleanup up list of list, etc.
+ type_data = TypeData('Sequence')
+ item_info = self.TypeInfo('any')
+ return SequenceIDLTypeInfo(type_name, type_data, item_info)
+ elif self.HasTypeDef(type_name):
+ # It's a typedef (implied union)
+ return self.TypeInfo('any')
+
if 'Callback' in interface.ext_attrs:
return CallbackIDLTypeInfo(type_name, TypeData('Callback',
self._renamer.DartifyTypeName(type_name)))
diff --git a/tools/dom/scripts/go.sh b/tools/dom/scripts/go.sh
index c17719f..a830a9b 100755
--- a/tools/dom/scripts/go.sh
+++ b/tools/dom/scripts/go.sh
@@ -18,7 +18,7 @@
#
# To generate a subset of systems:
#
-# ./go.sh dart2js,htmldart2js
+# ./go.sh dart2js,htmldartium
#
# The following gives a picture of the changes due to 'work'
#
@@ -29,7 +29,7 @@
# ./go.sh
# meld ../generated0 ../generated # compare directories with too
-ALLSYSTEMS="htmldart2js,htmldartium"
+ALLSYSTEMS="htmldart2js,htmldartium,_blink"
SYSTEMS="$ALLSYSTEMS"
if [[ "$1" != "" ]] ; then
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index e7e500f..b93b0ca 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -311,6 +311,11 @@
self.EmitAttribute(attribute, attr_name, read_only)
def AddOperation(self, info, declare_only=False, dart_js_interop=False):
+ # TODO(terry): Hack window has 2 overloaded getter one returns Window and
+ # and other object (we'll always return Window)?
+ if self._interface.id == "Window" and info.name == '__getter__':
+ info.operations[1].type = info.operations[0].type;
+
""" Adds an operation to the generated class.
Arguments:
info - The operation info of the operation to be added.
@@ -528,7 +533,9 @@
def _AddConstructor(self,
constructor_info, factory_name, factory_constructor_name):
# Hack to ignore the Image constructor used by JavaScript.
- if ((self._interface.id == 'HTMLImageElement' or self._interface.id == 'Blob')
+ if ((self._interface.id == 'HTMLImageElement' or
+ self._interface.id == 'Blob' or
+ self._interface.id == 'DOMException')
and not constructor_info.pure_dart_constructor):
return
@@ -850,17 +857,20 @@
verified_type = temp_type # verified by assignment in checked mode.
else:
converted_arguments.append(info.param_infos[position].name)
- param_type = self._NarrowInputType(arg.type.id)
- # Verified by argument checking on entry to the dispatcher.
-
- verified_type = self._InputType(
- info.param_infos[position].type_id, info)
- # The native method does not need an argument type if we know the type.
- # But we do need the native methods to have correct function types, so
- # be conservative.
- if param_type == verified_type:
- if param_type in ['String', 'num', 'int', 'double', 'bool', 'Object']:
- param_type = 'dynamic'
+ if self._database.HasTypeDef(arg.type.id):
+ param_type = 'dynamic'
+ else:
+ param_type = self._NarrowInputType(arg.type.id)
+ # Verified by argument checking on entry to the dispatcher.
+
+ verified_type = self._InputType(
+ info.param_infos[position].type_id, info)
+ # The native method does not need an argument type if we know the type.
+ # But we do need the native methods to have correct function types, so
+ # be conservative.
+ if param_type == verified_type:
+ if param_type in ['String', 'num', 'int', 'double', 'bool', 'Object']:
+ param_type = 'dynamic'
target_parameters.append(
'%s%s' % (TypeOrNothing(param_type), param_name))
@@ -872,4 +882,8 @@
if conversion:
return conversion.input_type
else:
- return self._NarrowInputType(type_name) if type_name else 'dynamic'
+ # If typedef it's a union return dynamic.
+ if self._database.HasTypeDef(type_name):
+ return 'dynamic'
+ else:
+ return self._NarrowInputType(type_name) if type_name else 'dynamic'
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 78193a5..823666c 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -60,7 +60,8 @@
'SVGSVGElement': 'SvgSvgElement', # Manual to avoid name conflicts.
'Stream': 'FileStream',
'StringCallback': '_StringCallback',
- 'WebGLVertexArrayObjectOES': 'VertexArrayObject',
+ 'WebGL2RenderingContext': 'RenderingContext2',
+ 'WebGL2RenderingContextBase': 'RenderingContextBase2',
'WindowTimers': '_WindowTimers',
'XMLHttpRequest': 'HttpRequest',
'XMLHttpRequestUpload': 'HttpRequestUpload',
diff --git a/tools/dom/scripts/idlnode.py b/tools/dom/scripts/idlnode.py
index e09c8c8..8dfd3b8 100755
--- a/tools/dom/scripts/idlnode.py
+++ b/tools/dom/scripts/idlnode.py
@@ -8,9 +8,7 @@
import idl_definitions
from idl_types import IdlType, IdlNullableType, IdlUnionType, IdlArrayOrSequenceType
-
-from compute_interfaces_info_overall import interfaces_info
-
+import dependency
new_asts = {}
@@ -363,7 +361,7 @@
# Special handling for dart.idl we need to remember the interface,
# since we could have many (not one interface / file). Then build up
# the IDLImplementsStatement for any implements in dart.idl.
- interface_info = interfaces_info['__dart_idl___'];
+ interface_info = dependency.get_interfaces_info()['__dart_idl___'];
self.implementsStatements = []
@@ -377,10 +375,10 @@
implemented_name)
self.implementsStatements.append(implement_statement)
- elif interface.id in interfaces_info:
- interface_info = interfaces_info[interface.id]
+ elif interface.id in dependency.get_interfaces_info():
+ interface_info = dependency.get_interfaces_info()[interface.id]
- implements = interface_info['implements_interfaces']
+ implements = interface_info['implements_interfaces'] if interface_info.has_key('implements_interfaces') else []
if not(blink_interface.is_partial) and len(implements) > 0:
implementor = new_asts[interface.id].interfaces.get(interface.id)
@@ -400,6 +398,15 @@
# No reason to handle typedef they're already aliased in Blink's AST.
self.typeDefs = [] if is_blink else self._convert_all(ast, 'TypeDef', IDLTypeDef)
+ # Hack to record typedefs that are unions.
+ for typedefName in ast.typedefs:
+ typedef_type = ast.typedefs[typedefName]
+ if isinstance(typedef_type.idl_type, IdlUnionType):
+ self.typeDefs.append(IDLTypeDef(typedef_type))
+ elif typedef_type.idl_type.base_type == 'Dictionary':
+ dictionary = IDLDictionary(typedef_type, True)
+ self.dictionaries.append(dictionary)
+
self.enums = self._convert_all(ast, 'Enum', IDLEnum)
def _createImplementsStatement(self, implementor, implemented_name):
@@ -433,7 +440,7 @@
# implements is handled by the interface merging step (see the function
# merge_interface_dependencies).
for interface in self.interfaces:
- interface_info = interfaces_info[interface.id]
+ interface_info = get_interfaces_info()[interface.id]
# TODO(terry): Same handling for implementsStatements as in IDLFile?
self.implementsStatements = interface_info['implements_interfaces']
else:
@@ -567,13 +574,12 @@
if isinstance(ast, IdlType) or isinstance(ast, IdlArrayOrSequenceType) or \
isinstance(ast, IdlNullableType):
type_name = str(ast)
-
# TODO(terry): For now don't handle unrestricted types see
# https://code.google.com/p/chromium/issues/detail?id=354298
type_name = type_name.replace('unrestricted ', '', 1);
- # TODO(terry): Handled ScalarValueString as a DOMString.
- type_name = type_name.replace('ScalarValueString', 'DOMString', 1)
+ # TODO(terry): Handled USVString as a DOMString.
+ type_name = type_name.replace('USVString', 'DOMString', 1)
self.id = type_name
else:
@@ -635,13 +641,16 @@
"""IDLDictionary node contains members,
as well as parent references."""
- def __init__(self, ast):
+ def __init__(self, ast, typedefDictionary=False):
IDLNode.__init__(self, ast)
self.javascript_binding_name = self.id
- self._convert_ext_attrs(ast)
- self._convert_constants(ast, self.id)
-
+ if (typedefDictionary):
+ # Dictionary is a typedef to a union.
+ self._convert_ext_attrs(None)
+ else:
+ self._convert_ext_attrs(ast)
+ self._convert_constants(ast, self.id)
class IDLDictionaryMembers(IDLDictNode):
"""IDLDictionaryMembers specialization for a list of FremontCut dictionary values."""
@@ -754,6 +763,8 @@
# Handling __propertyQuery__ the extended attribute is:
# [Custom=PropertyQuery] getter boolean (DOMString name);
self.id = '__propertyQuery__'
+ elif self.ext_attrs.get('ImplementedAs'):
+ self.id = self.ext_attrs.get('ImplementedAs')
else:
self.id = '__getter__'
elif self.specials == ['setter']:
diff --git a/tools/dom/scripts/idlsync.py b/tools/dom/scripts/idlsync.py
index dc49fce..24aae09 100755
--- a/tools/dom/scripts/idlsync.py
+++ b/tools/dom/scripts/idlsync.py
@@ -7,6 +7,7 @@
import os
import os.path
import re
+import requests
import shutil
import subprocess
import sys
@@ -15,9 +16,10 @@
SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__))
DART_PATH = os.path.abspath(os.path.join(SCRIPT_PATH, '..', '..', '..'))
-# Dartium DEPS file with Chrome and WebKit revisions.
-DEPS = ('http://dart.googlecode.com/svn/branches/'
- 'bleeding_edge/deps/dartium.deps/DEPS')
+# Dartium DEPS file from the DEPS file checked into the dart-lang/sdk integration
+# branch.
+DEPS_GIT = ('https://raw.githubusercontent.com/dart-lang/sdk/'
+ 'integration/tools/deps/dartium.deps/DEPS')
# Whitelist of files to keep.
WHITELIST = [
@@ -29,7 +31,7 @@
]
# WebKit / WebCore info.
-CHROME_TRUNK = "http://src.chromium.org"
+CHROME_TRUNK = "https://src.chromium.org"
WEBKIT_URL_PATTERN = r'"dartium_webkit_branch": "(\S+)",'
WEBKIT_REV_PATTERN = r'"dartium_webkit_revision": "(\d+)",'
WEBCORE_SUBPATH = 'Source/core'
@@ -84,7 +86,7 @@
# DEPS file.
DEPS_PATTERNS = {
'webkit': (CHROME_TRUNK, WEBKIT_URL_PATTERN, WEBKIT_REV_PATTERN),
- 'chrome': (CHROME_TRUNK, CHROME_URL_PATTERN, CHROME_REV_PATTERN),
+# 'chrome': (CHROME_TRUNK, CHROME_URL_PATTERN, CHROME_REV_PATTERN),
}
# List of components to update.
@@ -130,11 +132,9 @@
print 'FAILED. RET_CODE=%d' % pipe.returncode
sys.exit(pipe.returncode)
-
-def GetDeps():
- """Returns the DEPS file contents with pinned revision info."""
- return RunCommand(['svn', 'cat', DEPS])
-
+def GetDepsFromGit():
+ req = requests.get(DEPS_GIT)
+ return req.text
def GetSvnRevision(deps, component):
"""Returns a tuple with the (dartium webkit repo, latest revision)."""
@@ -208,21 +208,15 @@
help='WebKit IDL revision to install', default=None)
parser.add_option('--chrome-revision', '-c', dest='chrome_revision',
help='Chrome IDL revision to install', default=None)
- parser.add_option('--update', '-u', dest='update',
- help='IDL to update (webkit | chrome | all)',
- default='webkit')
args, _ = parser.parse_args()
update = {}
- if args.update == 'all' or args.update == 'chrome':
- update['chrome'] = args.chrome_revision
- if args.update == 'all' or args.update == 'webkit':
- update['webkit'] = args.webkit_revision
+ update['webkit'] = args.webkit_revision
return update
def main():
- deps = GetDeps()
update = ParseOptions()
+ deps = GetDepsFromGit()
for (component, remote_path, local_path, readme, depth) in UPDATE_LIST:
if component in update.keys():
revision = update[component]
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index e9e3720..b624dd0 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -774,7 +774,7 @@
return [
"inspect",
(o) {
- host.callMethod("inspect", [o]);
+ host.callMethod("_inspect", [unwrap_jso(o)]);
return o;
},
"dir",
diff --git a/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate b/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
index cf3c4e4..1b3280d 100644
--- a/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_MessageEvent.darttemplate
@@ -21,11 +21,22 @@
type, canBubble, cancelable, data, origin, lastEventId, source,
messagePorts);
}
-$endif
+$endif
var event = document._createEvent("MessageEvent");
event._initMessageEvent(type, canBubble, cancelable, data, origin,
lastEventId, source, messagePorts);
return event;
}
+
+$if DARTIUM
+ // TODO(alanknight): This really should be generated by the
+ // _OutputConversion in the systemnative.py script, but that doesn't
+ // use those conversions right now, so do this as a one-off.
+ @DomName('MessageEvent.data')
+ @DocsEditable()
+ dynamic get data => convertNativeToDart_SerializedScriptValue(
+ _blink.BlinkMessageEvent.instance.data_Getter_(unwrap_jso(this)));
+$endif
+
$!MEMBERS
}
diff --git a/tools/observatory_tool.py b/tools/observatory_tool.py
index 67c52d7..4cb5dbf 100755
--- a/tools/observatory_tool.py
+++ b/tools/observatory_tool.py
@@ -144,7 +144,8 @@
# development flow.
# REMOVE THE FOLLOWING LINE TO USE the dart_bootstrap binary.
# return False
- print >> sys.stderr, ('Running command "%s"') % (executable + command)
+ if not silent:
+ print >> sys.stderr, ('Running command "%s"') % (executable + command)
return subprocess.call(executable + command,
stdout=silent_sink if silent else None,
stderr=silent_sink if silent else None)
diff --git a/tools/precompilation/test_linux.sh b/tools/precompilation/test_linux.sh
index 93de570..514ac04 100755
--- a/tools/precompilation/test_linux.sh
+++ b/tools/precompilation/test_linux.sh
@@ -10,6 +10,6 @@
./out/DebugX64/dart_no_snapshot --gen-precompiled-snapshot --package-root=out/DebugX64/packages/ "$1"
-gcc -m64 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.S
+gcc -nostartfiles -m64 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.S
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" gdb -ex run --args ./out/DebugX64/dart_precompiled_runtime --run-precompiled-snapshot not_used.dart
diff --git a/tools/precompilation/test_linux_simarm.sh b/tools/precompilation/test_linux_simarm.sh
index 8a8f36c..bd0f1f0 100755
--- a/tools/precompilation/test_linux_simarm.sh
+++ b/tools/precompilation/test_linux_simarm.sh
@@ -10,6 +10,6 @@
./out/DebugSIMARM/dart_no_snapshot --gen-precompiled-snapshot --package-root=out/DebugX64/packages/ "$1"
-gcc -m32 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.S
+gcc -nostartfiles -m32 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.S
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" gdb -ex run --args ./out/DebugSIMARM/dart_precompiled_runtime --run-precompiled-snapshot not_used.dart
diff --git a/tools/precompilation/test_macos.sh b/tools/precompilation/test_macos.sh
index e853b1b..ed90d12 100755
--- a/tools/precompilation/test_macos.sh
+++ b/tools/precompilation/test_macos.sh
@@ -10,6 +10,6 @@
./xcodebuild/DebugX64/dart_no_snapshot --gen-precompiled-snapshot --package-root=xcodebuild/DebugX64/packages/ "$1"
-clang -m64 -dynamiclib -o libprecompiled.dylib precompiled.S
+clang -nostartfiles -m64 -dynamiclib -o libprecompiled.dylib precompiled.S
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" lldb -- ./xcodebuild/DebugX64/dart_precompiled_runtime --run-precompiled-snapshot not_used.dart
diff --git a/tools/sdks/linux/dart-sdk.tar.gz.sha1 b/tools/sdks/linux/dart-sdk.tar.gz.sha1
index 90b6e73..9083f2b 100644
--- a/tools/sdks/linux/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/linux/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-2709941a74b808414feb005dfa50986680f9bd20
\ No newline at end of file
+360de5bc1ad8b525f2ccc98c80fd87131caaefe2
\ No newline at end of file
diff --git a/tools/sdks/mac/dart-sdk.tar.gz.sha1 b/tools/sdks/mac/dart-sdk.tar.gz.sha1
index 9f3c196..292199a 100644
--- a/tools/sdks/mac/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/mac/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-8d928e400289862483a11e798743e49815c06c43
\ No newline at end of file
+45bb23f239c67de5e01a24e7efcf4b323eb9c36c
\ No newline at end of file
diff --git a/tools/sdks/win/dart-sdk.tar.gz.sha1 b/tools/sdks/win/dart-sdk.tar.gz.sha1
index a5b7f6a..54587b2 100644
--- a/tools/sdks/win/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/win/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-90d43da115a1eafe707f6f5c5c0d718ff716c227
\ No newline at end of file
+1264ca2ff3131284a53ccffadeb230835300c602
\ No newline at end of file
diff --git a/tools/test.py b/tools/test.py
index 69b9ed8..9a32fa5 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -16,7 +16,8 @@
tools_dir = os.path.dirname(os.path.realpath(__file__))
dart_script_name = 'test.dart'
dart_test_script = string.join([tools_dir, dart_script_name], os.sep)
- command = [utils.DartBinary(), '--checked', dart_test_script] + args
+ command = [utils.CheckedInSdkExecutable(),
+ '--checked', dart_test_script] + args
exit_code = subprocess.call(command)
utils.DiagnoseExitCode(exit_code, command)
return exit_code
diff --git a/tools/testing/bin/linux/dart-arm.sha1 b/tools/testing/bin/linux/dart-arm.sha1
deleted file mode 100644
index c00a011..0000000
--- a/tools/testing/bin/linux/dart-arm.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5246a42926c8d5c2ac785c952b76b746270c9484
\ No newline at end of file
diff --git a/tools/testing/bin/linux/dart-mips.sha1 b/tools/testing/bin/linux/dart-mips.sha1
deleted file mode 100644
index 6100eae..0000000
--- a/tools/testing/bin/linux/dart-mips.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7ab189bca5c5cf2997b9ab5770a5b418cd4fa5b1
\ No newline at end of file
diff --git a/tools/testing/bin/linux/dart.sha1 b/tools/testing/bin/linux/dart.sha1
deleted file mode 100644
index d8f03be..0000000
--- a/tools/testing/bin/linux/dart.sha1
+++ /dev/null
@@ -1 +0,0 @@
-701c1f2bda5c7fa3cc0f044d7515237bdc2cc163
\ No newline at end of file
diff --git a/tools/testing/bin/macos/dart.sha1 b/tools/testing/bin/macos/dart.sha1
deleted file mode 100644
index c30354b..0000000
--- a/tools/testing/bin/macos/dart.sha1
+++ /dev/null
@@ -1 +0,0 @@
-ecefe6ba96b8da00d171e199b2801982f98cc78d
\ No newline at end of file
diff --git a/tools/testing/bin/windows/dart.exe.sha1 b/tools/testing/bin/windows/dart.exe.sha1
deleted file mode 100644
index c43f346..0000000
--- a/tools/testing/bin/windows/dart.exe.sha1
+++ /dev/null
@@ -1 +0,0 @@
-c1394c6a589c47f7a6a1315eb1f9885d66852d67
\ No newline at end of file
diff --git a/tools/testing/dart/co19_test.dart b/tools/testing/dart/co19_test.dart
index f138688e..d826263 100644
--- a/tools/testing/dart/co19_test.dart
+++ b/tools/testing/dart/co19_test.dart
@@ -11,7 +11,7 @@
* co19.
*
* Usage:
- * [: ./tools/testing/bin/$OS/dart tools/testing/dart/co19_test.dart :]
+ * [: dart tools/testing/dart/co19_test.dart :]
*/
library co19_test;
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 70c1264..931a53d 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -73,6 +73,9 @@
isHostChecked: isHostChecked, useCps: useCps, useSdk: useSdk,
isCsp: isCsp, extraDart2jsOptions:
TestUtils.getExtraOptions(configuration, 'dart2js_options'));
+ case 'dart2app':
+ return new Dart2AppSnapshotCompilerConfiguration(
+ isDebug: isDebug, isChecked: isChecked);
case 'precompiler':
return new PrecompilerCompilerConfiguration(
isDebug: isDebug, isChecked: isChecked);
@@ -214,22 +217,11 @@
arguments = new List.from(arguments);
arguments.add('--out=$outputFileName');
- // We want all dart2js compilers to run the vm with the
- // --abort-on-assertion-errors flag.
- // We have allowed constant maps as environmentOverrides,
- // so we modify a new map.
- var newOverrides = {'DART_VM_OPTIONS': '--abort-on-assertion-errors'};
- if (environmentOverrides != null) {
- newOverrides.addAll(environmentOverrides);
- if (environmentOverrides.containsKey('DART_VM_OPTIONS')) {
- newOverrides['DART_VM_OPTIONS'] += ' --abort-on-assertion-errors';
- }
- }
return commandBuilder.getCompilationCommand(
moniker, outputFileName, !useSdk,
bootstrapDependencies(buildDir),
computeCompilerPath(buildDir),
- arguments, newOverrides);
+ arguments, environmentOverrides);
}
List<Uri> bootstrapDependencies(String buildDir) {
@@ -394,6 +386,93 @@
}
+class Dart2AppSnapshotCompilerConfiguration extends CompilerConfiguration {
+ Dart2AppSnapshotCompilerConfiguration({
+ 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)],
+ computeOutputName(tempDir),
+ 'application/dart-snapshot');
+ }
+
+ String computeOutputName(String tempDir) {
+ return '$tempDir/test.snapshot';
+ }
+
+ CompilationCommand computeCompilationCommand(
+ String tempDir,
+ String buildDir,
+ CommandBuilder commandBuilder,
+ List arguments,
+ Map<String, String> environmentOverrides) {
+ var exec = "$buildDir/dart_no_snapshot";
+ var args = new List();
+ args.add("--full-snapshot-after-run=${computeOutputName(tempDir)}");
+ args.addAll(arguments);
+
+ return commandBuilder.getCompilationCommand(
+ 'dart2snapshot', computeOutputName(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/http_server.dart b/tools/testing/dart/http_server.dart
index 843aaaf..1cfdb65 100644
--- a/tools/testing/dart/http_server.dart
+++ b/tools/testing/dart/http_server.dart
@@ -172,7 +172,7 @@
}
String httpServerCommandline() {
- var dart = TestUtils.dartTestExecutable.toNativePath();
+ var dart = Platform.resolvedExecutable;
var dartDir = TestUtils.dartDir;
var script = dartDir.join(new Path("tools/testing/dart/http_server.dart"));
var buildDirectory = _buildDirectory.toNativePath();
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 8596c6f..c2b2aed 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_product':
+ return new DartProductRuntimeConfiguration();
+
case 'dart_precompiled':
return new DartPrecompiledRuntimeConfiguration();
@@ -218,7 +221,7 @@
if (script != null && type != 'application/dart') {
throw "Dart VM cannot run files of type '$type'.";
}
- String executable = suite.configuration['noopt']
+ String executable = suite.configuration['noopt']
? suite.dartVmNooptBinaryFileName
: suite.dartVmBinaryFileName;
return <Command>[commandBuilder.getVmCommand(
@@ -226,6 +229,29 @@
}
}
+class DartProductRuntimeConfiguration 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-snapshot') {
+ throw "dart_product cannot run files of type '$type'.";
+ }
+
+ var augmentedArgs = new List();
+ augmentedArgs.add("--run-full-snapshot=${artifact.filename}");
+ augmentedArgs.addAll(arguments);
+
+ return <Command>[commandBuilder.getVmCommand(
+ suite.dartVmProductBinaryFileName,
+ augmentedArgs,
+ environmentOverrides)];
+ }
+}
class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration {
List<Command> computeRuntimeCommands(
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 8e23169..26d5249 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -65,9 +65,13 @@
none (compile only)),
dart2analyzer: Perform static analysis on Dart code by running the analyzer
- (only valid with the following runtimes: none)''',
+ (only valid with the following runtimes: none)
+
+ dart2app: Compile the Dart code into an app snapshot before running the test
+ (only valid with the following runtimes: dart_product)''',
['-c', '--compiler'],
- ['none', 'precompiler', 'dart2js', 'dart2analyzer'],
+ ['none', 'precompiler', 'dart2js', 'dart2analyzer',
+ 'dart2app'],
'none'),
// TODO(antonm): fix the option drt.
new _TestOptionSpecification(
@@ -78,6 +82,8 @@
dart_precompiled: Run a precompiled snapshot on a variant of the standalone
dart vm lacking a JIT.
+ dart_product: Run a full app snapshot in product mode.
+
d8: Run JavaScript from the command line using v8.
jsshell: Run JavaScript from the command line using firefox js-shell.
@@ -98,7 +104,8 @@
none: No runtime, compile only (for example, used for dart2analyzer static
analysis tests).''',
['-r', '--runtime'],
- ['vm', 'dart_precompiled', 'd8', 'jsshell', 'drt', 'dartium',
+ ['vm', 'dart_precompiled', 'dart_product',
+ 'd8', 'jsshell', 'drt', 'dartium',
'ff', 'firefox',
'chrome', 'safari', 'ie9', 'ie10', 'ie11', 'opera',
'chromeOnAndroid', 'safarimobilesim',
@@ -648,6 +655,9 @@
case 'dart2analyzer':
validRuntimes = const ['none'];
break;
+ case 'dart2app':
+ validRuntimes = const ['dart_product'];
+ break;
case 'precompiler':
validRuntimes = const ['dart_precompiled'];
break;
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index ffd9921..42dba81 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -292,7 +292,7 @@
retry == other.retry;
String get reproductionCommand {
- var parts = [TestUtils.dartTestExecutable.toString(),
+ var parts = [io.Platform.resolvedExecutable,
'tools/testing/dart/launch_browser.dart',
browser,
url];
@@ -1679,7 +1679,8 @@
return new VmCommandOutputImpl(
command, exitCode, timedOut, stdout, stderr, time, pid);
} else if (command is CompilationCommand) {
- if (command.displayName == 'precompiler.dart') {
+ if (command.displayName == 'precompiler.dart' ||
+ command.displayName == 'dart2snapshot') {
return new VmCommandOutputImpl(
command, exitCode, timedOut, stdout, stderr, time, pid);
}
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index ed354d2..21a99a8 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -240,6 +240,21 @@
return dartExecutable;
}
+ String get dartVmProductBinaryFileName {
+ // Controlled by user with the option "--dart".
+ String dartExecutable = configuration['dart'];
+
+ if (dartExecutable == '') {
+ String suffix = executableBinarySuffix;
+ dartExecutable = useSdk
+ ? '$buildDir/dart-sdk/bin/dart_product$suffix'
+ : '$buildDir/dart_product$suffix';
+ }
+
+ TestUtils.ensureExists(dartExecutable, configuration);
+ return dartExecutable;
+ }
+
String get d8FileName {
var suffix = getExecutableSuffix('d8');
var d8Dir = TestUtils.dartDir.append('third_party/d8');
@@ -1807,8 +1822,9 @@
}
List<List<String>> getVmOptions(Map optionsFromFile) {
- var COMPILERS = const ['none', 'precompiler'];
- var RUNTIMES = const ['none', 'dart_precompiled', 'vm', 'drt', 'dartium',
+ var COMPILERS = const ['none', 'precompiler', 'dart2app'];
+ var RUNTIMES = const ['none', 'dart_precompiled', 'dart_product', 'vm',
+ 'drt', 'dartium',
'ContentShellOnAndroid', 'DartiumOnAndroid'];
var needsVmOptions = COMPILERS.contains(configuration['compiler']) &&
RUNTIMES.contains(configuration['runtime']);
@@ -2371,19 +2387,6 @@
}
/**
- * Returns the path to the dart binary checked into the repo, used for
- * bootstrapping test.dart.
- */
- static Path get dartTestExecutable {
- var path = '$dartDir/tools/testing/bin/'
- '${Platform.operatingSystem}/dart';
- if (Platform.operatingSystem == 'windows') {
- path = '$path.exe';
- }
- return new Path(path);
- }
-
- /**
* Gets extra options under [key] passed to the testing script.
*/
static List<String> getExtraOptions(Map configuration, String key) {
diff --git a/tools/utils.py b/tools/utils.py
index 8ea1874..69d6a39 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -573,38 +573,6 @@
return pipe.returncode, output
-def DartBinary():
- # TODO(24311): Replace all uses of this with CheckedInSdk[Fix]Executable().
- tools_dir = os.path.dirname(os.path.realpath(__file__))
- dart_binary_prefix = os.path.join(tools_dir, 'testing', 'bin')
- if IsWindows():
- return os.path.join(dart_binary_prefix, 'windows', 'dart.exe')
- else:
- arch = GuessArchitecture()
- system = GuessOS()
- if arch == 'armv5te':
- # TODO(zra): This binary does not exist, yet. Check one in once we have
- # sufficient stability.
- return os.path.join(dart_binary_prefix, system, 'dart-armv5te')
- elif arch == 'armv6':
- # TODO(zra): Ditto.
- return os.path.join(dart_binary_prefix, system, 'dart-armv6')
- elif arch == 'arm':
- return os.path.join(dart_binary_prefix, system, 'dart-arm')
- elif arch == 'arm64':
- return os.path.join(dart_binary_prefix, system, 'dart-arm64')
- elif arch == 'mips':
- return os.path.join(dart_binary_prefix, system, 'dart-mips')
- else:
- return os.path.join(dart_binary_prefix, system, 'dart')
-
-
-def DartSdkBinary():
- tools_dir = os.path.dirname(os.path.realpath(__file__))
- dart_binary_prefix = os.path.join(tools_dir, '..', 'sdk' , 'bin')
- return os.path.join(dart_binary_prefix, 'dart')
-
-
# The checked-in SDKs are documented at
# https://github.com/dart-lang/sdk/wiki/The-checked-in-SDK-in-tools
def CheckedInSdkPath():
@@ -635,7 +603,14 @@
elif arch == 'arm':
name = 'dart-arm'
elif arch == 'arm64':
- name = 'dart-arm'
+ name = 'dart-arm64'
+ elif arch == 'armv5te':
+ # TODO(zra): This binary does not exist, yet. Check one in once we have
+ # sufficient stability.
+ name = 'dart-armv5te'
+ elif arch == 'armv6':
+ # TODO(zra): Ditto.
+ name = 'dart-armv6'
return os.path.join(CheckedInSdkPath(), 'bin', name)